diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 74779668f9a..ef63ee1a26e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -72,6 +72,7 @@ target_sources(vk_layer_validation_tests PRIVATE unit/graphics_library.cpp unit/graphics_library_positive.cpp unit/host_image_copy.cpp + unit/host_image_copy_positive.cpp unit/image.cpp unit/image_positive.cpp unit/imageless_framebuffer.cpp diff --git a/tests/framework/layer_validation_tests.h b/tests/framework/layer_validation_tests.h index ad8bd77fe73..ab9d53e7ba0 100644 --- a/tests/framework/layer_validation_tests.h +++ b/tests/framework/layer_validation_tests.h @@ -415,12 +415,18 @@ class GraphicsLibraryTest : public VkLayerTest { class NegativeGraphicsLibrary : public GraphicsLibraryTest {}; class PositiveGraphicsLibrary : public GraphicsLibraryTest {}; -class NegativeHostImageCopy : public virtual VkLayerTest { - protected: - void InitHostImageCopyTest(const VkImageCreateInfo image_ci, std::vector ©_src_layouts, - std::vector ©_dst_layouts, VkFormat &compressed_format, - bool &separate_depth_stencil); +class HostImageCopyTest : public VkLayerTest { + public: + void InitHostImageCopyTest(const VkImageCreateInfo &image_ci); + bool CopyLayoutSupported(const std::vector ©_src_layouts, const std::vector ©_dst_layouts, + VkImageLayout layout); + VkFormat compressed_format = VK_FORMAT_UNDEFINED; + bool separate_depth_stencil = false; + std::vector copy_src_layouts; + std::vector copy_dst_layouts; }; +class NegativeHostImageCopy : public HostImageCopyTest {}; +class PositiveHostImageCopy : public HostImageCopyTest {}; class ImageTest : public VkLayerTest { public: diff --git a/tests/unit/host_image_copy.cpp b/tests/unit/host_image_copy.cpp index 093d26d641b..98c081a9d87 100644 --- a/tests/unit/host_image_copy.cpp +++ b/tests/unit/host_image_copy.cpp @@ -15,71 +15,8 @@ #include "utils/vk_layer_utils.h" #include "generated/enum_flag_bits.h" -bool copy_layout_supported(std::vector ©_src_layouts, std::vector ©_dst_layouts, - VkImageLayout layout) { - return ((std::find(copy_src_layouts.begin(), copy_src_layouts.end(), layout) != copy_src_layouts.end()) && - (std::find(copy_dst_layouts.begin(), copy_dst_layouts.end(), layout) != copy_dst_layouts.end())); -} - -void NegativeHostImageCopy::InitHostImageCopyTest(const VkImageCreateInfo image_ci, - std::vector ©_src_layouts, - std::vector ©_dst_layouts, 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()); - // Assumes VK_KHR_sampler_ycbcr_conversion and VK_EXT_separate_stencil_usage, - if (DeviceValidationVersion() < VK_API_VERSION_1_2) { - GTEST_SKIP() << "Need 1.2 api version"; - } - if (!AreRequiredExtensionsEnabled()) { - GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; - } - - 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) hostImageCopy"; - } - separate_depth_stencil = separate_depth_stencil_layouts_features.separateDepthStencilLayouts; - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - compressed_format = VK_FORMAT_UNDEFINED; - if (device_features.textureCompressionBC) { - compressed_format = VK_FORMAT_BC3_SRGB_BLOCK; - } else if (device_features.textureCompressionETC2) { - compressed_format = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - } else if (device_features.textureCompressionASTC_LDR) { - compressed_format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; - } - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &host_copy_features)); - 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); - 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"; - } -} - TEST_F(NegativeHostImageCopy, HostCopyImageToFromMemory) { 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; - std::vector copy_src_layouts; - std::vector copy_dst_layouts; uint32_t width = 32; uint32_t height = 32; VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; @@ -87,7 +24,7 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToFromMemory) { 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); - InitHostImageCopyTest(image_ci, copy_src_layouts, copy_dst_layouts, compressed_format, separate_depth_stencil); + InitHostImageCopyTest(image_ci); if (::testing::Test::IsSkipped()) return; VkImageFormatProperties img_prop = {}; @@ -529,7 +466,7 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToFromMemory) { region_to_image.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region_from_image.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - if (copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)) { + if (CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)) { auto stencil_format = FindSupportedDepthStencilFormat(gpu()); VkImageObj image_stencil(m_device); image_ci.format = stencil_format; @@ -659,7 +596,7 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToFromMemory) { copy_from_image.srcImage = image; } - if (!copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)) { + if (!CopyLayoutSupported(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); copy_to_image.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; @@ -727,10 +664,6 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToFromMemory) { TEST_F(NegativeHostImageCopy, HostCopyImageToImage) { TEST_DESCRIPTION("Use VK_EXT_host_image_copy to copy from an image to another image"); - VkFormat compressed_format = VK_FORMAT_UNDEFINED; - bool separate_depth_stencil = false; - std::vector copy_src_layouts; - std::vector copy_dst_layouts; uint32_t width = 32; uint32_t height = 32; VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; @@ -738,7 +671,7 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToImage) { 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); - InitHostImageCopyTest(image_ci, copy_src_layouts, copy_dst_layouts, compressed_format, separate_depth_stencil); + InitHostImageCopyTest(image_ci); if (::testing::Test::IsSkipped()) return; VkImageFormatProperties img_prop = {}; @@ -788,7 +721,7 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToImage) { // Note that because the images need to be identical to avoid 09069, we'll go ahead and test for src and dst errors in one call - if (copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)) { + if (CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)) { auto stencil_format = FindSupportedDepthStencilFormat(gpu()); VkImageObj image_stencil1(m_device); VkImageObj image_stencil2(m_device); @@ -1200,7 +1133,7 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToImage) { copy_image_to_image.srcImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; copy_image_to_image.dstImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - if (!copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)) { + if (!CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)) { // layout must be one of the image layouts returned in VkPhysicalDeviceHostImageCopyPropertiesEXT::pCopySrcLayouts image1.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); image2.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); @@ -1259,10 +1192,6 @@ TEST_F(NegativeHostImageCopy, HostCopyImageToImage) { TEST_F(NegativeHostImageCopy, HostTransitionImageLayout) { TEST_DESCRIPTION("Use VK_EXT_host_image_copy to transition image layouts"); - VkFormat compressed_format = VK_FORMAT_UNDEFINED; - bool separate_depth_stencil = false; - std::vector copy_src_layouts; - std::vector copy_dst_layouts; uint32_t width = 32; uint32_t height = 32; VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; @@ -1270,7 +1199,7 @@ TEST_F(NegativeHostImageCopy, HostTransitionImageLayout) { 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); - InitHostImageCopyTest(image_ci, copy_src_layouts, copy_dst_layouts, compressed_format, separate_depth_stencil); + InitHostImageCopyTest(image_ci); if (::testing::Test::IsSkipped()) return; VkImageFormatProperties img_prop = {}; @@ -1403,9 +1332,9 @@ TEST_F(NegativeHostImageCopy, HostTransitionImageLayout) { 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)) { + if (CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) && + CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL) && + CopyLayoutSupported(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, @@ -1462,7 +1391,7 @@ TEST_F(NegativeHostImageCopy, HostTransitionImageLayout) { } } - if (!copy_layout_supported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)) { + if (!CopyLayoutSupported(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; diff --git a/tests/unit/host_image_copy_positive.cpp b/tests/unit/host_image_copy_positive.cpp new file mode 100644 index 00000000000..3aba291e1c3 --- /dev/null +++ b/tests/unit/host_image_copy_positive.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2023 The Khronos Group Inc. + * Copyright (c) 2023 Valve Corporation + * Copyright (c) 2023 LunarG, Inc. + * Copyright (c) 2023 Google, Inc. + * + * 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 "../framework/layer_validation_tests.h" +#include "utils/vk_layer_utils.h" + +bool HostImageCopyTest::CopyLayoutSupported(const std::vector ©_src_layouts, + const std::vector ©_dst_layouts, VkImageLayout layout) { + return ((std::find(copy_src_layouts.begin(), copy_src_layouts.end(), layout) != copy_src_layouts.end()) && + (std::find(copy_dst_layouts.begin(), copy_dst_layouts.end(), layout) != copy_dst_layouts.end())); +} + +void HostImageCopyTest::InitHostImageCopyTest(const VkImageCreateInfo &image_ci) { + SetTargetApiVersion(VK_API_VERSION_1_2); + AddRequiredExtensions(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME); + ASSERT_NO_FATAL_FAILURE(InitFramework()); + // Assumes VK_KHR_sampler_ycbcr_conversion and VK_EXT_separate_stencil_usage, + if (DeviceValidationVersion() < VK_API_VERSION_1_2) { + GTEST_SKIP() << "Need 1.2 api version"; + } + if (!AreRequiredExtensionsEnabled()) { + GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; + } + + 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) hostImageCopy"; + } + separate_depth_stencil = separate_depth_stencil_layouts_features.separateDepthStencilLayouts; + VkPhysicalDeviceFeatures device_features = {}; + ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); + compressed_format = VK_FORMAT_UNDEFINED; + if (device_features.textureCompressionBC) { + compressed_format = VK_FORMAT_BC3_SRGB_BLOCK; + } else if (device_features.textureCompressionETC2) { + compressed_format = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + } else if (device_features.textureCompressionASTC_LDR) { + compressed_format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; + } + + ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &host_copy_features)); + 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); + 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 (!CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) || + !CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_GENERAL)) { + GTEST_SKIP() << "Required formats/features not supported"; + } +} + + +TEST_F(PositiveHostImageCopy, BasicUsage) { + TEST_DESCRIPTION("Use VK_EXT_host_image_copy to copy to and from host memory"); + + 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); + InitHostImageCopyTest(image_ci); + if (::testing::Test::IsSkipped()) return; + + if (IsPlatform(kMockICD)) { + GTEST_SKIP() << "Positive host image copy test requires a driver that can copy."; + } + if (!CopyLayoutSupported(copy_src_layouts, copy_dst_layouts, VK_IMAGE_LAYOUT_GENERAL)) { + GTEST_SKIP() << "Required formats/features not supported"; + } + + VkImageLayout layout = VK_IMAGE_LAYOUT_GENERAL; + VkImageObj image(m_device); + image.Init(image_ci); + image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, layout); + + std::vector pixels(width * height * 4); + // Fill image with random values + for (auto &channel : pixels) { + const uint32_t r = static_cast(std::rand()); + channel = static_cast((r & 0xffu) | ((r >> 8) & 0xff) | ((r >> 16) & 0xff) | (r >> 24)); + } + + auto region_to_image = LvlInitStruct(); + region_to_image.pHostPointer = pixels.data(); + region_to_image.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region_to_image.imageSubresource.layerCount = 1; + region_to_image.imageExtent.width = width; + region_to_image.imageExtent.height = height; + region_to_image.imageExtent.depth = 1; + + auto copy_to_image = LvlInitStruct(); + copy_to_image.flags = 0; + copy_to_image.dstImage = image; + copy_to_image.dstImageLayout = layout; + copy_to_image.regionCount = 1; + copy_to_image.pRegions = ®ion_to_image; + + VkResult result = vk::CopyMemoryToImageEXT(*m_device, ©_to_image); + ASSERT_VK_SUCCESS(result); + + // Copy back to host memory + std::vector welcome_back(width * height * 4); + + auto region_from_image = LvlInitStruct(); + region_from_image.pHostPointer = welcome_back.data(); + region_from_image.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region_from_image.imageSubresource.layerCount = 1; + region_from_image.imageExtent.width = width; + region_from_image.imageExtent.height = height; + region_from_image.imageExtent.depth = 1; + + auto copy_from_image = LvlInitStruct(); + copy_from_image.flags = 0; + copy_from_image.srcImage = image; + copy_from_image.srcImageLayout = layout; + copy_from_image.regionCount = 1; + copy_from_image.pRegions = ®ion_from_image; + + result = vk::CopyImageToMemoryEXT(*m_device, ©_from_image); + ASSERT_VK_SUCCESS(result); + ASSERT_EQ(pixels, welcome_back); + + // Copy from one image to another + VkImageObj image2(m_device); + image2.Init(image_ci); + image2.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, layout); + + auto image_copy_2 = LvlInitStruct(); + image_copy_2.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + image_copy_2.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + image_copy_2.extent = {width, height, 1}; + auto copy_image_to_image = LvlInitStruct(); + copy_image_to_image.regionCount = 1; + copy_image_to_image.pRegions = &image_copy_2; + copy_image_to_image.srcImageLayout = layout; + copy_image_to_image.dstImageLayout = layout; + copy_image_to_image.srcImage = image; + copy_image_to_image.dstImage = image2; + + result = vk::CopyImageToImageEXT(*m_device, ©_image_to_image); + ASSERT_VK_SUCCESS(result); + + // Copy back from destination image to memory + std::vector after_image_copy(width * height * 4); + + copy_from_image.srcImage = image2; + region_from_image.pHostPointer = after_image_copy.data(); + result = vk::CopyImageToMemoryEXT(*m_device, ©_from_image); + ASSERT_VK_SUCCESS(result); + ASSERT_EQ(pixels, after_image_copy); + + // Do a layout transition, then use the image in new layout + auto transition_info = LvlInitStruct(); + transition_info.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + transition_info.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + transition_info.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + transition_info.image = image2; + result = vk::TransitionImageLayoutEXT(*m_device, 1, &transition_info); + ASSERT_VK_SUCCESS(result); + VkImageSubresource image_sub = VkImageObj::subresource(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0); + VkImageSubresourceRange image_sub_range = VkImageObj::subresource_range(image_sub); + VkImageMemoryBarrier image_barrier = + image2.image_memory_barrier(0, 0, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, image_sub_range); + + image_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + m_commandBuffer->begin(); + vk::CmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, + nullptr, 0, nullptr, 1, &image_barrier); + m_commandBuffer->end(); + m_commandBuffer->QueueCommandBuffer(true); + + // Get memory size of tiled image + auto subresource = LvlInitStruct(); + subresource.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + auto host_copy_size = LvlInitStruct(); + auto subresource_layout = LvlInitStruct(&host_copy_size); + vk::GetImageSubresourceLayout2EXT(*m_device, image, &subresource, &subresource_layout); + ASSERT_NE(host_copy_size.size, 0); + + auto perf_data = LvlInitStruct(); + auto image_format_properties = LvlInitStruct(&perf_data); + auto image_format_info = LvlInitStruct(); + image_format_info.format = VK_FORMAT_R8G8B8A8_UNORM; + image_format_info.type = VK_IMAGE_TYPE_2D; + image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_format_info.usage = VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT; + image_format_info.flags = 0; + vk::GetPhysicalDeviceImageFormatProperties2KHR(gpu(), &image_format_info, &image_format_properties); +}