forked from KhronosGroup/Vulkan-ValidationLayers
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: Add a positive test for host image copy
Also share utils between positive and negative tests
- Loading branch information
1 parent
919b88a
commit 38b78a1
Showing
5 changed files
with
184 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
/* | ||
* 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" | ||
|
||
TEST_F(PositiveHostImageCopy, BasicUsage) { | ||
TEST_DESCRIPTION("Use VK_EXT_host_image_copy to copy to and from host memory"); | ||
|
||
VkFormat compressed_format = VK_FORMAT_UNDEFINED; | ||
bool separate_depth_stencil = false; | ||
std::vector<VkImageLayout> copy_src_layouts; | ||
std::vector<VkImageLayout> copy_dst_layouts; | ||
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, copy_src_layouts, copy_dst_layouts, compressed_format, | ||
separate_depth_stencil); | ||
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<uint8_t> pixels(width * height * 4); | ||
// Fill image with random values | ||
for (auto &channel : pixels) { | ||
const uint32_t r = static_cast<uint32_t>(std::rand()); | ||
channel = static_cast<uint8_t>((r & 0xffu) | ((r >> 8) & 0xff) | ((r >> 16) & 0xff) | (r >> 24)); | ||
} | ||
|
||
auto region_to_image = LvlInitStruct<VkMemoryToImageCopyEXT>(); | ||
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<VkCopyMemoryToImageInfoEXT>(); | ||
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<uint8_t> welcome_back(width * height * 4); | ||
|
||
auto region_from_image = LvlInitStruct<VkImageToMemoryCopyEXT>(); | ||
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<VkCopyImageToMemoryInfoEXT>(); | ||
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<VkImageCopy2>(); | ||
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<VkCopyImageToImageInfoEXT>(); | ||
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<uint8_t> 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<VkHostImageLayoutTransitionInfoEXT>(); | ||
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<VkImageSubresource2KHR>(); | ||
subresource.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | ||
auto host_copy_size = LvlInitStruct<VkSubresourceHostMemcpySizeEXT>(); | ||
auto subresource_layout = LvlInitStruct<VkSubresourceLayout2KHR>(&host_copy_size); | ||
vk::GetImageSubresourceLayout2EXT(*m_device, image, &subresource, &subresource_layout); | ||
ASSERT_NE(host_copy_size.size, 0); | ||
|
||
auto perf_data = LvlInitStruct<VkHostImageCopyDevicePerformanceQueryEXT>(); | ||
auto image_format_properties = LvlInitStruct<VkImageFormatProperties2>(&perf_data); | ||
auto image_format_info = LvlInitStruct<VkPhysicalDeviceImageFormatInfo2>(); | ||
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); | ||
} |