mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-17 17:05:31 +00:00
D3D12/Vulkan: Insert storage buffer barriers between compute pass dipatches
This patch extends the BindGroupTracker in the D3D12 and Vulkan backends to track bound storage buffers. We insert barriers between dispatches to properly synchronize writes to storage buffers. Bug: dawn:236 Change-Id: Iab3f964c345b64755557ab206e05a2ff7b0a3a1f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/12301 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
2c8b5c6370
commit
7b3cc35cb6
147
src/tests/unittests/validation/ComputePassValidationTests.cpp
Normal file
147
src/tests/unittests/validation/ComputePassValidationTests.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2019 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 "tests/unittests/validation/ValidationTest.h"
|
||||
|
||||
#include "utils/DawnHelpers.h"
|
||||
|
||||
class ComputePassValidationTest : public ValidationTest {};
|
||||
|
||||
// Test that it is invalid to use a buffer with both read and write usages in a compute pass.
|
||||
TEST_F(ComputePassValidationTest, ReadWriteUsage) {
|
||||
dawn::BufferDescriptor bufferDesc = {};
|
||||
bufferDesc.usage = dawn::BufferUsage::Storage | dawn::BufferUsage::Uniform;
|
||||
bufferDesc.size = 4;
|
||||
dawn::Buffer buffer = device.CreateBuffer(&bufferDesc);
|
||||
|
||||
dawn::ShaderModule module =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
|
||||
#version 450
|
||||
layout(std430, set = 0, binding = 0) buffer BufA { uint bufA; };
|
||||
layout(std140, set = 0, binding = 1) uniform BufB { uint bufB; };
|
||||
void main() {}
|
||||
)");
|
||||
|
||||
dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
||||
device, {{0, dawn::ShaderStage::Compute, dawn::BindingType::StorageBuffer},
|
||||
{1, dawn::ShaderStage::Compute, dawn::BindingType::UniformBuffer}});
|
||||
|
||||
dawn::BindGroup bindGroup = utils::MakeBindGroup(device, bgl,
|
||||
{
|
||||
{0, buffer, 0, 4},
|
||||
{1, buffer, 0, 4},
|
||||
});
|
||||
|
||||
dawn::PipelineLayout layout = utils::MakeBasicPipelineLayout(device, &bgl);
|
||||
|
||||
dawn::ComputePipelineDescriptor pipelineDesc = {};
|
||||
pipelineDesc.layout = layout;
|
||||
pipelineDesc.computeStage.module = module;
|
||||
pipelineDesc.computeStage.entryPoint = "main";
|
||||
dawn::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDesc);
|
||||
|
||||
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
dawn::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||
pass.SetPipeline(pipeline);
|
||||
pass.SetBindGroup(0, bindGroup);
|
||||
|
||||
pass.Dispatch(1, 1, 1);
|
||||
pass.Dispatch(1, 1, 1);
|
||||
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Test that it is valid to use a buffer with a single write usage multiple times in a compute pass.
|
||||
TEST_F(ComputePassValidationTest, MultipleWrites) {
|
||||
dawn::BufferDescriptor bufferDesc = {};
|
||||
bufferDesc.usage = dawn::BufferUsage::Storage;
|
||||
bufferDesc.size = 4;
|
||||
dawn::Buffer buffer = device.CreateBuffer(&bufferDesc);
|
||||
|
||||
dawn::ShaderModule module =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
|
||||
#version 450
|
||||
layout(std430, set = 0, binding = 0) buffer Buf { uint buf; };
|
||||
void main() {}
|
||||
)");
|
||||
|
||||
dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
||||
device, {{0, dawn::ShaderStage::Compute, dawn::BindingType::StorageBuffer}});
|
||||
|
||||
dawn::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, buffer, 0, 4}});
|
||||
|
||||
dawn::PipelineLayout layout = utils::MakeBasicPipelineLayout(device, &bgl);
|
||||
|
||||
dawn::ComputePipelineDescriptor pipelineDesc = {};
|
||||
pipelineDesc.layout = layout;
|
||||
pipelineDesc.computeStage.module = module;
|
||||
pipelineDesc.computeStage.entryPoint = "main";
|
||||
dawn::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDesc);
|
||||
|
||||
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
dawn::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||
pass.SetPipeline(pipeline);
|
||||
pass.SetBindGroup(0, bindGroup);
|
||||
|
||||
pass.Dispatch(1, 1, 1);
|
||||
pass.Dispatch(1, 1, 1);
|
||||
|
||||
pass.EndPass();
|
||||
encoder.Finish();
|
||||
}
|
||||
|
||||
// Test that it is valid to use a buffer with a single write usage multiple times in a compute pass,
|
||||
// even if the buffer is referenced in separate bind groups.
|
||||
TEST_F(ComputePassValidationTest, MultipleWritesSeparateBindGroups) {
|
||||
dawn::BufferDescriptor bufferDesc = {};
|
||||
bufferDesc.usage = dawn::BufferUsage::Storage;
|
||||
bufferDesc.size = 4;
|
||||
dawn::Buffer buffer = device.CreateBuffer(&bufferDesc);
|
||||
|
||||
dawn::ShaderModule module =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
|
||||
#version 450
|
||||
#define kNumValues 100
|
||||
layout(std430, set = 0, binding = 0) buffer Buf { uint buf; };
|
||||
void main() {}
|
||||
)");
|
||||
|
||||
dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
||||
device, {{0, dawn::ShaderStage::Compute, dawn::BindingType::StorageBuffer}});
|
||||
|
||||
dawn::BindGroup bindGroupA = utils::MakeBindGroup(device, bgl, {{0, buffer, 0, 4}});
|
||||
dawn::BindGroup bindGroupB = utils::MakeBindGroup(device, bgl, {{0, buffer, 0, 4}});
|
||||
|
||||
dawn::PipelineLayout layout = utils::MakeBasicPipelineLayout(device, &bgl);
|
||||
|
||||
dawn::ComputePipelineDescriptor pipelineDesc = {};
|
||||
pipelineDesc.layout = layout;
|
||||
pipelineDesc.computeStage.module = module;
|
||||
pipelineDesc.computeStage.entryPoint = "main";
|
||||
dawn::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDesc);
|
||||
|
||||
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
dawn::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||
pass.SetPipeline(pipeline);
|
||||
|
||||
pass.SetBindGroup(0, bindGroupA);
|
||||
pass.Dispatch(1, 1, 1);
|
||||
|
||||
pass.SetBindGroup(0, bindGroupB);
|
||||
pass.Dispatch(1, 1, 1);
|
||||
|
||||
pass.EndPass();
|
||||
encoder.Finish();
|
||||
}
|
||||
Reference in New Issue
Block a user