Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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,
60 settings,
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++;
100 if (r.fType == ComputeStep::ResourceType::kSampledTexture) {
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) {
115 case ComputeStep::ResourceType::kUniformBuffer:
116 entry.buffer.type = wgpu::BufferBindingType::Uniform;
117 break;
118 case ComputeStep::ResourceType::kStorageBuffer:
119 case ComputeStep::ResourceType::kIndirectBuffer:
120 entry.buffer.type = wgpu::BufferBindingType::Storage;
121 break;
122 case ComputeStep::ResourceType::kReadOnlyStorageBuffer:
123 entry.buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
124 break;
125 case ComputeStep::ResourceType::kReadOnlyTexture:
126 entry.texture.sampleType = wgpu::TextureSampleType::Float;
127 entry.texture.viewDimension = wgpu::TextureViewDimension::e2D;
128 break;
129 case ComputeStep::ResourceType::kWriteOnlyStorageTexture: {
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 }
138 case ComputeStep::ResourceType::kSampledTexture: {
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;
166 pipelineLayoutDesc.label = step->name();
167 pipelineLayoutDesc.bindGroupLayoutCount = 1;
168 pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout;
169 wgpu::PipelineLayout layout = device.CreatePipelineLayout(&pipelineLayoutDesc);
170 if (!layout) {
171 return nullptr;
172 }
173
174 wgpu::ComputePipelineDescriptor descriptor;
175 descriptor.label = step->name();
176 descriptor.compute.module = std::move(shaderModule);
177 descriptor.compute.entryPoint = entryPointName.c_str();
178 descriptor.layout = std::move(layout);
179
180 std::optional<DawnErrorChecker> errorChecker;
181 if (sharedContext->dawnCaps()->allowScopedErrorChecks()) {
182 errorChecker.emplace(sharedContext);
183 }
184 wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&descriptor);
185 SkASSERT(pipeline);
186 if (errorChecker.has_value() && errorChecker->popErrorScopes() != DawnErrorType::kNoError) {
187 return nullptr;
188 }
189
191 sharedContext, std::move(pipeline), std::move(bindGroupLayout)));
192}
193
194DawnComputePipeline::DawnComputePipeline(const SharedContext* sharedContext,
195 wgpu::ComputePipeline pso,
196 wgpu::BindGroupLayout groupLayout)
197 : ComputePipeline(sharedContext)
198 , fPipeline(std::move(pso))
199 , fGroupLayout(std::move(groupLayout)) {}
200
201void DawnComputePipeline::freeGpuData() { fPipeline = nullptr; }
202
203} // 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 SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
const ResourceBindingRequirements & resourceBindingRequirements() const
Definition Caps.h:143
virtual TextureInfo getDefaultStorageTextureInfo(SkColorType) const =0
const ComputeStep * computeStep() const
static sk_sp< DawnComputePipeline > Make(const DawnSharedContext *, const ComputePipelineDesc &)
const SharedContext * sharedContext() const
Definition Resource.h:187
const Caps * caps() const
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 ref_ptr.h:256