Flutter Engine
The Flutter Engine
DawnComputePipeline.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
20
21namespace skgpu::graphite {
22namespace {
23
24struct ShaderInfo {
25 wgpu::ShaderModule fModule;
26 std::string fEntryPoint;
27
28 bool isValid() const { return static_cast<bool>(fModule); }
29};
30
31static ShaderInfo compile_shader_module(const DawnSharedContext* sharedContext,
32 const ComputePipelineDesc& pipelineDesc) {
33 SkASSERT(sharedContext);
34
35 ShaderInfo info;
36
37 const Caps* caps = sharedContext->caps();
38 const ComputeStep* step = pipelineDesc.computeStep();
39 ShaderErrorHandler* errorHandler = caps->shaderErrorHandler();
40
41 if (step->supportsNativeShader()) {
42 auto nativeShader = step->nativeShaderSource(ComputeStep::NativeShaderFormat::kWGSL);
43 if (!DawnCompileWGSLShaderModule(sharedContext,
44 step->name(),
45 std::string(nativeShader.fSource),
46 &info.fModule,
47 errorHandler)) {
48 return {};
49 }
50 info.fEntryPoint = std::move(nativeShader.fEntryPoint);
51 } else {
52 std::string wgsl;
55
56 std::string sksl = BuildComputeSkSL(caps, step);
57 if (skgpu::SkSLToWGSL(caps->shaderCaps(),
58 sksl,
61 &wgsl,
62 &interface,
63 errorHandler)) {
64 if (!DawnCompileWGSLShaderModule(sharedContext, step->name(), wgsl,
65 &info.fModule, errorHandler)) {
66 return {};
67 }
68 info.fEntryPoint = "main";
69 }
70 }
71
72 return info;
73}
74
75} // namespace
76
78 const ComputePipelineDesc& pipelineDesc) {
79 auto [shaderModule, entryPointName] = compile_shader_module(sharedContext, pipelineDesc);
80 if (!shaderModule) {
81 return nullptr;
82 }
83
84 const ComputeStep* step = pipelineDesc.computeStep();
85
86 // ComputeStep resources are listed in the order that they must be declared in the shader. This
87 // order is then used for the index assignment using an "indexed by order" policy that has
88 // backend-specific semantics. The semantics on Dawn is to assign the index number in increasing
89 // order.
90 //
91 // All resources get assigned to a single bind group at index 0.
93 std::vector<wgpu::BindGroupLayoutEntry> bindGroupLayoutEntries;
94 auto resources = step->resources();
95
96 // Sampled textures count as 2 resources (1 texture and 1 sampler). All other types count as 1.
97 size_t resourceCount = 0;
98 for (const ComputeStep::ResourceDesc& r : resources) {
99 resourceCount++;
101 resourceCount++;
102 }
103 }
104
105 bindGroupLayoutEntries.reserve(resourceCount);
106 int declarationIndex = 0;
107 for (const ComputeStep::ResourceDesc& r : resources) {
108 bindGroupLayoutEntries.emplace_back();
109 uint32_t bindingIndex = bindGroupLayoutEntries.size() - 1;
110
111 wgpu::BindGroupLayoutEntry& entry = bindGroupLayoutEntries.back();
112 entry.binding = bindingIndex;
113 entry.visibility = wgpu::ShaderStage::Compute;
114 switch (r.fType) {
116 entry.buffer.type = wgpu::BufferBindingType::Uniform;
117 break;
120 entry.buffer.type = wgpu::BufferBindingType::Storage;
121 break;
123 entry.buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
124 break;
126 entry.texture.sampleType = wgpu::TextureSampleType::Float;
127 entry.texture.viewDimension = wgpu::TextureViewDimension::e2D;
128 break;
130 entry.storageTexture.access = wgpu::StorageTextureAccess::WriteOnly;
131 entry.storageTexture.viewDimension = wgpu::TextureViewDimension::e2D;
132
133 auto [_, colorType] = step->calculateTextureParameters(declarationIndex, r);
135 entry.storageTexture.format = textureInfo.dawnTextureSpec().getViewFormat();
136 break;
137 }
139 entry.sampler.type = wgpu::SamplerBindingType::Filtering;
140
141 // Add an additional entry for the texture.
142 bindGroupLayoutEntries.emplace_back();
143 wgpu::BindGroupLayoutEntry& texEntry = bindGroupLayoutEntries.back();
144 texEntry.binding = bindingIndex + 1;
145 texEntry.visibility = wgpu::ShaderStage::Compute;
146 texEntry.texture.sampleType = wgpu::TextureSampleType::Float;
147 texEntry.texture.viewDimension = wgpu::TextureViewDimension::e2D;
148 break;
149 }
150 }
151 declarationIndex++;
152 }
153
154 const wgpu::Device& device = sharedContext->device();
155
156 // All resources of a ComputeStep currently get assigned to a single bind group at index 0.
157 wgpu::BindGroupLayoutDescriptor bindGroupLayoutDesc;
158 bindGroupLayoutDesc.entryCount = bindGroupLayoutEntries.size();
159 bindGroupLayoutDesc.entries = bindGroupLayoutEntries.data();
160 wgpu::BindGroupLayout bindGroupLayout = device.CreateBindGroupLayout(&bindGroupLayoutDesc);
161 if (!bindGroupLayout) {
162 return nullptr;
163 }
164
165 wgpu::PipelineLayoutDescriptor pipelineLayoutDesc;
167 pipelineLayoutDesc.label = step->name();
168 }
169 pipelineLayoutDesc.bindGroupLayoutCount = 1;
170 pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout;
171 wgpu::PipelineLayout layout = device.CreatePipelineLayout(&pipelineLayoutDesc);
172 if (!layout) {
173 return nullptr;
174 }
175
176 wgpu::ComputePipelineDescriptor descriptor;
177 // Always set the label for pipelines, dawn may need it for tracing.
178 descriptor.label = step->name();
179 descriptor.compute.module = std::move(shaderModule);
180 descriptor.compute.entryPoint = entryPointName.c_str();
181 descriptor.layout = std::move(layout);
182
183 std::optional<DawnErrorChecker> errorChecker;
184 if (sharedContext->dawnCaps()->allowScopedErrorChecks()) {
185 errorChecker.emplace(sharedContext);
186 }
187 wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&descriptor);
188 SkASSERT(pipeline);
189 if (errorChecker.has_value() && errorChecker->popErrorScopes() != DawnErrorType::kNoError) {
190 return nullptr;
191 }
192
194 sharedContext, std::move(pipeline), std::move(bindGroupLayout)));
195}
196
197DawnComputePipeline::DawnComputePipeline(const SharedContext* sharedContext,
198 wgpu::ComputePipeline pso,
199 wgpu::BindGroupLayout groupLayout)
200 : ComputePipeline(sharedContext)
201 , fPipeline(std::move(pso))
202 , fGroupLayout(std::move(groupLayout)) {}
203
204void DawnComputePipeline::freeGpuData() { fPipeline = nullptr; }
205
206} // namespace skgpu::graphite
static int step(int x, SkScalar min, SkScalar max)
Definition: BlurTest.cpp:215
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
std::string fEntryPoint
wgpu::ShaderModule fModule
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool ComputeStep(const SkPoint &a, const SkPoint &b, SkScalar radius, SkPoint *step)
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
SkMeshSpecification::Uniform Uniform
Definition: SkMesh.cpp:66
const ResourceBindingRequirements & resourceBindingRequirements() const
Definition: Caps.h:150
virtual TextureInfo getDefaultStorageTextureInfo(SkColorType) const =0
bool setBackendLabels() const
Definition: Caps.h:297
const ComputeStep * computeStep() const
static sk_sp< DawnComputePipeline > Make(const DawnSharedContext *, const ComputePipelineDesc &)
const SharedContext * sharedContext() const
Definition: Resource.h:189
const Caps * caps() const
Definition: SharedContext.h:39
VkDevice device
Definition: main.cc:53
std::string BuildComputeSkSL(const Caps *caps, const ComputeStep *step)
bool DawnCompileWGSLShaderModule(const DawnSharedContext *sharedContext, const char *label, const std::string &wgsl, wgpu::ShaderModule *module, ShaderErrorHandler *errorHandler)
bool SkSLToWGSL(const SkSL::ShaderCaps *caps, const std::string &sksl, SkSL::ProgramKind programKind, const SkSL::ProgramSettings &settings, std::string *wgsl, SkSL::ProgramInterface *outInterface, ShaderErrorHandler *errorHandler)
Definition: DawnUtilsPriv.h:29
Definition: ref_ptr.h:256