[Static samplers] Add ability to chain static sampler in binding layout
This CL adds the ability to chain a static sampler in a sampler binding
layout, as well as initial validation and testing of static samplers:
* They can be chained only if the relevant feature is enabled
* If a static sampler is chained, it must contain a valid sampler object
Nothing yet uses static samplers - that will be for followup CLs.
Followup work will also add validation of the sampler object against the
type specified in the sampler binding layout and tests of this
validation.
Change-Id: Ie5379590e36ab741ed659a07f92907ff471d6227
Bug: dawn:2463
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/179704
Commit-Queue: Colin Blundell <blundell@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Nicolette Prevost <nicolettep@google.com>
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 0c1dc75..64491b3 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -375,7 +375,15 @@
{"name": "type", "type": "sampler binding type", "default": "undefined"}
]
},
-
+ "static sampler": {
+ "category": "structure",
+ "chained": "in",
+ "chain roots": ["sampler binding layout"],
+ "tags": ["dawn"],
+ "members": [
+ {"name": "sampler", "type": "sampler"}
+ ]
+ },
"texture sample type": {
"category": "enum",
"values": [
@@ -3680,7 +3688,8 @@
{"value": 1211, "name": "shared fence DXGI shared handle export info", "tags": ["dawn", "native"]},
{"value": 1212, "name": "shared fence MTL shared event descriptor", "tags": ["dawn", "native"]},
{"value": 1213, "name": "shared fence MTL shared event export info", "tags": ["dawn", "native"]},
- {"value": 1214, "name": "shared buffer memory D3D12 resource descriptor", "tags": ["dawn", "native"]}
+ {"value": 1214, "name": "shared buffer memory D3D12 resource descriptor", "tags": ["dawn", "native"]},
+ {"value": 1215, "name": "static sampler", "tags": ["dawn"]}
]
},
"texture": {
diff --git a/src/dawn/native/BindGroupLayoutInternal.cpp b/src/dawn/native/BindGroupLayoutInternal.cpp
index 89b3c1b..46fc853 100644
--- a/src/dawn/native/BindGroupLayoutInternal.cpp
+++ b/src/dawn/native/BindGroupLayoutInternal.cpp
@@ -40,10 +40,13 @@
#include "dawn/common/MatchVariant.h"
#include "dawn/native/ChainUtils.h"
#include "dawn/native/Device.h"
+#include "dawn/native/Instance.h"
#include "dawn/native/ObjectBase.h"
#include "dawn/native/ObjectContentHasher.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/PerStage.h"
+#include "dawn/native/PhysicalDevice.h"
+#include "dawn/native/Sampler.h"
#include "dawn/native/ValidationUtils_autogen.h"
namespace dawn::native {
@@ -119,6 +122,21 @@
if (entry->sampler.type != wgpu::SamplerBindingType::Undefined) {
bindingMemberCount++;
DAWN_TRY(ValidateSamplerBindingType(entry->sampler.type));
+
+ UnpackedPtr<SamplerBindingLayout> samplerLayout;
+ DAWN_TRY_ASSIGN(samplerLayout, ValidateAndUnpack(&entry->sampler));
+
+ auto staticSampler = samplerLayout.Get<StaticSampler>();
+ if (staticSampler) {
+ DAWN_INVALID_IF(!device->HasFeature(Feature::StaticSamplers),
+ "Static samplers used without the %s feature enabled.",
+ device->GetPhysicalDevice()
+ ->GetInstance()
+ ->GetFeatureInfo(ToAPI(Feature::StaticSamplers))
+ ->name);
+
+ DAWN_TRY(device->ValidateObject(staticSampler->sampler));
+ }
}
if (entry->texture.sampleType != wgpu::TextureSampleType::Undefined) {
diff --git a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
index 766a1a7..64e01f3 100644
--- a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -1753,6 +1753,90 @@
});
}
+// Tests that chaining an arbitrary struct onto a sampler binding layout raises
+// an error.
+TEST_F(BindGroupLayoutValidationTest, SamplerBindingLayoutInvalidChainedStruct) {
+ wgpu::BindGroupLayoutEntry binding = {};
+ binding.binding = 0;
+ binding.sampler.type = wgpu::SamplerBindingType::Filtering;
+ wgpu::ExternalTextureBindingLayout invalidChainedStruct = {};
+ binding.sampler.nextInChain = &invalidChainedStruct;
+
+ wgpu::BindGroupLayoutDescriptor desc = {};
+ desc.entryCount = 1;
+ desc.entries = &binding;
+
+ ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&desc));
+}
+
+// Tests that creating a bind group layout with a valid static sampler raises an error
+// if the required feature is not enabled.
+TEST_F(BindGroupLayoutValidationTest, StaticSamplerNotSupportedWithoutFeatureEnabled) {
+ wgpu::BindGroupLayoutEntry binding = {};
+ binding.binding = 0;
+ binding.sampler.type = wgpu::SamplerBindingType::Filtering;
+ wgpu::StaticSampler staticSampler = {};
+ staticSampler.sampler = device.CreateSampler();
+ binding.sampler.nextInChain = &staticSampler;
+
+ wgpu::BindGroupLayoutDescriptor desc = {};
+ desc.entryCount = 1;
+ desc.entries = &binding;
+
+ ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&desc));
+}
+
+class BindGroupLayoutWithStaticSamplersValidationTest : public BindGroupLayoutValidationTest {
+ WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
+ wgpu::DeviceDescriptor descriptor) override {
+ wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::StaticSamplers};
+ descriptor.requiredFeatures = requiredFeatures;
+ descriptor.requiredFeatureCount = 1;
+ return dawnAdapter.CreateDevice(&descriptor);
+ }
+};
+
+// Tests that creating a bind group layout with a valid static sampler succeeds if the
+// required feature is enabled.
+TEST_F(BindGroupLayoutWithStaticSamplersValidationTest, StaticSamplerSupportedWhenFeatureEnabled) {
+ wgpu::BindGroupLayoutEntry binding = {};
+ binding.binding = 0;
+ binding.sampler.type = wgpu::SamplerBindingType::Filtering;
+ wgpu::StaticSampler staticSampler = {};
+ staticSampler.sampler = device.CreateSampler();
+ binding.sampler.nextInChain = &staticSampler;
+
+ wgpu::BindGroupLayoutDescriptor desc = {};
+ desc.entryCount = 1;
+ desc.entries = &binding;
+
+ device.CreateBindGroupLayout(&desc);
+}
+
+// Tests that creating a bind group layout with a static sampler that has an
+// invalid sampler object fails.
+TEST_F(BindGroupLayoutWithStaticSamplersValidationTest, StaticSamplerWithInvalidSamplerObject) {
+ wgpu::BindGroupLayoutEntry binding = {};
+ binding.binding = 0;
+ binding.sampler.type = wgpu::SamplerBindingType::Filtering;
+ wgpu::StaticSampler staticSampler = {};
+
+ wgpu::SamplerDescriptor samplerDesc;
+ samplerDesc.minFilter = static_cast<wgpu::FilterMode>(0xFFFFFFFF);
+
+ wgpu::Sampler errorSampler;
+ ASSERT_DEVICE_ERROR(errorSampler = device.CreateSampler(&samplerDesc));
+
+ staticSampler.sampler = errorSampler;
+ binding.sampler.nextInChain = &staticSampler;
+
+ wgpu::BindGroupLayoutDescriptor desc = {};
+ desc.entryCount = 1;
+ desc.entries = &binding;
+
+ ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&desc));
+}
+
constexpr uint32_t kBindingSize = 8;
class SetBindGroupValidationTest : public ValidationTest {