Validate effective storage or read-only storage buffer size be multiple of 4

This patch adds a validation that the effective buffer size must be a multiple
of 4 when the binding type is storage or read-only storage to match the latest
WebGPU SPEC.

This patch also fixes some typos in BindGroupValidationTests.

Bug: dawn:1542
Test: dawn_unittest
Change-Id: I30234bcf718be0d82d4a09b9980127a98ebe8172
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105101
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Jiawei Shao 2022-10-12 00:55:37 +00:00 committed by Dawn LUCI CQ
parent a44e3d8bea
commit 75a8574b29
4 changed files with 135 additions and 73 deletions

View File

@ -49,30 +49,6 @@ MaybeError ValidateBufferBinding(const DeviceBase* device,
ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer); ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);
wgpu::BufferUsage requiredUsage;
uint64_t maxBindingSize;
uint64_t requiredBindingAlignment;
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
requiredUsage = wgpu::BufferUsage::Uniform;
maxBindingSize = device->GetLimits().v1.maxUniformBufferBindingSize;
requiredBindingAlignment = device->GetLimits().v1.minUniformBufferOffsetAlignment;
break;
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage:
requiredUsage = wgpu::BufferUsage::Storage;
maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
break;
case kInternalStorageBufferBinding:
requiredUsage = kInternalStorageBuffer;
maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
uint64_t bufferSize = entry.buffer->GetSize(); uint64_t bufferSize = entry.buffer->GetSize();
// Handle wgpu::WholeSize, avoiding overflows. // Handle wgpu::WholeSize, avoiding overflows.
@ -95,6 +71,33 @@ MaybeError ValidateBufferBinding(const DeviceBase* device,
"Binding range (offset: %u, size: %u) doesn't fit in the size (%u) of %s.", "Binding range (offset: %u, size: %u) doesn't fit in the size (%u) of %s.",
entry.offset, bufferSize, bindingSize, entry.buffer); entry.offset, bufferSize, bindingSize, entry.buffer);
wgpu::BufferUsage requiredUsage;
uint64_t maxBindingSize;
uint64_t requiredBindingAlignment;
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
requiredUsage = wgpu::BufferUsage::Uniform;
maxBindingSize = device->GetLimits().v1.maxUniformBufferBindingSize;
requiredBindingAlignment = device->GetLimits().v1.minUniformBufferOffsetAlignment;
break;
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage:
requiredUsage = wgpu::BufferUsage::Storage;
maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
DAWN_INVALID_IF(bindingSize % 4 != 0,
"Binding size (%u) isn't a multiple of 4 when binding type is (%s).",
bindingSize, bindingInfo.buffer.type);
break;
case kInternalStorageBufferBinding:
requiredUsage = kInternalStorageBuffer;
maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
DAWN_INVALID_IF(!IsAligned(entry.offset, requiredBindingAlignment), DAWN_INVALID_IF(!IsAligned(entry.offset, requiredBindingAlignment),
"Offset (%u) does not satisfy the minimum %s alignment (%u).", entry.offset, "Offset (%u) does not satisfy the minimum %s alignment (%u).", entry.offset,
bindingInfo.buffer.type, requiredBindingAlignment); bindingInfo.buffer.type, requiredBindingAlignment);

View File

