mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-05 06:03:34 +00:00
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:
parent
61a5aeb70b
commit
a50efb961d
@ -331,6 +331,8 @@ source_set("dawn_native_sources") {
|
|||||||
"VertexFormat.cpp",
|
"VertexFormat.cpp",
|
||||||
"VertexFormat.h",
|
"VertexFormat.h",
|
||||||
"dawn_platform.h",
|
"dawn_platform.h",
|
||||||
|
"utils/WGPUHelpers.cpp",
|
||||||
|
"utils/WGPUHelpers.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (dawn_use_x11) {
|
if (dawn_use_x11) {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "dawn_native/ObjectType_autogen.h"
|
#include "dawn_native/ObjectType_autogen.h"
|
||||||
#include "dawn_native/PassResourceUsageTracker.h"
|
#include "dawn_native/PassResourceUsageTracker.h"
|
||||||
#include "dawn_native/QuerySet.h"
|
#include "dawn_native/QuerySet.h"
|
||||||
|
#include "dawn_native/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
@ -39,13 +40,10 @@ namespace dawn_native {
|
|||||||
return store->dispatchIndirectValidationPipeline.Get();
|
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
|
// TODO(https://crbug.com/dawn/1108): Propagate validation feedback from this
|
||||||
// shader in various failure modes.
|
// shader in various failure modes.
|
||||||
wgslDesc.source = R"(
|
Ref<ShaderModuleBase> shaderModule;
|
||||||
|
DAWN_TRY_ASSIGN(shaderModule, utils::CreateShaderModule(device, R"(
|
||||||
[[block]] struct UniformParams {
|
[[block]] struct UniformParams {
|
||||||
maxComputeWorkgroupsPerDimension: u32;
|
maxComputeWorkgroupsPerDimension: u32;
|
||||||
clientOffsetInU32: u32;
|
clientOffsetInU32: u32;
|
||||||
@ -73,34 +71,23 @@ namespace dawn_native {
|
|||||||
validatedParams.data[i] = numWorkgroups;
|
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;
|
Ref<BindGroupLayoutBase> bindGroupLayout;
|
||||||
DAWN_TRY_ASSIGN(bindGroupLayout,
|
DAWN_TRY_ASSIGN(
|
||||||
device->CreateBindGroupLayout(&bindGroupLayoutDescriptor, true));
|
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;
|
Ref<PipelineLayoutBase> pipelineLayout;
|
||||||
DAWN_TRY_ASSIGN(pipelineLayout, device->CreatePipelineLayout(&pipelineDescriptor));
|
DAWN_TRY_ASSIGN(pipelineLayout,
|
||||||
|
utils::MakeBasicPipelineLayout(device, bindGroupLayout));
|
||||||
|
|
||||||
ComputePipelineDescriptor computePipelineDescriptor = {};
|
ComputePipelineDescriptor computePipelineDescriptor = {};
|
||||||
computePipelineDescriptor.layout = pipelineLayout.Get();
|
computePipelineDescriptor.layout = pipelineLayout.Get();
|
||||||
@ -211,21 +198,15 @@ namespace dawn_native {
|
|||||||
uint32_t storageBufferOffsetAlignment =
|
uint32_t storageBufferOffsetAlignment =
|
||||||
device->GetLimits().v1.minStorageBufferOffsetAlignment;
|
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|.
|
// Let the offset be the indirectOffset, aligned down to |storageBufferOffsetAlignment|.
|
||||||
const uint32_t clientOffsetFromAlignedBoundary =
|
const uint32_t clientOffsetFromAlignedBoundary =
|
||||||
indirectOffset % storageBufferOffsetAlignment;
|
indirectOffset % storageBufferOffsetAlignment;
|
||||||
const uint64_t clientOffsetAlignedDown = indirectOffset - clientOffsetFromAlignedBoundary;
|
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.
|
// 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 {
|
struct UniformParams {
|
||||||
uint32_t maxComputeWorkgroupsPerDimension;
|
uint32_t maxComputeWorkgroupsPerDimension;
|
||||||
@ -235,46 +216,30 @@ namespace dawn_native {
|
|||||||
// Create a uniform buffer to hold parameters for the shader.
|
// Create a uniform buffer to hold parameters for the shader.
|
||||||
Ref<BufferBase> uniformBuffer;
|
Ref<BufferBase> uniformBuffer;
|
||||||
{
|
{
|
||||||
BufferDescriptor uniformDesc = {};
|
UniformParams params;
|
||||||
uniformDesc.size = sizeof(UniformParams);
|
params.maxComputeWorkgroupsPerDimension =
|
||||||
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 =
|
|
||||||
device->GetLimits().v1.maxComputeWorkgroupsPerDimension;
|
device->GetLimits().v1.maxComputeWorkgroupsPerDimension;
|
||||||
params->clientOffsetInU32 = clientOffsetFromAlignedBoundary / sizeof(uint32_t);
|
params.clientOffsetInU32 = clientOffsetFromAlignedBoundary / sizeof(uint32_t);
|
||||||
uniformBuffer->Unmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uniform buffer binding pointing to the uniform parameters.
|
DAWN_TRY_ASSIGN(uniformBuffer, utils::CreateBufferFromData(
|
||||||
BindGroupEntry& uniformBinding = bindings[1];
|
device, wgpu::BufferUsage::Uniform, {params}));
|
||||||
uniformBinding.binding = 0;
|
}
|
||||||
uniformBinding.buffer = uniformBuffer.Get();
|
|
||||||
uniformBinding.offset = 0;
|
|
||||||
uniformBinding.size = sizeof(UniformParams);
|
|
||||||
|
|
||||||
// Reserve space in the scratch buffer to hold the validated indirect params.
|
// Reserve space in the scratch buffer to hold the validated indirect params.
|
||||||
ScratchBuffer& scratchBuffer = store->scratchIndirectStorage;
|
ScratchBuffer& scratchBuffer = store->scratchIndirectStorage;
|
||||||
DAWN_TRY(scratchBuffer.EnsureCapacity(kDispatchIndirectSize));
|
DAWN_TRY(scratchBuffer.EnsureCapacity(kDispatchIndirectSize));
|
||||||
Ref<BufferBase> validatedIndirectBuffer = scratchBuffer.GetBuffer();
|
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;
|
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.
|
// Issue commands to validate the indirect buffer.
|
||||||
APISetPipeline(validationPipeline.Get());
|
APISetPipeline(validationPipeline.Get());
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "dawn_native/Sampler.h"
|
#include "dawn_native/Sampler.h"
|
||||||
#include "dawn_native/Texture.h"
|
#include "dawn_native/Texture.h"
|
||||||
#include "dawn_native/ValidationUtils_autogen.h"
|
#include "dawn_native/ValidationUtils_autogen.h"
|
||||||
|
#include "dawn_native/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -191,13 +192,9 @@ namespace dawn_native {
|
|||||||
if (GetCachedPipeline(store, dstFormat) == nullptr) {
|
if (GetCachedPipeline(store, dstFormat) == nullptr) {
|
||||||
// Create vertex shader module if not cached before.
|
// Create vertex shader module if not cached before.
|
||||||
if (store->copyTextureForBrowser == nullptr) {
|
if (store->copyTextureForBrowser == nullptr) {
|
||||||
ShaderModuleDescriptor descriptor;
|
DAWN_TRY_ASSIGN(
|
||||||
ShaderModuleWGSLDescriptor wgslDesc;
|
store->copyTextureForBrowser,
|
||||||
wgslDesc.source = sCopyTextureForBrowserShader;
|
utils::CreateShaderModule(device, sCopyTextureForBrowserShader));
|
||||||
descriptor.nextInChain = reinterpret_cast<ChainedStruct*>(&wgslDesc);
|
|
||||||
|
|
||||||
DAWN_TRY_ASSIGN(store->copyTextureForBrowser,
|
|
||||||
device->CreateShaderModule(&descriptor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModuleBase* shaderModule = store->copyTextureForBrowser.Get();
|
ShaderModuleBase* shaderModule = store->copyTextureForBrowser.Get();
|
||||||
@ -307,13 +304,6 @@ namespace dawn_native {
|
|||||||
Ref<BindGroupLayoutBase> layout;
|
Ref<BindGroupLayoutBase> layout;
|
||||||
DAWN_TRY_ASSIGN(layout, pipeline->GetBindGroupLayout(0));
|
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();
|
Extent3D srcTextureSize = source->texture->GetSize();
|
||||||
|
|
||||||
// Prepare binding 0 resource: uniform buffer.
|
// Prepare binding 0 resource: uniform buffer.
|
||||||
@ -336,14 +326,11 @@ namespace dawn_native {
|
|||||||
// Set alpha op.
|
// Set alpha op.
|
||||||
uniformData.alphaOp = options->alphaOp;
|
uniformData.alphaOp = options->alphaOp;
|
||||||
|
|
||||||
BufferDescriptor uniformDesc = {};
|
|
||||||
uniformDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform;
|
|
||||||
uniformDesc.size = sizeof(uniformData);
|
|
||||||
Ref<BufferBase> uniformBuffer;
|
Ref<BufferBase> uniformBuffer;
|
||||||
DAWN_TRY_ASSIGN(uniformBuffer, device->CreateBuffer(&uniformDesc));
|
DAWN_TRY_ASSIGN(
|
||||||
|
uniformBuffer,
|
||||||
DAWN_TRY(device->GetQueue()->WriteBuffer(uniformBuffer.Get(), 0, &uniformData,
|
utils::CreateBufferFromData(
|
||||||
sizeof(uniformData)));
|
device, wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform, {uniformData}));
|
||||||
|
|
||||||
// Prepare binding 1 resource: sampler
|
// Prepare binding 1 resource: sampler
|
||||||
// Use default configuration, filterMode set to Nearest for min and mag.
|
// Use default configuration, filterMode set to Nearest for min and mag.
|
||||||
@ -360,18 +347,11 @@ namespace dawn_native {
|
|||||||
DAWN_TRY_ASSIGN(srcTextureView,
|
DAWN_TRY_ASSIGN(srcTextureView,
|
||||||
device->CreateTextureView(source->texture, &srcTextureViewDesc));
|
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.
|
// Create bind group after all binding entries are set.
|
||||||
Ref<BindGroupBase> bindGroup;
|
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.
|
// Create command encoder.
|
||||||
CommandEncoderDescriptor encoderDesc = {};
|
CommandEncoderDescriptor encoderDesc = {};
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "dawn_native/Device.h"
|
#include "dawn_native/Device.h"
|
||||||
#include "dawn_native/InternalPipelineStore.h"
|
#include "dawn_native/InternalPipelineStore.h"
|
||||||
#include "dawn_native/Queue.h"
|
#include "dawn_native/Queue.h"
|
||||||
|
#include "dawn_native/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -138,37 +139,27 @@ namespace dawn_native {
|
|||||||
if (store->renderValidationPipeline == nullptr) {
|
if (store->renderValidationPipeline == nullptr) {
|
||||||
// Create compute shader module if not cached before.
|
// Create compute shader module if not cached before.
|
||||||
if (store->renderValidationShader == nullptr) {
|
if (store->renderValidationShader == nullptr) {
|
||||||
ShaderModuleDescriptor descriptor;
|
DAWN_TRY_ASSIGN(
|
||||||
ShaderModuleWGSLDescriptor wgslDesc;
|
store->renderValidationShader,
|
||||||
wgslDesc.source = sRenderValidationShaderSource;
|
utils::CreateShaderModule(device, sRenderValidationShaderSource));
|
||||||
descriptor.nextInChain = reinterpret_cast<ChainedStruct*>(&wgslDesc);
|
|
||||||
DAWN_TRY_ASSIGN(store->renderValidationShader,
|
|
||||||
device->CreateShaderModule(&descriptor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
Ref<BindGroupLayoutBase> bindGroupLayout;
|
||||||
DAWN_TRY_ASSIGN(bindGroupLayout,
|
DAWN_TRY_ASSIGN(
|
||||||
device->CreateBindGroupLayout(&bindGroupLayoutDescriptor, true));
|
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;
|
Ref<PipelineLayoutBase> pipelineLayout;
|
||||||
DAWN_TRY_ASSIGN(pipelineLayout, device->CreatePipelineLayout(&pipelineDescriptor));
|
DAWN_TRY_ASSIGN(pipelineLayout,
|
||||||
|
utils::MakeBasicPipelineLayout(device, bindGroupLayout));
|
||||||
|
|
||||||
ComputePipelineDescriptor computePipelineDescriptor = {};
|
ComputePipelineDescriptor computePipelineDescriptor = {};
|
||||||
computePipelineDescriptor.layout = pipelineLayout.Get();
|
computePipelineDescriptor.layout = pipelineLayout.Get();
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "dawn_native/ComputePipeline.h"
|
#include "dawn_native/ComputePipeline.h"
|
||||||
#include "dawn_native/Device.h"
|
#include "dawn_native/Device.h"
|
||||||
#include "dawn_native/InternalPipelineStore.h"
|
#include "dawn_native/InternalPipelineStore.h"
|
||||||
|
#include "dawn_native/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
@ -113,36 +114,27 @@ namespace dawn_native {
|
|||||||
if (store->timestampComputePipeline == nullptr) {
|
if (store->timestampComputePipeline == nullptr) {
|
||||||
// Create compute shader module if not cached before.
|
// Create compute shader module if not cached before.
|
||||||
if (store->timestampCS == nullptr) {
|
if (store->timestampCS == nullptr) {
|
||||||
ShaderModuleDescriptor descriptor;
|
DAWN_TRY_ASSIGN(
|
||||||
ShaderModuleWGSLDescriptor wgslDesc;
|
store->timestampCS,
|
||||||
wgslDesc.source = sConvertTimestampsToNanoseconds;
|
utils::CreateShaderModule(device, sConvertTimestampsToNanoseconds));
|
||||||
descriptor.nextInChain = reinterpret_cast<ChainedStruct*>(&wgslDesc);
|
|
||||||
|
|
||||||
DAWN_TRY_ASSIGN(store->timestampCS, device->CreateShaderModule(&descriptor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create binding group layout
|
// 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;
|
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
|
// Create pipeline layout
|
||||||
PipelineLayoutDescriptor plDesc;
|
|
||||||
plDesc.bindGroupLayoutCount = 1;
|
|
||||||
plDesc.bindGroupLayouts = &bgl.Get();
|
|
||||||
Ref<PipelineLayoutBase> layout;
|
Ref<PipelineLayoutBase> layout;
|
||||||
DAWN_TRY_ASSIGN(layout, device->CreatePipelineLayout(&plDesc));
|
DAWN_TRY_ASSIGN(layout, utils::MakeBasicPipelineLayout(device, bgl));
|
||||||
|
|
||||||
// Create ComputePipeline.
|
// Create ComputePipeline.
|
||||||
ComputePipelineDescriptor computePipelineDesc = {};
|
ComputePipelineDescriptor computePipelineDesc = {};
|
||||||
@ -173,27 +165,11 @@ namespace dawn_native {
|
|||||||
Ref<BindGroupLayoutBase> layout;
|
Ref<BindGroupLayoutBase> layout;
|
||||||
DAWN_TRY_ASSIGN(layout, pipeline->GetBindGroupLayout(0));
|
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.
|
// Create bind group after all binding entries are set.
|
||||||
Ref<BindGroupBase> bindGroup;
|
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.
|
// Create compute encoder and issue dispatch.
|
||||||
ComputePassDescriptor passDesc = {};
|
ComputePassDescriptor passDesc = {};
|
||||||
|
188
src/dawn_native/utils/WGPUHelpers.cpp
Normal file
188
src/dawn_native/utils/WGPUHelpers.cpp
Normal 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
|
120
src/dawn_native/utils/WGPUHelpers.h
Normal file
120
src/dawn_native/utils/WGPUHelpers.h
Normal 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_
|
Loading…
x
Reference in New Issue
Block a user