[YCbCr Samplers] Add and use YCbCrVkDescriptor struct

Replace current YCbCrVulkanDescriptor struct with YCbCrVkDescriptor
that adds ints for all the VkSamplerYcbcrConversionCreateInfo members.

Change-Id: I689619172003e8238d8705093f1a56266c35835c
Bug: dawn:2476
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/186542
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Saifuddin Hitawala <hitawala@chromium.org>
diff --git a/include/dawn/native/VulkanBackend.h b/include/dawn/native/VulkanBackend.h
index 141e4b5..201bc32 100644
--- a/include/dawn/native/VulkanBackend.h
+++ b/include/dawn/native/VulkanBackend.h
@@ -82,13 +82,6 @@
     using ExternalImageExportInfo::ExternalImageExportInfo;
 };
 
-// Can be chained in WGPUSamplerDescriptor and WGPUTextureViewDescriptor
-struct DAWN_NATIVE_EXPORT YCbCrVulkanDescriptor : wgpu::ChainedStruct {
-    YCbCrVulkanDescriptor();
-
-    ::VkSamplerYcbcrConversionCreateInfo vulkanYCbCrInfo;
-};
-
 // Can't use DAWN_PLATFORM_IS(LINUX) since header included in both Dawn and Chrome
 #if defined(__linux__) || defined(__Fuchsia__)
 
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index e6ac73d..2a347d1 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -3753,7 +3753,7 @@
             {"value": 1214, "name": "shared fence MTL shared event export info", "tags": ["dawn", "native"]},
             {"value": 1215, "name": "shared buffer memory D3D12 resource descriptor", "tags": ["dawn", "native"]},
             {"value": 1216, "name": "static sampler binding layout", "tags": ["dawn"]},
-            {"value": 1217, "name": "y cb cr vulkan descriptor", "tags": ["dawn", "native"]}
+            {"value": 1217, "name": "y cb cr vk descriptor", "tags": ["dawn"]}
         ]
     },
     "texture": {
@@ -4058,6 +4058,26 @@
             {"value": 6, "name": "3D"}
         ]
     },
+    "y cb cr vk descriptor": {
+        "category": "structure",
+        "chained": "in",
+        "chain roots": ["sampler descriptor", "texture view descriptor"],
+        "tags": ["dawn"],
+        "members": [
+            {"name": "vk format", "type": "uint32_t", "default": "0"},
+            {"name": "vk y cb cr model", "type": "uint32_t", "default": "0"},
+            {"name": "vk y cb cr range", "type": "uint32_t", "default": "0"},
+            {"name": "vk component swizzle red", "type": "uint32_t", "default": "0"},
+            {"name": "vk component swizzle green", "type": "uint32_t", "default": "0"},
+            {"name": "vk component swizzle blue", "type": "uint32_t", "default": "0"},
+            {"name": "vk component swizzle alpha", "type": "uint32_t", "default": "0"},
+            {"name": "vk x chroma offset", "type": "uint32_t", "default": "0"},
+            {"name": "vk y chroma offset", "type": "uint32_t", "default": "0"},
+            {"name": "vk chroma filter", "type": "uint32_t", "default": "0"},
+            {"name": "force explicit reconstruction", "type": "bool", "default": "false"},
+            {"name": "external format", "type": "uint64_t", "default": "0"}
+        ]
+    },
     "vertex format": {
         "category": "enum",
         "values": [
diff --git a/src/dawn/native/ChainUtilsImpl.inl b/src/dawn/native/ChainUtilsImpl.inl
index c94d4da..5c3b45b 100644
--- a/src/dawn/native/ChainUtilsImpl.inl
+++ b/src/dawn/native/ChainUtilsImpl.inl
@@ -103,22 +103,6 @@
         AdditionalExtensionsList<const d3d12::SharedBufferMemoryD3D12ResourceDescriptor*>;
 };
 
-template <>
-constexpr inline wgpu::SType STypeForImpl<vulkan::YCbCrVulkanDescriptor> =
-    wgpu::SType(WGPUSType_YCbCrVulkanDescriptor);
-
-template <>
-struct AdditionalExtensions<SamplerDescriptor> {
-    using List =
-        AdditionalExtensionsList<const vulkan::YCbCrVulkanDescriptor*>;
-};
-
-template <>
-struct AdditionalExtensions<TextureViewDescriptor> {
-    using List =
-        AdditionalExtensionsList<const vulkan::YCbCrVulkanDescriptor*>;
-};
-
 }  // namespace detail
 }  // namespace dawn::native
 