@ -1041,7 +1041,7 @@ TEST_F(BindGroupValidationTest, MaxStorageBufferBindingSize) {
// Success case, this is one less than the limit (check it is not an alignment constraint) // Success case, this is one less than the limit (check it is not an alignment constraint)
utils::MakeBindGroup(device, uniformLayout, utils::MakeBindGroup(device, uniformLayout,
{{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize - 1}}); {{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize - 4}});
wgpu::BindGroupLayout doubleUniformLayout = utils::MakeBindGroupLayout( wgpu::BindGroupLayout doubleUniformLayout = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage}, device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage},
@ -1055,7 +1055,51 @@ TEST_F(BindGroupValidationTest, MaxStorageBufferBindingSize) {
// Error case, this is above the limit // Error case, this is above the limit
ASSERT_DEVICE_ERROR(utils::MakeBindGroup( ASSERT_DEVICE_ERROR(utils::MakeBindGroup(
device, uniformLayout, {{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize + 1}})); device, uniformLayout, {{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize + 4}}));
}
// Test constraints to be sure the effective storage and read-only storage buffer binding size must
// be a multiple of 4.
TEST_F(BindGroupValidationTest, EffectiveStorageBufferBindingSize) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 262;
descriptor.usage = wgpu::BufferUsage::Storage;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
constexpr std::array<wgpu::BufferBindingType, 2> kStorageBufferBindingTypes = {
{wgpu::BufferBindingType::Storage, wgpu::BufferBindingType::ReadOnlyStorage}};
for (wgpu::BufferBindingType bufferBindingType : kStorageBufferBindingTypes) {
wgpu::BindGroupLayout layout = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Compute, bufferBindingType}});
// Error case, as the effective buffer binding size (262) isn't a multiple of 4.
{
constexpr uint32_t kOffset = 0;
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, kOffset}}));
}
// Error case, as the effective buffer binding size (6) isn't a multiple of 4.
{
constexpr uint32_t kOffset = 256;
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, kOffset}}));
}
// Error case, as the effective buffer binding size (2) isn't a multiple of 4.
{
constexpr uint32_t kOffset = 0;
constexpr uint32_t kBindingSize = 2;
ASSERT_DEVICE_ERROR(
utils::MakeBindGroup(device, layout, {{0, buffer, kOffset, kBindingSize}}));
}
// Success case, as the effective buffer binding size (4) is a multiple of 4.
{
constexpr uint32_t kOffset = 0;
constexpr uint32_t kBindingSize = 4;
utils::MakeBindGroup(device, layout, {{0, buffer, kOffset, kBindingSize}});
}
}
} }
// Test what happens when the layout is an error. // Test what happens when the layout is an error.
@ -1626,7 +1670,7 @@ TEST_F(BindGroupLayoutValidationTest, MultisampledTextureSampleType) {
}); });
} }
constexpr uint32_t kBindingSize = 9; constexpr uint32_t kBindingSize = 8;
class SetBindGroupValidationTest : public ValidationTest { class SetBindGroupValidationTest : public ValidationTest {
public: public:
@ -1919,17 +1963,19 @@ TEST_F(SetBindGroupValidationTest, OffsetOutOfBoundDynamicStorageBuffer) {
// Test cases that test dynamic uniform buffer out of bound situation because of binding size. // Test cases that test dynamic uniform buffer out of bound situation because of binding size.
TEST_F(SetBindGroupValidationTest, BindingSizeOutOfBoundDynamicUniformBuffer) { TEST_F(SetBindGroupValidationTest, BindingSizeOutOfBoundDynamicUniformBuffer) {
// Set up bind group, but binding size is larger than // Set up bind group, but binding size is larger than (mBufferSize - DynamicOffset).
wgpu::Buffer uniformBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Uniform); wgpu::Buffer uniformBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Uniform);
wgpu::Buffer storageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage); wgpu::Buffer storageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage); wgpu::Buffer readonlyStorageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout, constexpr uint32_t kLargeBindingSize = kBindingSize + 4u;
{{0, uniformBuffer, 0, kBindingSize}, wgpu::BindGroup bindGroup =
{1, uniformBuffer, 0, kBindingSize}, utils::MakeBindGroup(device, mBindGroupLayout,
{2, storageBuffer, 0, kBindingSize}, {{0, uniformBuffer, 0, kLargeBindingSize},
{3, readonlyStorageBuffer, 0, kBindingSize}}); {1, uniformBuffer, 0, kLargeBindingSize},
{2, storageBuffer, 0, kLargeBindingSize},
{3, readonlyStorageBuffer, 0, kLargeBindingSize}});
// Dynamic offset + offset isn't larger than buffer size. // c + offset isn't larger than buffer size.
// But with binding size, it will trigger OOB error. // But with binding size, it will trigger OOB error.
std::array<uint32_t, 3> offsets = {768, 256, 0}; std::array<uint32_t, 3> offsets = {768, 256, 0};
@ -1943,11 +1989,13 @@ TEST_F(SetBindGroupValidationTest, BindingSizeOutOfBoundDynamicStorageBuffer) {
wgpu::Buffer uniformBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Uniform); wgpu::Buffer uniformBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Uniform);
wgpu::Buffer storageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage); wgpu::Buffer storageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
wgpu::Buffer readonlyStorageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage); wgpu::Buffer readonlyStorageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout, constexpr uint32_t kLargeBindingSize = kBindingSize + 4u;
{{0, uniformBuffer, 0, kBindingSize}, wgpu::BindGroup bindGroup =
{1, uniformBuffer, 0, kBindingSize}, utils::MakeBindGroup(device, mBindGroupLayout,
{2, storageBuffer, 0, kBindingSize}, {{0, uniformBuffer, 0, kLargeBindingSize},
{3, readonlyStorageBuffer, 0, kBindingSize}}); {1, uniformBuffer, 0, kLargeBindingSize},
{2, storageBuffer, 0, kLargeBindingSize},
{3, readonlyStorageBuffer, 0, kLargeBindingSize}});
// Dynamic offset + offset isn't larger than buffer size. // Dynamic offset + offset isn't larger than buffer size.
// But with binding size, it will trigger OOB error. // But with binding size, it will trigger OOB error.
std::array<uint32_t, 3> offsets = {0, 256, 768}; std::array<uint32_t, 3> offsets = {0, 256, 768};
@ -2593,7 +2641,7 @@ TEST_F(BindingsValidationTest, PipelineLayoutWithMoreBindingsThanPipeline) {
// Test that it is invalid to set a pipeline layout that doesn't have all necessary bindings // Test that it is invalid to set a pipeline layout that doesn't have all necessary bindings
// required by the pipeline. // required by the pipeline.
TEST_F(BindingsValidationTest, PipelineLayoutWithLessBindingsThanPipeline) { TEST_F(BindingsValidationTest, PipelineLayoutWithFewerBindingsThanPipeline) {
// Set up bind group layout. // Set up bind group layout.
wgpu::BindGroupLayout bgl0 = utils::MakeBindGroupLayout( wgpu::BindGroupLayout bgl0 = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment, device, {{0, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
@ -2672,7 +2720,7 @@ TEST_F(BindingsValidationTest, BindGroupsWithMoreBindingsThanPipelineLayout) {
// Test that it is invalid to set bind groups that don't have all necessary bindings required // Test that it is invalid to set bind groups that don't have all necessary bindings required
// by the pipeline layout. Note that both pipeline layout and bind group have enough bindings for // by the pipeline layout. Note that both pipeline layout and bind group have enough bindings for
// pipeline in the following test. // pipeline in the following test.
TEST_F(BindingsValidationTest, BindGroupsWithLessBindingsThanPipelineLayout) { TEST_F(BindingsValidationTest, BindGroupsWithFewerBindingsThanPipelineLayout) {
// Set up bind group layouts, buffers, bind groups, pipeline layouts and pipelines. // Set up bind group layouts, buffers, bind groups, pipeline layouts and pipelines.
std::array<wgpu::BindGroupLayout, kBindingNum> bgl; std::array<wgpu::BindGroupLayout, kBindingNum> bgl;
std::array<wgpu::BindGroup, kBindingNum> bg; std::array<wgpu::BindGroup, kBindingNum> bg;

View File

@ -55,18 +55,19 @@ void WithEachSizeOffsetBy(int64_t offset, const std::vector<uint64_t>& originalS
template <typename F> template <typename F>
void CheckSizeBounds(const std::vector<uint64_t>& correctSizes, F func) { void CheckSizeBounds(const std::vector<uint64_t>& correctSizes, F func) {
// To validate size: // To validate size:
// Check invalid with bind group with one less // Check invalid with bind group with 4 less (the effective storage / read-only storage buffer
// size must be a multiple of 4).
// Check valid with bind group with correct size // Check valid with bind group with correct size
// Make sure (every size - 1) produces an error // Make sure (every size - 4) produces an error
WithEachSizeOffsetBy(-1, correctSizes, WithEachSizeOffsetBy(-4, correctSizes,
[&](const std::vector<uint64_t>& sizes) { func(sizes, false); }); [&](const std::vector<uint64_t>& sizes) { func(sizes, false); });
// Make sure correct sizes work // Make sure correct sizes work
func(correctSizes, true); func(correctSizes, true);
// Make sure (every size + 1) works // Make sure (every size + 4) works
WithEachSizeOffsetBy(1, correctSizes, WithEachSizeOffsetBy(4, correctSizes,
[&](const std::vector<uint64_t>& sizes) { func(sizes, true); }); [&](const std::vector<uint64_t>& sizes) { func(sizes, true); });
} }
@ -324,8 +325,8 @@ class MinBufferSizePipelineCreationTests : public MinBufferSizeTestsBase {};
// Pipeline can be created if minimum buffer size in layout is specified as 0 // Pipeline can be created if minimum buffer size in layout is specified as 0
TEST_F(MinBufferSizePipelineCreationTests, ZeroMinBufferSize) { TEST_F(MinBufferSizePipelineCreationTests, ZeroMinBufferSize) {
std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8}, std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
{0, 1, "c : f32,", "f32", "c", 4}}; {0, 1, "d : f32, e : f32", "f32", "d", 8}};
std::string computeShader = CreateComputeShaderWithBindings(bindings); std::string computeShader = CreateComputeShaderWithBindings(bindings);
std::string vertexShader = CreateVertexShaderWithBindings({}); std::string vertexShader = CreateVertexShaderWithBindings({});
@ -338,14 +339,14 @@ TEST_F(MinBufferSizePipelineCreationTests, ZeroMinBufferSize) {
// Fail if layout given has non-zero minimum sizes smaller than shader requirements // Fail if layout given has non-zero minimum sizes smaller than shader requirements
TEST_F(MinBufferSizePipelineCreationTests, LayoutSizesTooSmall) { TEST_F(MinBufferSizePipelineCreationTests, LayoutSizesTooSmall) {
std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8}, std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c: f32", "f32", "a", 12},
{0, 1, "c : f32,", "f32", "c", 4}}; {0, 1, "d : f32, e : f32", "f32", "d", 8}};
std::string computeShader = CreateComputeShaderWithBindings(bindings); std::string computeShader = CreateComputeShaderWithBindings(bindings);
std::string vertexShader = CreateVertexShaderWithBindings({}); std::string vertexShader = CreateVertexShaderWithBindings({});
std::string fragShader = CreateFragmentShaderWithBindings(bindings); std::string fragShader = CreateFragmentShaderWithBindings(bindings);
CheckSizeBounds({8, 4}, [&](const std::vector<uint64_t>& sizes, bool expectation) { CheckSizeBounds({12, 8}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
wgpu::BindGroupLayout layout = CreateBindGroupLayout(bindings, sizes); wgpu::BindGroupLayout layout = CreateBindGroupLayout(bindings, sizes);
if (expectation) { if (expectation) {
CreateRenderPipeline({layout}, vertexShader, fragShader); CreateRenderPipeline({layout}, vertexShader, fragShader);
@ -359,18 +360,19 @@ TEST_F(MinBufferSizePipelineCreationTests, LayoutSizesTooSmall) {
// Fail if layout given has non-zero minimum sizes smaller than shader requirements // Fail if layout given has non-zero minimum sizes smaller than shader requirements
TEST_F(MinBufferSizePipelineCreationTests, LayoutSizesTooSmallMultipleGroups) { TEST_F(MinBufferSizePipelineCreationTests, LayoutSizesTooSmallMultipleGroups) {
std::vector<BindingDescriptor> bg0Bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8}, std::vector<BindingDescriptor> bg0Bindings = {
{0, 1, "c : f32,", "f32", "c", 4}}; {0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
{0, 1, "d : f32, e : f32", "f32", "d", 8}};
std::vector<BindingDescriptor> bg1Bindings = { std::vector<BindingDescriptor> bg1Bindings = {
{1, 0, "d : f32, e : f32, f : f32,", "f32", "e", 12}, {1, 0, "f : f32, g : f32, h : f32,", "f32", "f", 12},
{1, 1, "g : mat2x2<f32>,", "mat2x2<f32>", "g", 16}}; {1, 1, "i : mat2x2<f32>,", "mat2x2<f32>", "i", 16}};
std::vector<BindingDescriptor> bindings = CombineBindings({bg0Bindings, bg1Bindings}); std::vector<BindingDescriptor> bindings = CombineBindings({bg0Bindings, bg1Bindings});
std::string computeShader = CreateComputeShaderWithBindings(bindings); std::string computeShader = CreateComputeShaderWithBindings(bindings);
std::string vertexShader = CreateVertexShaderWithBindings({}); std::string vertexShader = CreateVertexShaderWithBindings({});
std::string fragShader = CreateFragmentShaderWithBindings(bindings); std::string fragShader = CreateFragmentShaderWithBindings(bindings);
CheckSizeBounds({8, 4, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) { CheckSizeBounds({12, 8, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
wgpu::BindGroupLayout layout0 = CreateBindGroupLayout(bg0Bindings, {sizes[0], sizes[1]}); wgpu::BindGroupLayout layout0 = CreateBindGroupLayout(bg0Bindings, {sizes[0], sizes[1]});
wgpu::BindGroupLayout layout1 = CreateBindGroupLayout(bg1Bindings, {sizes[2], sizes[3]}); wgpu::BindGroupLayout layout1 = CreateBindGroupLayout(bg1Bindings, {sizes[2], sizes[3]});
if (expectation) { if (expectation) {
@ -388,11 +390,11 @@ class MinBufferSizeBindGroupCreationTests : public MinBufferSizeTestsBase {};
// Fail if a binding is smaller than minimum buffer size // Fail if a binding is smaller than minimum buffer size
TEST_F(MinBufferSizeBindGroupCreationTests, BindingTooSmall) { TEST_F(MinBufferSizeBindGroupCreationTests, BindingTooSmall) {
std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8}, std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
{0, 1, "c : f32,", "f32", "c", 4}}; {0, 1, "d : f32, e : f32", "f32", "d", 8}};
wgpu::BindGroupLayout layout = CreateBindGroupLayout(bindings, {8, 4}); wgpu::BindGroupLayout layout = CreateBindGroupLayout(bindings, {12, 8});
CheckSizeBounds({8, 4}, [&](const std::vector<uint64_t>& sizes, bool expectation) { CheckSizeBounds({12, 8}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
if (expectation) { if (expectation) {
CreateBindGroup(layout, bindings, sizes); CreateBindGroup(layout, bindings, sizes);
} else { } else {
@ -422,8 +424,8 @@ class MinBufferSizeDrawTimeValidationTests : public MinBufferSizeTestsBase {};
// Fail if binding sizes are too small at draw time // Fail if binding sizes are too small at draw time
TEST_F(MinBufferSizeDrawTimeValidationTests, ZeroMinSizeAndTooSmallBinding) { TEST_F(MinBufferSizeDrawTimeValidationTests, ZeroMinSizeAndTooSmallBinding) {
std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8}, std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
{0, 1, "c : f32,", "f32", "c", 4}}; {0, 1, "d : f32, e : f32", "f32", "d", 8}};
std::string computeShader = CreateComputeShaderWithBindings(bindings); std::string computeShader = CreateComputeShaderWithBindings(bindings);
std::string vertexShader = CreateVertexShaderWithBindings({}); std::string vertexShader = CreateVertexShaderWithBindings({});
@ -434,7 +436,7 @@ TEST_F(MinBufferSizeDrawTimeValidationTests, ZeroMinSizeAndTooSmallBinding) {
wgpu::ComputePipeline computePipeline = CreateComputePipeline({layout}, computeShader); wgpu::ComputePipeline computePipeline = CreateComputePipeline({layout}, computeShader);
wgpu::RenderPipeline renderPipeline = CreateRenderPipeline({layout}, vertexShader, fragShader); wgpu::RenderPipeline renderPipeline = CreateRenderPipeline({layout}, vertexShader, fragShader);
CheckSizeBounds({8, 4}, [&](const std::vector<uint64_t>& sizes, bool expectation) { CheckSizeBounds({12, 8}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
wgpu::BindGroup bindGroup = CreateBindGroup(layout, bindings, sizes); wgpu::BindGroup bindGroup = CreateBindGroup(layout, bindings, sizes);
TestDispatch(computePipeline, {bindGroup}, expectation); TestDispatch(computePipeline, {bindGroup}, expectation);
TestDraw(renderPipeline, {bindGroup}, expectation); TestDraw(renderPipeline, {bindGroup}, expectation);
@ -445,8 +447,8 @@ TEST_F(MinBufferSizeDrawTimeValidationTests, ZeroMinSizeAndTooSmallBinding) {
TEST_F(MinBufferSizeDrawTimeValidationTests, UnorderedBindings) { TEST_F(MinBufferSizeDrawTimeValidationTests, UnorderedBindings) {
std::vector<BindingDescriptor> bindings = { std::vector<BindingDescriptor> bindings = {
{0, 2, "a : f32, b : f32,", "f32", "a", 8}, {0, 2, "a : f32, b : f32,", "f32", "a", 8},
{0, 0, "c : f32,", "f32", "c", 4}, {0, 0, "c : f32, d : f32, e : f32", "f32", "c", 12},
{0, 4, "d : f32, e : f32, f : f32,", "f32", "e", 12}}; {0, 4, "f : f32, g : f32, h : f32, i : f32", "f32", "f", 16}};
std::string computeShader = CreateComputeShaderWithBindings(bindings); std::string computeShader = CreateComputeShaderWithBindings(bindings);
std::string vertexShader = CreateVertexShaderWithBindings({}); std::string vertexShader = CreateVertexShaderWithBindings({});
@ -457,7 +459,7 @@ TEST_F(MinBufferSizeDrawTimeValidationTests, UnorderedBindings) {
wgpu::ComputePipeline computePipeline = CreateComputePipeline({layout}, computeShader); wgpu::ComputePipeline computePipeline = CreateComputePipeline({layout}, computeShader);
wgpu::RenderPipeline renderPipeline = CreateRenderPipeline({layout}, vertexShader, fragShader); wgpu::RenderPipeline renderPipeline = CreateRenderPipeline({layout}, vertexShader, fragShader);
CheckSizeBounds({8, 4, 12}, [&](const std::vector<uint64_t>& sizes, bool expectation) { CheckSizeBounds({8, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
wgpu::BindGroup bindGroup = CreateBindGroup(layout, bindings, sizes); wgpu::BindGroup bindGroup = CreateBindGroup(layout, bindings, sizes);
TestDispatch(computePipeline, {bindGroup}, expectation); TestDispatch(computePipeline, {bindGroup}, expectation);
TestDraw(renderPipeline, {bindGroup}, expectation); TestDraw(renderPipeline, {bindGroup}, expectation);
@ -466,11 +468,12 @@ TEST_F(MinBufferSizeDrawTimeValidationTests, UnorderedBindings) {
// Draw time validation works for multiple bind groups // Draw time validation works for multiple bind groups
TEST_F(MinBufferSizeDrawTimeValidationTests, MultipleGroups) { TEST_F(MinBufferSizeDrawTimeValidationTests, MultipleGroups) {
std::vector<BindingDescriptor> bg0Bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8}, std::vector<BindingDescriptor> bg0Bindings = {
{0, 1, "c : f32,", "f32", "c", 4}}; {0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
{0, 1, "d : f32, e : f32", "f32", "d", 8}};
std::vector<BindingDescriptor> bg1Bindings = { std::vector<BindingDescriptor> bg1Bindings = {
{1, 0, "d : f32, e : f32, f : f32,", "f32", "e", 12}, {1, 0, "f : f32, g : f32, h : f32,", "f32", "f", 12},
{1, 1, "g : mat2x2<f32>,", "mat2x2<f32>", "g", 16}}; {1, 1, "i : mat2x2<f32>,", "mat2x2<f32>", "i", 16}};
std::vector<BindingDescriptor> bindings = CombineBindings({bg0Bindings, bg1Bindings}); std::vector<BindingDescriptor> bindings = CombineBindings({bg0Bindings, bg1Bindings});
std::string computeShader = CreateComputeShaderWithBindings(bindings); std::string computeShader = CreateComputeShaderWithBindings(bindings);
@ -485,7 +488,7 @@ TEST_F(MinBufferSizeDrawTimeValidationTests, MultipleGroups) {
wgpu::RenderPipeline renderPipeline = wgpu::RenderPipeline renderPipeline =
CreateRenderPipeline({layout0, layout1}, vertexShader, fragShader); CreateRenderPipeline({layout0, layout1}, vertexShader, fragShader);
CheckSizeBounds({8, 4, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) { CheckSizeBounds({12, 8, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
wgpu::BindGroup bindGroup0 = CreateBindGroup(layout0, bg0Bindings, {sizes[0], sizes[1]}); wgpu::BindGroup bindGroup0 = CreateBindGroup(layout0, bg0Bindings, {sizes[0], sizes[1]});
wgpu::BindGroup bindGroup1 = CreateBindGroup(layout0, bg0Bindings, {sizes[2], sizes[3]}); wgpu::BindGroup bindGroup1 = CreateBindGroup(layout0, bg0Bindings, {sizes[2], sizes[3]});
TestDispatch(computePipeline, {bindGroup0, bindGroup1}, expectation); TestDispatch(computePipeline, {bindGroup0, bindGroup1}, expectation);

View File

@ -769,6 +769,16 @@ crbug.com/1357206 [ nvidia-0x2184 win10 ] worker_webgpu:api,validation,buffer,ma
################################################################################ ################################################################################
crbug.com/dawn/1539 [ ubuntu ] webgpu:api,validation,render_pipeline,fragment_state:pipeline_output_targets:isAsync=true;* [ Failure ] crbug.com/dawn/1539 [ ubuntu ] webgpu:api,validation,render_pipeline,fragment_state:pipeline_output_targets:isAsync=true;* [ Failure ]
################################################################################
# storage buffer binding size failures
################################################################################
crbug.com/dawn/1542 webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="read-only-storage" [ Failure ]
crbug.com/dawn/1542 webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="storage" [ Failure ]
crbug.com/dawn/1542 webgpu:api,validation,createBindGroup:minBindingSize: [ Failure ]
crbug.com/dawn/1542 webgpu:api,validation,encoding,cmds,setBindGroup:buffer_dynamic_offsets:type="read-only-storage";* [ Failure ]
crbug.com/dawn/1542 webgpu:api,validation,encoding,cmds,setBindGroup:buffer_dynamic_offsets:type="storage";* [ Failure ]
crbug.com/dawn/1542 webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_match_expectations_in_pass_encoder:* [ Failure ]
################################################################################ ################################################################################
# untriaged failures # untriaged failures
# KEEP # KEEP
@ -788,8 +798,6 @@ crbug.com/dawn/0000 [ dawn-backend-validation nvidia-0x2184 target-cpu-64 win10
# New failures. Please triage: # New failures. Please triage:
crbug.com/dawn/0000 [ intel-gen-9 win10 ] webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="2d" [ Failure ] crbug.com/dawn/0000 [ intel-gen-9 win10 ] webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="2d" [ Failure ]
crbug.com/dawn/0000 webgpu:api,validation,compute_pipeline:overrides,workgroup_size,limits,* [ Failure ] crbug.com/dawn/0000 webgpu:api,validation,compute_pipeline:overrides,workgroup_size,limits,* [ Failure ]
crbug.com/dawn/0000 [ win10 ] webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="read-only-storage" [ Failure ]
crbug.com/dawn/0000 [ win10 ] webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="storage" [ Failure ]
crbug.com/dawn/0000 webgpu:api,validation,createBindGroupLayout:multisampled_validation:viewDimension="2d" [ Failure ] crbug.com/dawn/0000 webgpu:api,validation,createBindGroupLayout:multisampled_validation:viewDimension="2d" [ Failure ]
crbug.com/dawn/0000 webgpu:api,validation,createBindGroupLayout:multisampled_validation:viewDimension="_undef_" [ Failure ] crbug.com/dawn/0000 webgpu:api,validation,createBindGroupLayout:multisampled_validation:viewDimension="_undef_" [ Failure ]
crbug.com/dawn/0000 [ nvidia-0x2184 target-cpu-32 webgpu-adapter-default win10 ] webgpu:shader,execution,shader_io,compute_builtins:inputs:method="mixed";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1} [ Failure ] crbug.com/dawn/0000 [ nvidia-0x2184 target-cpu-32 webgpu-adapter-default win10 ] webgpu:shader,execution,shader_io,compute_builtins:inputs:method="mixed";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1} [ Failure ]