diff --git a/tests/framework/layer_validation_tests.h b/tests/framework/layer_validation_tests.h index 6a6b662fe7c..2e26c3b39b8 100644 --- a/tests/framework/layer_validation_tests.h +++ b/tests/framework/layer_validation_tests.h @@ -417,7 +417,7 @@ class PositiveGraphicsLibrary : public GraphicsLibraryTest {}; class NegativeHostImageCopy : public virtual VkLayerTest { protected: - void InitHostImageCopyTest(VkFormat &compressed_format); + void InitHostImageCopyTest(VkFormat &compressed_format, bool separate_depth_stencil = false); }; ; diff --git a/tests/unit/host_image_copy.cpp b/tests/unit/host_image_copy.cpp index 00a0d45cd8d..d68e5e3c28e 100644 --- a/tests/unit/host_image_copy.cpp +++ b/tests/unit/host_image_copy.cpp @@ -21,7 +21,7 @@ bool copy_layout_supported(std::vector ©_src_layouts, std::ve (std::find(copy_dst_layouts.begin(), copy_dst_layouts.end(), layout) != copy_dst_layouts.end())); } -void NegativeHostImageCopy::InitHostImageCopyTest(VkFormat &compressed_format) { +void NegativeHostImageCopy::InitHostImageCopyTest(VkFormat &compressed_format, bool separate_depth_stencil) { SetTargetApiVersion(VK_API_VERSION_1_2); AddRequiredExtensions(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME); ASSERT_NO_FATAL_FAILURE(InitFramework()); @@ -33,12 +33,13 @@ void NegativeHostImageCopy::InitHostImageCopyTest(VkFormat &compressed_format) { GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; } - auto host_copy_features = LvlInitStruct(); + auto separate_depth_stencil_layouts_features = LvlInitStruct(); + auto host_copy_features = LvlInitStruct(&separate_depth_stencil_layouts_features); GetPhysicalDeviceFeatures2(host_copy_features); if (!host_copy_features.hostImageCopy) { GTEST_SKIP() << "Test requires (unsupported) multiDraw"; } - + separate_depth_stencil = separate_depth_stencil_layouts_features.separateDepthStencilLayouts; VkPhysicalDeviceFeatures device_features = {}; ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); compressed_format = VK_FORMAT_UNDEFINED; @@ -1269,3 +1270,202 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToImage) { m_errorMonitor->VerifyFound(); image_copy_2.srcSubresource.layerCount = 1; } + +TEST_F(NegativeHostImageCopy, HostTransitionImageLayout) { + TEST_DESCRIPTION("Use VK_EXT_host_image_copy to copy from images to memory and vice versa"); + VkFormat compressed_format = VK_FORMAT_UNDEFINED; + bool separate_depth_stencil = false; + InitHostImageCopyTest(compressed_format, separate_depth_stencil); + if (::testing::Test::IsSkipped()) return; + + uint32_t width = 32; + uint32_t height = 32; + VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; + + auto image_ci = VkImageObj::ImageCreateInfo2D( + width, height, 1, 1, format, + VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + VK_IMAGE_TILING_OPTIMAL); + VkImageFormatProperties img_prop = {}; + if (VK_SUCCESS != vk::GetPhysicalDeviceImageFormatProperties(m_device->phy().handle(), image_ci.format, image_ci.imageType, + image_ci.tiling, image_ci.usage, image_ci.flags, &img_prop)) { + GTEST_SKIP() << "Required formats/features not supported"; + } + + auto host_image_copy_props = LvlInitStruct(); + GetPhysicalDeviceProperties2(host_image_copy_props); + std::vector copy_src_layouts; + std::vector copy_dst_layouts; + copy_src_layouts.resize(host_image_copy_props.copySrcLayoutCount); + copy_dst_layouts.resize(host_image_copy_props.copyDstLayoutCount); + host_image_copy_props.pCopySrcLayouts = copy_src_layouts.data(); + host_image_copy_props.pCopyDstLayouts = copy_dst_layouts.data(); + GetPhysicalDeviceProperties2(host_image_copy_props); + if (!copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) || + !copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_GENERAL)) { + GTEST_SKIP() << "Required formats/features not supported"; + } + + VkImageSubresourceRange range = {}; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.layerCount = 1; + range.levelCount = 1; + auto transition_info = LvlInitStruct(); + transition_info.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + transition_info.newLayout = VK_IMAGE_LAYOUT_GENERAL; + transition_info.subresourceRange = range; + + { + auto image_ci_no_transfer = VkImageObj::ImageCreateInfo2D(width, height, 1, 1, format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_IMAGE_TILING_OPTIMAL); + // Missing transfer usage + VkImageObj image_no_transfer(m_device); + image_no_transfer.Init(image_ci_no_transfer); + image_no_transfer.SetLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + transition_info.image = image_no_transfer; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-image-09055"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + } + + VkImageObj image(m_device); + image.Init(image_ci); + transition_info.image = image; + + // Bad baseMipLevel + transition_info.subresourceRange.baseMipLevel = 1; + transition_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01486"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + transition_info.subresourceRange.baseMipLevel = 0; + + // Bad baseMipLevel + levelCount + transition_info.subresourceRange.levelCount = 2; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01724"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + transition_info.subresourceRange.levelCount = 1; + + // Bad baseArrayLayer + // Also has to get baseArrayLayer + layerCount > arrayLayers, so test both + transition_info.subresourceRange.baseArrayLayer = 1; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01725"); + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01488"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + transition_info.subresourceRange.baseArrayLayer = 0; + + { + // No image memory + VkImageObj image_no_mem(m_device); + image_no_mem.init_no_mem(*m_device, image_ci); + transition_info.image = image_no_mem; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-image-01932"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + } + + // Bad aspectMask + transition_info.image = image; + transition_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-image-01671"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + transition_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + if (VK_SUCCESS == vk::GetPhysicalDeviceImageFormatProperties( + m_device->phy().handle(), VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &img_prop)) { + // imageSubresource.aspectMask must be VK_IMAGE_ASPECT_PLANE_0_BIT or VK_IMAGE_ASPECT_PLANE_1_BIT + VkImageObj image_multi_planar(m_device); + image_multi_planar.Init(128, 128, 1, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, + 0); + image_multi_planar.SetLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + transition_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + transition_info.image = image_multi_planar; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-image-01671"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + transition_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + transition_info.image = image; + } + + if (copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) && + copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL) && + copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL)) { + auto stencil_format = FindSupportedDepthStencilFormat(gpu()); + if (VK_SUCCESS == vk::GetPhysicalDeviceImageFormatProperties( + m_device->phy().handle(), stencil_format, image_ci.imageType, image_ci.tiling, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT, image_ci.flags, + &img_prop)) { + VkImageObj image_stencil(m_device); + image_ci.format = stencil_format; + image_ci.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT; + image_stencil.Init(image_ci); + image_stencil.SetLayout((VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT), + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); + transition_info.image = image_stencil; + transition_info.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + if (separate_depth_stencil) { + transition_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; + // Will get error for aspect != color + m_errorMonitor->SetUnexpectedError("VUID-VkHostImageLayoutTransitionInfoEXT-image-01671"); + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-image-03319"); + } else { + transition_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + // Will get error for aspect != color + m_errorMonitor->SetUnexpectedError("VUID-VkHostImageLayoutTransitionInfoEXT-image-01671"); + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-image-03320"); + } + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + + // subresourceRange includes VK_IMAGE_ASPECT_DEPTH_BIT, oldLayout and newLayout must not be one of + // VK_IMAGE_LAYOUT_STENCIL_*_OPTIMAL + transition_info.subresourceRange.aspectMask = (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT); + transition_info.newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL; + // Will get error for aspect != color + m_errorMonitor->SetUnexpectedError("VUID-VkHostImageLayoutTransitionInfoEXT-image-01671"); + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-aspectMask-08702"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + + // subresourceRange includes VK_IMAGE_ASPECT_STENCIL_BIT, oldLayout and newLayout must not be one of + // VK_IMAGE_LAYOUT_DEPTH_*_OPTIMAL + transition_info.subresourceRange.aspectMask = (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT); + transition_info.newLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; + // Will get error for aspect != color + m_errorMonitor->SetUnexpectedError("VUID-VkHostImageLayoutTransitionInfoEXT-image-01671"); + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-aspectMask-08703"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + + image_ci.format = format; + image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + transition_info.image = image; + transition_info.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + transition_info.newLayout = VK_IMAGE_LAYOUT_GENERAL; + transition_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + } + + if (!copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)) { + // layout must be one of the image layouts returned in VkPhysicalDeviceHostImageCopyPropertiesEXT::pCopySrcLayouts + image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + transition_info.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-oldLayout-09056"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + transition_info.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + // layout must be one of the image layouts returned in VkPhysicalDeviceHostImageCopyPropertiesEXT::pCopyDstLayouts + transition_info.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkHostImageLayoutTransitionInfoEXT-newLayout-09057"); + vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + m_errorMonitor->VerifyFound(); + transition_info.newLayout = VK_IMAGE_LAYOUT_GENERAL; + } +}