28constexpr int kBufferBindingSizeAlignment = 16;
29constexpr int kMaxNumberOfCachedBufferBindGroups = 32;
30constexpr int kMaxNumberOfCachedTextureBindGroups = 4096;
32wgpu::ShaderModule create_shader_module(
const wgpu::Device&
device,
const char*
source) {
33 wgpu::ShaderModuleWGSLDescriptor wgslDesc;
35 wgpu::ShaderModuleDescriptor descriptor;
36 descriptor.nextInChain = &wgslDesc;
37 return device.CreateShaderModule(&descriptor);
40wgpu::RenderPipeline create_blit_render_pipeline(
const DawnSharedContext* sharedContext,
42 wgpu::ShaderModule vsModule,
43 wgpu::ShaderModule fsModule,
44 wgpu::TextureFormat renderPassColorFormat,
45 wgpu::TextureFormat renderPassDepthStencilFormat,
47 wgpu::RenderPipelineDescriptor descriptor;
49 descriptor.label = label;
51 descriptor.layout =
nullptr;
53 wgpu::ColorTargetState colorTarget;
54 colorTarget.format = renderPassColorFormat;
55 colorTarget.blend =
nullptr;
56 colorTarget.writeMask = wgpu::ColorWriteMask::All;
58 wgpu::DepthStencilState depthStencil;
59 if (renderPassDepthStencilFormat != wgpu::TextureFormat::Undefined) {
60 depthStencil.format = renderPassDepthStencilFormat;
61 depthStencil.depthWriteEnabled =
false;
62 depthStencil.depthCompare = wgpu::CompareFunction::Always;
64 descriptor.depthStencil = &depthStencil;
67 wgpu::FragmentState fragment;
68 fragment.module = std::move(fsModule);
69 fragment.entryPoint =
"main";
70 fragment.targetCount = 1;
71 fragment.targets = &colorTarget;
72 descriptor.fragment = &fragment;
74 descriptor.vertex.module = std::move(vsModule);
75 descriptor.vertex.entryPoint =
"main";
76 descriptor.vertex.constantCount = 0;
77 descriptor.vertex.constants =
nullptr;
78 descriptor.vertex.bufferCount = 0;
79 descriptor.vertex.buffers =
nullptr;
81 descriptor.primitive.frontFace = wgpu::FrontFace::CCW;
82 descriptor.primitive.cullMode = wgpu::CullMode::None;
83 descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleStrip;
84 descriptor.primitive.stripIndexFormat = wgpu::IndexFormat::Undefined;
86 descriptor.multisample.count = numSamples;
87 descriptor.multisample.mask = 0xFFFFFFFF;
88 descriptor.multisample.alphaToCoverageEnabled =
false;
90 std::optional<DawnErrorChecker> errorChecker;
91 if (sharedContext->dawnCaps()->allowScopedErrorChecks()) {
92 errorChecker.emplace(sharedContext);
94 auto pipeline = sharedContext->device().CreateRenderPipeline(&descriptor);
102UniqueKey make_ubo_bind_group_key(
103 const std::array<std::pair<const DawnBuffer*, uint32_t>, 3>& boundBuffersAndSizes) {
114 &uniqueKey, kBufferBindGroupDomain, 6,
"GraphicsPipelineBufferBindGroup");
116 for (uint32_t i = 0; i < boundBuffersAndSizes.size(); ++i) {
117 const DawnBuffer* boundBuffer = boundBuffersAndSizes[i].first;
118 const uint32_t bindingSize = boundBuffersAndSizes[i].second;
120 builder[2 * i] = boundBuffer->uniqueID().asUInt();
121 builder[2 * i + 1] = bindingSize;
134UniqueKey make_texture_bind_group_key(
const DawnSampler* sampler,
const DawnTexture*
texture) {
139 UniqueKey::Builder
builder(&uniqueKey,
140 kTextureBindGroupDomain,
142 "GraphicsPipelineSingleTextureSamplerBindGroup");
144 builder[0] = sampler->uniqueID().asUInt();
157 size_t resourceBudget)
159 , fUniformBufferBindGroupCache(kMaxNumberOfCachedBufferBindGroups)
160 , fSingleTextureSamplerBindGroups(kMaxNumberOfCachedTextureBindGroups) {}
166 uint64_t renderPassKey =
168 wgpu::RenderPipeline pipeline = fBlitWithDrawPipelines[renderPassKey];
170 static constexpr char kVertexShaderText[] = R
"(
171 var<private> fullscreenTriPositions : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
172 vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
175 fn main(@builtin(vertex_index) vertexIndex : u32) -> @builtin(position) vec4<f32> {
176 return vec4(fullscreenTriPositions[vertexIndex], 1.0, 1.0);
180 static constexpr char kFragmentShaderText[] = R
"(
181 @group(0) @binding(0) var colorMap: texture_2d<f32>;
184 fn main(@builtin(position) fragPosition : vec4<f32>) -> @location(0) vec4<f32> {
185 var coords : vec2<i32> = vec2<i32>(i32(fragPosition.x), i32(fragPosition.y));
186 return textureLoad(colorMap, coords, 0);
190 auto vsModule = create_shader_module(dawnSharedContext()->
device(), kVertexShaderText);
191 auto fsModule = create_shader_module(dawnSharedContext()->
device(), kFragmentShaderText);
193 pipeline = create_blit_render_pipeline(
204 : wgpu::TextureFormat::Undefined,
208 fBlitWithDrawPipelines.
set(renderPassKey, pipeline);
217 wgpu::Texture dawnTexture =
texture.getDawnTexturePtr();
218 wgpu::TextureView dawnTextureView =
texture.getDawnTextureViewPtr();
219 SkASSERT(!dawnTexture || !dawnTextureView);
221 if (!dawnTexture && !dawnTextureView) {
229 std::move(dawnTexture));
234 std::move(dawnTextureView));
244 msaaInfo.getDawnTextureInfo(&dawnMsaaLoadTextureInfo);
246 dawnMsaaLoadTextureInfo.
fUsage |= wgpu::TextureUsage::TextureBinding;
248#if !defined(__EMSCRIPTEN__)
255 dawnMsaaLoadTextureInfo.
fUsage &= (
~wgpu::TextureUsage::TransientAttachment);
288 std::string_view label) {
321 wgpu::TextureView::Acquire(
texture.getDawnTextureViewPtr());
329 wgpu::Texture::Acquire(
texture.getDawnTexturePtr()).Destroy();
339 std::string_view label) {
346 if (fUniformBuffersBindGroupLayout) {
347 return fUniformBuffersBindGroupLayout;
350 std::array<wgpu::BindGroupLayoutEntry, 3> entries;
352 entries[0].visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment;
353 entries[0].buffer.type = wgpu::BufferBindingType::Uniform;
354 entries[0].buffer.hasDynamicOffset =
true;
355 entries[0].buffer.minBindingSize = 0;
358 entries[1].visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment;
360 ? wgpu::BufferBindingType::ReadOnlyStorage
361 : wgpu::BufferBindingType::Uniform;
362 entries[1].buffer.hasDynamicOffset =
true;
363 entries[1].buffer.minBindingSize = 0;
366 entries[2].visibility = wgpu::ShaderStage::Fragment;
368 ? wgpu::BufferBindingType::ReadOnlyStorage
369 : wgpu::BufferBindingType::Uniform;
370 entries[2].buffer.hasDynamicOffset =
true;
371 entries[2].buffer.minBindingSize = 0;
373 wgpu::BindGroupLayoutDescriptor groupLayoutDesc;
375 groupLayoutDesc.label =
"Uniform buffers bind group layout";
378 groupLayoutDesc.entryCount = entries.size();
379 groupLayoutDesc.entries = entries.data();
380 fUniformBuffersBindGroupLayout =
381 this->dawnSharedContext()->
device().CreateBindGroupLayout(&groupLayoutDesc);
383 return fUniformBuffersBindGroupLayout;
386const wgpu::BindGroupLayout&
388 if (fSingleTextureSamplerBindGroupLayout) {
389 return fSingleTextureSamplerBindGroupLayout;
392 std::array<wgpu::BindGroupLayoutEntry, 2> entries;
394 entries[0].binding = 0;
395 entries[0].visibility = wgpu::ShaderStage::Fragment;
396 entries[0].sampler.type = wgpu::SamplerBindingType::Filtering;
398 entries[1].binding = 1;
399 entries[1].visibility = wgpu::ShaderStage::Fragment;
400 entries[1].texture.sampleType = wgpu::TextureSampleType::Float;
401 entries[1].texture.viewDimension = wgpu::TextureViewDimension::e2D;
402 entries[1].texture.multisampled =
false;
404 wgpu::BindGroupLayoutDescriptor groupLayoutDesc;
406 groupLayoutDesc.label =
"Single texture + sampler bind group layout";
409 groupLayoutDesc.entryCount = entries.size();
410 groupLayoutDesc.entries = entries.data();
411 fSingleTextureSamplerBindGroupLayout =
412 this->dawnSharedContext()->
device().CreateBindGroupLayout(&groupLayoutDesc);
414 return fSingleTextureSamplerBindGroupLayout;
417const wgpu::Buffer& DawnResourceProvider::getOrCreateNullBuffer() {
419 wgpu::BufferDescriptor desc;
421 desc.label =
"UnusedBufferSlot";
423 desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform |
424 wgpu::BufferUsage::Storage;
425 desc.size = kBufferBindingSizeAlignment;
426 desc.mappedAtCreation =
false;
428 fNullBuffer = this->dawnSharedContext()->
device().CreateBuffer(&desc);
436 const std::array<std::pair<const DawnBuffer*, uint32_t>, 3>& boundBuffersAndSizes) {
437 auto key = make_ubo_bind_group_key(boundBuffersAndSizes);
438 auto* existingBindGroup = fUniformBufferBindGroupCache.
find(
key);
439 if (existingBindGroup) {
441 return *existingBindGroup;
445 std::array<wgpu::BindGroupEntry, 3> entries;
447 constexpr uint32_t kBindingIndices[] = {
453 for (uint32_t i = 0; i < boundBuffersAndSizes.size(); ++i) {
454 const DawnBuffer* boundBuffer = boundBuffersAndSizes[i].first;
455 const uint32_t bindingSize = boundBuffersAndSizes[i].second;
457 entries[i].binding = kBindingIndices[i];
458 entries[i].offset = 0;
460 entries[i].buffer = boundBuffer->
dawnBuffer();
461 entries[i].size =
SkAlignTo(bindingSize, kBufferBindingSizeAlignment);
463 entries[i].buffer = this->getOrCreateNullBuffer();
464 entries[i].size = wgpu::kWholeSize;
468 wgpu::BindGroupDescriptor desc;
470 desc.entryCount = entries.size();
471 desc.entries = entries.data();
473 const auto&
device = this->dawnSharedContext()->
device();
474 auto bindGroup =
device.CreateBindGroup(&desc);
476 return *fUniformBufferBindGroupCache.
insert(
key, bindGroup);
481 auto key = make_texture_bind_group_key(sampler,
texture);
482 auto* existingBindGroup = fSingleTextureSamplerBindGroups.
find(
key);
483 if (existingBindGroup) {
485 return *existingBindGroup;
488 std::array<wgpu::BindGroupEntry, 2> entries;
490 entries[0].binding = 0;
492 entries[1].binding = 1;
493 entries[1].textureView =
texture->sampleTextureView();
495 wgpu::BindGroupDescriptor desc;
497 desc.entryCount = entries.size();
498 desc.entries = entries.data();
500 const auto&
device = this->dawnSharedContext()->
device();
501 auto bindGroup =
device.CreateBindGroup(&desc);
503 return *fSingleTextureSamplerBindGroups.
insert(
key, bindGroup);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static constexpr size_t SkAlignTo(size_t x, size_t alignment)
V * insert(const K &key, V value)
static Domain GenerateDomain()
bool storageBufferPreferred() const
static sk_sp< DawnBuffer > Make(const DawnSharedContext *, size_t size, BufferType type, AccessPattern, std::string_view label)
const wgpu::Buffer & dawnBuffer() const
uint64_t getRenderPassDescKey(const RenderPassDesc &renderPassDesc) const
static sk_sp< DawnComputePipeline > Make(const DawnSharedContext *, const ComputePipelineDesc &)
static constexpr unsigned int kRenderStepUniformBufferIndex
static constexpr unsigned int kPaintUniformBufferIndex
static sk_sp< DawnGraphicsPipeline > Make(const DawnSharedContext *sharedContext, DawnResourceProvider *resourceProvider, const RuntimeEffectDictionary *runtimeDict, const GraphicsPipelineDesc &pipelineDesc, const RenderPassDesc &renderPassDesc)
static constexpr unsigned int kIntrinsicUniformBufferIndex
~DawnResourceProvider() override
sk_sp< Sampler > createSampler(const SamplerDesc &) override
sk_sp< GraphicsPipeline > createGraphicsPipeline(const RuntimeEffectDictionary *, const GraphicsPipelineDesc &, const RenderPassDesc &) override
const wgpu::BindGroup & findOrCreateSingleTextureSamplerBindGroup(const DawnSampler *sampler, const DawnTexture *texture)
DawnResourceProvider(SharedContext *sharedContext, SingleOwner *, uint32_t recorderID, size_t resourceBudget)
BackendTexture onCreateBackendTexture(SkISize dimensions, const TextureInfo &) override
const wgpu::BindGroupLayout & getOrCreateSingleTextureSamplerBindGroupLayout()
sk_sp< DawnTexture > findOrCreateDiscardableMSAALoadTexture(SkISize dimensions, const TextureInfo &msaaInfo)
sk_sp< Buffer > createBuffer(size_t size, BufferType type, AccessPattern, std::string_view label) override
sk_sp< Texture > createTexture(SkISize, const TextureInfo &, skgpu::Budgeted) override
sk_sp< Texture > createWrappedTexture(const BackendTexture &) override
const wgpu::BindGroupLayout & getOrCreateUniformBuffersBindGroupLayout()
const wgpu::BindGroup & findOrCreateUniformBuffersBindGroup(const std::array< std::pair< const DawnBuffer *, uint32_t >, 3 > &boundBuffersAndSizes)
void onDeleteBackendTexture(const BackendTexture &) override
wgpu::RenderPipeline findOrCreateBlitWithDrawPipeline(const RenderPassDesc &renderPassDesc)
sk_sp< DawnBuffer > findOrCreateDawnBuffer(size_t size, BufferType type, AccessPattern, std::string_view label)
sk_sp< ComputePipeline > createComputePipeline(const ComputePipelineDesc &) override
const wgpu::Sampler & dawnSampler() const
static sk_sp< DawnSampler > Make(const DawnSharedContext *, const SkSamplingOptions &samplingOptions, SkTileMode xTileMode, SkTileMode yTileMode)
const DawnCaps * dawnCaps() const
const wgpu::Device & device() const
static sk_sp< Texture > MakeWrapped(const DawnSharedContext *, SkISize dimensions, const TextureInfo &, wgpu::Texture)
static wgpu::Texture MakeDawnTexture(const DawnSharedContext *, SkISize dimensions, const TextureInfo &)
static sk_sp< Texture > Make(const DawnSharedContext *, SkISize dimensions, const TextureInfo &, skgpu::Budgeted)
sk_sp< Texture > findOrCreateDiscardableMSAAAttachment(SkISize dimensions, const TextureInfo &)
sk_sp< Buffer > findOrCreateBuffer(size_t size, BufferType type, AccessPattern, std::string_view label)
SharedContext * fSharedContext
const Caps * caps() const
uint32_t numSamples() const
static const uint8_t buffer[]
wgpu::TextureUsage fUsage
AttachmentDesc fDepthStencilAttachment
AttachmentDesc fColorAttachment
SkTileMode tileModeX() const
SkSamplingOptions samplingOptions() const
SkTileMode tileModeY() const