diff --git a/src/dawn/native/Sampler.cpp b/src/dawn/native/Sampler.cpp
index 4bab8c0..392dd8e 100644
--- a/src/dawn/native/Sampler.cpp
+++ b/src/dawn/native/Sampler.cpp
@@ -36,10 +36,6 @@
 
 namespace dawn::native {
 
-namespace vulkan {
-struct YCbCrVulkanDescriptor;
-}
-
 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,
@@ -75,8 +71,7 @@
     DAWN_TRY(ValidateCompareFunction(descriptor->compare));
 
     UnpackedPtr<SamplerDescriptor> unpacked = Unpack(descriptor);
-
-    if (unpacked.Get<vulkan::YCbCrVulkanDescriptor>()) {
+    if (unpacked.Get<YCbCrVkDescriptor>()) {
         DAWN_INVALID_IF(!device->HasFeature(Feature::YCbCrVulkanSamplers), "%s is not enabled.",
                         wgpu::FeatureName::YCbCrVulkanSamplers);
     }
@@ -100,7 +95,7 @@
       mLodMaxClamp(descriptor->lodMaxClamp),
       mCompareFunction(descriptor->compare),
       mMaxAnisotropy(descriptor->maxAnisotropy) {
-    if (Unpack(descriptor).Get<vulkan::YCbCrVulkanDescriptor>()) {
+    if (Unpack(descriptor).Get<YCbCrVkDescriptor>()) {
         mIsYCbCr = true;
     }
 }
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp
index dbbbb37..07e1d3c 100644
--- a/src/dawn/native/Texture.cpp
+++ b/src/dawn/native/Texture.cpp
@@ -47,10 +47,6 @@
 
 namespace dawn::native {
 
-namespace vulkan {
-struct YCbCrVulkanDescriptor;
-}
-
 namespace {
 
 MaybeError ValidateTextureViewFormatCompatibility(const DeviceBase* device,
@@ -635,7 +631,7 @@
     DAWN_TRY(ValidateCanViewTextureAs(device, texture, *viewFormat, descriptor->aspect));
     DAWN_TRY(ValidateTextureViewDimensionCompatibility(device, texture, descriptor));
 
-    if (descriptor.Get<vulkan::YCbCrVulkanDescriptor>()) {
+    if (descriptor.Get<YCbCrVkDescriptor>()) {
         DAWN_INVALID_IF(!device->HasFeature(Feature::YCbCrVulkanSamplers), "%s is not enabled.",
                         wgpu::FeatureName::YCbCrVulkanSamplers);
     }
diff --git a/src/dawn/native/vulkan/BackendVk.cpp b/src/dawn/native/vulkan/BackendVk.cpp
index 3f8e885..0015890 100644
--- a/src/dawn/native/vulkan/BackendVk.cpp
+++ b/src/dawn/native/vulkan/BackendVk.cpp
@@ -283,10 +283,6 @@
 
 }  // anonymous namespace
 
-YCbCrVulkanDescriptor::YCbCrVulkanDescriptor() {
-    sType = wgpu::SType::YCbCrVulkanDescriptor;
-}
-
 VulkanInstance::VulkanInstance() = default;
 
 VulkanInstance::~VulkanInstance() {
diff --git a/src/dawn/native/vulkan/SamplerVk.cpp b/src/dawn/native/vulkan/SamplerVk.cpp
index f6c3c2e..ffdf8a2 100644
--- a/src/dawn/native/vulkan/SamplerVk.cpp
+++ b/src/dawn/native/vulkan/SamplerVk.cpp
@@ -122,14 +122,27 @@
     }
 
     VkSamplerYcbcrConversionInfo samplerYCbCrInfo = {};
-    if (auto* vulkanYCbCrDescriptor = Unpack(descriptor).Get<vulkan::YCbCrVulkanDescriptor>()) {
-        const VkSamplerYcbcrConversionCreateInfo& vulkanYCbCrInfo =
-            vulkanYCbCrDescriptor->vulkanYCbCrInfo;
-        DAWN_TRY(ValidateCanCreateSamplerYCbCrConversion(vulkanYCbCrInfo));
-        DAWN_TRY(CheckVkSuccess(
-            device->fn.CreateSamplerYcbcrConversion(device->GetVkDevice(), &vulkanYCbCrInfo,
-                                                    nullptr, &*mSamplerYCbCrConversion),
-            "CreateSamplerYcbcrConversion"));
+    if (auto* yCbCrDescriptor = Unpack(descriptor).Get<YCbCrVkDescriptor>()) {
+        DAWN_TRY_ASSIGN(mYcbcrConversionCreateInfo,
+                        CreateSamplerYCbCrConversionCreateInfo(yCbCrDescriptor));
+
+        mExternalFormat = yCbCrDescriptor->externalFormat;
+#if DAWN_PLATFORM_IS(ANDROID)
+        VkExternalFormatANDROID vulkanExternalFormat;
+        // Chain VkExternalFormatANDROID only if needed.
+        if (mExternalFormat != 0) {
+            vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
+            vulkanExternalFormat.pNext = nullptr;
+            vulkanExternalFormat.externalFormat = mExternalFormat;
+
+            mYcbcrConversionCreateInfo.pNext = &vulkanExternalFormat;
+        }
+#endif  // DAWN_PLATFORM_IS(ANDROID)
+
+        DAWN_TRY(CheckVkSuccess(device->fn.CreateSamplerYcbcrConversion(
+                                    device->GetVkDevice(), &mYcbcrConversionCreateInfo, nullptr,
+                                    &*mSamplerYCbCrConversion),
+                                "CreateSamplerYcbcrConversion"));
 
         samplerYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
         samplerYCbCrInfo.pNext = nullptr;
diff --git a/src/dawn/native/vulkan/SamplerVk.h b/src/dawn/native/vulkan/SamplerVk.h
index bbde4ae..a80724f 100644
--- a/src/dawn/native/vulkan/SamplerVk.h
+++ b/src/dawn/native/vulkan/SamplerVk.h
@@ -54,6 +54,8 @@
 
     VkSampler mHandle = VK_NULL_HANDLE;
     VkSamplerYcbcrConversion mSamplerYCbCrConversion = VK_NULL_HANDLE;
+    VkSamplerYcbcrConversionCreateInfo mYcbcrConversionCreateInfo = {};
+    uint64_t mExternalFormat = 0u;
 };
 
 }  // namespace dawn::native::vulkan
diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp
index 2459f64..cf3de24 100644
--- a/src/dawn/native/vulkan/TextureVk.cpp
+++ b/src/dawn/native/vulkan/TextureVk.cpp
@@ -1767,14 +1767,26 @@
     createInfo.pNext = &usageInfo;
 
     VkSamplerYcbcrConversionInfo samplerYCbCrInfo = {};
-    if (auto* vulkanYCbCrDescriptor = descriptor.Get<vulkan::YCbCrVulkanDescriptor>()) {
-        // TODO(crbug.com/dawn/2476): Validate mSamplerYcbcrConversionCreateInfo matches with that
-        // in SamplerDescriptor.
-        mSamplerYcbcrConversionCreateInfo = vulkanYCbCrDescriptor->vulkanYCbCrInfo;
-        DAWN_TRY(ValidateCanCreateSamplerYCbCrConversion(mSamplerYcbcrConversionCreateInfo));
+    if (auto* yCbCrDescriptor = descriptor.Get<YCbCrVkDescriptor>()) {
+        DAWN_TRY_ASSIGN(mYcbcrConversionCreateInfo,
+                        CreateSamplerYCbCrConversionCreateInfo(yCbCrDescriptor));
+
+        mExternalFormat = yCbCrDescriptor->externalFormat;
+#if DAWN_PLATFORM_IS(ANDROID)
+        VkExternalFormatANDROID vulkanExternalFormat;
+        // Chain VkExternalFormatANDROID only if needed.
+        if (mExternalFormat != 0) {
+            vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
+            vulkanExternalFormat.pNext = nullptr;
+            vulkanExternalFormat.externalFormat = mExternalFormat;
+
+            mYcbcrConversionCreateInfo.pNext = &vulkanExternalFormat;
+        }
+#endif  // DAWN_PLATFORM_IS(ANDROID)
+
         DAWN_TRY(CheckVkSuccess(device->fn.CreateSamplerYcbcrConversion(
-                                    device->GetVkDevice(), &mSamplerYcbcrConversionCreateInfo,
-                                    nullptr, &*mSamplerYCbCrConversion),
+                                    device->GetVkDevice(), &mYcbcrConversionCreateInfo, nullptr,
+                                    &*mSamplerYCbCrConversion),
                                 "CreateSamplerYcbcrConversion for vkImageView"));
 
         samplerYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
diff --git a/src/dawn/native/vulkan/TextureVk.h b/src/dawn/native/vulkan/TextureVk.h
index 9923e86..fe38192 100644
--- a/src/dawn/native/vulkan/TextureVk.h
+++ b/src/dawn/native/vulkan/TextureVk.h
@@ -258,7 +258,8 @@
     VkImageView mHandle = VK_NULL_HANDLE;
     VkImageView mHandleForBGRA8UnormStorage = VK_NULL_HANDLE;
     VkSamplerYcbcrConversion mSamplerYCbCrConversion = VK_NULL_HANDLE;
-    VkSamplerYcbcrConversionCreateInfo mSamplerYcbcrConversionCreateInfo;
+    VkSamplerYcbcrConversionCreateInfo mYcbcrConversionCreateInfo = {};
+    uint64_t mExternalFormat = 0u;
     std::vector<VkImageView> mHandlesFor2DViewOn3D;
 };
 
diff --git a/src/dawn/native/vulkan/UtilsVulkan.cpp b/src/dawn/native/vulkan/UtilsVulkan.cpp
index 5dc630c..2baef43 100644
--- a/src/dawn/native/vulkan/UtilsVulkan.cpp
+++ b/src/dawn/native/vulkan/UtilsVulkan.cpp
@@ -327,23 +327,37 @@
     return DAWN_VALIDATION_ERROR("DRM format modifier %u not supported.", modifier);
 }
 
-MaybeError ValidateCanCreateSamplerYCbCrConversion(
-    const VkSamplerYcbcrConversionCreateInfo& vulkanYCbCrInfo) {
-#if DAWN_PLATFORM_IS(ANDROID)
-    const VkBaseInStructure* chain = static_cast<const VkBaseInStructure*>(vulkanYCbCrInfo.pNext);
-    while (chain != nullptr) {
-        if (chain->sType == VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID) {
-            const VkExternalFormatANDROID* vkExternalFormat =
-                reinterpret_cast<const VkExternalFormatANDROID*>(chain);
-            DAWN_INVALID_IF((vkExternalFormat->externalFormat == 0 &&
-                             vulkanYCbCrInfo.format == VK_FORMAT_UNDEFINED),
-                            "Both VkFormat and VkExternalFormatANDROID are undefined.");
-            break;
-        }
-        chain = chain->pNext;
-    }
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-    return {};
+ResultOrError<VkSamplerYcbcrConversionCreateInfo> CreateSamplerYCbCrConversionCreateInfo(
+    const YCbCrVkDescriptor* yCbCrDescriptor) {
+    uint64_t externalFormat = yCbCrDescriptor->externalFormat;
+    VkFormat vulkanFormat = static_cast<VkFormat>(yCbCrDescriptor->vkFormat);
+    DAWN_INVALID_IF((externalFormat == 0 && vulkanFormat == VK_FORMAT_UNDEFINED),
+                    "Both VkFormat and VkExternalFormatANDROID are undefined.");
+
+    VkComponentMapping vulkanComponent;
+    vulkanComponent.r = static_cast<VkComponentSwizzle>(yCbCrDescriptor->vkComponentSwizzleRed);
+    vulkanComponent.g = static_cast<VkComponentSwizzle>(yCbCrDescriptor->vkComponentSwizzleGreen);
+    vulkanComponent.b = static_cast<VkComponentSwizzle>(yCbCrDescriptor->vkComponentSwizzleBlue);
+    vulkanComponent.a = static_cast<VkComponentSwizzle>(yCbCrDescriptor->vkComponentSwizzleAlpha);
+
+    VkSamplerYcbcrConversionCreateInfo vulkanYCbCrCreateInfo;
+    vulkanYCbCrCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
+    vulkanYCbCrCreateInfo.pNext = nullptr;
+    vulkanYCbCrCreateInfo.format = vulkanFormat;
+    vulkanYCbCrCreateInfo.ycbcrModel =
+        static_cast<VkSamplerYcbcrModelConversion>(yCbCrDescriptor->vkYCbCrModel);
+    vulkanYCbCrCreateInfo.ycbcrRange =
+        static_cast<VkSamplerYcbcrRange>(yCbCrDescriptor->vkYCbCrRange);
+    vulkanYCbCrCreateInfo.components = vulkanComponent;
+    vulkanYCbCrCreateInfo.xChromaOffset =
+        static_cast<VkChromaLocation>(yCbCrDescriptor->vkXChromaOffset);
+    vulkanYCbCrCreateInfo.yChromaOffset =
+        static_cast<VkChromaLocation>(yCbCrDescriptor->vkYChromaOffset);
+    vulkanYCbCrCreateInfo.chromaFilter = static_cast<VkFilter>(yCbCrDescriptor->vkChromaFilter);
+    vulkanYCbCrCreateInfo.forceExplicitReconstruction =
+        static_cast<VkBool32>(yCbCrDescriptor->forceExplicitReconstruction);
+
+    return vulkanYCbCrCreateInfo;
 }
 
 }  // namespace dawn::native::vulkan
diff --git a/src/dawn/native/vulkan/UtilsVulkan.h b/src/dawn/native/vulkan/UtilsVulkan.h
index 81a9799..d7d94a6 100644
--- a/src/dawn/native/vulkan/UtilsVulkan.h
+++ b/src/dawn/native/vulkan/UtilsVulkan.h
@@ -179,8 +179,8 @@
     VkFormat format,
     uint64_t modifier);
 
-MaybeError ValidateCanCreateSamplerYCbCrConversion(
-    const VkSamplerYcbcrConversionCreateInfo& vulkanYCbCrInfo);
+ResultOrError<VkSamplerYcbcrConversionCreateInfo> CreateSamplerYCbCrConversionCreateInfo(
+    const YCbCrVkDescriptor* yCbCrDescriptor);
 
 }  // namespace dawn::native::vulkan
 
diff --git a/src/dawn/tests/end2end/YCbCrInfoTests.cpp b/src/dawn/tests/end2end/YCbCrInfoTests.cpp
index 0707640..7e8fa4d7 100644
--- a/src/dawn/tests/end2end/YCbCrInfoTests.cpp
+++ b/src/dawn/tests/end2end/YCbCrInfoTests.cpp
@@ -74,7 +74,8 @@
   protected:
     void SetUp() override {
         DawnTest::SetUp();
-
+        // Skip tests if platform is not Android.
+        DAWN_TEST_UNSUPPORTED_IF(!DAWN_PLATFORM_IS(ANDROID));
         // Skip all tests if ycbcr sampler feature is not supported
         DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::YCbCrVulkanSamplers}));
     }
