Raise maxStorageTexturesPerShaderStage to 8
The higher tier for this limit is available on all D3D12, all Metal,
and most Vulkan devices.
Bug: dawn:685
Change-Id: Ic2a39ad7908ea178e7aac48b7bb54b262d7039cf
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121543
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Shrek Shao <shrekshao@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/common/Constants.h b/src/dawn/common/Constants.h
index ca4c3b6..3604b5c 100644
--- a/src/dawn/common/Constants.h
+++ b/src/dawn/common/Constants.h
@@ -31,11 +31,11 @@
static constexpr uint64_t kAssumedMaxBufferSize =
0x80000000u; // Use 2 GB when the limit is unavailable
-// Per stage limits
+// Per stage maximum limits used to optimized Dawn internals.
static constexpr uint32_t kMaxSampledTexturesPerShaderStage = 16;
static constexpr uint32_t kMaxSamplersPerShaderStage = 16;
static constexpr uint32_t kMaxStorageBuffersPerShaderStage = 8;
-static constexpr uint32_t kMaxStorageTexturesPerShaderStage = 4;
+static constexpr uint32_t kMaxStorageTexturesPerShaderStage = 8;
static constexpr uint32_t kMaxUniformBuffersPerShaderStage = 12;
// Indirect command sizes
diff --git a/src/dawn/native/BindingInfo.cpp b/src/dawn/native/BindingInfo.cpp
index ba96937..24ce3f5 100644
--- a/src/dawn/native/BindingInfo.cpp
+++ b/src/dawn/native/BindingInfo.cpp
@@ -112,80 +112,85 @@
limits.v1.maxDynamicStorageBuffersPerPipelineLayout);
for (SingleShaderStage stage : IterateStages(kAllStages)) {
- DAWN_INVALID_IF(
- bindingCounts.perStage[stage].sampledTextureCount > kMaxSampledTexturesPerShaderStage,
- "The number of sampled textures (%u) in the %s stage exceeds the maximum "
- "per-stage limit (%u).",
- bindingCounts.perStage[stage].sampledTextureCount, stage,
- kMaxSampledTexturesPerShaderStage);
+ DAWN_INVALID_IF(bindingCounts.perStage[stage].sampledTextureCount >
+ limits.v1.maxSampledTexturesPerShaderStage,
+ "The number of sampled textures (%u) in the %s stage exceeds the maximum "
+ "per-stage limit (%u).",
+ bindingCounts.perStage[stage].sampledTextureCount, stage,
+ limits.v1.maxSampledTexturesPerShaderStage);
// The per-stage number of external textures is bound by the maximum sampled textures
// per stage.
- DAWN_INVALID_IF(bindingCounts.perStage[stage].externalTextureCount >
- kMaxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture,
- "The number of external textures (%u) in the %s stage exceeds the maximum "
- "per-stage limit (%u).",
- bindingCounts.perStage[stage].externalTextureCount, stage,
- kMaxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture);
+ DAWN_INVALID_IF(
+ bindingCounts.perStage[stage].externalTextureCount >
+ limits.v1.maxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture,
+ "The number of external textures (%u) in the %s stage exceeds the maximum "
+ "per-stage limit (%u).",
+ bindingCounts.perStage[stage].externalTextureCount, stage,
+ limits.v1.maxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture);
DAWN_INVALID_IF(
bindingCounts.perStage[stage].sampledTextureCount +
(bindingCounts.perStage[stage].externalTextureCount *
kSampledTexturesPerExternalTexture) >
- kMaxSampledTexturesPerShaderStage,
+ limits.v1.maxSampledTexturesPerShaderStage,
"The combination of sampled textures (%u) and external textures (%u) in the %s "
"stage exceeds the maximum per-stage limit (%u).",
bindingCounts.perStage[stage].sampledTextureCount,
bindingCounts.perStage[stage].externalTextureCount, stage,
- kMaxSampledTexturesPerShaderStage);
+ limits.v1.maxSampledTexturesPerShaderStage);
DAWN_INVALID_IF(
- bindingCounts.perStage[stage].samplerCount > kMaxSamplersPerShaderStage,
+ bindingCounts.perStage[stage].samplerCount > limits.v1.maxSamplersPerShaderStage,
"The number of samplers (%u) in the %s stage exceeds the maximum per-stage limit "
"(%u).",
- bindingCounts.perStage[stage].samplerCount, stage, kMaxSamplersPerShaderStage);
+ bindingCounts.perStage[stage].samplerCount, stage, limits.v1.maxSamplersPerShaderStage);
DAWN_INVALID_IF(
bindingCounts.perStage[stage].samplerCount +
(bindingCounts.perStage[stage].externalTextureCount *
kSamplersPerExternalTexture) >
- kMaxSamplersPerShaderStage,
+ limits.v1.maxSamplersPerShaderStage,
"The combination of samplers (%u) and external textures (%u) in the %s stage "
"exceeds the maximum per-stage limit (%u).",
bindingCounts.perStage[stage].samplerCount,
- bindingCounts.perStage[stage].externalTextureCount, stage, kMaxSamplersPerShaderStage);
+ bindingCounts.perStage[stage].externalTextureCount, stage,
+ limits.v1.maxSamplersPerShaderStage);
DAWN_INVALID_IF(
- bindingCounts.perStage[stage].storageBufferCount > kMaxStorageBuffersPerShaderStage,
+ bindingCounts.perStage[stage].storageBufferCount >
+ limits.v1.maxStorageBuffersPerShaderStage,
"The number of storage buffers (%u) in the %s stage exceeds the maximum per-stage "
"limit (%u).",
bindingCounts.perStage[stage].storageBufferCount, stage,
- kMaxStorageBuffersPerShaderStage);
+ limits.v1.maxStorageBuffersPerShaderStage);
DAWN_INVALID_IF(
- bindingCounts.perStage[stage].storageTextureCount > kMaxStorageTexturesPerShaderStage,
+ bindingCounts.perStage[stage].storageTextureCount >
+ limits.v1.maxStorageTexturesPerShaderStage,
"The number of storage textures (%u) in the %s stage exceeds the maximum per-stage "
"limit (%u).",
bindingCounts.perStage[stage].storageTextureCount, stage,
- kMaxStorageTexturesPerShaderStage);
+ limits.v1.maxStorageTexturesPerShaderStage);
DAWN_INVALID_IF(
- bindingCounts.perStage[stage].uniformBufferCount > kMaxUniformBuffersPerShaderStage,
+ bindingCounts.perStage[stage].uniformBufferCount >
+ limits.v1.maxUniformBuffersPerShaderStage,
"The number of uniform buffers (%u) in the %s stage exceeds the maximum per-stage "
"limit (%u).",
bindingCounts.perStage[stage].uniformBufferCount, stage,
- kMaxUniformBuffersPerShaderStage);
+ limits.v1.maxUniformBuffersPerShaderStage);
DAWN_INVALID_IF(
bindingCounts.perStage[stage].uniformBufferCount +
(bindingCounts.perStage[stage].externalTextureCount *
kUniformsPerExternalTexture) >
- kMaxUniformBuffersPerShaderStage,
+ limits.v1.maxUniformBuffersPerShaderStage,
"The combination of uniform buffers (%u) and external textures (%u) in the %s "
"stage exceeds the maximum per-stage limit (%u).",
bindingCounts.perStage[stage].uniformBufferCount,
bindingCounts.perStage[stage].externalTextureCount, stage,
- kMaxUniformBuffersPerShaderStage);
+ limits.v1.maxUniformBuffersPerShaderStage);
}
return {};
diff --git a/src/dawn/native/Limits.cpp b/src/dawn/native/Limits.cpp
index a17c355..fb14fd2 100644
--- a/src/dawn/native/Limits.cpp
+++ b/src/dawn/native/Limits.cpp
@@ -38,6 +38,11 @@
#define LIMITS_RESOURCE_BINDINGS(X) \
X(Maximum, maxDynamicUniformBuffersPerPipelineLayout, 8, 10) \
X(Maximum, maxDynamicStorageBuffersPerPipelineLayout, 4, 8) \
+ X(Maximum, maxSampledTexturesPerShaderStage, 16, 16) \
+ X(Maximum, maxSamplersPerShaderStage, 16, 16) \
+ X(Maximum, maxStorageBuffersPerShaderStage, 8, 8) \
+ X(Maximum, maxStorageTexturesPerShaderStage, 4, 8) \
+ X(Maximum, maxUniformBuffersPerShaderStage, 12, 12)
// TODO(crbug.com/dawn/685):
// These limits don't have tiers yet. Define two tiers with the same values since the macros
@@ -49,11 +54,6 @@
X(Maximum, maxTextureArrayLayers, 256, 256) \
X(Maximum, maxBindGroups, 4, 4) \
X(Maximum, maxBindingsPerBindGroup, 640, 640) \
- X(Maximum, maxSampledTexturesPerShaderStage, 16, 16) \
- X(Maximum, maxSamplersPerShaderStage, 16, 16) \
- X(Maximum, maxStorageBuffersPerShaderStage, 8, 8) \
- X(Maximum, maxStorageTexturesPerShaderStage, 4, 4) \
- X(Maximum, maxUniformBuffersPerShaderStage, 12, 12) \
X(Maximum, maxUniformBufferBindingSize, 65536, 65536) \
X(Alignment, minUniformBufferOffsetAlignment, 256, 256) \
X(Alignment, minStorageBufferOffsetAlignment, 256, 256) \
diff --git a/src/dawn/tests/end2end/BindGroupTests.cpp b/src/dawn/tests/end2end/BindGroupTests.cpp
index a7b6e0d..2117c2e 100644
--- a/src/dawn/tests/end2end/BindGroupTests.cpp
+++ b/src/dawn/tests/end2end/BindGroupTests.cpp
@@ -1427,150 +1427,6 @@
EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, renderPass.color, 0, 0);
}
-// Test that creating a large bind group, with each binding type at the max count, works and can be
-// used correctly. The test loads a different value from each binding, and writes 1 to a storage
-// buffer if all values are correct.
-TEST_P(BindGroupTests, ReallyLargeBindGroup) {
- DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
- std::ostringstream interface;
- std::ostringstream body;
- uint32_t binding = 0;
- uint32_t expectedValue = 42;
-
- wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
-
- auto CreateTextureWithRedData = [&](wgpu::TextureFormat format, uint32_t value,
- wgpu::TextureUsage usage) {
- wgpu::TextureDescriptor textureDesc = {};
- textureDesc.usage = wgpu::TextureUsage::CopyDst | usage;
- textureDesc.size = {1, 1, 1};
- textureDesc.format = format;
- wgpu::Texture texture = device.CreateTexture(&textureDesc);
-
- if (format == wgpu::TextureFormat::R8Unorm) {
- ASSERT(expectedValue < 255u);
- }
- wgpu::Buffer textureData =
- utils::CreateBufferFromData(device, wgpu::BufferUsage::CopySrc, {value});
-
- wgpu::ImageCopyBuffer imageCopyBuffer = {};
- imageCopyBuffer.buffer = textureData;
- imageCopyBuffer.layout.bytesPerRow = 256;
-
- wgpu::ImageCopyTexture imageCopyTexture = {};
- imageCopyTexture.texture = texture;
-
- wgpu::Extent3D copySize = {1, 1, 1};
-
- commandEncoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyTexture, ©Size);
- return texture;
- };
-
- std::vector<wgpu::BindGroupEntry> bgEntries;
- static_assert(kMaxSampledTexturesPerShaderStage == kMaxSamplersPerShaderStage,
- "Please update this test");
- for (uint32_t i = 0; i < kMaxSampledTexturesPerShaderStage; ++i) {
- wgpu::Texture texture = CreateTextureWithRedData(
- wgpu::TextureFormat::R8Unorm, expectedValue, wgpu::TextureUsage::TextureBinding);
- bgEntries.push_back({nullptr, binding, nullptr, 0, 0, nullptr, texture.CreateView()});
-
- interface << "@group(0) @binding(" << binding++ << ") "
- << "var tex" << i << " : texture_2d<f32>;\n";
-
- bgEntries.push_back({nullptr, binding, nullptr, 0, 0, device.CreateSampler(), nullptr});
-
- interface << "@group(0) @binding(" << binding++ << ")"
- << "var samp" << i << " : sampler;\n";
-
- body << "if (abs(textureSampleLevel(tex" << i << ", samp" << i
- << ", vec2f(0.5, 0.5), 0.0).r - " << expectedValue++ << ".0 / 255.0) > 0.0001) {\n";
- body << " return;\n";
- body << "}\n";
- }
- for (uint32_t i = 0; i < kMaxStorageTexturesPerShaderStage; ++i) {
- wgpu::Texture texture = CreateTextureWithRedData(
- wgpu::TextureFormat::R32Uint, expectedValue, wgpu::TextureUsage::StorageBinding);
- bgEntries.push_back({nullptr, binding, nullptr, 0, 0, nullptr, texture.CreateView()});
-
- interface << "@group(0) @binding(" << binding++ << ") "
- << "var image" << i << " : texture_storage_2d<r32uint, write>;\n";
-
- body << "_ = image" << i << ";";
- }
-
- for (uint32_t i = 0; i < kMaxUniformBuffersPerShaderStage; ++i) {
- wgpu::Buffer buffer = utils::CreateBufferFromData<uint32_t>(
- device, wgpu::BufferUsage::Uniform, {expectedValue, 0, 0, 0});
- bgEntries.push_back({nullptr, binding, buffer, 0, 4 * sizeof(uint32_t), nullptr, nullptr});
-
- interface << "struct UniformBuffer" << i << R"({
- value : u32
- }
- )";
- interface << "@group(0) @binding(" << binding++ << ") "
- << "var<uniform> ubuf" << i << " : UniformBuffer" << i << ";\n";
-
- body << "if (ubuf" << i << ".value != " << expectedValue++ << "u) {\n";
- body << " return;\n";
- body << "}\n";
- }
- // Save one storage buffer for writing the result
- for (uint32_t i = 0; i < kMaxStorageBuffersPerShaderStage - 1; ++i) {
- wgpu::Buffer buffer = utils::CreateBufferFromData<uint32_t>(
- device, wgpu::BufferUsage::Storage, {expectedValue});
- bgEntries.push_back({nullptr, binding, buffer, 0, sizeof(uint32_t), nullptr, nullptr});
-
- interface << "struct ReadOnlyStorageBuffer" << i << R"({
- value : u32
- }
- )";
- interface << "@group(0) @binding(" << binding++ << ") "
- << "var<storage, read> sbuf" << i << " : ReadOnlyStorageBuffer" << i << ";\n";
-
- body << "if (sbuf" << i << ".value != " << expectedValue++ << "u) {\n";
- body << " return;\n";
- body << "}\n";
- }
-
- wgpu::Buffer result = utils::CreateBufferFromData<uint32_t>(
- device, wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc, {0});
- bgEntries.push_back({nullptr, binding, result, 0, sizeof(uint32_t), nullptr, nullptr});
-
- interface << R"(struct ReadWriteStorageBuffer{
- value : u32
- }
- )";
- interface << "@group(0) @binding(" << binding++ << ") "
- << "var<storage, read_write> result : ReadWriteStorageBuffer;\n";
-
- body << "result.value = 1u;\n";
-
- std::string shader =
- interface.str() + "@compute @workgroup_size(1) fn main() {\n" + body.str() + "}\n";
- wgpu::ComputePipelineDescriptor cpDesc;
- cpDesc.compute.module = utils::CreateShaderModule(device, shader.c_str());
- cpDesc.compute.entryPoint = "main";
- wgpu::ComputePipeline cp = device.CreateComputePipeline(&cpDesc);
-
- wgpu::BindGroupDescriptor bgDesc = {};
- bgDesc.layout = cp.GetBindGroupLayout(0);
- bgDesc.entryCount = static_cast<uint32_t>(bgEntries.size());
- bgDesc.entries = bgEntries.data();
-
- wgpu::BindGroup bg = device.CreateBindGroup(&bgDesc);
-
- wgpu::ComputePassEncoder pass = commandEncoder.BeginComputePass();
- pass.SetPipeline(cp);
- pass.SetBindGroup(0, bg);
- pass.DispatchWorkgroups(1, 1, 1);
- pass.End();
-
- wgpu::CommandBuffer commands = commandEncoder.Finish();
- queue.Submit(1, &commands);
-
- EXPECT_BUFFER_U32_EQ(1, result, 0);
-}
-
// This is a regression test for crbug.com/dawn/319 where creating a bind group with a
// destroyed resource would crash the backend.
TEST_P(BindGroupTests, CreateWithDestroyedResource) {
diff --git a/src/dawn/tests/end2end/MaxLimitTests.cpp b/src/dawn/tests/end2end/MaxLimitTests.cpp
index 2e3320e..1654bb9 100644
--- a/src/dawn/tests/end2end/MaxLimitTests.cpp
+++ b/src/dawn/tests/end2end/MaxLimitTests.cpp
@@ -392,6 +392,152 @@
EXPECT_TEXTURE_EQ(&expected, renderTarget, {0, 0}, {1, 1});
}
+// Test that creating a large bind group, with each binding type at the max count, works and can be
+// used correctly. The test loads a different value from each binding, and writes 1 to a storage
+// buffer if all values are correct.
+TEST_P(MaxLimitTests, ReallyLargeBindGroup) {
+ DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
+ wgpu::Limits limits = GetSupportedLimits().limits;
+
+ std::ostringstream interface;
+ std::ostringstream body;
+ uint32_t binding = 0;
+ uint32_t expectedValue = 42;
+
+ wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
+
+ auto CreateTextureWithRedData = [&](wgpu::TextureFormat format, uint32_t value,
+ wgpu::TextureUsage usage) {
+ wgpu::TextureDescriptor textureDesc = {};
+ textureDesc.usage = wgpu::TextureUsage::CopyDst | usage;
+ textureDesc.size = {1, 1, 1};
+ textureDesc.format = format;
+ wgpu::Texture texture = device.CreateTexture(&textureDesc);
+
+ if (format == wgpu::TextureFormat::R8Unorm) {
+ ASSERT(expectedValue < 255u);
+ }
+ wgpu::Buffer textureData =
+ utils::CreateBufferFromData(device, wgpu::BufferUsage::CopySrc, {value});
+
+ wgpu::ImageCopyBuffer imageCopyBuffer = {};
+ imageCopyBuffer.buffer = textureData;
+ imageCopyBuffer.layout.bytesPerRow = 256;
+
+ wgpu::ImageCopyTexture imageCopyTexture = {};
+ imageCopyTexture.texture = texture;
+
+ wgpu::Extent3D copySize = {1, 1, 1};
+
+ commandEncoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyTexture, ©Size);
+ return texture;
+ };
+
+ std::vector<wgpu::BindGroupEntry> bgEntries;
+ for (uint32_t i = 0;
+ i < std::min(limits.maxSampledTexturesPerShaderStage, limits.maxSamplersPerShaderStage);
+ ++i) {
+ wgpu::Texture texture = CreateTextureWithRedData(
+ wgpu::TextureFormat::R8Unorm, expectedValue, wgpu::TextureUsage::TextureBinding);
+ bgEntries.push_back({nullptr, binding, nullptr, 0, 0, nullptr, texture.CreateView()});
+
+ interface << "@group(0) @binding(" << binding++ << ") "
+ << "var tex" << i << " : texture_2d<f32>;\n";
+
+ bgEntries.push_back({nullptr, binding, nullptr, 0, 0, device.CreateSampler(), nullptr});
+
+ interface << "@group(0) @binding(" << binding++ << ")"
+ << "var samp" << i << " : sampler;\n";
+
+ body << "if (abs(textureSampleLevel(tex" << i << ", samp" << i
+ << ", vec2f(0.5, 0.5), 0.0).r - " << expectedValue++ << ".0 / 255.0) > 0.0001) {\n";
+ body << " return;\n";
+ body << "}\n";
+ }
+ for (uint32_t i = 0; i < limits.maxStorageTexturesPerShaderStage; ++i) {
+ wgpu::Texture texture = CreateTextureWithRedData(
+ wgpu::TextureFormat::R32Uint, expectedValue, wgpu::TextureUsage::StorageBinding);
+ bgEntries.push_back({nullptr, binding, nullptr, 0, 0, nullptr, texture.CreateView()});
+
+ interface << "@group(0) @binding(" << binding++ << ") "
+ << "var image" << i << " : texture_storage_2d<r32uint, write>;\n";
+
+ body << "_ = image" << i << ";";
+ }
+
+ for (uint32_t i = 0; i < limits.maxUniformBuffersPerShaderStage; ++i) {
+ wgpu::Buffer buffer = utils::CreateBufferFromData<uint32_t>(
+ device, wgpu::BufferUsage::Uniform, {expectedValue, 0, 0, 0});
+ bgEntries.push_back({nullptr, binding, buffer, 0, 4 * sizeof(uint32_t), nullptr, nullptr});
+
+ interface << "struct UniformBuffer" << i << R"({
+ value : u32
+ }
+ )";
+ interface << "@group(0) @binding(" << binding++ << ") "
+ << "var<uniform> ubuf" << i << " : UniformBuffer" << i << ";\n";
+
+ body << "if (ubuf" << i << ".value != " << expectedValue++ << "u) {\n";
+ body << " return;\n";
+ body << "}\n";
+ }
+ // Save one storage buffer for writing the result
+ for (uint32_t i = 0; i < limits.maxStorageBuffersPerShaderStage - 1; ++i) {
+ wgpu::Buffer buffer = utils::CreateBufferFromData<uint32_t>(
+ device, wgpu::BufferUsage::Storage, {expectedValue});
+ bgEntries.push_back({nullptr, binding, buffer, 0, sizeof(uint32_t), nullptr, nullptr});
+
+ interface << "struct ReadOnlyStorageBuffer" << i << R"({
+ value : u32
+ }
+ )";
+ interface << "@group(0) @binding(" << binding++ << ") "
+ << "var<storage, read> sbuf" << i << " : ReadOnlyStorageBuffer" << i << ";\n";
+
+ body << "if (sbuf" << i << ".value != " << expectedValue++ << "u) {\n";
+ body << " return;\n";
+ body << "}\n";
+ }
+
+ wgpu::Buffer result = utils::CreateBufferFromData<uint32_t>(
+ device, wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc, {0});
+ bgEntries.push_back({nullptr, binding, result, 0, sizeof(uint32_t), nullptr, nullptr});
+
+ interface << R"(struct ReadWriteStorageBuffer{
+ value : u32
+ }
+ )";
+ interface << "@group(0) @binding(" << binding++ << ") "
+ << "var<storage, read_write> result : ReadWriteStorageBuffer;\n";
+
+ body << "result.value = 1u;\n";
+
+ std::string shader =
+ interface.str() + "@compute @workgroup_size(1) fn main() {\n" + body.str() + "}\n";
+ wgpu::ComputePipelineDescriptor cpDesc;
+ cpDesc.compute.module = utils::CreateShaderModule(device, shader.c_str());
+ cpDesc.compute.entryPoint = "main";
+ wgpu::ComputePipeline cp = device.CreateComputePipeline(&cpDesc);
+
+ wgpu::BindGroupDescriptor bgDesc = {};
+ bgDesc.layout = cp.GetBindGroupLayout(0);
+ bgDesc.entryCount = static_cast<uint32_t>(bgEntries.size());
+ bgDesc.entries = bgEntries.data();
+
+ wgpu::BindGroup bg = device.CreateBindGroup(&bgDesc);
+
+ wgpu::ComputePassEncoder pass = commandEncoder.BeginComputePass();
+ pass.SetPipeline(cp);
+ pass.SetBindGroup(0, bg);
+ pass.DispatchWorkgroups(1, 1, 1);
+ pass.End();
+
+ wgpu::CommandBuffer commands = commandEncoder.Finish();
+ queue.Submit(1, &commands);
+
+ EXPECT_BUFFER_U32_EQ(1, result, 0);
+}
+
DAWN_INSTANTIATE_TEST(MaxLimitTests,
D3D12Backend(),
MetalBackend(),
diff --git a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
index 4e8c069..87c0f6f 100644
--- a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -1293,25 +1293,32 @@
wgpu::BindGroupLayoutEntry otherEntry;
};
+ wgpu::Limits limits = GetSupportedLimits().limits;
+
std::array<TestInfo, 7> kTestInfos = {
- TestInfo{kMaxSampledTexturesPerShaderStage, BGLEntryType(wgpu::TextureSampleType::Float),
+ TestInfo{limits.maxSampledTexturesPerShaderStage,
+ BGLEntryType(wgpu::TextureSampleType::Float),
BGLEntryType(wgpu::BufferBindingType::Uniform)},
- TestInfo{kMaxSamplersPerShaderStage, BGLEntryType(wgpu::SamplerBindingType::Filtering),
+ TestInfo{limits.maxSamplersPerShaderStage,
+ BGLEntryType(wgpu::SamplerBindingType::Filtering),
BGLEntryType(wgpu::BufferBindingType::Uniform)},
- TestInfo{kMaxSamplersPerShaderStage, BGLEntryType(wgpu::SamplerBindingType::Comparison),
+ TestInfo{limits.maxSamplersPerShaderStage,
+ BGLEntryType(wgpu::SamplerBindingType::Comparison),
BGLEntryType(wgpu::BufferBindingType::Uniform)},
- TestInfo{kMaxStorageBuffersPerShaderStage, BGLEntryType(wgpu::BufferBindingType::Storage),
+ TestInfo{limits.maxStorageBuffersPerShaderStage,
+ BGLEntryType(wgpu::BufferBindingType::Storage),
BGLEntryType(wgpu::BufferBindingType::Uniform)},
TestInfo{
- kMaxStorageTexturesPerShaderStage,
+ limits.maxStorageTexturesPerShaderStage,
BGLEntryType(wgpu::StorageTextureAccess::WriteOnly, wgpu::TextureFormat::RGBA8Unorm),
BGLEntryType(wgpu::BufferBindingType::Uniform)},
- TestInfo{kMaxUniformBuffersPerShaderStage, BGLEntryType(wgpu::BufferBindingType::Uniform),
+ TestInfo{limits.maxUniformBuffersPerShaderStage,
+ BGLEntryType(wgpu::BufferBindingType::Uniform),
BGLEntryType(wgpu::TextureSampleType::Float)},
// External textures use multiple bindings (3 sampled textures, 1 sampler, 1 uniform buffer)
// that count towards the per stage binding limits. The number of external textures are
// currently restricted by the maximum number of sampled textures.
- TestInfo{kMaxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture,
+ TestInfo{limits.maxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture,
BGLEntryType(&utils::kExternalTextureBindingLayout),
BGLEntryType(wgpu::BufferBindingType::Uniform)}};
@@ -1388,14 +1395,16 @@
wgpu::BindGroupLayoutEntry otherEntry;
};
+ wgpu::Limits limits = GetSupportedLimits().limits;
+
std::array<TestInfo, 3> kTestInfos = {
- TestInfo{kMaxSampledTexturesPerShaderStage, kSampledTexturesPerExternalTexture,
+ TestInfo{limits.maxSampledTexturesPerShaderStage, kSampledTexturesPerExternalTexture,
BGLEntryType(wgpu::TextureSampleType::Float),
BGLEntryType(wgpu::BufferBindingType::Uniform)},
- TestInfo{kMaxSamplersPerShaderStage, kSamplersPerExternalTexture,
+ TestInfo{limits.maxSamplersPerShaderStage, kSamplersPerExternalTexture,
BGLEntryType(wgpu::SamplerBindingType::Filtering),
BGLEntryType(wgpu::BufferBindingType::Uniform)},
- TestInfo{kMaxUniformBuffersPerShaderStage, kUniformsPerExternalTexture,
+ TestInfo{limits.maxUniformBuffersPerShaderStage, kUniformsPerExternalTexture,
BGLEntryType(wgpu::BufferBindingType::Uniform),
BGLEntryType(wgpu::TextureSampleType::Float)},
};
@@ -1480,8 +1489,10 @@
// In this test, we use all the same shader stage. Ensure that this does not exceed the
// per-stage limit.
- ASSERT(limits.maxDynamicUniformBuffersPerPipelineLayout <= kMaxUniformBuffersPerShaderStage);
- ASSERT(limits.maxDynamicStorageBuffersPerPipelineLayout <= kMaxStorageBuffersPerShaderStage);
+ ASSERT(limits.maxDynamicUniformBuffersPerPipelineLayout <=
+ limits.maxUniformBuffersPerShaderStage);
+ ASSERT(limits.maxDynamicStorageBuffersPerPipelineLayout <=
+ limits.maxStorageBuffersPerShaderStage);
for (uint32_t i = 0; i < limits.maxDynamicUniformBuffersPerPipelineLayout; ++i) {
maxUniformDB.push_back(utils::BindingLayoutEntryInitializationHelper(