| /* |
| * Copyright (c) 2015-2023 The Khronos Group Inc. |
| * Copyright (c) 2015-2023 Valve Corporation |
| * Copyright (c) 2015-2023 LunarG, Inc. |
| * Copyright (c) 2015-2023 Google, Inc. |
| * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| */ |
| |
| #include "utils/cast_utils.h" |
| #include "generated/enum_flag_bits.h" |
| #include "../framework/layer_validation_tests.h" |
| #include "utils/vk_layer_utils.h" |
| |
| TEST_F(VkLayerTest, CreateYCbCrSampler) { |
| TEST_DESCRIPTION("Verify YCbCr sampler creation."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| auto ycbcr_features = LvlInitStruct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(); |
| GetPhysicalDeviceFeatures2(ycbcr_features); |
| if (ycbcr_features.samplerYcbcrConversion != VK_TRUE) { |
| GTEST_SKIP() << "samplerYcbcrConversion feature not supported"; |
| } |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required."; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &ycbcr_features)); |
| |
| PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr; |
| PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr; |
| if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { |
| GTEST_SKIP() << "Failed to load device profile layer."; |
| } |
| |
| VkSamplerYcbcrConversion ycbcr_conv = VK_NULL_HANDLE; |
| VkSamplerYcbcrConversionCreateInfo sycci = LvlInitStruct<VkSamplerYcbcrConversionCreateInfo>(); |
| sycci.format = VK_FORMAT_UNDEFINED; |
| sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; |
| sycci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; |
| sycci.forceExplicitReconstruction = VK_FALSE; |
| sycci.chromaFilter = VK_FILTER_NEAREST; |
| sycci.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| |
| // test non external conversion with a VK_FORMAT_UNDEFINED |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-format-04060"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // test for non unorm |
| sycci.format = VK_FORMAT_R8G8B8A8_SNORM; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-format-04060"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkSamplerYcbcrConversionCreateInfo-format-01650"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // Force the multi-planar format support desired format features |
| VkFormat mp_format = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM; |
| VkFormatProperties formatProps; |
| fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), mp_format, &formatProps); |
| formatProps.linearTilingFeatures = 0; |
| formatProps.optimalTilingFeatures = 0; |
| fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), mp_format, formatProps); |
| |
| // Check that errors are caught when format feature don't exist |
| sycci.format = mp_format; |
| |
| // No Chroma Sampler Bit set |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-format-01650"); |
| // 01651 set off twice for both xChromaOffset and yChromaOffset |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // Cosited feature supported, but midpoint samples set |
| formatProps.linearTilingFeatures = 0; |
| formatProps.optimalTilingFeatures = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT; |
| fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), mp_format, formatProps); |
| sycci.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT; |
| sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // Moving support to Linear to test that it checks either linear or optimal |
| formatProps.linearTilingFeatures = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT; |
| formatProps.optimalTilingFeatures = 0; |
| fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), mp_format, formatProps); |
| sycci.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT; |
| sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // Using forceExplicitReconstruction without feature bit |
| sycci.forceExplicitReconstruction = VK_TRUE; |
| sycci.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-forceExplicitReconstruction-01656"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // Linear chroma filtering without feature bit |
| sycci.forceExplicitReconstruction = VK_FALSE; |
| sycci.chromaFilter = VK_FILTER_LINEAR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-01657"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // Add linear feature bit so can create valid SamplerYcbcrConversion |
| formatProps.linearTilingFeatures = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT; |
| formatProps.optimalTilingFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT; |
| fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), mp_format, formatProps); |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, sycci); |
| |
| // Try to create a Sampler with non-matching filters without feature bit set |
| VkSamplerYcbcrConversionInfo sampler_ycbcr_info = LvlInitStruct<VkSamplerYcbcrConversionInfo>(); |
| sampler_ycbcr_info.conversion = conversion.handle(); |
| VkSampler sampler; |
| VkSamplerCreateInfo sampler_info = SafeSaneSamplerCreateInfo(); |
| sampler_info.minFilter = VK_FILTER_NEAREST; // Different than chromaFilter |
| sampler_info.magFilter = VK_FILTER_LINEAR; |
| sampler_info.pNext = (void *)&sampler_ycbcr_info; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerCreateInfo-minFilter-01645"); |
| vk::CreateSampler(device(), &sampler_info, nullptr, &sampler); |
| m_errorMonitor->VerifyFound(); |
| |
| sampler_info.magFilter = VK_FILTER_NEAREST; |
| sampler_info.minFilter = VK_FILTER_LINEAR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerCreateInfo-minFilter-01645"); |
| vk::CreateSampler(device(), &sampler_info, nullptr, &sampler); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkLayerTest, InvalidSwizzleYCbCr) { |
| TEST_DESCRIPTION("Verify Invalid use of siwizzle components when dealing with YCbCr."); |
| |
| // Use 1.1 to get VK_KHR_sampler_ycbcr_conversion easier |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| if (DeviceValidationVersion() < VK_API_VERSION_1_2) { |
| GTEST_SKIP() << "At least Vulkan version 1.2 is required"; |
| } |
| |
| auto features11 = LvlInitStruct<VkPhysicalDeviceVulkan11Features>(); |
| auto features2 = GetPhysicalDeviceFeatures2(features11); |
| if (features11.samplerYcbcrConversion != VK_TRUE) { |
| GTEST_SKIP() << "samplerYcbcrConversion not supported, skipping test"; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| const VkFormat mp_format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; |
| |
| // Make sure components doesn't affect _444 formats |
| VkFormatProperties format_props; |
| vk::GetPhysicalDeviceFormatProperties(gpu(), mp_format, &format_props); |
| if ((format_props.optimalTilingFeatures & |
| (VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT | VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT)) == 0) { |
| GTEST_SKIP() << "Device does not support chroma sampling of 3plane 420 format"; |
| } |
| |
| const VkComponentMapping identity = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; |
| |
| VkSamplerYcbcrConversion ycbcr_conv = VK_NULL_HANDLE; |
| VkSamplerYcbcrConversionCreateInfo sycci = LvlInitStruct<VkSamplerYcbcrConversionCreateInfo>(); |
| sycci.format = mp_format; |
| sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; |
| sycci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; |
| sycci.forceExplicitReconstruction = VK_FALSE; |
| sycci.chromaFilter = VK_FILTER_NEAREST; |
| sycci.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| |
| // test components.g |
| // This test is also serves as positive form of VU 01655 since SWIZZLE_A is considered only valid with this format because |
| // ycbcrModel RGB_IDENTITY |
| sycci.components = identity; |
| sycci.components.g = VK_COMPONENT_SWIZZLE_A; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02581"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, NULL, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // test components.a |
| sycci.components = identity; |
| sycci.components.a = VK_COMPONENT_SWIZZLE_R; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02582"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, NULL, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // make sure zero and one are allowed for components.a |
| { |
| sycci.components.a = VK_COMPONENT_SWIZZLE_ONE; |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, sycci); |
| } |
| { |
| sycci.components.a = VK_COMPONENT_SWIZZLE_ZERO; |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, sycci); |
| } |
| |
| // test components.r |
| sycci.components = identity; |
| sycci.components.r = VK_COMPONENT_SWIZZLE_G; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02583"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, NULL, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // test components.b |
| sycci.components = identity; |
| sycci.components.b = VK_COMPONENT_SWIZZLE_G; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02584"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, NULL, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // test components.r and components.b together |
| sycci.components = identity; |
| sycci.components.r = VK_COMPONENT_SWIZZLE_B; |
| sycci.components.b = VK_COMPONENT_SWIZZLE_B; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, NULL, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // make sure components.r and components.b can be swapped |
| { |
| sycci.components = identity; |
| sycci.components.r = VK_COMPONENT_SWIZZLE_B; |
| sycci.components.b = VK_COMPONENT_SWIZZLE_R; |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, sycci); |
| } |
| |
| // Non RGB Identity model |
| sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY; |
| { |
| // Non RGB Identity can't have a explicit zero swizzle |
| sycci.components = identity; |
| sycci.components.g = VK_COMPONENT_SWIZZLE_ZERO; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-01655"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02581"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // Non RGB Identity can't have a explicit one swizzle |
| sycci.components = identity; |
| sycci.components.g = VK_COMPONENT_SWIZZLE_ONE; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-01655"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02581"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| |
| // VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM has 3 component so RGBA conversion has implicit A as one |
| sycci.components = identity; |
| sycci.components.g = VK_COMPONENT_SWIZZLE_A; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-01655"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSamplerYcbcrConversionCreateInfo-components-02581"); |
| vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv); |
| m_errorMonitor->VerifyFound(); |
| } |
| sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; // reset |
| |
| // Make sure components doesn't affect _444 formats |
| vk::GetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, &format_props); |
| if ((format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) != 0) { |
| sycci.format = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM; |
| sycci.components = identity; |
| sycci.components.g = VK_COMPONENT_SWIZZLE_R; |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, sycci); |
| } |
| |
| // Create a valid conversion with guaranteed support |
| sycci.format = mp_format; |
| sycci.components = identity; |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, sycci, false); |
| |
| VkImageObj image(m_device); |
| image.Init(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); |
| ASSERT_TRUE(image.initialized()); |
| |
| VkSamplerYcbcrConversionInfo conversion_info = LvlInitStruct<VkSamplerYcbcrConversionInfo>(); |
| conversion_info.conversion = conversion.handle(); |
| |
| VkImageView image_view; |
| VkImageViewCreateInfo image_view_create_info = LvlInitStruct<VkImageViewCreateInfo>(&conversion_info); |
| image_view_create_info.image = image.handle(); |
| image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; |
| image_view_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; |
| image_view_create_info.subresourceRange.layerCount = 1; |
| image_view_create_info.subresourceRange.baseMipLevel = 0; |
| image_view_create_info.subresourceRange.levelCount = 1; |
| image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| image_view_create_info.components = identity; |
| image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_B; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkImageViewCreateInfo-pNext-01970"); |
| vk::CreateImageView(m_device->device(), &image_view_create_info, nullptr, &image_view); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkLayerTest, CreateImageYcbcrFormats) { |
| TEST_DESCRIPTION("Creating images with Ycbcr Formats."); |
| |
| // Enable KHR multiplane req'd extensions |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr; |
| PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr; |
| if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { |
| GTEST_SKIP() << "Failed to load device profile layer."; |
| } |
| |
| if (!ImageFormatIsSupported(gpu(), VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM)) { |
| GTEST_SKIP() << "VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM is unsupported"; |
| } |
| |
| // Set format features as needed for tests |
| VkFormatProperties formatProps; |
| const VkFormat mp_format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; |
| fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), mp_format, &formatProps); |
| formatProps.optimalTilingFeatures |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT; |
| formatProps.optimalTilingFeatures = formatProps.optimalTilingFeatures & ~VK_FORMAT_FEATURE_DISJOINT_BIT; |
| fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), mp_format, formatProps); |
| |
| // Create ycbcr image with all valid values |
| // Each test changes needed values and returns them back after |
| VkImageCreateInfo image_create_info = LvlInitStruct<VkImageCreateInfo>(); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = mp_format; |
| image_create_info.extent.width = 32; |
| image_create_info.extent.height = 32; |
| image_create_info.extent.depth = 1; |
| image_create_info.mipLevels = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| image_create_info.arrayLayers = 1; |
| VkImageCreateInfo reset_create_info = image_create_info; |
| |
| VkImageFormatProperties img_limits; |
| ASSERT_VK_SUCCESS(GPDIFPHelper(gpu(), &image_create_info, &img_limits)); |
| |
| // invalid mipLevels |
| if (img_limits.maxMipLevels == 1) { |
| printf("Multiplane image maxMipLevels is already 1. Skipping test.\n"); |
| } else { |
| // needs to be 2 |
| // if more then 2 the VU since its larger the (depth^2 + 1) |
| // if up the depth the VU for IMAGE_TYPE_2D and depth != 1 hits |
| image_create_info.mipLevels = 2; |
| CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-format-06410"); |
| image_create_info = reset_create_info; |
| } |
| |
| // invalid samples count |
| image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; |
| // Might need to add extra validation because implementation probably doesn't support YUV |
| VkImageFormatProperties image_format_props; |
| vk::GetPhysicalDeviceImageFormatProperties(gpu(), mp_format, image_create_info.imageType, image_create_info.tiling, |
| image_create_info.usage, image_create_info.flags, &image_format_props); |
| if ((image_format_props.sampleCounts & VK_SAMPLE_COUNT_4_BIT) == 0) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkImageCreateInfo-samples-02258"); |
| } |
| CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-format-06411"); |
| image_create_info = reset_create_info; |
| |
| // invalid width |
| image_create_info.extent.width = 31; |
| CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-format-04712"); |
| image_create_info = reset_create_info; |
| |
| // invalid height (since 420 format) |
| image_create_info.extent.height = 31; |
| CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-format-04713"); |
| image_create_info = reset_create_info; |
| |
| // invalid imageType |
| image_create_info.imageType = VK_IMAGE_TYPE_1D; |
| // Check that image format is valid |
| if (vk::GetPhysicalDeviceImageFormatProperties(gpu(), mp_format, image_create_info.imageType, image_create_info.tiling, |
| image_create_info.usage, image_create_info.flags, |
| &image_format_props) == VK_SUCCESS) { |
| // Can't just set height to 1 as stateless validation will hit 04713 first |
| m_errorMonitor->SetUnexpectedError("VUID-VkImageCreateInfo-imageType-00956"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkImageCreateInfo-extent-02253"); |
| CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-format-06412"); |
| } |
| image_create_info = reset_create_info; |
| |
| // Test using a format that doesn't support disjoint |
| image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT; |
| CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260"); |
| image_create_info = reset_create_info; |
| } |
| |
| TEST_F(VkLayerTest, CopyImageSinglePlane422Alignment) { |
| // Image copy tests on single-plane _422 formats with block alignment errors |
| |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState()); |
| |
| // Select a _422 format and verify support |
| VkImageCreateInfo ci = LvlInitStruct<VkImageCreateInfo>(); |
| ci.flags = 0; |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.format = VK_FORMAT_G8B8G8R8_422_UNORM_KHR; |
| ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| ci.mipLevels = 1; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| ci.queueFamilyIndexCount = 0; |
| ci.pQueueFamilyIndices = NULL; |
| ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| |
| // Verify formats |
| VkFormatFeatureFlags features = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT; |
| bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); |
| if (!supported) { |
| // Assume there's low ROI on searching for different mp formats |
| GTEST_SKIP() << "Single-plane _422 image format not supported"; |
| } |
| |
| // Create images |
| ci.extent = {64, 64, 1}; |
| VkImageObj image_422(m_device); |
| image_422.init(&ci); |
| ASSERT_TRUE(image_422.initialized()); |
| |
| ci.extent = {64, 64, 1}; |
| ci.format = VK_FORMAT_R8G8B8A8_UNORM; |
| VkImageObj image_ucmp(m_device); |
| image_ucmp.init(&ci); |
| ASSERT_TRUE(image_ucmp.initialized()); |
| |
| m_commandBuffer->begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {48, 48, 1}; |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.srcSubresource.mipLevel = 0; |
| copy_region.dstSubresource.mipLevel = 0; |
| copy_region.srcSubresource.baseArrayLayer = 0; |
| copy_region.dstSubresource.baseArrayLayer = 0; |
| copy_region.srcSubresource.layerCount = 1; |
| copy_region.dstSubresource.layerCount = 1; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| // Src offsets must be multiples of compressed block sizes |
| copy_region.srcOffset = {3, 4, 0}; // source offset x |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-pRegions-07278"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-srcOffset-01783"); |
| m_commandBuffer->CopyImage(image_422.image(), VK_IMAGE_LAYOUT_GENERAL, image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.srcOffset = {0, 0, 0}; |
| |
| // Dst offsets must be multiples of compressed block sizes |
| copy_region.dstOffset = {1, 0, 0}; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-pRegions-07281"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-dstOffset-01784"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-dstOffset-00150"); |
| m_commandBuffer->CopyImage(image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, image_422.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| // Copy extent must be multiples of compressed block sizes if not full width/height |
| copy_region.extent = {31, 60, 1}; // 422 source, extent.x |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-srcImage-01728"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-srcOffset-01783"); |
| m_commandBuffer->CopyImage(image_422.image(), VK_IMAGE_LAYOUT_GENERAL, image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // 422 dest |
| m_commandBuffer->CopyImage(image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, image_422.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(VkLayerTest, CopyImageMultiplaneAspectBits) { |
| // Image copy tests on multiplane images with aspect errors |
| |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState()); |
| |
| // Select multi-plane formats and verify support |
| VkFormat mp3_format = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR; |
| VkFormat mp2_format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR; |
| |
| VkImageCreateInfo ci = LvlInitStruct<VkImageCreateInfo>(); |
| ci.flags = 0; |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.format = mp2_format; |
| ci.extent = {256, 256, 1}; |
| ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| ci.mipLevels = 1; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| ci.queueFamilyIndexCount = 0; |
| ci.pQueueFamilyIndices = NULL; |
| ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| |
| // Verify formats |
| VkFormatFeatureFlags features = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT; |
| bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); |
| ci.format = VK_FORMAT_D24_UNORM_S8_UINT; |
| supported = supported && ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); |
| ci.format = mp3_format; |
| supported = supported && ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); |
| if (!supported) { |
| // Assume there's low ROI on searching for different mp formats |
| GTEST_SKIP() << "Multiplane image formats or optimally tiled depth-stencil buffers not supported"; |
| } |
| |
| // Create images |
| VkImageObj mp3_image(m_device); |
| mp3_image.init(&ci); |
| ASSERT_TRUE(mp3_image.initialized()); |
| |
| ci.format = mp2_format; |
| VkImageObj mp2_image(m_device); |
| mp2_image.init(&ci); |
| ASSERT_TRUE(mp2_image.initialized()); |
| |
| ci.format = VK_FORMAT_D24_UNORM_S8_UINT; |
| VkImageObj sp_image(m_device); |
| sp_image.init(&ci); |
| ASSERT_TRUE(sp_image.initialized()); |
| |
| m_commandBuffer->begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {128, 128, 1}; |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; |
| copy_region.srcSubresource.mipLevel = 0; |
| copy_region.dstSubresource.mipLevel = 0; |
| copy_region.srcSubresource.baseArrayLayer = 0; |
| copy_region.dstSubresource.baseArrayLayer = 0; |
| copy_region.srcSubresource.layerCount = 1; |
| copy_region.dstSubresource.layerCount = 1; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-srcImage-08713"); |
| m_commandBuffer->CopyImage(mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-srcImage-08713"); |
| m_commandBuffer->CopyImage(mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-dstImage-08714"); |
| m_commandBuffer->CopyImage(mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-dstImage-08714"); |
| m_commandBuffer->CopyImage(mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-srcImage-01556"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-None-01549"); // since also non-compatiable |
| m_commandBuffer->CopyImage(mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, sp_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-dstImage-01557"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyImage-None-01549"); // since also non-compatiable |
| m_commandBuffer->CopyImage(sp_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(VkLayerTest, CreateSamplerYcbcrConversionEnable) { |
| TEST_DESCRIPTION("Checks samplerYcbcrConversion is enabled before calling vkCreateSamplerYcbcrConversion"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| // Explictly not enable Ycbcr Conversion Features |
| VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcr_features = LvlInitStruct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(); |
| ycbcr_features.samplerYcbcrConversion = VK_FALSE; |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &ycbcr_features)); |
| |
| PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionFunction = |
| (PFN_vkCreateSamplerYcbcrConversionKHR)vk::GetDeviceProcAddr(m_device->handle(), "vkCreateSamplerYcbcrConversionKHR"); |
| |
| // Create Ycbcr conversion |
| VkSamplerYcbcrConversion conversions; |
| VkSamplerYcbcrConversionCreateInfo ycbcr_create_info = {VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, |
| NULL, |
| VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR, |
| VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, |
| VK_SAMPLER_YCBCR_RANGE_ITU_FULL, |
| {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}, |
| VK_CHROMA_LOCATION_COSITED_EVEN, |
| VK_CHROMA_LOCATION_COSITED_EVEN, |
| VK_FILTER_NEAREST, |
| false}; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCreateSamplerYcbcrConversion-None-01648"); |
| vkCreateSamplerYcbcrConversionFunction(m_device->handle(), &ycbcr_create_info, nullptr, &conversions); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkLayerTest, ClearColorImageWithInvalidFormat) { |
| TEST_DESCRIPTION("Record clear color with an invalid image formats"); |
| |
| // Enable KHR multiplane req'd extensions |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| VkImageObj mp_image(m_device); |
| VkFormat mp_format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; |
| |
| VkImageCreateInfo image_create_info = LvlInitStruct<VkImageCreateInfo>(); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = mp_format; |
| image_create_info.extent.width = 32; |
| image_create_info.extent.height = 32; |
| image_create_info.extent.depth = 1; |
| image_create_info.mipLevels = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| image_create_info.arrayLayers = 1; |
| |
| bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), image_create_info, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); |
| if (supported == false) { |
| GTEST_SKIP() << "Multiplane image format not supported"; |
| } |
| |
| mp_image.init(&image_create_info); |
| m_commandBuffer->begin(); |
| |
| VkClearColorValue color_clear_value = {}; |
| VkImageSubresourceRange clear_range; |
| clear_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| clear_range.baseMipLevel = 0; |
| clear_range.baseArrayLayer = 0; |
| clear_range.layerCount = 1; |
| clear_range.levelCount = 1; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdClearColorImage-image-01545"); |
| m_commandBuffer->ClearColorImage(mp_image.handle(), VK_IMAGE_LAYOUT_GENERAL, &color_clear_value, 1, &clear_range); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkLayerTest, WriteDescriptorSetYcbcr) { |
| TEST_DESCRIPTION("Attempt to use VkSamplerYcbcrConversion ImageView to update descriptors that are not allowed."); |
| |
| // Enable KHR multiplane req'd extensions |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported."; |
| } |
| |
| // Enable Sampler YCbCr Conversion |
| auto ycbcr_features = LvlInitStruct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(); |
| auto features2 = GetPhysicalDeviceFeatures2(ycbcr_features); |
| if (ycbcr_features.samplerYcbcrConversion == VK_FALSE) { |
| GTEST_SKIP() << "samplerYcbcrConversion feature not supported. Skipped."; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| if (!ImageFormatAndFeaturesSupported(gpu(), VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) { |
| GTEST_SKIP() << "Required formats/features not supported"; |
| } |
| |
| // Create Ycbcr conversion |
| VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; // guaranteed sampling support |
| auto ycbcr_create_info = LvlInitStruct<VkSamplerYcbcrConversionCreateInfo>( |
| nullptr, mp_format, VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, VK_SAMPLER_YCBCR_RANGE_ITU_FULL, |
| VkComponentMapping{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY}, |
| VK_CHROMA_LOCATION_COSITED_EVEN, VK_CHROMA_LOCATION_COSITED_EVEN, VK_FILTER_NEAREST, VK_FALSE); |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, ycbcr_create_info, true); |
| |
| OneOffDescriptorSet descriptor_set(m_device, { |
| {0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| }); |
| |
| VkImageObj image_obj(m_device); |
| auto image_ci = LvlInitStruct<VkImageCreateInfo>( |
| nullptr, VkImageCreateFlags{VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT}, // need for multi-planar |
| VK_IMAGE_TYPE_2D, mp_format, VkExtent3D{64, 64u, 1u}, 1u, 1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, |
| VkImageUsageFlags{VK_IMAGE_USAGE_SAMPLED_BIT}, VK_SHARING_MODE_EXCLUSIVE, 0u, nullptr, VK_IMAGE_LAYOUT_UNDEFINED); |
| image_obj.init(&image_ci); |
| ASSERT_TRUE(image_obj.initialized()); |
| |
| auto ycbcr_info = LvlInitStruct<VkSamplerYcbcrConversionInfo>(); |
| ycbcr_info.conversion = conversion.handle(); |
| |
| auto image_view_create_info = LvlInitStruct<VkImageViewCreateInfo>(&ycbcr_info); |
| image_view_create_info.image = image_obj.handle(); |
| image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; |
| image_view_create_info.format = mp_format; |
| image_view_create_info.subresourceRange.layerCount = 1; |
| image_view_create_info.subresourceRange.baseMipLevel = 0; |
| image_view_create_info.subresourceRange.levelCount = 1; |
| image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| vk_testing::ImageView image_view(*m_device, image_view_create_info); |
| |
| descriptor_set.WriteDescriptorImageInfo(0, image_view.handle(), VK_NULL_HANDLE, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkWriteDescriptorSet-descriptorType-01946"); |
| descriptor_set.UpdateDescriptorSets(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkLayerTest, MultiplaneImageLayoutBadAspectFlags) { |
| TEST_DESCRIPTION("Query layout of a multiplane image using illegal aspect flag masks"); |
| |
| // Enable KHR multiplane req'd extensions |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState()); |
| |
| VkImageCreateInfo ci = LvlInitStruct<VkImageCreateInfo>(); |
| ci.flags = 0; |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR; |
| ci.extent = {128, 128, 1}; |
| ci.mipLevels = 1; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.tiling = VK_IMAGE_TILING_LINEAR; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| |
| // Verify formats |
| bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); |
| ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR; |
| supported = supported && ImageFormatAndFeaturesSupported(instance(), gpu(), ci, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); |
| if (!supported) { |
| // Assume there's low ROI on searching for different mp formats |
| GTEST_SKIP() << "Multiplane image format not supported"; |
| } |
| |
| VkImage image_2plane, image_3plane; |
| ci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR; |
| VkResult err = vk::CreateImage(device(), &ci, NULL, &image_2plane); |
| ASSERT_VK_SUCCESS(err); |
| |
| ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR; |
| err = vk::CreateImage(device(), &ci, NULL, &image_3plane); |
| ASSERT_VK_SUCCESS(err); |
| |
| // Query layout of 3rd plane, for a 2-plane image |
| VkImageSubresource subres = {}; |
| subres.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; |
| subres.mipLevel = 0; |
| subres.arrayLayer = 0; |
| VkSubresourceLayout layout = {}; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkGetImageSubresourceLayout-tiling-08717"); |
| vk::GetImageSubresourceLayout(device(), image_2plane, &subres, &layout); |
| m_errorMonitor->VerifyFound(); |
| |
| // Query layout using color aspect, for a 3-plane image |
| subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkGetImageSubresourceLayout-tiling-08717"); |
| vk::GetImageSubresourceLayout(device(), image_3plane, &subres, &layout); |
| m_errorMonitor->VerifyFound(); |
| |
| // Clean up |
| vk::DestroyImage(device(), image_2plane, NULL); |
| vk::DestroyImage(device(), image_3plane, NULL); |
| } |
| |
| TEST_F(VkLayerTest, BindInvalidMemoryYcbcr) { |
| // Enable KHR YCbCr req'd extensions for Disjoint Bit |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState()); |
| |
| // Create aliased function pointers for 1.0 and 1.1 contexts |
| PFN_vkBindImageMemory2KHR vkBindImageMemory2Function = nullptr; |
| PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2Function = nullptr; |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { |
| vkBindImageMemory2Function = vk::BindImageMemory2; |
| vkGetImageMemoryRequirements2Function = vk::GetImageMemoryRequirements2; |
| } else { |
| vkBindImageMemory2Function = (PFN_vkBindImageMemory2KHR)vk::GetDeviceProcAddr(m_device->handle(), "vkBindImageMemory2KHR"); |
| vkGetImageMemoryRequirements2Function = |
| (PFN_vkGetImageMemoryRequirements2KHR)vk::GetDeviceProcAddr(m_device->handle(), "vkGetImageMemoryRequirements2KHR"); |
| } |
| |
| // Try to bind an image created with Disjoint bit |
| VkFormatProperties format_properties; |
| VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| vk::GetPhysicalDeviceFormatProperties(m_device->phy().handle(), mp_format, &format_properties); |
| // Need to make sure disjoint is supported for format |
| // Also need to support an arbitrary image usage feature |
| constexpr VkFormatFeatureFlags disjoint_sampled = VK_FORMAT_FEATURE_DISJOINT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; |
| if (disjoint_sampled != (format_properties.optimalTilingFeatures & disjoint_sampled)) { |
| printf("test requires disjoint and sampled feature bit on format. Skipping.\n"); |
| } else { |
| VkImageCreateInfo image_create_info = LvlInitStruct<VkImageCreateInfo>(); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = mp_format; |
| image_create_info.extent.width = 64; |
| image_create_info.extent.height = 64; |
| image_create_info.extent.depth = 1; |
| image_create_info.mipLevels = 1; |
| image_create_info.arrayLayers = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT; |
| |
| VkImage image; |
| ASSERT_VK_SUCCESS(vk::CreateImage(device(), &image_create_info, NULL, &image)); |
| |
| VkImagePlaneMemoryRequirementsInfo image_plane_req = LvlInitStruct<VkImagePlaneMemoryRequirementsInfo>(); |
| image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| |
| VkImageMemoryRequirementsInfo2 mem_req_info2 = LvlInitStruct<VkImageMemoryRequirementsInfo2>(&image_plane_req); |
| mem_req_info2.image = image; |
| VkMemoryRequirements2 mem_req2 = LvlInitStruct<VkMemoryRequirements2>(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mem_req2); |
| |
| // Find a valid memory type index to memory to be allocated from |
| VkMemoryAllocateInfo alloc_info = LvlInitStruct<VkMemoryAllocateInfo>(); |
| alloc_info.allocationSize = mem_req2.memoryRequirements.size; |
| ASSERT_TRUE(m_device->phy().set_memory_type(mem_req2.memoryRequirements.memoryTypeBits, &alloc_info, 0)); |
| |
| VkDeviceMemory image_memory; |
| ASSERT_VK_SUCCESS(vk::AllocateMemory(device(), &alloc_info, NULL, &image_memory)); |
| |
| // Bind disjoint with BindImageMemory instead of BindImageMemory2 |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkBindImageMemory-image-01608"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-image-07736"); |
| vk::BindImageMemory(device(), image, image_memory, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| VkBindImagePlaneMemoryInfo plane_memory_info = LvlInitStruct<VkBindImagePlaneMemoryInfo>(); |
| ASSERT_TRUE(FormatPlaneCount(mp_format) == 2); |
| plane_memory_info.planeAspect = VK_IMAGE_ASPECT_PLANE_2_BIT; |
| |
| VkBindImageMemoryInfo bind_image_info = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info); |
| bind_image_info.image = image; |
| bind_image_info.memory = image_memory; |
| bind_image_info.memoryOffset = 0; |
| |
| // Set invalid planeAspect |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImagePlaneMemoryInfo-planeAspect-02283"); |
| // Error is thrown from not having both planes bound |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkBindImageMemory2-pBindInfos-02858"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkBindImageMemory2-pBindInfos-02858"); |
| // Might happen as plane2 wasn't queried for its memroy type |
| m_errorMonitor->SetUnexpectedError("VUID-VkBindImageMemoryInfo-pNext-01619"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkBindImageMemoryInfo-pNext-01621"); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::FreeMemory(device(), image_memory, NULL); |
| vk::DestroyImage(device(), image, nullptr); |
| } |
| |
| // Bind image with VkBindImagePlaneMemoryInfo without disjoint bit in image |
| // Need to support an arbitrary image usage feature for multi-planar format |
| if (0 == (format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { |
| printf("test requires sampled feature bit on multi-planar format. Skipping.\n"); |
| } else { |
| VkImageCreateInfo image_create_info = LvlInitStruct<VkImageCreateInfo>(); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = mp_format; |
| image_create_info.extent.width = 64; |
| image_create_info.extent.height = 64; |
| image_create_info.extent.depth = 1; |
| image_create_info.mipLevels = 1; |
| image_create_info.arrayLayers = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| image_create_info.flags = 0; // no disjoint bit set |
| |
| VkImage image; |
| ASSERT_VK_SUCCESS(vk::CreateImage(device(), &image_create_info, NULL, &image)); |
| |
| VkImageMemoryRequirementsInfo2 mem_req_info2 = LvlInitStruct<VkImageMemoryRequirementsInfo2>(); |
| mem_req_info2.image = image; |
| VkMemoryRequirements2 mem_req2 = LvlInitStruct<VkMemoryRequirements2>(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mem_req2); |
| |
| // Find a valid memory type index to memory to be allocated from |
| VkMemoryAllocateInfo alloc_info = LvlInitStruct<VkMemoryAllocateInfo>(); |
| alloc_info.allocationSize = mem_req2.memoryRequirements.size; |
| ASSERT_TRUE(m_device->phy().set_memory_type(mem_req2.memoryRequirements.memoryTypeBits, &alloc_info, 0)); |
| |
| VkDeviceMemory image_memory; |
| ASSERT_VK_SUCCESS(vk::AllocateMemory(device(), &alloc_info, NULL, &image_memory)); |
| |
| VkBindImagePlaneMemoryInfo plane_memory_info = LvlInitStruct<VkBindImagePlaneMemoryInfo>(); |
| plane_memory_info.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| VkBindImageMemoryInfo bind_image_info = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info); |
| bind_image_info.image = image; |
| bind_image_info.memory = image_memory; |
| bind_image_info.memoryOffset = 0; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-pNext-01618"); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::FreeMemory(device(), image_memory, NULL); |
| vk::DestroyImage(device(), image, nullptr); |
| } |
| } |
| |
| TEST_F(VkLayerTest, BindInvalidMemory2Disjoint) { |
| TEST_DESCRIPTION("These tests deal with VK_KHR_bind_memory_2 and disjoint memory being bound"); |
| |
| // Enable KHR YCbCr req'd extensions for Disjoint Bit |
| AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); |
| AddOptionalExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| AddOptionalExtensions(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| const bool mp_supported = IsExtensionsEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| bool amd_coherent_mem = IsExtensionsEnabled(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME); |
| |
| if (amd_coherent_mem) { |
| auto coherent_mem_features = LvlInitStruct<VkPhysicalDeviceCoherentMemoryFeaturesAMD>(); |
| GetPhysicalDeviceFeatures2(coherent_mem_features); |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &coherent_mem_features)); |
| } else { |
| ASSERT_NO_FATAL_FAILURE(InitState()); |
| } |
| |
| // Create aliased function pointers for 1.0 and 1.1 contexts |
| PFN_vkBindImageMemory2KHR vkBindImageMemory2Function = nullptr; |
| PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2Function = nullptr; |
| |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { |
| vkBindImageMemory2Function = vk::BindImageMemory2; |
| } else { |
| vkBindImageMemory2Function = (PFN_vkBindImageMemory2KHR)vk::GetDeviceProcAddr(m_device->handle(), "vkBindImageMemory2KHR"); |
| } |
| |
| if (mp_supported) { |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { |
| vkGetImageMemoryRequirements2Function = vk::GetImageMemoryRequirements2; |
| } else { |
| vkGetImageMemoryRequirements2Function = |
| (PFN_vkGetImageMemoryRequirements2KHR)vk::GetDeviceProcAddr(m_device->handle(), "vkGetImageMemoryRequirements2KHR"); |
| } |
| } |
| |
| const VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM; |
| |
| VkImageCreateInfo image_create_info = LvlInitStruct<VkImageCreateInfo>(); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = tex_format; |
| image_create_info.extent.width = 256; |
| image_create_info.extent.height = 256; |
| image_create_info.extent.depth = 1; |
| image_create_info.mipLevels = 1; |
| image_create_info.arrayLayers = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| image_create_info.flags = 0; |
| |
| // Only gets used in MP tests |
| VkImageCreateInfo mp_image_create_info = image_create_info; |
| mp_image_create_info.format = mp_format; |
| mp_image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT; |
| |
| // Check for support of format used by all multi-planar tests |
| // Need seperate boolean as its valid to do tests that support YCbCr but not disjoint |
| bool mp_disjoint_support = false; |
| if (mp_supported) { |
| VkFormatProperties mp_format_properties; |
| vk::GetPhysicalDeviceFormatProperties(m_device->phy().handle(), mp_format, &mp_format_properties); |
| if ((mp_format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DISJOINT_BIT) && |
| (mp_format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { |
| mp_disjoint_support = true; |
| } |
| } |
| |
| // Try to bind memory to an object with an invalid memoryOffset |
| |
| vk_testing::Image image; |
| image.init_no_mem(*m_device, image_create_info); |
| ASSERT_TRUE(image.initialized()); |
| VkMemoryRequirements image_mem_reqs = {}; |
| vk::GetImageMemoryRequirements(device(), image.handle(), &image_mem_reqs); |
| VkMemoryAllocateInfo image_alloc_info = LvlInitStruct<VkMemoryAllocateInfo>(); |
| // Leave some extra space for alignment wiggle room |
| image_alloc_info.allocationSize = image_mem_reqs.size + image_mem_reqs.alignment; |
| ASSERT_TRUE(m_device->phy().set_memory_type(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0)); |
| vk_testing::DeviceMemory image_mem(*m_device, image_alloc_info); |
| ASSERT_TRUE(image_mem.initialized()); |
| |
| // Keep values outside scope so multiple tests cases can reuse |
| vk_testing::Image mp_image; |
| vk_testing::DeviceMemory mp_image_mem[2]; |
| VkMemoryRequirements2 mp_image_mem_reqs2[2]; |
| VkMemoryAllocateInfo mp_image_alloc_info[2]; |
| if (mp_disjoint_support) { |
| mp_image.init_no_mem(*m_device, mp_image_create_info); |
| ASSERT_TRUE(mp_image.initialized()); |
| |
| VkImagePlaneMemoryRequirementsInfo image_plane_req = LvlInitStruct<VkImagePlaneMemoryRequirementsInfo>(); |
| image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| |
| VkImageMemoryRequirementsInfo2 mem_req_info2 = LvlInitStruct<VkImageMemoryRequirementsInfo2>(&image_plane_req); |
| mem_req_info2.image = mp_image.handle(); |
| mp_image_mem_reqs2[0] = LvlInitStruct<VkMemoryRequirements2>(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mp_image_mem_reqs2[0]); |
| |
| image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| mp_image_mem_reqs2[1] = LvlInitStruct<VkMemoryRequirements2>(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mp_image_mem_reqs2[1]); |
| |
| mp_image_alloc_info[0] = LvlInitStruct<VkMemoryAllocateInfo>(); |
| mp_image_alloc_info[1] = LvlInitStruct<VkMemoryAllocateInfo>(); |
| // Leave some extra space for alignment wiggle room |
| // plane 0 |
| mp_image_alloc_info[0].allocationSize = |
| mp_image_mem_reqs2[0].memoryRequirements.size + mp_image_mem_reqs2[0].memoryRequirements.alignment; |
| ASSERT_TRUE( |
| m_device->phy().set_memory_type(mp_image_mem_reqs2[0].memoryRequirements.memoryTypeBits, &mp_image_alloc_info[0], 0)); |
| // Exact size as VU will always be for plane 1 |
| // plane 1 |
| mp_image_alloc_info[1].allocationSize = mp_image_mem_reqs2[1].memoryRequirements.size; |
| ASSERT_TRUE( |
| m_device->phy().set_memory_type(mp_image_mem_reqs2[1].memoryRequirements.memoryTypeBits, &mp_image_alloc_info[1], 0)); |
| |
| mp_image_mem[0].init(*m_device, mp_image_alloc_info[0]); |
| ASSERT_TRUE(mp_image_mem[0].initialized()); |
| mp_image_mem[1].init(*m_device, mp_image_alloc_info[1]); |
| ASSERT_TRUE(mp_image_mem[1].initialized()); |
| } |
| |
| // All planes must be bound at once the same here |
| VkBindImagePlaneMemoryInfo plane_memory_info[2]; |
| plane_memory_info[0] = LvlInitStruct<VkBindImagePlaneMemoryInfo>(); |
| plane_memory_info[0].planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| plane_memory_info[1] = LvlInitStruct<VkBindImagePlaneMemoryInfo>(); |
| plane_memory_info[1].planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| |
| // Test unaligned memory offset |
| |
| // single-plane image |
| VkBindImageMemoryInfo bind_image_info = LvlInitStruct<VkBindImageMemoryInfo>(); |
| bind_image_info.image = image.handle(); |
| bind_image_info.memory = image_mem.handle(); |
| bind_image_info.memoryOffset = 1; // off alignment |
| |
| if (mp_disjoint_support == true) { |
| VkImageMemoryRequirementsInfo2 mem_req_info2 = LvlInitStruct<VkImageMemoryRequirementsInfo2>(); |
| mem_req_info2.image = image.handle(); |
| VkMemoryRequirements2 mem_req2 = LvlInitStruct<VkMemoryRequirements2>(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mem_req2); |
| |
| if (mem_req2.memoryRequirements.alignment > 1) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-pNext-01616"); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| } else { |
| // Same as 01048 but with bindImageMemory2 call |
| if (image_mem_reqs.alignment > 1) { |
| const char *vuid = |
| (mp_supported) ? "VUID-VkBindImageMemoryInfo-pNext-01616" : "VUID-VkBindImageMemoryInfo-memoryOffset-01613"; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, vuid); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Multi-plane image |
| if (mp_disjoint_support == true) { |
| if (mp_image_mem_reqs2[0].memoryRequirements.alignment > 1) { |
| VkBindImageMemoryInfo bind_image_infos[2]; |
| bind_image_infos[0] = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info[0]); |
| bind_image_infos[0].image = mp_image.handle(); |
| bind_image_infos[0].memory = mp_image_mem[0].handle(); |
| bind_image_infos[0].memoryOffset = 1; // off alignment |
| bind_image_infos[1] = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info[1]); |
| bind_image_infos[1].image = mp_image.handle(); |
| bind_image_infos[1].memory = mp_image_mem[1].handle(); |
| bind_image_infos[1].memoryOffset = 0; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-pNext-01620"); |
| vkBindImageMemory2Function(device(), 2, bind_image_infos); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Test memory offsets within the memory allocation, but which leave too little memory for |
| // the resource. |
| // single-plane image |
| bind_image_info = LvlInitStruct<VkBindImageMemoryInfo>(); |
| bind_image_info.image = image.handle(); |
| bind_image_info.memory = image_mem.handle(); |
| |
| if (mp_disjoint_support == true) { |
| VkImageMemoryRequirementsInfo2 mem_req_info2 = LvlInitStruct<VkImageMemoryRequirementsInfo2>(); |
| mem_req_info2.image = image.handle(); |
| VkMemoryRequirements2 mem_req2 = LvlInitStruct<VkMemoryRequirements2>(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mem_req2); |
| |
| VkDeviceSize image2_offset = (mem_req2.memoryRequirements.size - 1) & ~(mem_req2.memoryRequirements.alignment - 1); |
| if ((image2_offset > 0) && |
| (mem_req2.memoryRequirements.size < (image_alloc_info.allocationSize - mem_req2.memoryRequirements.alignment))) { |
| bind_image_info.memoryOffset = image2_offset; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-pNext-01617"); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| } else { |
| // Same as 01049 but with bindImageMemory2 call |
| VkDeviceSize image_offset = (image_mem_reqs.size - 1) & ~(image_mem_reqs.alignment - 1); |
| if ((image_offset > 0) && (image_mem_reqs.size < (image_alloc_info.allocationSize - image_mem_reqs.alignment))) { |
| bind_image_info.memoryOffset = image_offset; |
| const char *vuid = |
| (mp_supported) ? "VUID-VkBindImageMemoryInfo-pNext-01617" : "VUID-VkBindImageMemoryInfo-memory-01614"; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, vuid); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Multi-plane image |
| if (mp_disjoint_support == true) { |
| VkDeviceSize mp_image_offset = |
| (mp_image_mem_reqs2[0].memoryRequirements.size - 1) & ~(mp_image_mem_reqs2[0].memoryRequirements.alignment - 1); |
| if ((mp_image_offset > 0) && |
| (mp_image_mem_reqs2[0].memoryRequirements.size < |
| (mp_image_alloc_info[0].allocationSize - mp_image_mem_reqs2[0].memoryRequirements.alignment))) { |
| VkBindImageMemoryInfo bind_image_infos[2]; |
| bind_image_infos[0] = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info[0]); |
| bind_image_infos[0].image = mp_image.handle(); |
| bind_image_infos[0].memory = mp_image_mem[0].handle(); |
| bind_image_infos[0].memoryOffset = mp_image_offset; // mis-offset |
| bind_image_infos[1] = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info[1]); |
| bind_image_infos[1].image = mp_image.handle(); |
| bind_image_infos[1].memory = mp_image_mem[1].handle(); |
| bind_image_infos[1].memoryOffset = 0; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-pNext-01621"); |
| vkBindImageMemory2Function(device(), 2, bind_image_infos); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Try to bind memory to an object with an invalid memory type |
| |
| // Create a mask of available memory types *not* supported by these resources, and try to use one of them. |
| VkPhysicalDeviceMemoryProperties memory_properties = {}; |
| vk::GetPhysicalDeviceMemoryProperties(m_device->phy().handle(), &memory_properties); |
| |
| // single-plane image |
| bind_image_info = LvlInitStruct<VkBindImageMemoryInfo>(); |
| bind_image_info.image = image.handle(); |
| bind_image_info.memoryOffset = 0; |
| |
| if (mp_disjoint_support == true) { |
| VkImageMemoryRequirementsInfo2 mem_req_info2 = LvlInitStruct<VkImageMemoryRequirementsInfo2>(); |
| mem_req_info2.image = image.handle(); |
| VkMemoryRequirements2 mem_req2 = LvlInitStruct<VkMemoryRequirements2>(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mem_req2); |
| |
| uint32_t image2_unsupported_mem_type_bits = |
| ((1 << memory_properties.memoryTypeCount) - 1) & ~mem_req2.memoryRequirements.memoryTypeBits; |
| if (image2_unsupported_mem_type_bits != 0) { |
| ASSERT_TRUE(m_device->phy().set_memory_type(image2_unsupported_mem_type_bits, &image_alloc_info, 0)); |
| vk_testing::DeviceMemory image_mem_tmp(*m_device, image_alloc_info); |
| ASSERT_TRUE(image_mem_tmp.initialized()); |
| bind_image_info.memory = image_mem_tmp.handle(); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-pNext-01615"); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| } else { |
| // Same as 01047 but with bindImageMemory2 call |
| uint32_t image_unsupported_mem_type_bits = ((1 << memory_properties.memoryTypeCount) - 1) & ~image_mem_reqs.memoryTypeBits; |
| if (image_unsupported_mem_type_bits != 0) { |
| ASSERT_TRUE(m_device->phy().set_memory_type(image_unsupported_mem_type_bits, &image_alloc_info, 0)); |
| vk_testing::DeviceMemory image_mem_tmp(*m_device, image_alloc_info); |
| ASSERT_TRUE(image_mem_tmp.initialized()); |
| bind_image_info.memory = image_mem_tmp.handle(); |
| const char *vuid = |
| (mp_supported) ? "VUID-VkBindImageMemoryInfo-pNext-01615" : "VUID-VkBindImageMemoryInfo-memory-01612"; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, vuid); |
| vkBindImageMemory2Function(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Multi-plane image |
| if (mp_disjoint_support == true) { |
| // Get plane 0 memory requirements |
| VkImagePlaneMemoryRequirementsInfo image_plane_req = LvlInitStruct<VkImagePlaneMemoryRequirementsInfo>(); |
| image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| |
| VkImageMemoryRequirementsInfo2 mem_req_info2 = LvlInitStruct<VkImageMemoryRequirementsInfo2>(&image_plane_req); |
| mem_req_info2.image = mp_image.handle(); |
| vkGetImageMemoryRequirements2Function(device(), &mem_req_info2, &mp_image_mem_reqs2[0]); |
| |
| uint32_t mp_image_unsupported_mem_type_bits = |
| ((1 << memory_properties.memoryTypeCount) - 1) & ~mp_image_mem_reqs2[0].memoryRequirements.memoryTypeBits; |
| if (mp_image_unsupported_mem_type_bits != 0) { |
| mp_image_alloc_info[0].allocationSize = mp_image_mem_reqs2[0].memoryRequirements.size; |
| ASSERT_TRUE(m_device->phy().set_memory_type(mp_image_unsupported_mem_type_bits, &mp_image_alloc_info[0], 0)); |
| vk_testing::DeviceMemory mp_image_mem_tmp(*m_device, mp_image_alloc_info[0]); |
| ASSERT_TRUE(mp_image_mem_tmp.initialized()); |
| |
| VkBindImageMemoryInfo bind_image_infos[2]; |
| bind_image_infos[0] = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info[0]); |
| bind_image_infos[0].image = mp_image.handle(); |
| bind_image_infos[0].memory = mp_image_mem_tmp.handle(); |
| bind_image_infos[0].memoryOffset = 0; |
| bind_image_infos[1] = LvlInitStruct<VkBindImageMemoryInfo>(&plane_memory_info[1]); |
| bind_image_infos[1].image = mp_image.handle(); |
| bind_image_infos[1].memory = mp_image_mem[1].handle(); |
| bind_image_infos[1].memoryOffset = 0; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindImageMemoryInfo-pNext-01619"); |
| vkBindImageMemory2Function(device(), 2, bind_image_infos); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| } |
| |
| TEST_F(VkLayerTest, MismatchedImageViewAndSamplerYcbcrFormat) { |
| TEST_DESCRIPTION("Create image view with a different format that SamplerYcbcr was created with."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| if (DeviceValidationVersion() < VK_API_VERSION_1_2) { |
| GTEST_SKIP() << "At least Vulkan version 1.2 is required"; |
| } |
| |
| auto features11 = LvlInitStruct<VkPhysicalDeviceVulkan11Features>(); |
| auto features2 = LvlInitStruct<VkPhysicalDeviceFeatures2>(&features11); |
| vk::GetPhysicalDeviceFeatures2(gpu(), &features2); |
| if (features11.samplerYcbcrConversion != VK_TRUE) { |
| GTEST_SKIP() << "SamplerYcbcrConversion not supported"; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| VkImageObj image(m_device); |
| image.Init(128, 128, 1, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); |
| ASSERT_TRUE(image.initialized()); |
| |
| auto sampler_conversion_ci = LvlInitStruct<VkSamplerYcbcrConversionCreateInfo>(); |
| sampler_conversion_ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; |
| sampler_conversion_ci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; |
| sampler_conversion_ci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; |
| sampler_conversion_ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY}; |
| sampler_conversion_ci.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| sampler_conversion_ci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| sampler_conversion_ci.chromaFilter = VK_FILTER_NEAREST; |
| sampler_conversion_ci.forceExplicitReconstruction = false; |
| |
| vk_testing::SamplerYcbcrConversion sampler_conversion; |
| sampler_conversion.init(*m_device, sampler_conversion_ci, false); |
| |
| auto sampler_ycbcr_conversion_info = LvlInitStruct<VkSamplerYcbcrConversionInfo>(); |
| sampler_ycbcr_conversion_info.conversion = sampler_conversion.handle(); |
| |
| VkImageViewCreateInfo view_info = LvlInitStruct<VkImageViewCreateInfo>(&sampler_ycbcr_conversion_info); |
| view_info.flags = 0; |
| view_info.image = image.handle(); |
| view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; |
| view_info.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| view_info.subresourceRange.layerCount = 1; |
| view_info.subresourceRange.baseMipLevel = 0; |
| view_info.subresourceRange.levelCount = 1; |
| view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| |
| CreateImageViewTest(*this, &view_info, "VUID-VkImageViewCreateInfo-pNext-06658"); |
| } |
| |
| TEST_F(VkLayerTest, MultiplaneIncompatibleViewFormat) { |
| TEST_DESCRIPTION("Postive/negative tests of multiplane imageview format compatibility"); |
| |
| // Use 1.1 to get VK_KHR_sampler_ycbcr_conversion easier |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| if (DeviceValidationVersion() < VK_API_VERSION_1_2) { |
| GTEST_SKIP() << "At least Vulkan version 1.2 is required"; |
| } |
| // This test hits a bug in the driver, CTS was written, but incase using an old driver |
| if (IsDriver(VK_DRIVER_ID_NVIDIA_PROPRIETARY)) { |
| GTEST_SKIP() << "This test should not be run on the NVIDIA proprietary driver."; |
| } |
| |
| auto features11 = LvlInitStruct<VkPhysicalDeviceVulkan11Features>(); |
| auto features2 = GetPhysicalDeviceFeatures2(features11); |
| if (features11.samplerYcbcrConversion != VK_TRUE) { |
| printf("samplerYcbcrConversion not supported, skipping test\n"); |
| return; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| if (!ImageFormatAndFeaturesSupported(gpu(), VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) { |
| GTEST_SKIP() << "Required formats/features not supported"; |
| } |
| |
| VkSamplerYcbcrConversionCreateInfo ycbcr_create_info = LvlInitStruct<VkSamplerYcbcrConversionCreateInfo>(); |
| ycbcr_create_info.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; |
| ycbcr_create_info.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; |
| ycbcr_create_info.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; |
| ycbcr_create_info.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY}; |
| ycbcr_create_info.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| ycbcr_create_info.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| ycbcr_create_info.chromaFilter = VK_FILTER_NEAREST; |
| ycbcr_create_info.forceExplicitReconstruction = false; |
| |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, ycbcr_create_info); |
| |
| VkSamplerYcbcrConversionInfo ycbcr_info = LvlInitStruct<VkSamplerYcbcrConversionInfo>(); |
| ycbcr_info.conversion = conversion; |
| |
| VkImageCreateInfo ci = LvlInitStruct<VkImageCreateInfo>(); |
| ci.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; |
| ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| ci.extent = {128, 128, 1}; |
| ci.mipLevels = 1; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| |
| const VkFormatFeatureFlags features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; |
| bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); |
| // Verify format 3 Plane format |
| if (!supported) { |
| printf("Multiplane image format not supported. Skipping test.\n"); |
| } else { |
| VkImageObj image_obj(m_device); |
| image_obj.init(&ci); |
| ASSERT_TRUE(image_obj.initialized()); |
| |
| VkImageViewCreateInfo ivci = LvlInitStruct<VkImageViewCreateInfo>(); |
| ivci.image = image_obj.image(); |
| ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; |
| ivci.format = VK_FORMAT_R8G8_UNORM; // Compat is VK_FORMAT_R8_UNORM |
| ivci.subresourceRange.layerCount = 1; |
| ivci.subresourceRange.baseMipLevel = 0; |
| ivci.subresourceRange.levelCount = 1; |
| ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| |
| // Incompatible format error |
| CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-image-01586"); |
| |
| // Correct format succeeds |
| ivci.format = VK_FORMAT_R8_UNORM; |
| CreateImageViewTest(*this, &ivci); |
| |
| // R8_SNORM is compatible with R8_UNORM |
| ivci.format = VK_FORMAT_R8_SNORM; |
| CreateImageViewTest(*this, &ivci); |
| |
| // Try a multiplane imageview |
| ivci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; |
| ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-format-06415"); |
| |
| // If using multiplan format, need a matching VkSamplerYcbcrConversion |
| ivci.pNext = &ycbcr_info; |
| CreateImageViewTest(*this, &ivci); |
| } |
| |
| ci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); |
| // Verify format 2 Plane format |
| if (!supported) { |
| printf("Multiplane image format not supported. Skipping test.\n"); |
| } else { |
| VkImageObj image_obj(m_device); |
| image_obj.init(&ci); |
| ASSERT_TRUE(image_obj.initialized()); |
| |
| VkImageViewCreateInfo ivci = LvlInitStruct<VkImageViewCreateInfo>(); |
| ivci.image = image_obj.image(); |
| ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; |
| ivci.subresourceRange.layerCount = 1; |
| ivci.subresourceRange.baseMipLevel = 0; |
| ivci.subresourceRange.levelCount = 1; |
| |
| // Plane 0 is compatible with VK_FORMAT_R8_UNORM |
| // Plane 1 is compatible with VK_FORMAT_R8G8_UNORM |
| |
| // Correct format succeeds |
| ivci.format = VK_FORMAT_R8_UNORM; |
| ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| CreateImageViewTest(*this, &ivci); |
| |
| ivci.format = VK_FORMAT_R8G8_UNORM; |
| ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| CreateImageViewTest(*this, &ivci); |
| |
| // Incompatible format error |
| ivci.format = VK_FORMAT_R8_UNORM; |
| ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-image-01586"); |
| |
| ivci.format = VK_FORMAT_R8G8_UNORM; |
| ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-image-01586"); |
| } |
| } |
| |
| TEST_F(VkLayerTest, MultiplaneAspectBits) { |
| TEST_DESCRIPTION("Attempt to update descriptor sets for images that do not have correct aspect bits sets."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| auto ycbcr_features = LvlInitStruct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(); |
| GetPhysicalDeviceFeatures2(ycbcr_features); |
| if (ycbcr_features.samplerYcbcrConversion != VK_TRUE) { |
| GTEST_SKIP() << "samplerYcbcrConversion feature not supported"; |
| } |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required."; |
| } |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &ycbcr_features)); |
| |
| if (!ImageFormatAndFeaturesSupported(gpu(), VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) { |
| GTEST_SKIP() << "Required formats/features not supported"; |
| } |
| |
| VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; // commonly supported multi-planar format |
| VkImageObj image_obj(m_device); |
| VkFormatProperties format_props; |
| vk::GetPhysicalDeviceFormatProperties(m_device->phy().handle(), mp_format, &format_props); |
| if (!image_obj.IsCompatible(VK_IMAGE_USAGE_SAMPLED_BIT, format_props.optimalTilingFeatures)) { |
| GTEST_SKIP() << "multi-planar format cannot be sampled for optimalTiling."; |
| } |
| |
| auto image_ci = LvlInitStruct<VkImageCreateInfo>( |
| nullptr, VkImageCreateFlags{VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT}, // need for multi-planar |
| VK_IMAGE_TYPE_2D, mp_format, VkExtent3D{64, 64, 1}, 1u, 1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, |
| VkImageUsageFlags{VK_IMAGE_USAGE_SAMPLED_BIT}, VK_SHARING_MODE_EXCLUSIVE, 0u, nullptr, VK_IMAGE_LAYOUT_UNDEFINED); |
| image_obj.init(&image_ci); |
| ASSERT_TRUE(image_obj.initialized()); |
| |
| auto ycbcr_create_info = LvlInitStruct<VkSamplerYcbcrConversionCreateInfo>(); |
| ycbcr_create_info.format = mp_format; |
| ycbcr_create_info.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; |
| ycbcr_create_info.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; |
| ycbcr_create_info.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY}; |
| ycbcr_create_info.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| ycbcr_create_info.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| ycbcr_create_info.chromaFilter = VK_FILTER_NEAREST; |
| ycbcr_create_info.forceExplicitReconstruction = false; |
| |
| vk_testing::SamplerYcbcrConversion conversion(*m_device, ycbcr_create_info, true); |
| |
| auto ycbcr_info = LvlInitStruct<VkSamplerYcbcrConversionInfo>(); |
| ycbcr_info.conversion = conversion.handle(); |
| |
| auto image_view_ci = image_obj.TargetViewCI(mp_format); |
| image_view_ci.pNext = &ycbcr_info; |
| auto image_view = image_obj.targetView(image_view_ci); |
| |
| VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); |
| sampler_ci.pNext = &ycbcr_info; |
| vk_testing::Sampler sampler(*m_device, sampler_ci); |
| ASSERT_TRUE(sampler.initialized()); |
| |
| OneOffDescriptorSet descriptor_set( |
| m_device, { |
| {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, &sampler.handle()}, |
| }); |
| |
| if (descriptor_set.set_ == VK_NULL_HANDLE) { |
| GTEST_SKIP() << "Couldn't create descriptor set"; |
| } |
| |
| // TODO - 01564 appears to be impossible to hit due to the following check in descriptor_validation.cpp: |
| // if (sampler && !desc->IsImmutableSampler() && FormatIsMultiplane(image_state->createInfo.format)) ... |
| // - !desc->IsImmutableSampler() will cause 02738; IOW, multi-plane conversion _requires_ an immutable sampler |
| // - !desc->IsImmutableSampler() must be removed for 01564 to get hit, but it's not clear whether or not this is |
| // correct based on the comments in the code |
| // m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkDescriptorImageInfo-sampler-01564"); |
| descriptor_set.WriteDescriptorImageInfo(0, image_view, sampler.handle(), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); |
| descriptor_set.UpdateDescriptorSets(); |
| // m_errorMonitor->VerifyFound(); |
| } |