@@ -92,11 +93,8 @@
 // Test that it is possible to create the sampler with ycbcr vulkan descriptor.
 TEST_P(YCbCrInfoTest, YCbCrSamplerValidWhenFeatureEnabled) {
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
-
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
+    yCbCrDesc.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
     samplerDesc.nextInChain = &yCbCrDesc;
 
     device.CreateSampler(&samplerDesc);
@@ -106,21 +104,10 @@
 // format set.
 TEST_P(YCbCrInfoTest, YCbCrSamplerValidWithOnlyVkFormat) {
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
-
-#if DAWN_PLATFORM_IS(ANDROID)
-    VkExternalFormatANDROID vulkanExternalFormat = {};
-    vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
-    vulkanExternalFormat.pNext = nullptr;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
+    yCbCrDesc.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
     // format is set as VK_FORMAT.
-    vulkanExternalFormat.externalFormat = 0;
-
-    yCbCrDesc.vulkanYCbCrInfo.pNext = &vulkanExternalFormat;
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
+    yCbCrDesc.externalFormat = 0;
     samplerDesc.nextInChain = &yCbCrDesc;
 
     device.CreateSampler(&samplerDesc);
@@ -130,21 +117,10 @@
 // format set.
 TEST_P(YCbCrInfoTest, YCbCrSamplerValidWithOnlyExternalFormat) {
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     // format is set as externalFormat.
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_UNDEFINED;
-
-#if DAWN_PLATFORM_IS(ANDROID)
-    VkExternalFormatANDROID vulkanExternalFormat = {};
-    vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
-    vulkanExternalFormat.pNext = nullptr;
-    vulkanExternalFormat.externalFormat = 5;
-
-    yCbCrDesc.vulkanYCbCrInfo.pNext = &vulkanExternalFormat;
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
+    yCbCrDesc.vkFormat = VK_FORMAT_UNDEFINED;
+    yCbCrDesc.externalFormat = 5;
     samplerDesc.nextInChain = &yCbCrDesc;
 
     device.CreateSampler(&samplerDesc);
@@ -154,20 +130,9 @@
 // set.
 TEST_P(YCbCrInfoTest, YCbCrSamplerInvalidWithNoFormat) {
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_UNDEFINED;
-
-#if DAWN_PLATFORM_IS(ANDROID)
-    VkExternalFormatANDROID vulkanExternalFormat = {};
-    vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
-    vulkanExternalFormat.pNext = nullptr;
-    vulkanExternalFormat.externalFormat = 0;
-
-    yCbCrDesc.vulkanYCbCrInfo.pNext = &vulkanExternalFormat;
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
+    yCbCrDesc.vkFormat = VK_FORMAT_UNDEFINED;
+    yCbCrDesc.externalFormat = 0;
     samplerDesc.nextInChain = &yCbCrDesc;
 
     ASSERT_DEVICE_ERROR(device.CreateSampler(&samplerDesc));
@@ -181,11 +146,8 @@
         CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
     descriptor.arrayLayerCount = 1;
 
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
-
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
+    yCbCrDesc.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
     descriptor.nextInChain = &yCbCrDesc;
 
     texture.CreateView(&descriptor);
@@ -200,21 +162,10 @@
         CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
     descriptor.arrayLayerCount = 1;
 
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
-
-#if DAWN_PLATFORM_IS(ANDROID)
-    VkExternalFormatANDROID vulkanExternalFormat = {};
-    vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
-    vulkanExternalFormat.pNext = nullptr;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
+    yCbCrDesc.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
     // format is set as VK_FORMAT.
-    vulkanExternalFormat.externalFormat = 0;
-
-    yCbCrDesc.vulkanYCbCrInfo.pNext = &vulkanExternalFormat;
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
+    yCbCrDesc.externalFormat = 0;
     descriptor.nextInChain = &yCbCrDesc;
 
     texture.CreateView(&descriptor);
@@ -229,21 +180,10 @@
         CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
     descriptor.arrayLayerCount = 1;
 
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     // format is set as externalFormat.
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_UNDEFINED;
-
-#if DAWN_PLATFORM_IS(ANDROID)
-    VkExternalFormatANDROID vulkanExternalFormat = {};
-    vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
-    vulkanExternalFormat.pNext = nullptr;
-    vulkanExternalFormat.externalFormat = 5;
-
-    yCbCrDesc.vulkanYCbCrInfo.pNext = &vulkanExternalFormat;
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
+    yCbCrDesc.vkFormat = VK_FORMAT_UNDEFINED;
+    yCbCrDesc.externalFormat = 5;
     descriptor.nextInChain = &yCbCrDesc;
 
     texture.CreateView(&descriptor);
@@ -258,20 +198,9 @@
         CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
     descriptor.arrayLayerCount = 1;
 
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
-    yCbCrDesc.vulkanYCbCrInfo.pNext = nullptr;
-    yCbCrDesc.vulkanYCbCrInfo.format = VK_FORMAT_UNDEFINED;
-
-#if DAWN_PLATFORM_IS(ANDROID)
-    VkExternalFormatANDROID vulkanExternalFormat = {};
-    vulkanExternalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
-    vulkanExternalFormat.pNext = nullptr;
-    vulkanExternalFormat.externalFormat = 0;
-
-    yCbCrDesc.vulkanYCbCrInfo.pNext = &vulkanExternalFormat;
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
+    yCbCrDesc.vkFormat = VK_FORMAT_UNDEFINED;
+    yCbCrDesc.externalFormat = 0;
     descriptor.nextInChain = &yCbCrDesc;
 
     ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
diff --git a/src/dawn/tests/unittests/validation/YCbCrInfoValidationTests.cpp b/src/dawn/tests/unittests/validation/YCbCrInfoValidationTests.cpp
index 43f384e..0092982 100644
--- a/src/dawn/tests/unittests/validation/YCbCrInfoValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/YCbCrInfoValidationTests.cpp
@@ -28,7 +28,6 @@
 #include <vulkan/vulkan.h>
 #include <vector>
 
-#include "dawn/native/VulkanBackend.h"
 #include "dawn/tests/unittests/validation/ValidationTest.h"
 #include "dawn/utils/WGPUHelpers.h"
 
@@ -79,7 +78,7 @@
 // if the required feature is not enabled.
 TEST_F(YCbCrInfoWithoutFeatureValidationTest, YCbCrSamplerNotSupported) {
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     samplerDesc.nextInChain = &yCbCrDesc;
 
     ASSERT_DEVICE_ERROR(device.CreateSampler(&samplerDesc));
@@ -93,13 +92,19 @@
     wgpu::TextureViewDescriptor descriptor =
         CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
     descriptor.arrayLayerCount = 1;
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     descriptor.nextInChain = &yCbCrDesc;
 
     ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
 }
 
 class YCbCrInfoWithFeatureValidationTest : public YCbCrInfoWithoutFeatureValidationTest {
+    void SetUp() override {
+        ValidationTest::SetUp();
+        DAWN_SKIP_TEST_IF(!DAWN_PLATFORM_IS(ANDROID));
+        DAWN_SKIP_TEST_IF(UsesWire());
+    }
+
     WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
                                 wgpu::DeviceDescriptor descriptor) override {
         wgpu::FeatureName requiredFeatures[2] = {wgpu::FeatureName::StaticSamplers,
@@ -114,8 +119,7 @@
 // required feature is enabled.
 TEST_F(YCbCrInfoWithFeatureValidationTest, YCbCrSamplerSupported) {
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     samplerDesc.nextInChain = &yCbCrDesc;
 
     device.CreateSampler(&samplerDesc);
@@ -129,8 +133,7 @@
     wgpu::StaticSamplerBindingLayout staticSamplerBinding = {};
 
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     samplerDesc.nextInChain = &yCbCrDesc;
 
     staticSamplerBinding.sampler = device.CreateSampler(&samplerDesc);
@@ -164,8 +167,7 @@
     wgpu::StaticSamplerBindingLayout staticSamplerBinding = {};
 
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     samplerDesc.nextInChain = &yCbCrDesc;
 
     staticSamplerBinding.sampler = device.CreateSampler(&samplerDesc);
@@ -199,8 +201,7 @@
     wgpu::StaticSamplerBindingLayout staticSamplerBinding = {};
 
     wgpu::SamplerDescriptor samplerDesc = {};
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     samplerDesc.nextInChain = &yCbCrDesc;
 
     staticSamplerBinding.sampler = device.CreateSampler(&samplerDesc);
@@ -227,8 +228,7 @@
     wgpu::TextureViewDescriptor descriptor =
         CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
     descriptor.arrayLayerCount = 1;
-    native::vulkan::YCbCrVulkanDescriptor yCbCrDesc = {};
-    yCbCrDesc.vulkanYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
+    wgpu::YCbCrVkDescriptor yCbCrDesc = {};
     descriptor.nextInChain = &yCbCrDesc;
 
     texture.CreateView(&descriptor);