From a50efb961d7657a16eab3c50f59553891ff31d04 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Thu, 4 Nov 2021 22:21:20 +0000 Subject: [PATCH] Copy some WGPUHelpers into dawn_native to simplify reentrant code Bug: none Change-Id: I9d48951019f5e1cfeca3815245a8818d79c3d1da Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/68282 Reviewed-by: Corentin Wallez Reviewed-by: Loko Kung Commit-Queue: Austin Eng --- src/dawn_native/BUILD.gn | 2 + src/dawn_native/ComputePassEncoder.cpp | 103 ++++------ .../CopyTextureForBrowserHelper.cpp | 42 +--- .../IndirectDrawValidationEncoder.cpp | 43 ++-- src/dawn_native/QueryHelper.cpp | 60 ++---- src/dawn_native/utils/WGPUHelpers.cpp | 188 ++++++++++++++++++ src/dawn_native/utils/WGPUHelpers.h | 120 +++++++++++ 7 files changed, 390 insertions(+), 168 deletions(-) create mode 100644 src/dawn_native/utils/WGPUHelpers.cpp create mode 100644 src/dawn_native/utils/WGPUHelpers.h diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn index cfea7074d7..39d7d4dcdb 100644 --- a/src/dawn_native/BUILD.gn +++ b/src/dawn_native/BUILD.gn @@ -331,6 +331,8 @@ source_set("dawn_native_sources") { "VertexFormat.cpp", "VertexFormat.h", "dawn_platform.h", + "utils/WGPUHelpers.cpp", + "utils/WGPUHelpers.h", ] if (dawn_use_x11) { diff --git a/src/dawn_native/ComputePassEncoder.cpp b/src/dawn_native/ComputePassEncoder.cpp index 7f83248955..f447bbfec3 100644 --- a/src/dawn_native/ComputePassEncoder.cpp +++ b/src/dawn_native/ComputePassEncoder.cpp @@ -26,6 +26,7 @@ #include "dawn_native/ObjectType_autogen.h" #include "dawn_native/PassResourceUsageTracker.h" #include "dawn_native/QuerySet.h" +#include "dawn_native/utils/WGPUHelpers.h" namespace dawn_native { @@ -39,13 +40,10 @@ namespace dawn_native { return store->dispatchIndirectValidationPipeline.Get(); } - ShaderModuleDescriptor descriptor; - ShaderModuleWGSLDescriptor wgslDesc; - descriptor.nextInChain = reinterpret_cast(&wgslDesc); - // TODO(https://crbug.com/dawn/1108): Propagate validation feedback from this // shader in various failure modes. - wgslDesc.source = R"( + Ref shaderModule; + DAWN_TRY_ASSIGN(shaderModule, utils::CreateShaderModule(device, R"( [[block]] struct UniformParams { maxComputeWorkgroupsPerDimension: u32; clientOffsetInU32: u32; @@ -73,34 +71,23 @@ namespace dawn_native { validatedParams.data[i] = numWorkgroups; } } - )"; + )")); - Ref shaderModule; - DAWN_TRY_ASSIGN(shaderModule, device->CreateShaderModule(&descriptor)); - - std::array entries; - entries[0].binding = 0; - entries[0].visibility = wgpu::ShaderStage::Compute; - entries[0].buffer.type = wgpu::BufferBindingType::Uniform; - entries[1].binding = 1; - entries[1].visibility = wgpu::ShaderStage::Compute; - entries[1].buffer.type = kInternalStorageBufferBinding; - entries[2].binding = 2; - entries[2].visibility = wgpu::ShaderStage::Compute; - entries[2].buffer.type = wgpu::BufferBindingType::Storage; - - BindGroupLayoutDescriptor bindGroupLayoutDescriptor; - bindGroupLayoutDescriptor.entryCount = entries.size(); - bindGroupLayoutDescriptor.entries = entries.data(); Ref bindGroupLayout; - DAWN_TRY_ASSIGN(bindGroupLayout, - device->CreateBindGroupLayout(&bindGroupLayoutDescriptor, true)); + DAWN_TRY_ASSIGN( + bindGroupLayout, + utils::MakeBindGroupLayout( + device, + { + {0, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Uniform}, + {1, wgpu::ShaderStage::Compute, kInternalStorageBufferBinding}, + {2, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Storage}, + }, + /* allowInternalBinding */ true)); - PipelineLayoutDescriptor pipelineDescriptor; - pipelineDescriptor.bindGroupLayoutCount = 1; - pipelineDescriptor.bindGroupLayouts = &bindGroupLayout.Get(); Ref pipelineLayout; - DAWN_TRY_ASSIGN(pipelineLayout, device->CreatePipelineLayout(&pipelineDescriptor)); + DAWN_TRY_ASSIGN(pipelineLayout, + utils::MakeBasicPipelineLayout(device, bindGroupLayout)); ComputePipelineDescriptor computePipelineDescriptor = {}; computePipelineDescriptor.layout = pipelineLayout.Get(); @@ -211,21 +198,15 @@ namespace dawn_native { uint32_t storageBufferOffsetAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment; - std::array bindings; - - // Storage binding holding the client's indirect buffer. - BindGroupEntry& clientIndirectBinding = bindings[0]; - clientIndirectBinding.binding = 1; - clientIndirectBinding.buffer = indirectBuffer; - // Let the offset be the indirectOffset, aligned down to |storageBufferOffsetAlignment|. const uint32_t clientOffsetFromAlignedBoundary = indirectOffset % storageBufferOffsetAlignment; const uint64_t clientOffsetAlignedDown = indirectOffset - clientOffsetFromAlignedBoundary; - clientIndirectBinding.offset = clientOffsetAlignedDown; + const uint64_t clientIndirectBindingOffset = clientOffsetAlignedDown; // Let the size of the binding be the additional offset, plus the size. - clientIndirectBinding.size = kDispatchIndirectSize + clientOffsetFromAlignedBoundary; + const uint64_t clientIndirectBindingSize = + kDispatchIndirectSize + clientOffsetFromAlignedBoundary; struct UniformParams { uint32_t maxComputeWorkgroupsPerDimension; @@ -235,46 +216,30 @@ namespace dawn_native { // Create a uniform buffer to hold parameters for the shader. Ref uniformBuffer; { - BufferDescriptor uniformDesc = {}; - uniformDesc.size = sizeof(UniformParams); - uniformDesc.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst; - uniformDesc.mappedAtCreation = true; - DAWN_TRY_ASSIGN(uniformBuffer, device->CreateBuffer(&uniformDesc)); - - UniformParams* params = static_cast( - uniformBuffer->GetMappedRange(0, sizeof(UniformParams))); - params->maxComputeWorkgroupsPerDimension = + UniformParams params; + params.maxComputeWorkgroupsPerDimension = device->GetLimits().v1.maxComputeWorkgroupsPerDimension; - params->clientOffsetInU32 = clientOffsetFromAlignedBoundary / sizeof(uint32_t); - uniformBuffer->Unmap(); - } + params.clientOffsetInU32 = clientOffsetFromAlignedBoundary / sizeof(uint32_t); - // Uniform buffer binding pointing to the uniform parameters. - BindGroupEntry& uniformBinding = bindings[1]; - uniformBinding.binding = 0; - uniformBinding.buffer = uniformBuffer.Get(); - uniformBinding.offset = 0; - uniformBinding.size = sizeof(UniformParams); + DAWN_TRY_ASSIGN(uniformBuffer, utils::CreateBufferFromData( + device, wgpu::BufferUsage::Uniform, {params})); + } // Reserve space in the scratch buffer to hold the validated indirect params. ScratchBuffer& scratchBuffer = store->scratchIndirectStorage; DAWN_TRY(scratchBuffer.EnsureCapacity(kDispatchIndirectSize)); Ref validatedIndirectBuffer = scratchBuffer.GetBuffer(); - // Binding for the validated indirect params. - BindGroupEntry& validatedParamsBinding = bindings[2]; - validatedParamsBinding.binding = 2; - validatedParamsBinding.buffer = validatedIndirectBuffer.Get(); - validatedParamsBinding.offset = 0; - validatedParamsBinding.size = kDispatchIndirectSize; - - BindGroupDescriptor bindGroupDescriptor = {}; - bindGroupDescriptor.layout = layout.Get(); - bindGroupDescriptor.entryCount = bindings.size(); - bindGroupDescriptor.entries = bindings.data(); - Ref validationBindGroup; - DAWN_TRY_ASSIGN(validationBindGroup, device->CreateBindGroup(&bindGroupDescriptor)); + DAWN_TRY_ASSIGN( + validationBindGroup, + utils::MakeBindGroup( + device, layout, + { + {0, uniformBuffer}, + {1, indirectBuffer, clientIndirectBindingOffset, clientIndirectBindingSize}, + {2, validatedIndirectBuffer, 0, kDispatchIndirectSize}, + })); // Issue commands to validate the indirect buffer. APISetPipeline(validationPipeline.Get()); diff --git a/src/dawn_native/CopyTextureForBrowserHelper.cpp b/src/dawn_native/CopyTextureForBrowserHelper.cpp index 6684f61a62..c840e17677 100644 --- a/src/dawn_native/CopyTextureForBrowserHelper.cpp +++ b/src/dawn_native/CopyTextureForBrowserHelper.cpp @@ -28,6 +28,7 @@ #include "dawn_native/Sampler.h" #include "dawn_native/Texture.h" #include "dawn_native/ValidationUtils_autogen.h" +#include "dawn_native/utils/WGPUHelpers.h" #include @@ -191,13 +192,9 @@ namespace dawn_native { if (GetCachedPipeline(store, dstFormat) == nullptr) { // Create vertex shader module if not cached before. if (store->copyTextureForBrowser == nullptr) { - ShaderModuleDescriptor descriptor; - ShaderModuleWGSLDescriptor wgslDesc; - wgslDesc.source = sCopyTextureForBrowserShader; - descriptor.nextInChain = reinterpret_cast(&wgslDesc); - - DAWN_TRY_ASSIGN(store->copyTextureForBrowser, - device->CreateShaderModule(&descriptor)); + DAWN_TRY_ASSIGN( + store->copyTextureForBrowser, + utils::CreateShaderModule(device, sCopyTextureForBrowserShader)); } ShaderModuleBase* shaderModule = store->copyTextureForBrowser.Get(); @@ -307,13 +304,6 @@ namespace dawn_native { Ref layout; DAWN_TRY_ASSIGN(layout, pipeline->GetBindGroupLayout(0)); - // Prepare bind group descriptor - BindGroupEntry bindGroupEntries[3] = {}; - BindGroupDescriptor bgDesc = {}; - bgDesc.layout = layout.Get(); - bgDesc.entryCount = 3; - bgDesc.entries = bindGroupEntries; - Extent3D srcTextureSize = source->texture->GetSize(); // Prepare binding 0 resource: uniform buffer. @@ -336,14 +326,11 @@ namespace dawn_native { // Set alpha op. uniformData.alphaOp = options->alphaOp; - BufferDescriptor uniformDesc = {}; - uniformDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform; - uniformDesc.size = sizeof(uniformData); Ref uniformBuffer; - DAWN_TRY_ASSIGN(uniformBuffer, device->CreateBuffer(&uniformDesc)); - - DAWN_TRY(device->GetQueue()->WriteBuffer(uniformBuffer.Get(), 0, &uniformData, - sizeof(uniformData))); + DAWN_TRY_ASSIGN( + uniformBuffer, + utils::CreateBufferFromData( + device, wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform, {uniformData})); // Prepare binding 1 resource: sampler // Use default configuration, filterMode set to Nearest for min and mag. @@ -360,18 +347,11 @@ namespace dawn_native { DAWN_TRY_ASSIGN(srcTextureView, device->CreateTextureView(source->texture, &srcTextureViewDesc)); - // Set bind group entries. - bindGroupEntries[0].binding = 0; - bindGroupEntries[0].buffer = uniformBuffer.Get(); - bindGroupEntries[0].size = sizeof(uniformData); - bindGroupEntries[1].binding = 1; - bindGroupEntries[1].sampler = sampler.Get(); - bindGroupEntries[2].binding = 2; - bindGroupEntries[2].textureView = srcTextureView.Get(); - // Create bind group after all binding entries are set. Ref bindGroup; - DAWN_TRY_ASSIGN(bindGroup, device->CreateBindGroup(&bgDesc)); + DAWN_TRY_ASSIGN(bindGroup, utils::MakeBindGroup( + device, layout, + {{0, uniformBuffer}, {1, sampler}, {2, srcTextureView}})); // Create command encoder. CommandEncoderDescriptor encoderDesc = {}; diff --git a/src/dawn_native/IndirectDrawValidationEncoder.cpp b/src/dawn_native/IndirectDrawValidationEncoder.cpp index 02cef8e12c..a58f9b03cb 100644 --- a/src/dawn_native/IndirectDrawValidationEncoder.cpp +++ b/src/dawn_native/IndirectDrawValidationEncoder.cpp @@ -24,6 +24,7 @@ #include "dawn_native/Device.h" #include "dawn_native/InternalPipelineStore.h" #include "dawn_native/Queue.h" +#include "dawn_native/utils/WGPUHelpers.h" #include #include @@ -138,37 +139,27 @@ namespace dawn_native { if (store->renderValidationPipeline == nullptr) { // Create compute shader module if not cached before. if (store->renderValidationShader == nullptr) { - ShaderModuleDescriptor descriptor; - ShaderModuleWGSLDescriptor wgslDesc; - wgslDesc.source = sRenderValidationShaderSource; - descriptor.nextInChain = reinterpret_cast(&wgslDesc); - DAWN_TRY_ASSIGN(store->renderValidationShader, - device->CreateShaderModule(&descriptor)); + DAWN_TRY_ASSIGN( + store->renderValidationShader, + utils::CreateShaderModule(device, sRenderValidationShaderSource)); } - BindGroupLayoutEntry entries[3]; - entries[0].binding = 0; - entries[0].visibility = wgpu::ShaderStage::Compute; - entries[0].buffer.type = wgpu::BufferBindingType::ReadOnlyStorage; - entries[1].binding = 1; - entries[1].visibility = wgpu::ShaderStage::Compute; - entries[1].buffer.type = kInternalStorageBufferBinding; - entries[2].binding = 2; - entries[2].visibility = wgpu::ShaderStage::Compute; - entries[2].buffer.type = wgpu::BufferBindingType::Storage; - - BindGroupLayoutDescriptor bindGroupLayoutDescriptor; - bindGroupLayoutDescriptor.entryCount = 3; - bindGroupLayoutDescriptor.entries = entries; Ref bindGroupLayout; - DAWN_TRY_ASSIGN(bindGroupLayout, - device->CreateBindGroupLayout(&bindGroupLayoutDescriptor, true)); + DAWN_TRY_ASSIGN( + bindGroupLayout, + utils::MakeBindGroupLayout( + device, + { + {0, wgpu::ShaderStage::Compute, + wgpu::BufferBindingType::ReadOnlyStorage}, + {1, wgpu::ShaderStage::Compute, kInternalStorageBufferBinding}, + {2, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Storage}, + }, + /* allowInternalBinding */ true)); - PipelineLayoutDescriptor pipelineDescriptor; - pipelineDescriptor.bindGroupLayoutCount = 1; - pipelineDescriptor.bindGroupLayouts = &bindGroupLayout.Get(); Ref pipelineLayout; - DAWN_TRY_ASSIGN(pipelineLayout, device->CreatePipelineLayout(&pipelineDescriptor)); + DAWN_TRY_ASSIGN(pipelineLayout, + utils::MakeBasicPipelineLayout(device, bindGroupLayout)); ComputePipelineDescriptor computePipelineDescriptor = {}; computePipelineDescriptor.layout = pipelineLayout.Get(); diff --git a/src/dawn_native/QueryHelper.cpp b/src/dawn_native/QueryHelper.cpp index 2614269364..03d21943be 100644 --- a/src/dawn_native/QueryHelper.cpp +++ b/src/dawn_native/QueryHelper.cpp @@ -22,6 +22,7 @@ #include "dawn_native/ComputePipeline.h" #include "dawn_native/Device.h" #include "dawn_native/InternalPipelineStore.h" +#include "dawn_native/utils/WGPUHelpers.h" namespace dawn_native { @@ -113,36 +114,27 @@ namespace dawn_native { if (store->timestampComputePipeline == nullptr) { // Create compute shader module if not cached before. if (store->timestampCS == nullptr) { - ShaderModuleDescriptor descriptor; - ShaderModuleWGSLDescriptor wgslDesc; - wgslDesc.source = sConvertTimestampsToNanoseconds; - descriptor.nextInChain = reinterpret_cast(&wgslDesc); - - DAWN_TRY_ASSIGN(store->timestampCS, device->CreateShaderModule(&descriptor)); + DAWN_TRY_ASSIGN( + store->timestampCS, + utils::CreateShaderModule(device, sConvertTimestampsToNanoseconds)); } // Create binding group layout - std::array entries = {}; - for (uint32_t i = 0; i < entries.size(); i++) { - entries[i].binding = i; - entries[i].visibility = wgpu::ShaderStage::Compute; - } - entries[0].buffer.type = kInternalStorageBufferBinding; - entries[1].buffer.type = wgpu::BufferBindingType::ReadOnlyStorage; - entries[2].buffer.type = wgpu::BufferBindingType::Uniform; - - BindGroupLayoutDescriptor bglDesc; - bglDesc.entryCount = static_cast(entries.size()); - bglDesc.entries = entries.data(); Ref bgl; - DAWN_TRY_ASSIGN(bgl, device->CreateBindGroupLayout(&bglDesc, true)); + DAWN_TRY_ASSIGN( + bgl, utils::MakeBindGroupLayout( + device, + { + {0, wgpu::ShaderStage::Compute, kInternalStorageBufferBinding}, + {1, wgpu::ShaderStage::Compute, + wgpu::BufferBindingType::ReadOnlyStorage}, + {2, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Uniform}, + }, + /* allowInternalBinding */ true)); // Create pipeline layout - PipelineLayoutDescriptor plDesc; - plDesc.bindGroupLayoutCount = 1; - plDesc.bindGroupLayouts = &bgl.Get(); Ref layout; - DAWN_TRY_ASSIGN(layout, device->CreatePipelineLayout(&plDesc)); + DAWN_TRY_ASSIGN(layout, utils::MakeBasicPipelineLayout(device, bgl)); // Create ComputePipeline. ComputePipelineDescriptor computePipelineDesc = {}; @@ -173,27 +165,11 @@ namespace dawn_native { Ref layout; DAWN_TRY_ASSIGN(layout, pipeline->GetBindGroupLayout(0)); - // Prepare bind group descriptor - std::array bindGroupEntries = {}; - BindGroupDescriptor bgDesc = {}; - bgDesc.layout = layout.Get(); - bgDesc.entryCount = 3; - bgDesc.entries = bindGroupEntries.data(); - - // Set bind group entries. - bindGroupEntries[0].binding = 0; - bindGroupEntries[0].buffer = timestamps; - bindGroupEntries[0].size = timestamps->GetSize(); - bindGroupEntries[1].binding = 1; - bindGroupEntries[1].buffer = availability; - bindGroupEntries[1].size = availability->GetSize(); - bindGroupEntries[2].binding = 2; - bindGroupEntries[2].buffer = params; - bindGroupEntries[2].size = params->GetSize(); - // Create bind group after all binding entries are set. Ref bindGroup; - DAWN_TRY_ASSIGN(bindGroup, device->CreateBindGroup(&bgDesc)); + DAWN_TRY_ASSIGN(bindGroup, + utils::MakeBindGroup(device, layout, + {{0, timestamps}, {1, availability}, {2, params}})); // Create compute encoder and issue dispatch. ComputePassDescriptor passDesc = {}; diff --git a/src/dawn_native/utils/WGPUHelpers.cpp b/src/dawn_native/utils/WGPUHelpers.cpp new file mode 100644 index 0000000000..c10c7a77bb --- /dev/null +++ b/src/dawn_native/utils/WGPUHelpers.cpp @@ -0,0 +1,188 @@ +// Copyright 2017 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/utils/WGPUHelpers.h" + +#include "common/Assert.h" +#include "common/Constants.h" +#include "dawn_native/BindGroup.h" +#include "dawn_native/BindGroupLayout.h" +#include "dawn_native/Buffer.h" +#include "dawn_native/Device.h" +#include "dawn_native/PipelineLayout.h" +#include "dawn_native/Queue.h" +#include "dawn_native/Sampler.h" +#include "dawn_native/ShaderModule.h" + +#include +#include +#include +#include +#include + +namespace dawn_native { namespace utils { + + ResultOrError> CreateShaderModule(DeviceBase* device, + const char* source) { + ShaderModuleWGSLDescriptor wgslDesc; + wgslDesc.source = source; + ShaderModuleDescriptor descriptor; + descriptor.nextInChain = &wgslDesc; + return device->CreateShaderModule(&descriptor); + } + + ResultOrError> CreateBufferFromData(DeviceBase* device, + wgpu::BufferUsage usage, + const void* data, + uint64_t size) { + BufferDescriptor descriptor; + descriptor.size = size; + descriptor.usage = usage; + descriptor.mappedAtCreation = true; + Ref buffer; + DAWN_TRY_ASSIGN(buffer, device->CreateBuffer(&descriptor)); + memcpy(buffer->GetMappedRange(0, size), data, size); + buffer->Unmap(); + return buffer; + } + + ResultOrError> MakeBasicPipelineLayout( + DeviceBase* device, + const Ref& bindGroupLayout) { + PipelineLayoutDescriptor descriptor; + descriptor.bindGroupLayoutCount = 1; + BindGroupLayoutBase* bgl = bindGroupLayout.Get(); + descriptor.bindGroupLayouts = &bgl; + return device->CreatePipelineLayout(&descriptor); + } + + ResultOrError> MakeBindGroupLayout( + DeviceBase* device, + std::initializer_list entriesInitializer, + bool allowInternalBinding) { + std::vector entries; + for (const BindingLayoutEntryInitializationHelper& entry : entriesInitializer) { + entries.push_back(entry); + } + + BindGroupLayoutDescriptor descriptor; + descriptor.entryCount = static_cast(entries.size()); + descriptor.entries = entries.data(); + return device->CreateBindGroupLayout(&descriptor, allowInternalBinding); + } + + BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper( + uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::BufferBindingType bufferType, + bool bufferHasDynamicOffset, + uint64_t bufferMinBindingSize) { + binding = entryBinding; + visibility = entryVisibility; + buffer.type = bufferType; + buffer.hasDynamicOffset = bufferHasDynamicOffset; + buffer.minBindingSize = bufferMinBindingSize; + } + + BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper( + uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::SamplerBindingType samplerType) { + binding = entryBinding; + visibility = entryVisibility; + sampler.type = samplerType; + } + + BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper( + uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::TextureSampleType textureSampleType, + wgpu::TextureViewDimension textureViewDimension, + bool textureMultisampled) { + binding = entryBinding; + visibility = entryVisibility; + texture.sampleType = textureSampleType; + texture.viewDimension = textureViewDimension; + texture.multisampled = textureMultisampled; + } + + BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper( + uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::StorageTextureAccess storageTextureAccess, + wgpu::TextureFormat format, + wgpu::TextureViewDimension textureViewDimension) { + binding = entryBinding; + visibility = entryVisibility; + storageTexture.access = storageTextureAccess; + storageTexture.format = format; + storageTexture.viewDimension = textureViewDimension; + } + + BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper( + const BindGroupLayoutEntry& entry) + : BindGroupLayoutEntry(entry) { + } + + BindingInitializationHelper::BindingInitializationHelper(uint32_t binding, + const Ref& sampler) + : binding(binding), sampler(sampler) { + } + + BindingInitializationHelper::BindingInitializationHelper( + uint32_t binding, + const Ref& textureView) + : binding(binding), textureView(textureView) { + } + + BindingInitializationHelper::BindingInitializationHelper(uint32_t binding, + const Ref& buffer, + uint64_t offset, + uint64_t size) + : binding(binding), buffer(buffer), offset(offset), size(size) { + } + + BindingInitializationHelper::~BindingInitializationHelper() = default; + + BindGroupEntry BindingInitializationHelper::GetAsBinding() const { + BindGroupEntry result; + + result.binding = binding; + result.sampler = sampler.Get(); + result.textureView = textureView.Get(); + result.buffer = buffer.Get(); + result.offset = offset; + result.size = size; + + return result; + } + + ResultOrError> MakeBindGroup( + DeviceBase* device, + const Ref& layout, + std::initializer_list entriesInitializer) { + std::vector entries; + for (const BindingInitializationHelper& helper : entriesInitializer) { + entries.push_back(helper.GetAsBinding()); + } + + BindGroupDescriptor descriptor; + descriptor.layout = layout.Get(); + descriptor.entryCount = entries.size(); + descriptor.entries = entries.data(); + + return device->CreateBindGroup(&descriptor); + } + +}} // namespace dawn_native::utils diff --git a/src/dawn_native/utils/WGPUHelpers.h b/src/dawn_native/utils/WGPUHelpers.h new file mode 100644 index 0000000000..730ab15ac4 --- /dev/null +++ b/src/dawn_native/utils/WGPUHelpers.h @@ -0,0 +1,120 @@ +// Copyright 2017 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef DAWNNATIVE_UTILS_WGPUHELPERS_H_ +#define DAWNNATIVE_UTILS_WGPUHELPERS_H_ + +#include + +#include +#include +#include + +#include "common/RefCounted.h" +#include "dawn_native/Error.h" + +namespace dawn_native { namespace utils { + + ResultOrError> CreateShaderModule(DeviceBase* device, const char* source); + + ResultOrError> CreateBufferFromData(DeviceBase* device, + wgpu::BufferUsage usage, + const void* data, + uint64_t size); + + template + ResultOrError> CreateBufferFromData(DeviceBase* device, + wgpu::BufferUsage usage, + std::initializer_list data) { + return CreateBufferFromData(device, usage, data.begin(), uint32_t(sizeof(T) * data.size())); + } + + ResultOrError> MakeBasicPipelineLayout( + DeviceBase* device, + const Ref& bindGroupLayout); + + // Helpers to make creating bind group layouts look nicer: + // + // utils::MakeBindGroupLayout(device, { + // {0, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::Uniform}, + // {1, wgpu::ShaderStage::Fragment, wgpu::SamplerBindingType::Filtering}, + // {3, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Float} + // }); + + struct BindingLayoutEntryInitializationHelper : BindGroupLayoutEntry { + BindingLayoutEntryInitializationHelper(uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::BufferBindingType bufferType, + bool bufferHasDynamicOffset = false, + uint64_t bufferMinBindingSize = 0); + BindingLayoutEntryInitializationHelper(uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::SamplerBindingType samplerType); + BindingLayoutEntryInitializationHelper( + uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::TextureSampleType textureSampleType, + wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::e2D, + bool textureMultisampled = false); + BindingLayoutEntryInitializationHelper( + uint32_t entryBinding, + wgpu::ShaderStage entryVisibility, + wgpu::StorageTextureAccess storageTextureAccess, + wgpu::TextureFormat format, + wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::e2D); + + BindingLayoutEntryInitializationHelper(const BindGroupLayoutEntry& entry); + }; + + ResultOrError> MakeBindGroupLayout( + DeviceBase* device, + std::initializer_list entriesInitializer, + bool allowInternalBinding = false); + + // Helpers to make creating bind groups look nicer: + // + // utils::MakeBindGroup(device, layout, { + // {0, mySampler}, + // {1, myBuffer, offset, size}, + // {3, myTextureView} + // }); + + // Structure with one constructor per-type of bindings, so that the initializer_list accepts + // bindings with the right type and no extra information. + struct BindingInitializationHelper { + BindingInitializationHelper(uint32_t binding, const Ref& sampler); + BindingInitializationHelper(uint32_t binding, const Ref& textureView); + BindingInitializationHelper(uint32_t binding, + const Ref& buffer, + uint64_t offset = 0, + uint64_t size = wgpu::kWholeSize); + ~BindingInitializationHelper(); + + BindGroupEntry GetAsBinding() const; + + uint32_t binding; + Ref sampler; + Ref textureView; + Ref buffer; + uint64_t offset = 0; + uint64_t size = 0; + }; + + ResultOrError> MakeBindGroup( + DeviceBase* device, + const Ref& layout, + std::initializer_list entriesInitializer); +}} // namespace dawn_native::utils + +#endif // DAWNNATIVE_UTILS_WGPUHELPERS_H_ \ No newline at end of file