1 /*
2 * Copyright 2022 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
8 #include "src/gpu/graphite/dawn/DawnResourceProvider.h"
9
10 #include "include/gpu/graphite/BackendTexture.h"
11 #include "src/gpu/graphite/ComputePipeline.h"
12 #include "src/gpu/graphite/dawn/DawnBuffer.h"
13 #include "src/gpu/graphite/dawn/DawnGraphicsPipeline.h"
14 #include "src/gpu/graphite/dawn/DawnSampler.h"
15 #include "src/gpu/graphite/dawn/DawnSharedContext.h"
16 #include "src/gpu/graphite/dawn/DawnTexture.h"
17
18 namespace skgpu::graphite {
19
20 namespace {
create_shader_module(const wgpu::Device & device,const char * source)21 wgpu::ShaderModule create_shader_module(const wgpu::Device& device, const char* source) {
22 wgpu::ShaderModuleWGSLDescriptor wgslDesc;
23 wgslDesc.source = source;
24 wgpu::ShaderModuleDescriptor descriptor;
25 descriptor.nextInChain = &wgslDesc;
26 return device.CreateShaderModule(&descriptor);
27 }
28
create_blit_render_pipeline(const wgpu::Device & device,const char * label,wgpu::ShaderModule vsModule,wgpu::ShaderModule fsModule,wgpu::TextureFormat renderPassColorFormat,wgpu::TextureFormat renderPassDepthStencilFormat,int numSamples)29 wgpu::RenderPipeline create_blit_render_pipeline(const wgpu::Device& device,
30 const char* label,
31 wgpu::ShaderModule vsModule,
32 wgpu::ShaderModule fsModule,
33 wgpu::TextureFormat renderPassColorFormat,
34 wgpu::TextureFormat renderPassDepthStencilFormat,
35 int numSamples) {
36 wgpu::RenderPipelineDescriptor descriptor;
37 #if defined(SK_DEBUG)
38 descriptor.label = label;
39 #endif
40 descriptor.layout = nullptr;
41
42 wgpu::ColorTargetState colorTarget;
43 colorTarget.format = renderPassColorFormat;
44 colorTarget.blend = nullptr;
45 colorTarget.writeMask = wgpu::ColorWriteMask::All;
46
47 wgpu::DepthStencilState depthStencil;
48 if (renderPassDepthStencilFormat != wgpu::TextureFormat::Undefined) {
49 depthStencil.format = renderPassDepthStencilFormat;
50 depthStencil.depthWriteEnabled = false;
51 depthStencil.depthCompare = wgpu::CompareFunction::Always;
52
53 descriptor.depthStencil = &depthStencil;
54 }
55
56 wgpu::FragmentState fragment;
57 fragment.module = std::move(fsModule);
58 fragment.entryPoint = "main";
59 fragment.targetCount = 1;
60 fragment.targets = &colorTarget;
61 descriptor.fragment = &fragment;
62
63 descriptor.vertex.module = std::move(vsModule);
64 descriptor.vertex.entryPoint = "main";
65 descriptor.vertex.constantCount = 0;
66 descriptor.vertex.constants = nullptr;
67 descriptor.vertex.bufferCount = 0;
68 descriptor.vertex.buffers = nullptr;
69
70 descriptor.primitive.frontFace = wgpu::FrontFace::CCW;
71 descriptor.primitive.cullMode = wgpu::CullMode::None;
72 descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleStrip;
73 descriptor.primitive.stripIndexFormat = wgpu::IndexFormat::Undefined;
74
75 descriptor.multisample.count = numSamples;
76 descriptor.multisample.mask = 0xFFFFFFFF;
77 descriptor.multisample.alphaToCoverageEnabled = false;
78
79 return device.CreateRenderPipeline(&descriptor);
80 }
81 }
82
DawnResourceProvider(SharedContext * sharedContext,SingleOwner * singleOwner)83 DawnResourceProvider::DawnResourceProvider(SharedContext* sharedContext,
84 SingleOwner* singleOwner)
85 : ResourceProvider(sharedContext, singleOwner) {}
86
87 DawnResourceProvider::~DawnResourceProvider() = default;
88
findOrCreateBlitWithDrawPipeline(const RenderPassDesc & renderPassDesc)89 wgpu::RenderPipeline DawnResourceProvider::findOrCreateBlitWithDrawPipeline(
90 const RenderPassDesc& renderPassDesc) {
91 uint64_t renderPassKey =
92 this->dawnSharedContext()->dawnCaps()->getRenderPassDescKey(renderPassDesc);
93 wgpu::RenderPipeline pipeline = fBlitWithDrawPipelines[renderPassKey];
94 if (!pipeline) {
95 static constexpr char kVertexShaderText[] = R"(
96 var<private> fullscreenTriPositions : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
97 vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
98
99 @vertex
100 fn main(@builtin(vertex_index) vertexIndex : u32) -> @builtin(position) vec4<f32> {
101 return vec4(fullscreenTriPositions[vertexIndex], 1.0, 1.0);
102 }
103 )";
104
105 static constexpr char kFragmentShaderText[] = R"(
106 @group(0) @binding(0) var colorMap: texture_2d<f32>;
107
108 @fragment
109 fn main(@builtin(position) fragPosition : vec4<f32>) -> @location(0) vec4<f32> {
110 var coords : vec2<i32> = vec2<i32>(i32(fragPosition.x), i32(fragPosition.y));
111 return textureLoad(colorMap, coords, 0);
112 }
113 )";
114
115 auto vsModule = create_shader_module(dawnSharedContext()->device(), kVertexShaderText);
116 auto fsModule = create_shader_module(dawnSharedContext()->device(), kFragmentShaderText);
117
118 pipeline = create_blit_render_pipeline(
119 dawnSharedContext()->device(),
120 /*label=*/"BlitWithDraw",
121 std::move(vsModule),
122 std::move(fsModule),
123 /*renderPassColorFormat=*/
124 renderPassDesc.fColorAttachment.fTextureInfo.dawnTextureSpec().fFormat,
125 /*renderPassDepthStencilFormat=*/
126 renderPassDesc.fDepthStencilAttachment.fTextureInfo.isValid()
127 ? renderPassDesc.fDepthStencilAttachment.fTextureInfo.dawnTextureSpec()
128 .fFormat
129 : wgpu::TextureFormat::Undefined,
130 /*numSamples=*/renderPassDesc.fColorAttachment.fTextureInfo.numSamples());
131
132 if (pipeline) {
133 fBlitWithDrawPipelines.set(renderPassKey, pipeline);
134 }
135 }
136
137 return pipeline;
138 }
139
createWrappedTexture(const BackendTexture & texture)140 sk_sp<Texture> DawnResourceProvider::createWrappedTexture(const BackendTexture& texture) {
141 wgpu::Texture dawnTexture = texture.getDawnTexture();
142 wgpu::TextureView dawnTextureView = texture.getDawnTextureView();
143 SkASSERT(!dawnTexture || !dawnTextureView);
144
145 if (!dawnTexture && !dawnTextureView) {
146 return {};
147 }
148
149 if (dawnTexture) {
150 return DawnTexture::MakeWrapped(this->dawnSharedContext(),
151 texture.dimensions(),
152 texture.info(),
153 std::move(dawnTexture));
154 } else {
155 return DawnTexture::MakeWrapped(this->dawnSharedContext(),
156 texture.dimensions(),
157 texture.info(),
158 std::move(dawnTextureView));
159 }
160 }
161
findOrCreateDiscardableMSAALoadTexture(SkISize dimensions,const TextureInfo & msaaInfo)162 sk_sp<DawnTexture> DawnResourceProvider::findOrCreateDiscardableMSAALoadTexture(
163 SkISize dimensions, const TextureInfo& msaaInfo) {
164 SkASSERT(msaaInfo.isValid());
165
166 DawnTextureInfo dawnMsaaLoadTextureInfo;
167 msaaInfo.getDawnTextureInfo(&dawnMsaaLoadTextureInfo);
168 dawnMsaaLoadTextureInfo.fSampleCount = 1;
169 dawnMsaaLoadTextureInfo.fUsage |= wgpu::TextureUsage::TextureBinding;
170
171 auto texture = this->findOrCreateDiscardableMSAAAttachment(dimensions, dawnMsaaLoadTextureInfo);
172
173 return sk_sp<DawnTexture>(static_cast<DawnTexture*>(texture.release()));
174 }
175
createGraphicsPipeline(const RuntimeEffectDictionary * runtimeDict,const GraphicsPipelineDesc & pipelineDesc,const RenderPassDesc & renderPassDesc)176 sk_sp<GraphicsPipeline> DawnResourceProvider::createGraphicsPipeline(
177 const RuntimeEffectDictionary* runtimeDict,
178 const GraphicsPipelineDesc& pipelineDesc,
179 const RenderPassDesc& renderPassDesc) {
180 return DawnGraphicsPipeline::Make(this->dawnSharedContext(),
181 this->skslCompiler(),
182 runtimeDict,
183 pipelineDesc,
184 renderPassDesc);
185 }
186
createComputePipeline(const ComputePipelineDesc &)187 sk_sp<ComputePipeline> DawnResourceProvider::createComputePipeline(const ComputePipelineDesc&) {
188 SkASSERT(false);
189 return nullptr;
190 }
191
createTexture(SkISize dimensions,const TextureInfo & info,skgpu::Budgeted budgeted)192 sk_sp<Texture> DawnResourceProvider::createTexture(SkISize dimensions,
193 const TextureInfo& info,
194 skgpu::Budgeted budgeted) {
195 return DawnTexture::Make(this->dawnSharedContext(), dimensions, info, budgeted);
196 }
197
createBuffer(size_t size,BufferType type,PrioritizeGpuReads prioritizeGpuReads)198 sk_sp<Buffer> DawnResourceProvider::createBuffer(size_t size,
199 BufferType type,
200 PrioritizeGpuReads prioritizeGpuReads) {
201 return DawnBuffer::Make(this->dawnSharedContext(), size, type, prioritizeGpuReads);
202 }
203
createSampler(const SkSamplingOptions & options,SkTileMode xTileMode,SkTileMode yTileMode)204 sk_sp<Sampler> DawnResourceProvider::createSampler(const SkSamplingOptions& options,
205 SkTileMode xTileMode,
206 SkTileMode yTileMode) {
207 return DawnSampler::Make(this->dawnSharedContext(), options, xTileMode, yTileMode);
208 }
209
onCreateBackendTexture(SkISize dimensions,const TextureInfo & info)210 BackendTexture DawnResourceProvider::onCreateBackendTexture(SkISize dimensions,
211 const TextureInfo& info) {
212 wgpu::Texture texture = DawnTexture::MakeDawnTexture(this->dawnSharedContext(),
213 dimensions,
214 info);
215 if (!texture) {
216 return {};
217 }
218
219 return BackendTexture(std::move(texture));
220 }
221
onDeleteBackendTexture(BackendTexture & texture)222 void DawnResourceProvider::onDeleteBackendTexture(BackendTexture& texture) {
223 SkASSERT(texture.isValid());
224 SkASSERT(texture.backend() == BackendApi::kDawn);
225
226 // Nothing to be done here as all the the cleanup of Dawn's resources will be done inside
227 // BackendTexture::~BackendTexture().
228 }
229
dawnSharedContext() const230 const DawnSharedContext* DawnResourceProvider::dawnSharedContext() const {
231 return static_cast<const DawnSharedContext*>(fSharedContext);
232 }
233
234 } // namespace skgpu::graphite
235