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 <cwallez@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2021-11-04 22:21:20 +00:00 committed by Dawn LUCI CQ
parent 61a5aeb70b
commit a50efb961d
7 changed files with 390 additions and 168 deletions

View File

@ -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) {

View File

@ -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<ChainedStruct*>(&wgslDesc);
// TODO(https://crbug.com/dawn/1108): Propagate validation feedback from this
// shader in various failure modes.
wgslDesc.source = R"(
Ref<ShaderModuleBase> 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<ShaderModuleBase> shaderModule;
DAWN_TRY_ASSIGN(shaderModule, device->CreateShaderModule(&descriptor));
std::array<BindGroupLayoutEntry, 3> 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<BindGroupLayoutBase> 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<PipelineLayoutBase> 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<BindGroupEntry, 3> 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<BufferBase> 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<UniformParams*>(
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<BufferBase> 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<BindGroupBase> 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());

View File

@ -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 <unordered_set>
@ -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<ChainedStruct*>(&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<BindGroupLayoutBase> 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<BufferBase> 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<BindGroupBase> 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 = {};

View File

@ -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 <cstdlib>
#include <limits>
@ -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<ChainedStruct*>(&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<BindGroupLayoutBase> 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<PipelineLayoutBase> pipelineLayout;
DAWN_TRY_ASSIGN(pipelineLayout, device->CreatePipelineLayout(&pipelineDescriptor));
DAWN_TRY_ASSIGN(pipelineLayout,
utils::MakeBasicPipelineLayout(device, bindGroupLayout));
ComputePipelineDescriptor computePipelineDescriptor = {};
computePipelineDescriptor.layout = pipelineLayout.Get();

View File

@ -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<ChainedStruct*>(&wgslDesc);
DAWN_TRY_ASSIGN(store->timestampCS, device->CreateShaderModule(&descriptor));
DAWN_TRY_ASSIGN(
store->timestampCS,
utils::CreateShaderModule(device, sConvertTimestampsToNanoseconds));
}
// Create binding group layout
std::array<BindGroupLayoutEntry, 3> 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<uint32_t>(entries.size());
bglDesc.entries = entries.data();
Ref<BindGroupLayoutBase> 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<PipelineLayoutBase> 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<BindGroupLayoutBase> layout;
DAWN_TRY_ASSIGN(layout, pipeline->GetBindGroupLayout(0));
// Prepare bind group descriptor
std::array<BindGroupEntry, 3> 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<BindGroupBase> 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 = {};

View File

@ -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 <cstring>
#include <iomanip>
#include <limits>
#include <mutex>
#include <sstream>
namespace dawn_native { namespace utils {
ResultOrError<Ref<ShaderModuleBase>> CreateShaderModule(DeviceBase* device,
const char* source) {
ShaderModuleWGSLDescriptor wgslDesc;
wgslDesc.source = source;
ShaderModuleDescriptor descriptor;
descriptor.nextInChain = &wgslDesc;
return device->CreateShaderModule(&descriptor);
}
ResultOrError<Ref<BufferBase>> CreateBufferFromData(DeviceBase* device,
wgpu::BufferUsage usage,
const void* data,
uint64_t size) {
BufferDescriptor descriptor;
descriptor.size = size;
descriptor.usage = usage;
descriptor.mappedAtCreation = true;
Ref<BufferBase> buffer;
DAWN_TRY_ASSIGN(buffer, device->CreateBuffer(&descriptor));
memcpy(buffer->GetMappedRange(0, size), data, size);
buffer->Unmap();
return buffer;
}
ResultOrError<Ref<PipelineLayoutBase>> MakeBasicPipelineLayout(
DeviceBase* device,
const Ref<BindGroupLayoutBase>& bindGroupLayout) {
PipelineLayoutDescriptor descriptor;
descriptor.bindGroupLayoutCount = 1;
BindGroupLayoutBase* bgl = bindGroupLayout.Get();
descriptor.bindGroupLayouts = &bgl;
return device->CreatePipelineLayout(&descriptor);
}
ResultOrError<Ref<BindGroupLayoutBase>> MakeBindGroupLayout(
DeviceBase* device,
std::initializer_list<BindingLayoutEntryInitializationHelper> entriesInitializer,
bool allowInternalBinding) {
std::vector<BindGroupLayoutEntry> entries;
for (const BindingLayoutEntryInitializationHelper& entry : entriesInitializer) {
entries.push_back(entry);
}
BindGroupLayoutDescriptor descriptor;
descriptor.entryCount = static_cast<uint32_t>(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<SamplerBase>& sampler)
: binding(binding), sampler(sampler) {
}
BindingInitializationHelper::BindingInitializationHelper(
uint32_t binding,
const Ref<TextureViewBase>& textureView)
: binding(binding), textureView(textureView) {
}
BindingInitializationHelper::BindingInitializationHelper(uint32_t binding,
const Ref<BufferBase>& 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<Ref<BindGroupBase>> MakeBindGroup(
DeviceBase* device,
const Ref<BindGroupLayoutBase>& layout,
std::initializer_list<BindingInitializationHelper> entriesInitializer) {
std::vector<BindGroupEntry> 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

View File

@ -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 <dawn_native/dawn_platform.h>
#include <array>
#include <initializer_list>
#include <vector>
#include "common/RefCounted.h"
#include "dawn_native/Error.h"
namespace dawn_native { namespace utils {
ResultOrError<Ref<ShaderModuleBase>> CreateShaderModule(DeviceBase* device, const char* source);
ResultOrError<Ref<BufferBase>> CreateBufferFromData(DeviceBase* device,
wgpu::BufferUsage usage,
const void* data,
uint64_t size);
template <typename T>
ResultOrError<Ref<BufferBase>> CreateBufferFromData(DeviceBase* device,
wgpu::BufferUsage usage,
std::initializer_list<T> data) {
return CreateBufferFromData(device, usage, data.begin(), uint32_t(sizeof(T) * data.size()));
}
ResultOrError<Ref<PipelineLayoutBase>> MakeBasicPipelineLayout(
DeviceBase* device,
const Ref<BindGroupLayoutBase>& 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<Ref<BindGroupLayoutBase>> MakeBindGroupLayout(
DeviceBase* device,
std::initializer_list<BindingLayoutEntryInitializationHelper> 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<SamplerBase>& sampler);
BindingInitializationHelper(uint32_t binding, const Ref<TextureViewBase>& textureView);
BindingInitializationHelper(uint32_t binding,
const Ref<BufferBase>& buffer,
uint64_t offset = 0,
uint64_t size = wgpu::kWholeSize);
~BindingInitializationHelper();
BindGroupEntry GetAsBinding() const;
uint32_t binding;
Ref<SamplerBase> sampler;
Ref<TextureViewBase> textureView;
Ref<BufferBase> buffer;
uint64_t offset = 0;
uint64_t size = 0;
};
ResultOrError<Ref<BindGroupBase>> MakeBindGroup(
DeviceBase* device,
const Ref<BindGroupLayoutBase>& layout,
std::initializer_list<BindingInitializationHelper> entriesInitializer);
}} // namespace dawn_native::utils
#endif // DAWNNATIVE_UTILS_WGPUHELPERS_H_