mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-20 18:29:23 +00:00
Support and pack unbounded binding numbers in the BGL
Also fixes a bug where we weren't validating duplicating bindings in the shader, and where dynamic offset validation could be incorrectly fetching the wrong bindings. Bug: dawn:354 Change-Id: I93178c34eb4d43119e8b9de5738ae4596e9277cd Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/17240 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
11652ff8f8
commit
a80993da44
@@ -780,4 +780,101 @@ TEST_P(BindGroupTests, BindGroupLayoutVisibilityCanBeNone) {
|
||||
queue.Submit(1, &commands);
|
||||
}
|
||||
|
||||
// Test that bind group bindings may have unbounded and arbitrary binding numbers
|
||||
TEST_P(BindGroupTests, ArbitraryBindingNumbers) {
|
||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||
|
||||
wgpu::ShaderModule vsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
void main() {
|
||||
const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f));
|
||||
gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f);
|
||||
})");
|
||||
|
||||
wgpu::ShaderModule fsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout (set = 0, binding = 953) uniform ubo1 {
|
||||
vec4 color1;
|
||||
};
|
||||
layout (set = 0, binding = 47) uniform ubo2 {
|
||||
vec4 color2;
|
||||
};
|
||||
layout (set = 0, binding = 111) uniform ubo3 {
|
||||
vec4 color3;
|
||||
};
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
void main() {
|
||||
fragColor = color1 + 2 * color2 + 4 * color3;
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
|
||||
pipelineDescriptor.vertexStage.module = vsModule;
|
||||
pipelineDescriptor.cFragmentStage.module = fsModule;
|
||||
pipelineDescriptor.cColorStates[0].format = renderPass.colorFormat;
|
||||
|
||||
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||
|
||||
wgpu::Buffer black =
|
||||
utils::CreateBufferFromData(device, wgpu::BufferUsage::Uniform, {0.f, 0.f, 0.f, 0.f});
|
||||
wgpu::Buffer red =
|
||||
utils::CreateBufferFromData(device, wgpu::BufferUsage::Uniform, {0.251f, 0.0f, 0.0f, 0.0f});
|
||||
wgpu::Buffer green =
|
||||
utils::CreateBufferFromData(device, wgpu::BufferUsage::Uniform, {0.0f, 0.251f, 0.0f, 0.0f});
|
||||
wgpu::Buffer blue =
|
||||
utils::CreateBufferFromData(device, wgpu::BufferUsage::Uniform, {0.0f, 0.0f, 0.251f, 0.0f});
|
||||
|
||||
auto DoTest = [&](wgpu::Buffer color1, wgpu::Buffer color2, wgpu::Buffer color3, RGBA8 filled) {
|
||||
auto DoTestInner = [&](wgpu::BindGroup bindGroup) {
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||
pass.SetPipeline(pipeline);
|
||||
pass.SetBindGroup(0, bindGroup);
|
||||
pass.Draw(3, 1, 0, 0);
|
||||
pass.EndPass();
|
||||
|
||||
wgpu::CommandBuffer commands = encoder.Finish();
|
||||
queue.Submit(1, &commands);
|
||||
|
||||
EXPECT_PIXEL_RGBA8_EQ(filled, renderPass.color, 1, 1);
|
||||
};
|
||||
|
||||
utils::BindingInitializationHelper bindings[] = {
|
||||
{953, color1, 0, 4 * sizeof(float)}, //
|
||||
{47, color2, 0, 4 * sizeof(float)}, //
|
||||
{111, color3, 0, 4 * sizeof(float)}, //
|
||||
};
|
||||
|
||||
// Should work regardless of what order the bindings are specified in.
|
||||
DoTestInner(utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||
{bindings[0], bindings[1], bindings[2]}));
|
||||
DoTestInner(utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||
{bindings[1], bindings[0], bindings[2]}));
|
||||
DoTestInner(utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||
{bindings[2], bindings[0], bindings[1]}));
|
||||
};
|
||||
|
||||
// first color is normal, second is 2x, third is 3x.
|
||||
DoTest(black, black, black, RGBA8(0, 0, 0, 0));
|
||||
|
||||
// Check the first binding maps to the first slot. We know this because the colors are
|
||||
// multiplied 1x.
|
||||
DoTest(red, black, black, RGBA8(64, 0, 0, 0));
|
||||
DoTest(green, black, black, RGBA8(0, 64, 0, 0));
|
||||
DoTest(blue, black, black, RGBA8(0, 0, 64, 0));
|
||||
|
||||
// Use multiple bindings and check the second color maps to the second slot.
|
||||
// We know this because the second slot is multiplied 2x.
|
||||
DoTest(green, blue, black, RGBA8(0, 64, 128, 0));
|
||||
DoTest(blue, green, black, RGBA8(0, 128, 64, 0));
|
||||
DoTest(red, green, black, RGBA8(64, 128, 0, 0));
|
||||
|
||||
// Use multiple bindings and check the third color maps to the third slot.
|
||||
// We know this because the third slot is multiplied 4x.
|
||||
DoTest(black, blue, red, RGBA8(255, 0, 128, 0));
|
||||
DoTest(blue, black, green, RGBA8(0, 255, 64, 0));
|
||||
DoTest(red, black, blue, RGBA8(64, 0, 255, 0));
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BindGroupTests, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
||||
|
||||
@@ -510,16 +510,15 @@ TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutStorageBindingsInVertexShad
|
||||
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BindingType::ReadonlyStorageBuffer}});
|
||||
}
|
||||
|
||||
// Tests setting OOB checks for kMaxBindingsPerGroup in bind group layouts.
|
||||
TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutBindingOOB) {
|
||||
// Checks that kMaxBindingsPerGroup - 1 is valid.
|
||||
utils::MakeBindGroupLayout(device, {{kMaxBindingsPerGroup - 1, wgpu::ShaderStage::Vertex,
|
||||
// Tests setting that bind group layout bindings numbers may be >= kMaxBindingsPerGroup.
|
||||
TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutBindingUnbounded) {
|
||||
// Checks that kMaxBindingsPerGroup is valid.
|
||||
utils::MakeBindGroupLayout(device, {{kMaxBindingsPerGroup, wgpu::ShaderStage::Vertex,
|
||||
wgpu::BindingType::UniformBuffer}});
|
||||
|
||||
// Checks that kMaxBindingsPerGroup is OOB
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroupLayout(
|
||||
device,
|
||||
{{kMaxBindingsPerGroup, wgpu::ShaderStage::Vertex, wgpu::BindingType::UniformBuffer}}));
|
||||
// Checks that kMaxBindingsPerGroup + 1 is valid.
|
||||
utils::MakeBindGroupLayout(device, {{kMaxBindingsPerGroup + 1, wgpu::ShaderStage::Vertex,
|
||||
wgpu::BindingType::UniformBuffer}});
|
||||
}
|
||||
|
||||
// This test verifies that the BindGroupLayout bindings are correctly validated, even if the
|
||||
@@ -698,8 +697,10 @@ class SetBindGroupValidationTest : public ValidationTest {
|
||||
device, {{0, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||
wgpu::BindingType::UniformBuffer, true},
|
||||
{1, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||
wgpu::BindingType::StorageBuffer, true},
|
||||
wgpu::BindingType::UniformBuffer, false},
|
||||
{2, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||
wgpu::BindingType::StorageBuffer, true},
|
||||
{3, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||
wgpu::BindingType::ReadonlyStorageBuffer, true}});
|
||||
}
|
||||
|
||||
@@ -723,13 +724,16 @@ class SetBindGroupValidationTest : public ValidationTest {
|
||||
wgpu::ShaderModule fsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout(std140, set = 0, binding = 0) uniform uBuffer {
|
||||
layout(std140, set = 0, binding = 0) uniform uBufferDynamic {
|
||||
vec2 value0;
|
||||
};
|
||||
layout(std140, set = 0, binding = 1) uniform uBuffer {
|
||||
vec2 value1;
|
||||
};
|
||||
layout(std140, set = 0, binding = 1) buffer SBuffer {
|
||||
layout(std140, set = 0, binding = 2) buffer SBufferDynamic {
|
||||
vec2 value2;
|
||||
} sBuffer;
|
||||
layout(std140, set = 0, binding = 2) readonly buffer RBuffer {
|
||||
layout(std140, set = 0, binding = 3) readonly buffer RBufferDynamic {
|
||||
vec2 value3;
|
||||
} rBuffer;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
@@ -753,13 +757,16 @@ class SetBindGroupValidationTest : public ValidationTest {
|
||||
const uint kInstances = 11;
|
||||
|
||||
layout(local_size_x = kTileSize, local_size_y = kTileSize, local_size_z = 1) in;
|
||||
layout(std140, set = 0, binding = 0) uniform UniformBuffer {
|
||||
layout(std140, set = 0, binding = 0) uniform UniformBufferDynamic {
|
||||
float value0;
|
||||
};
|
||||
layout(std140, set = 0, binding = 1) uniform UniformBuffer {
|
||||
float value1;
|
||||
};
|
||||
layout(std140, set = 0, binding = 1) buffer SBuffer {
|
||||
layout(std140, set = 0, binding = 2) buffer SBufferDynamic {
|
||||
float value2;
|
||||
} dst;
|
||||
layout(std140, set = 0, binding = 2) readonly buffer RBuffer {
|
||||
layout(std140, set = 0, binding = 3) readonly buffer RBufferDynamic {
|
||||
readonly float value3;
|
||||
} rdst;
|
||||
void main() {
|
||||
@@ -824,8 +831,9 @@ TEST_F(SetBindGroupValidationTest, Basic) {
|
||||
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(kBufferSize, wgpu::BufferUsage::Storage);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
|
||||
{{0, uniformBuffer, 0, kBindingSize},
|
||||
{1, storageBuffer, 0, kBindingSize},
|
||||
{2, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
{1, uniformBuffer, 0, kBindingSize},
|
||||
{2, storageBuffer, 0, kBindingSize},
|
||||
{3, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
|
||||
std::array<uint32_t, 3> offsets = {512, 256, 0};
|
||||
|
||||
@@ -842,8 +850,9 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetsMismatch) {
|
||||
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(kBufferSize, wgpu::BufferUsage::Storage);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
|
||||
{{0, uniformBuffer, 0, kBindingSize},
|
||||
{1, storageBuffer, 0, kBindingSize},
|
||||
{2, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
{1, uniformBuffer, 0, kBindingSize},
|
||||
{2, storageBuffer, 0, kBindingSize},
|
||||
{3, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
|
||||
// Number of offsets mismatch.
|
||||
std::array<uint32_t, 4> mismatchOffsets = {768, 512, 256, 0};
|
||||
@@ -865,8 +874,9 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetsNotAligned) {
|
||||
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(kBufferSize, wgpu::BufferUsage::Storage);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
|
||||
{{0, uniformBuffer, 0, kBindingSize},
|
||||
{1, storageBuffer, 0, kBindingSize},
|
||||
{2, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
{1, uniformBuffer, 0, kBindingSize},
|
||||
{2, storageBuffer, 0, kBindingSize},
|
||||
{3, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
|
||||
// Dynamic offsets are not aligned.
|
||||
std::array<uint32_t, 3> notAlignedOffsets = {512, 128, 0};
|
||||
@@ -884,8 +894,9 @@ TEST_F(SetBindGroupValidationTest, OffsetOutOfBoundDynamicUniformBuffer) {
|
||||
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(kBufferSize, wgpu::BufferUsage::Storage);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
|
||||
{{0, uniformBuffer, 0, kBindingSize},
|
||||
{1, storageBuffer, 0, kBindingSize},
|
||||
{2, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
{1, uniformBuffer, 0, kBindingSize},
|
||||
{2, storageBuffer, 0, kBindingSize},
|
||||
{3, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
|
||||
// Dynamic offset + offset is larger than buffer size.
|
||||
std::array<uint32_t, 3> overFlowOffsets = {1024, 256, 0};
|
||||
@@ -903,8 +914,9 @@ TEST_F(SetBindGroupValidationTest, OffsetOutOfBoundDynamicStorageBuffer) {
|
||||
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(kBufferSize, wgpu::BufferUsage::Storage);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
|
||||
{{0, uniformBuffer, 0, kBindingSize},
|
||||
{1, storageBuffer, 0, kBindingSize},
|
||||
{2, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
{1, uniformBuffer, 0, kBindingSize},
|
||||
{2, storageBuffer, 0, kBindingSize},
|
||||
{3, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
|
||||
// Dynamic offset + offset is larger than buffer size.
|
||||
std::array<uint32_t, 3> overFlowOffsets = {0, 256, 1024};
|
||||
@@ -922,8 +934,9 @@ TEST_F(SetBindGroupValidationTest, BindingSizeOutOfBoundDynamicUniformBuffer) {
|
||||
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(kBufferSize, wgpu::BufferUsage::Storage);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
|
||||
{{0, uniformBuffer, 0, kBindingSize},
|
||||
{1, storageBuffer, 0, kBindingSize},
|
||||
{2, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
{1, uniformBuffer, 0, kBindingSize},
|
||||
{2, storageBuffer, 0, kBindingSize},
|
||||
{3, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
|
||||
// Dynamic offset + offset isn't larger than buffer size.
|
||||
// But with binding size, it will trigger OOB error.
|
||||
@@ -941,8 +954,9 @@ TEST_F(SetBindGroupValidationTest, BindingSizeOutOfBoundDynamicStorageBuffer) {
|
||||
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(kBufferSize, wgpu::BufferUsage::Storage);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
|
||||
{{0, uniformBuffer, 0, kBindingSize},
|
||||
{1, storageBuffer, 0, kBindingSize},
|
||||
{2, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
{1, uniformBuffer, 0, kBindingSize},
|
||||
{2, storageBuffer, 0, kBindingSize},
|
||||
{3, readonlyStorageBuffer, 0, kBindingSize}});
|
||||
// Dynamic offset + offset isn't larger than buffer size.
|
||||
// But with binding size, it will trigger OOB error.
|
||||
std::array<uint32_t, 3> offsets = {0, 256, 768};
|
||||
|
||||
@@ -228,7 +228,7 @@ TEST_F(StorageTextureValidationTests, ComputePipeline) {
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform readonly image2D image0;
|
||||
layout(std430, set = 0, binding = 0) buffer Buf { uint buf; };
|
||||
layout(std430, set = 0, binding = 1) buffer Buf { uint buf; };
|
||||
void main() {
|
||||
vec4 pixel = imageLoad(image0, ivec2(gl_LocalInvocationID.xy));
|
||||
buf = uint(pixel.x);
|
||||
|
||||
Reference in New Issue
Block a user