[YCbCr Samplers] Add SamplerYCbCrVulkanDescriptor struct
Add SamplerYCbCrVulkanDescriptor as a chained struct on VulkanBackend.
Also add corresponding logic in ChainUtilsImpl and feature validation
in Sampler.cpp.
Change-Id: I253f30b8b88059fc304d9ef2cd66dc2c92ca9529
Bug: dawn:2476
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/182960
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Saifuddin Hitawala <hitawala@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/include/dawn/native/VulkanBackend.h b/include/dawn/native/VulkanBackend.h
index 0ad734e..0aad920 100644
--- a/include/dawn/native/VulkanBackend.h
+++ b/include/dawn/native/VulkanBackend.h
@@ -82,6 +82,13 @@
using ExternalImageExportInfo::ExternalImageExportInfo;
};
+// Can be chained in WGPUSamplerDescriptor
+struct DAWN_NATIVE_EXPORT SamplerYCbCrVulkanDescriptor : wgpu::ChainedStruct {
+ SamplerYCbCrVulkanDescriptor();
+
+ ::VkSamplerYcbcrConversionCreateInfo vulkanYCbCrInfo;
+};
+
// Can't use DAWN_PLATFORM_IS(LINUX) since header included in both Dawn and Chrome
#ifdef __linux__
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index cd838b2..d226e01 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -3735,7 +3735,8 @@
{"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": 1215, "name": "static sampler binding layout", "tags": ["dawn"]}
+ {"value": 1215, "name": "static sampler binding layout", "tags": ["dawn"]},
+ {"value": 1216, "name": "sampler y cb cr vulkan descriptor", "tags": ["dawn", "native"]}
]
},
"texture": {
diff --git a/src/dawn/native/ChainUtilsImpl.inl b/src/dawn/native/ChainUtilsImpl.inl
index c124da9..8b36ce7 100644
--- a/src/dawn/native/ChainUtilsImpl.inl
+++ b/src/dawn/native/ChainUtilsImpl.inl
@@ -49,6 +49,10 @@
struct RequestAdapterOptionsGetGLProc;
}
+namespace vulkan {
+struct SamplerYCbCrVulkanDescriptor;
+}
+
namespace detail {
template <>
@@ -99,6 +103,16 @@
AdditionalExtensionsList<const d3d12::SharedBufferMemoryD3D12ResourceDescriptor*>;
};
+template <>
+constexpr inline wgpu::SType STypeForImpl<vulkan::SamplerYCbCrVulkanDescriptor> =
+ wgpu::SType(WGPUSType_SamplerYCbCrVulkanDescriptor);
+
+template <>
+struct AdditionalExtensions<SamplerDescriptor> {
+ using List =
+ AdditionalExtensionsList<const vulkan::SamplerYCbCrVulkanDescriptor*>;
+};
+
} // namespace detail
} // namespace dawn::native
diff --git a/src/dawn/native/Sampler.cpp b/src/dawn/native/Sampler.cpp
index a04f7fb..37a6ecb 100644
--- a/src/dawn/native/Sampler.cpp
+++ b/src/dawn/native/Sampler.cpp
@@ -29,15 +29,18 @@
#include <cmath>
+#include "dawn/native/ChainUtils.h"
#include "dawn/native/Device.h"
#include "dawn/native/ObjectContentHasher.h"
#include "dawn/native/ValidationUtils_autogen.h"
namespace dawn::native {
-MaybeError ValidateSamplerDescriptor(DeviceBase*, const SamplerDescriptor* descriptor) {
- DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr");
+namespace vulkan {
+struct SamplerYCbCrVulkanDescriptor;
+}
+MaybeError ValidateSamplerDescriptor(DeviceBase* device, const SamplerDescriptor* descriptor) {
DAWN_INVALID_IF(std::isnan(descriptor->lodMinClamp) || std::isnan(descriptor->lodMaxClamp),
"LOD clamp bounds [%f, %f] contain a NaN.", descriptor->lodMinClamp,
descriptor->lodMaxClamp);
@@ -71,6 +74,13 @@
DAWN_TRY(ValidateAddressMode(descriptor->addressModeW));
DAWN_TRY(ValidateCompareFunction(descriptor->compare));
+ UnpackedPtr<SamplerDescriptor> unpacked = Unpack(descriptor);
+
+ if (auto* vulkanYCbCrDescriptor = unpacked.Get<vulkan::SamplerYCbCrVulkanDescriptor>()) {
+ DAWN_INVALID_IF(!device->HasFeature(Feature::YCbCrVulkanSamplers), "%s is not enabled.",
+ wgpu::FeatureName::YCbCrVulkanSamplers);
+ }
+
return {};
}
diff --git a/src/dawn/native/vulkan/BackendVk.cpp b/src/dawn/native/vulkan/BackendVk.cpp
index 823ae86..acad9cdb 100644
--- a/src/dawn/native/vulkan/BackendVk.cpp
+++ b/src/dawn/native/vulkan/BackendVk.cpp
@@ -283,6 +283,10 @@
} // anonymous namespace
+SamplerYCbCrVulkanDescriptor::SamplerYCbCrVulkanDescriptor() {
+ sType = wgpu::SType::SamplerYCbCrVulkanDescriptor;
+}
+
VulkanInstance::VulkanInstance() = default;
VulkanInstance::~VulkanInstance() {
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index 977f5b3..8333fc3 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -462,6 +462,10 @@
sources += [ "unittests/d3d12/CopySplitTests.cpp" ]
}
+ if (dawn_enable_vulkan) {
+ sources += [ "unittests/validation/YCbCrSamplerValidationTests.cpp" ]
+ }
+
# When building inside Chromium, use their gtest main function because it is
# needed to run in swarming correctly.
if (build_with_chromium) {
@@ -716,6 +720,10 @@
]
}
+ if (dawn_enable_vulkan) {
+ sources += [ "end2end/YCbCrSamplerTests.cpp" ]
+ }
+
if (dawn_enable_d3d11 || dawn_enable_d3d12 ||
(dawn_enable_vulkan && is_chromeos) || dawn_enable_metal) {
sources += [
diff --git a/src/dawn/tests/end2end/YCbCrSamplerTests.cpp b/src/dawn/tests/end2end/YCbCrSamplerTests.cpp
new file mode 100644
index 0000000..9e19b53
--- /dev/null
+++ b/src/dawn/tests/end2end/YCbCrSamplerTests.cpp
@@ -0,0 +1,67 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <vector>
+
+#include "dawn/native/VulkanBackend.h"
+#include "dawn/tests/DawnTest.h"
+
+namespace dawn {
+namespace {
+
+class YCbCrSamplerTest : public DawnTest {
+ protected:
+ void SetUp() override {
+ DawnTest::SetUp();
+
+ // Skip all tests if ycbcr sampler feature is not supported
+ DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::YCbCrVulkanSamplers}));
+ }
+
+ std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
+ std::vector<wgpu::FeatureName> requiredFeatures = {};
+ if (SupportsFeatures({wgpu::FeatureName::StaticSamplers}) &&
+ SupportsFeatures({wgpu::FeatureName::YCbCrVulkanSamplers})) {
+ requiredFeatures.push_back(wgpu::FeatureName::YCbCrVulkanSamplers);
+ }
+ return requiredFeatures;
+ }
+};
+
+// Test that it is possible to create the sampler with ycbcr sampler descriptor.
+TEST_P(YCbCrSamplerTest, YCbCrSamplerValidWhenFeatureEnabled) {
+ wgpu::SamplerDescriptor samplerDesc = {};
+ native::vulkan::SamplerYCbCrVulkanDescriptor samplerYCbCrDesc = {};
+ samplerDesc.nextInChain = &samplerYCbCrDesc;
+
+ device.CreateSampler(&samplerDesc);
+}
+
+DAWN_INSTANTIATE_TEST(YCbCrSamplerTest, VulkanBackend());
+
+} // anonymous namespace
+} // namespace dawn
diff --git a/src/dawn/tests/unittests/validation/YCbCrSamplerValidationTests.cpp b/src/dawn/tests/unittests/validation/YCbCrSamplerValidationTests.cpp
new file mode 100644
index 0000000..1ad87a4
--- /dev/null
+++ b/src/dawn/tests/unittests/validation/YCbCrSamplerValidationTests.cpp
@@ -0,0 +1,75 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <vulkan/vulkan.h>
+
+#include "dawn/native/VulkanBackend.h"
+#include "dawn/tests/unittests/validation/ValidationTest.h"
+
+namespace dawn {
+namespace {
+
+class YCbCrSamplerValidationTest : public ValidationTest {
+ void SetUp() override {
+ ValidationTest::SetUp();
+ DAWN_SKIP_TEST_IF(UsesWire());
+ }
+};
+
+// Tests that creating a sampler with a valid ycbcr sampler descriptor raises an error
+// if the required feature is not enabled.
+TEST_F(YCbCrSamplerValidationTest, YCbCrSamplerNotSupportedWithoutFeatureEnabled) {
+ wgpu::SamplerDescriptor samplerDesc = {};
+ native::vulkan::SamplerYCbCrVulkanDescriptor samplerYCbCrDesc = {};
+ samplerDesc.nextInChain = &samplerYCbCrDesc;
+
+ ASSERT_DEVICE_ERROR(device.CreateSampler(&samplerDesc));
+}
+
+class YCbCrSamplerWithFeatureValidationTest : public YCbCrSamplerValidationTest {
+ WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
+ wgpu::DeviceDescriptor descriptor) override {
+ wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::YCbCrVulkanSamplers};
+ descriptor.requiredFeatures = requiredFeatures;
+ descriptor.requiredFeatureCount = 1;
+ return dawnAdapter.CreateDevice(&descriptor);
+ }
+};
+
+// Tests that creating a sampler with a valid ycbcr sampler descriptor succeeds if the
+// required feature is enabled.
+TEST_F(YCbCrSamplerWithFeatureValidationTest, YCbCrSamplerSupportedWhenFeatureEnabled) {
+ wgpu::SamplerDescriptor samplerDesc = {};
+ native::vulkan::SamplerYCbCrVulkanDescriptor samplerYCbCrDesc = {};
+ samplerYCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
+ samplerDesc.nextInChain = &samplerYCbCrDesc;
+
+ device.CreateSampler(&samplerDesc);
+}
+
+} // anonymous namespace
+} // namespace dawn