| /* |
| * Copyright (c) 2015-2025 The Khronos Group Inc. |
| * Copyright (c) 2015-2025 Valve Corporation |
| * Copyright (c) 2015-2025 LunarG, Inc. |
| * Copyright (c) 2015-2025 Google, Inc. |
| * Modifications Copyright (C) 2022 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 <gtest/gtest.h> |
| #include "../framework/layer_validation_tests.h" |
| |
| class NegativeCopyBufferImage : public VkLayerTest {}; |
| |
| TEST_F(NegativeCopyBufferImage, ImageBufferCopy) { |
| TEST_DESCRIPTION("Image to buffer and buffer to image tests"); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| // Verify R8G8B8A8_UINT format is supported for transfer |
| bool missing_rgba_support = false; |
| VkFormatProperties props = {0, 0, 0}; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_R8G8B8A8_UINT, &props); |
| missing_rgba_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_rgba_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_rgba_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| |
| if (missing_rgba_support) { |
| GTEST_SKIP() << "R8G8B8A8_UINT transfer unsupported"; |
| } |
| |
| // 128^2 texels, 64k |
| vkt::Image image_64k(*m_device, 128, 128, 1, VK_FORMAT_R8G8B8A8_UINT, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| image_64k.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| // 64^2 texels, 16k |
| vkt::Image image_16k(*m_device, 64, 64, 1, VK_FORMAT_R8G8B8A8_UINT, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| image_16k.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkBufferUsageFlags transfer_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| vkt::Buffer buffer_64k(*m_device, 65536, transfer_usage); // 64k |
| vkt::Buffer buffer_16k(*m_device, 16384, transfer_usage); // 16k |
| |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.imageOffset = {0, 0, 0}; |
| region.imageExtent = {64, 64, 1}; |
| region.bufferOffset = 0; |
| |
| VkMemoryBarrier mem_barriers[3]; |
| mem_barriers[0] = vku::InitStructHelper(); |
| mem_barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[1] = vku::InitStructHelper(); |
| mem_barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| mem_barriers[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[2] = vku::InitStructHelper(); |
| mem_barriers[2].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[2].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| |
| // attempt copies before putting command buffer in recording state |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-commandBuffer-recording"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_64k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-commandBuffer-recording"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.Begin(); |
| |
| // successful copies |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barriers[2], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| region.imageOffset.x = 16; // 16k copy, offset requires larger image |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barriers[0], 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| region.imageExtent.height = 78; // > 16k copy requires larger buffer & image |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barriers[1], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_64k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| region.imageOffset.x = 0; |
| region.imageExtent.height = 64; |
| region.bufferOffset = 256; // 16k copy with buffer offset, requires larger buffer |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 2, |
| &mem_barriers[1], 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, |
| ®ion); |
| |
| // image/buffer too small (extent too large) on copy to image |
| region.imageExtent = {65, 64, 1}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-pRegions-00171"); // buffer too small |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-imageSubresource-07971"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageSubresource-07970"); // image too small |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_64k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // image/buffer too small (offset) on copy to image |
| region.imageExtent = {64, 64, 1}; |
| region.imageOffset = {0, 4, 0}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-pRegions-00171"); // buffer too small |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-imageSubresource-07971"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-imageSubresource-07972"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageSubresource-07970"); // image too small |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_64k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // image/buffer too small on copy to buffer |
| region.imageExtent = {64, 64, 1}; |
| region.imageOffset = {0, 0, 0}; |
| region.bufferOffset = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // buffer too small |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| region.imageExtent = {64, 65, 1}; |
| region.bufferOffset = 0; |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyImageToBuffer-imageSubresource-07972"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageSubresource-07970"); // image too small |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // buffer size OK but rowlength causes loose packing |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-pRegions-00183"); |
| region.imageExtent = {64, 64, 1}; |
| region.bufferRowLength = 68; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-imageExtent-06659"); |
| region.imageExtent.width = 0; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| region.imageExtent = {64, 64, 1}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageSubresource-09105"); // mis-matched aspect |
| region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| |
| // Out-of-range mip levels should fail |
| region.imageSubresource.mipLevel = image_16k.CreateInfo().mipLevels + 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageSubresource-07967"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyImageToBuffer-imageSubresource-07971"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyImageToBuffer-imageSubresource-07972"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyImageToBuffer-imageOffset-09104"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageSubresource-07970"); // unavoidable "region exceeds image |
| // bounds" for non-existent mip |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageSubresource-07967"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-imageSubresource-07971"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-imageSubresource-07972"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-imageOffset-09104"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageSubresource-07970"); // unavoidable "region exceeds image |
| // bounds" for non-existent mip |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| region.imageSubresource.mipLevel = 0; |
| |
| // Out-of-range array layers should fail |
| region.imageSubresource.baseArrayLayer = image_16k.CreateInfo().arrayLayers; |
| region.imageSubresource.layerCount = 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageSubresource-07968"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageSubresource-07968"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| region.imageSubresource.baseArrayLayer = 0; |
| |
| // Layout mismatch should fail |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_16k.handle(), 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImageLayout-00180"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_16k.handle(), |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageBufferCopyDepthStencil) { |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| // Verify all needed Depth/Stencil formats are supported |
| bool missing_ds_support = false; |
| VkFormatProperties props = {0, 0, 0}; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_D32_SFLOAT_S8_UINT, &props); |
| missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_D24_UNORM_S8_UINT, &props); |
| missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_D16_UNORM, &props); |
| missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_S8_UINT, &props); |
| missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| |
| if (missing_ds_support) { |
| GTEST_SKIP() << "Depth / Stencil formats unsupported"; |
| } |
| // 64^2 texels, depth, 16k |
| vkt::Image image_16k_depth(*m_device, 64, 64, 1, VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| image_16k_depth.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| // 256^2 texels, 512kb (256k depth, 64k stencil, 192k pack) |
| vkt::Image ds_image_4D_1S( |
| *m_device, 256, 256, 1, VK_FORMAT_D32_SFLOAT_S8_UINT, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| ds_image_4D_1S.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| // 256^2 texels, 256kb (192k depth, 64k stencil) |
| vkt::Image ds_image_3D_1S( |
| *m_device, 256, 256, 1, VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| ds_image_3D_1S.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| // 256^2 texels, 128k (128k depth) |
| vkt::Image ds_image_2D( |
| *m_device, 256, 256, 1, VK_FORMAT_D16_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| ds_image_2D.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| // 256^2 texels, 64k (64k stencil) |
| vkt::Image ds_image_1S( |
| *m_device, 256, 256, 1, VK_FORMAT_S8_UINT, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| ds_image_1S.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkBufferUsageFlags transfer_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| vkt::Buffer buffer_256k(*m_device, 262144, transfer_usage); // 256k |
| vkt::Buffer buffer_128k(*m_device, 131072, transfer_usage); // 128k |
| vkt::Buffer buffer_64k(*m_device, 65536, transfer_usage); // 64k |
| vkt::Buffer buffer_16k(*m_device, 16384, transfer_usage); // 16k |
| |
| VkBufferImageCopy ds_region = {}; |
| ds_region.bufferOffset = 0; |
| ds_region.bufferRowLength = 0; |
| ds_region.bufferImageHeight = 0; |
| ds_region.imageSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0, 1}; |
| ds_region.imageOffset = {0, 0, 0}; |
| ds_region.imageExtent = {256, 256, 1}; |
| |
| VkMemoryBarrier mem_barrier = vku::InitStructHelper(); |
| mem_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| |
| m_command_buffer.Begin(); |
| // Depth copies that should succeed |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_256k.handle(), 1, &ds_region); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_256k.handle(), 1, &ds_region); |
| |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_2D.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_128k.handle(), 1, &ds_region); |
| |
| // Depth copies that should fail |
| ds_region.bufferOffset = 4; |
| m_errorMonitor->SetDesiredError( |
| "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 4b depth per texel, pack into 256k buffer |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_256k.handle(), 1, &ds_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError( |
| "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 3b depth per texel, pack (loose) into 128k buffer |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_128k.handle(), 1, &ds_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Copy 2b depth per texel, into 128k buffer |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_2D.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_128k.handle(), 1, &ds_region); |
| m_errorMonitor->VerifyFound(); |
| |
| ds_region.bufferOffset = 5; |
| ds_region.imageExtent = {64, 64, 1}; // need smaller so offset works |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-07978"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_2D.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_128k.handle(), 1, &ds_region); |
| m_errorMonitor->VerifyFound(); |
| ds_region.imageExtent = {256, 256, 1}; |
| |
| // Stencil copies that should succeed |
| ds_region.bufferOffset = 0; |
| ds_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_64k.handle(), 1, &ds_region); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_64k.handle(), 1, &ds_region); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_64k.handle(), 1, &ds_region); |
| |
| // Stencil copies that should fail |
| m_errorMonitor->SetDesiredError( |
| "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 1b stencil per texel, pack into 64k buffer |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_16k.handle(), 1, &ds_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError( |
| "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 1b stencil per texel, pack into 64k buffer |
| ds_region.bufferRowLength = 260; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_64k.handle(), 1, &ds_region); |
| m_errorMonitor->VerifyFound(); |
| |
| ds_region.bufferRowLength = 0; |
| ds_region.bufferOffset = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Copy 1b depth per texel, into 64k buffer |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), ds_image_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| buffer_64k.handle(), 1, &ds_region); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageBufferCopyDepthStencil2) { |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| RETURN_IF_SKIP(Init()); |
| |
| bool missing_ds_support = false; |
| VkFormatProperties props = {0, 0, 0}; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_D32_SFLOAT_S8_UINT, &props); |
| missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| if (missing_ds_support) { |
| GTEST_SKIP() << "Depth / Stencil formats unsupported"; |
| } |
| |
| // 256^2 texels, 512kb (256k depth, 64k stencil, 192k pack) |
| vkt::Image ds_image_4D_1S( |
| *m_device, 256, 256, 1, VK_FORMAT_D32_SFLOAT_S8_UINT, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| ds_image_4D_1S.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| vkt::Buffer buffer_256k(*m_device, 262144, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| VkBufferImageCopy2 ds_region = vku::InitStructHelper(); |
| ds_region.bufferOffset = 4; // Extract 4b depth per texel, pack into 256k buffer// bad |
| ds_region.bufferRowLength = 0; |
| ds_region.bufferImageHeight = 0; |
| ds_region.imageSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0, 1}; |
| ds_region.imageOffset = {0, 0, 0}; |
| ds_region.imageExtent = {256, 256, 1}; |
| |
| VkCopyImageToBufferInfo2 image_buffer_info = vku::InitStructHelper(); |
| image_buffer_info.dstBuffer = buffer_256k; |
| image_buffer_info.srcImage = ds_image_4D_1S; |
| image_buffer_info.srcImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| image_buffer_info.regionCount = 1; |
| image_buffer_info.pRegions = &ds_region; |
| |
| m_command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageToBufferInfo2-pRegions-00183"); |
| vk::CmdCopyImageToBuffer2(m_command_buffer.handle(), &image_buffer_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageBufferCopyCompression) { |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPhysicalDeviceFeatures device_features = {}; |
| GetPhysicalDeviceFeatures(&device_features); |
| if (!(device_features.textureCompressionBC || device_features.textureCompressionETC2 || |
| device_features.textureCompressionASTC_LDR)) { |
| GTEST_SKIP() << "No compressed formats supported - block compression tests"; |
| } |
| // Verify transfer support for each compression format used blow |
| bool missing_bc_support = false; |
| bool missing_etc_support = false; |
| bool missing_astc_support = false; |
| |
| VkFormatProperties props = {0, 0, 0}; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_BC3_SRGB_BLOCK, &props); |
| missing_bc_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_bc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_bc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, &props); |
| missing_etc_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_etc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_etc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_ASTC_4x4_UNORM_BLOCK, &props); |
| missing_astc_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_astc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_astc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| |
| vkt::Image image_16k_4x4comp; // 128^2 texels as 32^2 compressed (4x4) blocks, 16k |
| vkt::Image image_NPOT_4x4comp; // 130^2 texels as 33^2 compressed (4x4) blocks |
| |
| if (device_features.textureCompressionBC && (!missing_bc_support)) { |
| image_16k_4x4comp.Init(*m_device, 128, 128, 1, VK_FORMAT_BC3_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image_16k_4x4comp.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| image_NPOT_4x4comp.Init(*m_device, 130, 130, 1, VK_FORMAT_BC3_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image_NPOT_4x4comp.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| } else if (device_features.textureCompressionETC2 && (!missing_etc_support)) { |
| image_16k_4x4comp.Init(*m_device, 128, 128, 1, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image_16k_4x4comp.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| image_NPOT_4x4comp.Init(*m_device, 130, 130, 1, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image_NPOT_4x4comp.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| } else if (device_features.textureCompressionASTC_LDR && (!missing_astc_support)) { |
| image_16k_4x4comp.Init(*m_device, 128, 128, 1, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image_16k_4x4comp.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| image_NPOT_4x4comp.Init(*m_device, 130, 130, 1, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image_NPOT_4x4comp.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| } else { |
| GTEST_SKIP() << "No compressed formats transfers bits are supported - block compression tests"; |
| } |
| ASSERT_TRUE(image_16k_4x4comp.initialized()); |
| |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.imageOffset = {0, 0, 0}; |
| region.imageExtent = {64, 64, 1}; |
| region.bufferOffset = 0; |
| |
| VkMemoryBarrier mem_barrier = vku::InitStructHelper(); |
| mem_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| |
| VkBufferUsageFlags transfer_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| vkt::Buffer buffer_64k(*m_device, 65536, transfer_usage); // 64k |
| vkt::Buffer buffer_16k(*m_device, 16384, transfer_usage); // 16k |
| |
| m_command_buffer.Begin(); |
| |
| // Just fits |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| region.imageExtent = {128, 128, 1}; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| |
| // with offset, too big for buffer |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-pRegions-00183"); |
| region.bufferOffset = 16; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| region.bufferOffset = 0; |
| |
| // extents that are not a multiple of compressed block size |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-00207"); // extent width not a multiple of block size |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageOffset-07747"); // image transfer granularity |
| region.imageExtent.width = 66; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), |
| 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| region.imageExtent.width = 128; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-00208"); // extent height not a multiple of block size |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageOffset-07747"); // image transfer granularity |
| region.imageExtent.height = 2; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), |
| 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| region.imageExtent.height = 128; |
| |
| // TODO: All available compressed formats are 2D, with block depth of 1. Unable to provoke VU_01277. |
| |
| // non-multiple extents are allowed if at the far edge of a non-block-multiple image - these should pass |
| region.imageExtent.width = 66; |
| region.imageOffset.x = 64; |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), |
| 1, ®ion); |
| region.imageExtent.width = 16; |
| region.imageOffset.x = 0; |
| region.imageExtent.height = 2; |
| region.imageOffset.y = 128; |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), |
| 1, ®ion); |
| region.imageOffset = {0, 0, 0}; |
| |
| // buffer offset must be a multiple of texel block size (16) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-07975"); |
| region.imageExtent = {64, 64, 1}; |
| region.bufferOffset = 24; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // rowlength not a multiple of block width (4) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-bufferRowLength-09106"); |
| region.bufferOffset = 0; |
| region.bufferRowLength = 130; |
| region.bufferImageHeight = 0; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // imageheight not a multiple of block height (4) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-bufferImageHeight-09107"); |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 130; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageBufferCopyCompression2) { |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredFeature(vkt::Feature::textureCompressionBC); |
| RETURN_IF_SKIP(Init()); |
| |
| bool missing_bc_support = false; |
| VkFormatProperties props = {0, 0, 0}; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_BC3_SRGB_BLOCK, &props); |
| missing_bc_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_bc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_bc_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| if (missing_bc_support) { |
| GTEST_SKIP() << "Format not supported"; |
| } |
| |
| vkt::Buffer buffer_16k(*m_device, 16384, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| // 128^2 texels as 32^2 compressed (4x4) blocks, 16k |
| vkt::Image image_16k_4x4comp(*m_device, 128, 128, 1, VK_FORMAT_BC3_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image_16k_4x4comp.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkBufferImageCopy2 region = vku::InitStructHelper(); |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.imageOffset = {0, 0, 0}; |
| region.imageExtent = {64, 64, 1}; |
| // buffer offset must be a multiple of texel block size (16) |
| region.bufferOffset = 24; |
| |
| m_command_buffer.Begin(); |
| |
| VkCopyImageToBufferInfo2 image_buffer_info = vku::InitStructHelper(); |
| image_buffer_info.dstBuffer = buffer_16k; |
| image_buffer_info.srcImage = image_16k_4x4comp; |
| image_buffer_info.srcImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| image_buffer_info.regionCount = 1; |
| image_buffer_info.pRegions = ®ion; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageToBufferInfo2-srcImage-07975"); |
| vk::CmdCopyImageToBuffer2(m_command_buffer.handle(), &image_buffer_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageBufferCopyMultiPlanar) { |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| // Try to use G8_B8R8_2PLANE_420_UNORM because need 2-plane format for some tests and likely supported due to copy support |
| // being required with samplerYcbcrConversion feature |
| bool missing_mp_support = false; |
| VkFormatProperties props = {0, 0, 0}; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, &props); |
| missing_mp_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_mp_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_mp_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| if (missing_mp_support) { |
| GTEST_SKIP() << "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM transfer not supported"; |
| } |
| |
| VkBufferImageCopy mp_region = {}; |
| mp_region.bufferOffset = 0; |
| mp_region.bufferRowLength = 0; |
| mp_region.bufferImageHeight = 0; |
| mp_region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| mp_region.imageOffset = {0, 0, 0}; |
| mp_region.imageExtent = {128, 128, 1}; |
| |
| vkt::Buffer buffer_16k(*m_device, 16384, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| // YUV420 means 1/2 width and height so plane_0 is 128x128 and plane_1 is 64x64 here |
| // 128^2 texels in plane_0 and 64^2 texels in plane_1 |
| vkt::Image image_multi_planar(*m_device, 128, 128, 1, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| image_multi_planar.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkMemoryBarrier mem_barrier = vku::InitStructHelper(); |
| mem_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| m_command_buffer.Begin(); |
| |
| // Copies into a mutli-planar image aspect properly |
| mp_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_multi_planar.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, &mp_region); |
| |
| // uses plane_2 without being 3 planar format |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07981"); |
| mp_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT; |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_multi_planar.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, &mp_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // uses single-plane aspect mask |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07981"); |
| mp_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_multi_planar.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, &mp_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // buffer offset must be a multiple of texel block size for VK_FORMAT_R8G8_UNORM (2) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07976"); |
| mp_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| mp_region.bufferOffset = 5; |
| mp_region.imageExtent = {8, 8, 1}; |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16k.handle(), image_multi_planar.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, &mp_region); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageLayerCountMismatch) { |
| TEST_DESCRIPTION( |
| "Try to copy between images with the source subresource having a different layerCount than the destination subresource"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddOptionalExtensions(VK_KHR_MAINTENANCE_1_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| const bool maintenance1 = |
| IsExtensionsEnabled(VK_KHR_MAINTENANCE_1_EXTENSION_NAME) || DeviceValidationVersion() >= VK_API_VERSION_1_1; |
| |
| VkFormat image_format = VK_FORMAT_B8G8R8A8_UNORM; |
| VkFormatProperties format_props; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), image_format, &format_props); |
| if ((format_props.optimalTilingFeatures & (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) == 0) { |
| GTEST_SKIP() << "Transfer for format is not supported"; |
| } |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 4, image_format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| vkt::Image src_image(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image dst_image(*m_device, image_ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| // Introduce failure by forcing the dst layerCount to differ from src |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 3}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = {1, 1, 1}; |
| |
| const char *vuid = (maintenance1 == true) ? "VUID-vkCmdCopyImage-srcImage-08793" : "VUID-VkImageCopy-apiVersion-07941"; |
| m_errorMonitor->SetDesiredError(vuid); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, CompressedImageMip) { |
| TEST_DESCRIPTION("Image/Buffer copies for higher mip levels"); |
| |
| AddOptionalExtensions(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::textureCompressionBC); |
| RETURN_IF_SKIP(Init()); |
| bool copy_commands2 = IsExtensionsEnabled(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 6, 1, VK_FORMAT_BC3_SRGB_BLOCK, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.extent = {31, 32, 1}; // Mips are [31,32] [15,16] [7,8] [3,4], [1,2] [1,1] |
| vkt::Image odd_image(*m_device, image_ci, vkt::set_layout); |
| |
| VkBufferUsageFlags transfer_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| vkt::Buffer buffer_1024(*m_device, 1024, transfer_usage); |
| vkt::Buffer buffer_64(*m_device, 64, transfer_usage); |
| vkt::Buffer buffer_16(*m_device, 16, transfer_usage); |
| vkt::Buffer buffer_8(*m_device, 8, transfer_usage); |
| |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.imageOffset = {0, 0, 0}; |
| region.bufferOffset = 0; |
| |
| m_command_buffer.Begin(); |
| |
| VkMemoryBarrier mem_barriers[3]; |
| mem_barriers[0] = vku::InitStructHelper(); |
| mem_barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[1] = vku::InitStructHelper(); |
| mem_barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| mem_barriers[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[2] = vku::InitStructHelper(); |
| mem_barriers[2].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barriers[2].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| |
| // Mip level copies that work - 5 levels |
| |
| // Mip 0 should fit in 1k buffer - 1k texels @ 1b each |
| region.imageExtent = {32, 32, 1}; |
| region.imageSubresource.mipLevel = 0; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_1024.handle(), 1, ®ion); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barriers[2], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_1024.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| |
| // Mip 2 should fit in 64b buffer - 64 texels @ 1b each |
| region.imageExtent = {8, 8, 1}; |
| region.imageSubresource.mipLevel = 2; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64.handle(), 1, ®ion); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 2, |
| &mem_barriers[1], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_64.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| |
| // Mip 3 should fit in 16b buffer - 16 texels @ 1b each |
| region.imageExtent = {4, 4, 1}; |
| region.imageSubresource.mipLevel = 3; |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 2, |
| &mem_barriers[1], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| |
| // Mip 4&5 should fit in 16b buffer with no complaint - 4 & 1 texels @ 1b each |
| region.imageExtent = {2, 2, 1}; |
| region.imageSubresource.mipLevel = 4; |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barriers[0], 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 2, |
| &mem_barriers[1], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| |
| region.imageExtent = {1, 1, 1}; |
| region.imageSubresource.mipLevel = 5; |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barriers[0], 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 2, |
| &mem_barriers[1], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| |
| // Buffer must accommodate a full compressed block, regardless of texel count |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-pRegions-00183"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_8.handle(), 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-pRegions-00171"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_8.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // Copy width < compressed block size, but not the full mip width |
| region.imageExtent = {1, 2, 1}; |
| region.imageSubresource.mipLevel = 4; |
| // width not a multiple of compressed block width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-00207"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageOffset-07747"); // image transfer granularity |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError( |
| "VUID-vkCmdCopyBufferToImage-dstImage-00207"); // width not a multiple of compressed block width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageOffset-07738"); // image transfer granularity |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // Copy height < compressed block size but not the full mip height |
| region.imageExtent = {2, 1, 1}; |
| m_errorMonitor->SetDesiredError( |
| "VUID-vkCmdCopyImageToBuffer-srcImage-00208"); // height not a multiple of compressed block width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageOffset-07747"); // image transfer granularity |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError( |
| "VUID-vkCmdCopyBufferToImage-dstImage-00208"); // height not a multiple of compressed block width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageOffset-07738"); // image transfer granularity |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // Offsets must be multiple of compressed block size |
| region.imageOffset = {1, 1, 0}; |
| region.imageExtent = {1, 1, 1}; |
| // imageOffset not a multiple of block size |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-07274"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-07275"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageOffset-07747"); // image transfer granularity |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // imageOffset not a multiple of block size |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07274"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07275"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageOffset-07738"); // image transfer granularity |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // Equivalent test using KHR_copy_commands2 |
| if (copy_commands2) { |
| const VkBufferImageCopy2 region2 = {VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, |
| NULL, |
| region.bufferOffset, |
| region.bufferRowLength, |
| region.bufferImageHeight, |
| region.imageSubresource, |
| region.imageOffset, |
| region.imageExtent}; |
| const VkCopyBufferToImageInfo2 copy_buffer_to_image_info2 = {VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2, |
| NULL, |
| buffer_16.handle(), |
| image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, |
| 1, |
| ®ion2}; |
| // imageOffset not a multiple of block size |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferToImageInfo2-dstImage-07274"); |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferToImageInfo2-dstImage-07275"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage2-imageOffset-07738"); // image transfer granularity |
| vk::CmdCopyBufferToImage2KHR(m_command_buffer.handle(), ©_buffer_to_image_info2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Offset + extent width = mip width - should succeed |
| region.imageOffset = {4, 4, 0}; |
| region.imageExtent = {3, 4, 1}; |
| region.imageSubresource.mipLevel = 2; |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barriers[0], 0, nullptr, 0, nullptr); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, |
| ®ion); |
| |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 2, |
| &mem_barriers[1], 0, nullptr, 0, nullptr); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| |
| // Offset + extent width < mip width and not a multiple of block width - should fail |
| region.imageExtent = {3, 3, 1}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-srcImage-00208"); // offset+extent not a multiple of block width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageOffset-07747"); // image transfer granularity |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-00208"); // offset+extent not a multiple of block width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageOffset-07738"); // image transfer granularity |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer_16.handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, Compressed) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-Docs/issues/1005"); |
| RETURN_IF_SKIP(Init()); |
| |
| if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_BC2_UNORM_BLOCK, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT) || |
| !FormatFeaturesAreSupported(Gpu(), VK_FORMAT_BC3_UNORM_BLOCK, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required formats/features not supported"; |
| } |
| |
| vkt::Image image_bc2(*m_device, 60, 60, 1, VK_FORMAT_BC2_UNORM_BLOCK, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image_bc3(*m_device, 60, 60, 1, VK_FORMAT_BC3_UNORM_BLOCK, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| |
| if (!image_bc2.initialized() || !image_bc3.initialized()) { |
| GTEST_SKIP() << "Unable to initialize surfaces"; |
| } |
| |
| VkImageCopy copy_region = {}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = {15, 16, 1}; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01728"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-01732"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); // image transfer granularity |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-01784"); // image transfer granularity |
| m_command_buffer.Begin(); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_bc2.handle(), VK_IMAGE_LAYOUT_GENERAL, image_bc3.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_command_buffer.End(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // issue being resolved in https://gitlab.khronos.org/vulkan/vulkan/-/issues/1762 |
| TEST_F(NegativeCopyBufferImage, CompressedMipLevels) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-Docs/issues/1005"); |
| RETURN_IF_SKIP(Init()); |
| |
| if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_BC2_UNORM_BLOCK, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required formats/features not supported"; |
| } |
| |
| // Mip 0 - 60 x 60 |
| // Mip 1 - 30 x 30 |
| // Mip 2 - 15 x 15 |
| vkt::Image image_src(*m_device, 60, 60, 3, VK_FORMAT_BC2_UNORM_BLOCK, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image_dst(*m_device, 60, 60, 3, VK_FORMAT_BC3_UNORM_BLOCK, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| |
| if (!image_src.initialized() || !image_dst.initialized()) { |
| GTEST_SKIP() << "Unable to initialize surfaces"; |
| } |
| |
| VkImageCopy copy_region = {}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 2, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| m_command_buffer.Begin(); |
| |
| copy_region.extent = {16, 16, 1}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00150"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00151"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_src.handle(), VK_IMAGE_LAYOUT_GENERAL, image_dst.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.extent = {15, 15, 1}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01728"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01729"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_src.handle(), VK_IMAGE_LAYOUT_GENERAL, image_dst.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, MiscImageLayer) { |
| TEST_DESCRIPTION("Image-related tests that don't belong elsewhere"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R16G16B16A16_UINT, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_R16G16B16A16_UINT features not supported"; |
| } else if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R8G8_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_R8G8_UNORM features not supported"; |
| } |
| |
| vkt::Image image(*m_device, 128, 128, 1, VK_FORMAT_R16G16B16A16_UINT, VK_IMAGE_USAGE_TRANSFER_DST_BIT); // 64bpp |
| image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| vkt::Buffer buffer(*m_device, 128 * 128 * 8, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0); |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 128; |
| region.bufferImageHeight = 128; |
| region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| // layerCount can't be 0 - Expect MISMATCHED_IMAGE_ASPECT |
| region.imageSubresource.layerCount = 1; |
| region.imageExtent = {4, 4, 1}; |
| |
| vkt::Image image2(*m_device, 128, 128, 1, VK_FORMAT_R8G8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT); // 16bpp |
| image2.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| vkt::Buffer buffer2(*m_device, 128 * 128 * 2, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0); |
| m_command_buffer.Begin(); |
| |
| // Image must have offset.z of 0 and extent.depth of 1 |
| // Introduce failure by setting imageExtent.depth to 0 |
| region.imageExtent.depth = 0; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07980"); |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-imageExtent-06661"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| region.imageExtent.depth = 1; |
| |
| // Image must have offset.z of 0 and extent.depth of 1 |
| // Introduce failure by setting imageOffset.z to 4 |
| // Note: Also (unavoidably) triggers 'region exceeds image' #1228 |
| region.imageOffset.z = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07980"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageOffset-09104"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageSubresource-07970"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| region.imageOffset.z = 0; |
| // BufferOffset must be a multiple of the calling command's VkImage parameter's texel size |
| // Introduce failure by setting bufferOffset to 1 and 1/2 texels |
| region.bufferOffset = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07975"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // BufferRowLength must be 0, or greater than or equal to the width member of imageExtent |
| region.bufferOffset = 0; |
| region.imageExtent.height = 128; |
| region.imageExtent.width = 128; |
| // Introduce failure by setting bufferRowLength > 0 but less than width |
| region.bufferRowLength = 64; |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-bufferRowLength-09101"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| // BufferImageHeight must be 0, or greater than or equal to the height member of imageExtent |
| region.bufferRowLength = 128; |
| // Introduce failure by setting bufferRowHeight > 0 but less than height |
| region.bufferImageHeight = 64; |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-bufferImageHeight-09102"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageTypeExtentMismatch) { |
| TEST_DESCRIPTION("Image copy tests where format type and extents don't match"); |
| RETURN_IF_SKIP(Init()); |
| |
| // Tests are designed to run without Maintenance1 which was promoted in 1.1 |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "Tests for 1.0 only"; |
| } |
| |
| // Create 1D image |
| VkImageCreateInfo ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image_2D(*m_device, ci, vkt::set_layout); |
| |
| ci.imageType = VK_IMAGE_TYPE_1D; |
| ci.extent.height = 1; |
| vkt::Image image_1D(*m_device, ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {32, 1, 1}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| // 1D texture w/ offset.y > 0. Source = VU 09c00124, dest = 09c00130 |
| copy_region.srcOffset.y = 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-00146"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00145"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.srcOffset.y = 0; |
| copy_region.dstOffset.y = 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-00152"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00151"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_1D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.dstOffset.y = 0; |
| |
| // 1D texture w/ extent.height > 1. Source = VU 09c00124, dest = 09c00130 |
| copy_region.extent.height = 2; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-00146"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00145"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-00152"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00151"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_1D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.extent.height = 1; |
| |
| // 1D texture w/ offset.z > 0. Source = VU 09c00df2, dest = 09c00df4 |
| copy_region.srcOffset.z = 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01785"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00147"); // also z-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.srcOffset.z = 0; |
| copy_region.dstOffset.z = 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-01786"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00153"); // also z-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_1D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.dstOffset.z = 0; |
| |
| // 1D texture w/ extent.depth > 1. Source = VU 09c00df2, dest = 09c00df4 |
| copy_region.extent.depth = 2; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01785"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00147"); // also z-dim overrun (src) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00153"); // also z-dim overrun (dst) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-08969"); // 2D needs to be 1 pre-Vulkan 1.1 |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-01786"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00147"); // also z-dim overrun (src) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00153"); // also z-dim overrun (dst) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-08969"); // 2D needs to be 1 pre-Vulkan 1.1 |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_1D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageTypeExtentMismatch3D) { |
| TEST_DESCRIPTION("Image copy tests where format type and extents don't match"); |
| RETURN_IF_SKIP(Init()); |
| |
| // Tests are designed to run without Maintenance1 which was promoted in 1.1 |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "Tests for 1.0 only"; |
| } |
| |
| // Create 1D image |
| VkImageCreateInfo ci = vkt::Image::ImageCreateInfo2D(32, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| ci.extent = {32, 32, 1}; |
| vkt::Image image_2D(*m_device, ci, vkt::set_layout); |
| |
| ci.imageType = VK_IMAGE_TYPE_3D; |
| ci.extent.depth = 8; |
| vkt::Image image_3D(*m_device, ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {32, 1, 1}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| // 2D texture w/ offset.z > 0. Source = VU 09c00df6, dest = 09c00df8 |
| copy_region.extent = {16, 16, 1}; |
| copy_region.srcOffset.z = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01787"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00147"); // also z-dim overrun (src) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_3D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.srcOffset.z = 0; |
| copy_region.dstOffset.z = 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-01788"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00153"); // also z-dim overrun (dst) |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_3D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.dstOffset.z = 0; |
| |
| // 3D texture accessing an array layer other than 0. VU 09c0011a |
| copy_region.extent = {4, 4, 1}; |
| copy_region.srcSubresource.baseArrayLayer = 1; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07932"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcSubresource-07968"); // also 'too many layers' |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage(m_command_buffer.handle(), image_3D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.srcSubresource.baseArrayLayer = 0; |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageTypeExtentMismatchCopyCommands2) { |
| TEST_DESCRIPTION("Image copy tests where format type and extents don't match"); |
| AddRequiredExtensions(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| // Tests are designed to run without Maintenance1 which was promoted in 1.1 |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "Tests for 1.0 only"; |
| } |
| |
| VkImageCreateInfo ci = vkt::Image::ImageCreateInfo2D(32, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| ci.imageType = VK_IMAGE_TYPE_1D; |
| vkt::Image image_1D(*m_device, ci, vkt::set_layout); |
| |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.extent = {32, 32, 1}; |
| vkt::Image image_2D(*m_device, ci, vkt::set_layout); |
| |
| ci.imageType = VK_IMAGE_TYPE_3D; |
| ci.extent = {32, 32, 8}; |
| vkt::Image image_3D(*m_device, ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy2 region2 = vku::InitStructHelper(); |
| region2.extent = {32, 1, 1}; |
| region2.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region2.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region2.srcOffset = {0, 0, 0}; |
| region2.dstOffset = {0, 0, 0}; |
| |
| VkCopyImageInfo2 copy_image_info2 = vku::InitStructHelper(); |
| copy_image_info2.dstImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| copy_image_info2.srcImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| copy_image_info2.regionCount = 1; |
| copy_image_info2.pRegions = ®ion2; |
| |
| // 1D texture w/ offset.y > 0. Source = VU 09c00124, dest = 09c00130 |
| { |
| region2.srcOffset.y = 1; |
| copy_image_info2.srcImage = image_1D; |
| copy_image_info2.dstImage = image_2D; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-srcImage-00146"); |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-srcOffset-00145"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage2KHR(m_command_buffer.handle(), ©_image_info2); |
| m_errorMonitor->VerifyFound(); |
| region2.srcOffset.y = 0; |
| } |
| |
| { |
| region2.dstOffset.y = 1; |
| copy_image_info2.srcImage = image_2D; |
| copy_image_info2.dstImage = image_1D; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-dstImage-00152"); |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-dstOffset-00151"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage2KHR(m_command_buffer.handle(), ©_image_info2); |
| m_errorMonitor->VerifyFound(); |
| region2.dstOffset.y = 0; |
| } |
| |
| // 1D texture w/ extent.height > 1. Source = VU 09c00124, dest = 09c00130 |
| { |
| region2.extent.height = 2; |
| copy_image_info2.srcImage = image_1D; |
| copy_image_info2.dstImage = image_2D; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-srcImage-00146"); |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-srcOffset-00145"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage2KHR(m_command_buffer.handle(), ©_image_info2); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_image_info2.srcImage = image_2D; |
| copy_image_info2.dstImage = image_1D; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-dstImage-00152"); |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-dstOffset-00151"); // also y-dim overrun |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-apiVersion-07933"); // not same image type |
| vk::CmdCopyImage2KHR(m_command_buffer.handle(), ©_image_info2); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageTypeExtentMismatchMaintenance1) { |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_1_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkFormat image_format = VK_FORMAT_R8G8B8A8_UNORM; |
| |
| VkImageCreateInfo ci = vku::InitStructHelper(); |
| ci.flags = 0; |
| ci.imageType = VK_IMAGE_TYPE_1D; |
| ci.format = image_format; |
| ci.extent = {32, 1, 1}; |
| ci.mipLevels = 1; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| // Create 1D image |
| vkt::Image image_1D(*m_device, ci, vkt::set_layout); |
| |
| // 2D image |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.extent = {32, 32, 1}; |
| vkt::Image image_2D(*m_device, ci, vkt::set_layout); |
| |
| // 3D image |
| ci.imageType = VK_IMAGE_TYPE_3D; |
| ci.extent = {32, 32, 8}; |
| vkt::Image image_3D(*m_device, ci, vkt::set_layout); |
| |
| // 2D image array |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.extent = {32, 32, 1}; |
| ci.arrayLayers = 8; |
| vkt::Image image_2D_array(*m_device, ci, vkt::set_layout); |
| |
| // second 2D image array |
| ci.imageType = VK_IMAGE_TYPE_2D; |
| ci.extent = {32, 32, 1}; |
| ci.arrayLayers = 8; |
| vkt::Image image_2D_array_2(*m_device, ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {32, 1, 1}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-07743"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Copy from layer not present |
| copy_region.srcSubresource.baseArrayLayer = 4; |
| copy_region.srcSubresource.layerCount = 6; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01791"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcSubresource-07968"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D_array.handle(), VK_IMAGE_LAYOUT_GENERAL, image_3D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.srcSubresource.baseArrayLayer = 0; |
| copy_region.srcSubresource.layerCount = 1; |
| |
| // Copy to layer not present |
| copy_region.dstSubresource.baseArrayLayer = 1; |
| copy_region.dstSubresource.layerCount = 8; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-01792"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstSubresource-07968"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_3D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D_array.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.dstSubresource.baseArrayLayer = 0; |
| copy_region.dstSubresource.layerCount = 1; |
| |
| // both 2D and extent.depth not 1 |
| // Need two 2D array images to prevent other errors |
| copy_region.extent = {4, 1, 2}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01790"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D_array.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D_array_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.extent = {32, 1, 1}; |
| |
| // 2D src / 3D dst and depth not equal to src layerCount |
| copy_region.extent = {4, 1, 2}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01791"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-08793"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2D_array.handle(), VK_IMAGE_LAYOUT_GENERAL, image_3D.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.extent = {32, 1, 1}; |
| |
| // 3D src / 2D dst and depth not equal to dst layerCount |
| copy_region.extent = {4, 1, 2}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-01792"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-08793"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_3D.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2D_array.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.extent = {32, 1, 1}; |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageCompressedBlockAlignment) { |
| // Image copy tests on compressed images with block alignment errors |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredFeature(vkt::Feature::textureCompressionBC); |
| RETURN_IF_SKIP(Init()); |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(64, 64, 1, 1, VK_FORMAT_BC3_SRGB_BLOCK, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| VkImageFormatProperties img_prop = {}; |
| if (VK_SUCCESS != vk::GetPhysicalDeviceImageFormatProperties(m_device->Physical().handle(), image_ci.format, image_ci.imageType, |
| image_ci.tiling, image_ci.usage, image_ci.flags, &img_prop)) { |
| GTEST_SKIP() << "No compressed formats supported"; |
| } |
| |
| vkt::Image image_1(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.extent = {62, 62, 1}; // slightly smaller and not divisible by block size |
| vkt::Image image_2(*m_device, image_ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {48, 48, 1}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| // Sanity check |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| const char* vuid = nullptr; |
| bool ycbcr = |
| (IsExtensionsEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME) || (DeviceValidationVersion() >= VK_API_VERSION_1_1)); |
| |
| // Src, Dest offsets must be multiples of compressed block sizes {4, 4, 1} |
| // Image transfer granularity gets set to compressed block size, so an ITG error is also (unavoidably) triggered. |
| copy_region.srcOffset = {2, 4, 0}; // source width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-pRegions-07278"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); // srcOffset image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.srcOffset = {12, 1, 0}; // source height |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-pRegions-07279"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); // srcOffset image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.srcOffset = {0, 0, 0}; |
| |
| copy_region.dstOffset = {1, 0, 0}; // dest width |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-pRegions-07281"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-01784"); // dstOffset image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.dstOffset = {4, 1, 0}; // dest height |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-pRegions-07282"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-01784"); // dstOffset image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| // Copy extent must be multiples of compressed block sizes {4, 4, 1} if not full width/height |
| vuid = ycbcr ? "VUID-vkCmdCopyImage-srcImage-01728" : "VUID-vkCmdCopyImage-srcImage-01728"; |
| copy_region.extent = {62, 60, 1}; // source width |
| m_errorMonitor->SetDesiredError(vuid); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); // src extent image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| vuid = ycbcr ? "VUID-vkCmdCopyImage-srcImage-01729" : "VUID-vkCmdCopyImage-srcImage-01729"; |
| copy_region.extent = {60, 62, 1}; // source height |
| m_errorMonitor->SetDesiredError(vuid); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); // src extent image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_1.handle(), VK_IMAGE_LAYOUT_GENERAL, image_2.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| vuid = ycbcr ? "VUID-vkCmdCopyImage-dstImage-01732" : "VUID-vkCmdCopyImage-dstImage-01732"; |
| copy_region.extent = {62, 60, 1}; // dest width |
| m_errorMonitor->SetDesiredError(vuid); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-01784"); // dst extent image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2.handle(), VK_IMAGE_LAYOUT_GENERAL, image_1.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| vuid = ycbcr ? "VUID-vkCmdCopyImage-dstImage-01733" : "VUID-vkCmdCopyImage-dstImage-01733"; |
| copy_region.extent = {60, 62, 1}; // dest height |
| m_errorMonitor->SetDesiredError(vuid); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-01784"); // dst extent image transfer granularity |
| vk::CmdCopyImage(m_command_buffer.handle(), image_2.handle(), VK_IMAGE_LAYOUT_GENERAL, image_1.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Note: "VUID-vkCmdCopyImage-srcImage-01730", "VUID-vkCmdCopyImage-dstImage-01734", "VUID-vkCmdCopyImage-srcImage-01730", |
| // "VUID-vkCmdCopyImage-dstImage-01734" |
| // There are currently no supported compressed formats with a block depth other than 1, |
| // so impossible to create a 'not a multiple' condition for depth. |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageSrcSizeExceeded) { |
| // Image copy with source region specified greater than src image size |
| RETURN_IF_SKIP(Init()); |
| |
| // Create images with full mip chain |
| VkImageCreateInfo ci = vku::InitStructHelper(); |
| ci.flags = 0; |
| ci.imageType = VK_IMAGE_TYPE_3D; |
| ci.format = VK_FORMAT_R8G8B8A8_UNORM; |
| ci.extent = {32, 32, 8}; |
| ci.mipLevels = 6; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| vkt::Image src_image(*m_device, ci, vkt::set_layout); |
| |
| // Dest image with one more mip level |
| ci.extent = {64, 64, 16}; |
| ci.mipLevels = 7; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image dst_image(*m_device, ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {32, 32, 8}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| // Source exceeded in x-dim |
| copy_region.srcOffset.x = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00144"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Dest exceeded in x-dim in negative direction (since offset is a signed in) |
| copy_region.extent.width = 4; |
| copy_region.srcOffset.x = -8; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00144"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.extent.width = 32; |
| |
| // Source exceeded in y-dim |
| copy_region.srcOffset.x = 0; |
| copy_region.extent.height = 48; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00145"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Source exceeded in z-dim |
| copy_region.extent = {4, 4, 4}; |
| copy_region.srcSubresource.mipLevel = 2; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00147"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageDstSizeExceeded) { |
| // Image copy with dest region specified greater than dest image size |
| RETURN_IF_SKIP(Init()); |
| |
| // Create images with full mip chain |
| VkImageCreateInfo ci = vku::InitStructHelper(); |
| ci.flags = 0; |
| ci.imageType = VK_IMAGE_TYPE_3D; |
| ci.format = VK_FORMAT_R8G8B8A8_UNORM; |
| ci.extent = {32, 32, 8}; |
| ci.mipLevels = 6; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image dst_image(*m_device, ci, vkt::set_layout); |
| |
| // Src image with one more mip level |
| ci.extent = {64, 64, 16}; |
| ci.mipLevels = 7; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| vkt::Image src_image(*m_device, ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.extent = {32, 32, 8}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| // Dest exceeded in x-dim |
| copy_region.dstOffset.x = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00150"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Dest exceeded in x-dim in negative direction (since offset is a signed in) |
| copy_region.extent.width = 4; |
| copy_region.dstOffset.x = -8; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00150"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.extent.width = 32; |
| |
| copy_region.dstOffset.x = 0; |
| copy_region.extent.height = 48; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00151"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Dest exceeded in z-dim |
| copy_region.extent = {4, 4, 4}; |
| copy_region.dstSubresource.mipLevel = 2; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00153"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageZeroSize) { |
| TEST_DESCRIPTION("Image Copy with empty regions"); |
| RETURN_IF_SKIP(Init()); |
| |
| // Create images with full mip chain |
| VkImageCreateInfo ci = vku::InitStructHelper(); |
| ci.flags = 0; |
| ci.imageType = VK_IMAGE_TYPE_3D; |
| ci.format = VK_FORMAT_R8G8B8A8_UNORM; |
| ci.extent = {32, 32, 8}; |
| ci.mipLevels = 6; |
| ci.arrayLayers = 1; |
| ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| vkt::Image src_image(*m_device, ci, vkt::set_layout); |
| |
| ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image dst_image(*m_device, ci, vkt::set_layout); |
| |
| // large enough for image |
| vkt::Buffer buffer(*m_device, 16384, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| |
| copy_region.extent = {4, 4, 0}; |
| m_errorMonitor->SetDesiredError("VUID-VkImageCopy-extent-06670"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.extent = {0, 0, 4}; |
| m_errorMonitor->SetDesiredError("VUID-VkImageCopy-extent-06668"); // width |
| m_errorMonitor->SetDesiredError("VUID-VkImageCopy-extent-06669"); // height |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| VkImageSubresourceLayers image_subresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| VkBufferImageCopy buffer_image_copy; |
| buffer_image_copy.bufferRowLength = 0; |
| buffer_image_copy.bufferImageHeight = 0; |
| buffer_image_copy.imageSubresource = image_subresource; |
| buffer_image_copy.imageOffset = {0, 0, 0}; |
| buffer_image_copy.bufferOffset = 0; |
| |
| buffer_image_copy.imageExtent = {4, 0, 1}; |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-imageExtent-06660"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer.handle(), 1, |
| &buffer_image_copy); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-imageExtent-06660"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), dst_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| &buffer_image_copy); |
| m_errorMonitor->VerifyFound(); |
| |
| // depth is now zero |
| buffer_image_copy.imageExtent = {4, 1, 0}; |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-imageExtent-06661"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer.handle(), 1, |
| &buffer_image_copy); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkBufferImageCopy-imageExtent-06661"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), dst_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| &buffer_image_copy); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageMultiPlaneSizeExceeded) { |
| TEST_DESCRIPTION("Image Copy for multi-planar format that exceed size of plane for both src and dst"); |
| |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| // Try to use VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM because need multi-plane format for some tests and likely supported due to |
| // copy support being required with samplerYcbcrConversion feature |
| VkFormatProperties props = {0, 0, 0}; |
| bool missing_format_support = false; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, &props); |
| missing_format_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); |
| missing_format_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; |
| missing_format_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; |
| |
| if (missing_format_support == true) { |
| GTEST_SKIP() << "VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM transfer not supported"; |
| } |
| |
| // 128^2 texels in plane_0 and 64^2 texels in plane_1 |
| vkt::Image src_image(*m_device, 128, 128, 1, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| src_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| vkt::Image dst_image(*m_device, 128, 128, 1, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| dst_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkImageCopy copy_region = {}; |
| copy_region.extent = {64, 64, 1}; // Size of plane 1 |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_PLANE_1_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_PLANE_1_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| VkImageCopy original_region = copy_region; |
| |
| m_command_buffer.Begin(); |
| |
| // Should be able to do a 64x64 copy from plane 1 -> Plane 1 |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| // Should be able to do a 64x64 copy from plane 0 -> Plane 0 |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| VkMemoryBarrier mem_barrier = vku::InitStructHelper(); |
| mem_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| mem_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| |
| // Should be able to do a 64x64 copy from plane 0 -> Plane 1 |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| // Should be able to do a 64x64 copy from plane 0 -> Plane 1 |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| // Should be able to do a 128x64 copy from plane 0 -> Plane 0 |
| copy_region.extent = {128, 64, 1}; |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, |
| &mem_barrier, 0, nullptr, 0, nullptr); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| // 128x64 copy from plane 0 -> Plane 1 |
| copy_region.extent = {128, 64, 1}; |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00150"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // 128x64 copy from plane 1 -> Plane 0 |
| copy_region.extent = {128, 64, 1}; |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00144"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // src exceeded in y-dim from offset |
| copy_region = original_region; |
| copy_region.srcOffset.y = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-00145"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // dst exceeded in y-dim from offset |
| copy_region = original_region; |
| copy_region.dstOffset.y = 4; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-00151"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageFormatSizeMismatch) { |
| TEST_DESCRIPTION("two single plane mismatch"); |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::samplerYcbcrConversion); |
| RETURN_IF_SKIP(Init()); |
| |
| if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R8_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_R8_UNORM features not supported"; |
| } else if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R8_UINT, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_R8_UINT features not supported"; |
| } else if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Format not supported"; |
| } |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_R8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image_8b_unorm(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.format = VK_FORMAT_R8_UINT; |
| vkt::Image image_8b_uint(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.format = VK_FORMAT_R8G8B8A8_UNORM; |
| vkt::Image image_32b_unorm(*m_device, image_ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = {1, 1, 1}; |
| |
| // Sanity check between two 8bit formats |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_uint.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01548"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_32b_unorm.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Swap src and dst |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01548"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_32b_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_unorm.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageFormatSizeMismatch2) { |
| TEST_DESCRIPTION("DstImage is a mismatched plane of a multi-planar format"); |
| AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::samplerYcbcrConversion); |
| RETURN_IF_SKIP(Init()); |
| |
| if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R8_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_R8_UNORM features not supported"; |
| } else if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R8_UINT, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_R8_UINT features not supported"; |
| } else if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Format not supported"; |
| } |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_R8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image_8b_unorm(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.format = VK_FORMAT_R8_UINT; |
| vkt::Image image_8b_uint(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| vkt::Image image_8b_16b_420_unorm(*m_device, image_ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = {1, 1, 1}; |
| |
| // First test single-plane -> multi-plan |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| |
| // Plane 0 is VK_FORMAT_R8_UNORM so this should succeed |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_16b_420_unorm.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| image_8b_16b_420_unorm.ImageMemoryBarrier(m_command_buffer, VK_IMAGE_ASPECT_PLANE_0_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, |
| VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL); |
| |
| // Make sure no false postiives if Compatible format |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_uint.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_16b_420_unorm.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| // Plane 1 is VK_FORMAT_R8G8_UNORM so this should fail |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-None-01549"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_16b_420_unorm.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Same tests but swap src and dst |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| |
| image_8b_unorm.ImageMemoryBarrier(m_command_buffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_ACCESS_TRANSFER_READ_BIT, |
| VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL); |
| image_8b_16b_420_unorm.ImageMemoryBarrier(m_command_buffer, VK_IMAGE_ASPECT_PLANE_0_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, |
| VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL); |
| |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_16b_420_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_unorm.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| image_8b_16b_420_unorm.ImageMemoryBarrier(m_command_buffer, VK_IMAGE_ASPECT_PLANE_0_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, |
| VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL); |
| |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_16b_420_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_uint.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-None-01549"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_8b_16b_420_unorm.handle(), VK_IMAGE_LAYOUT_GENERAL, image_8b_unorm.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageDepthStencilFormatMismatch) { |
| RETURN_IF_SKIP(Init()); |
| auto depth_format = FindSupportedDepthStencilFormat(Gpu()); |
| |
| VkFormatProperties properties; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), VK_FORMAT_D32_SFLOAT, &properties); |
| if (properties.optimalTilingFeatures == 0) { |
| GTEST_SKIP() << "Image format not supported"; |
| } |
| |
| vkt::Image srcImage(*m_device, 32, 32, 1, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| srcImage.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| vkt::Image dstImage(*m_device, 32, 32, 1, depth_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| dstImage.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| // Create two images of different types and try to copy between them |
| |
| m_command_buffer.Begin(); |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0, 1}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = {1, 1, 1}; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01548"); |
| vk::CmdCopyImage(m_command_buffer.handle(), srcImage.handle(), VK_IMAGE_LAYOUT_GENERAL, dstImage.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageSampleCountMismatch) { |
| TEST_DESCRIPTION("Image copies with sample count mis-matches"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| VkImageFormatProperties image_format_properties; |
| vk::GetPhysicalDeviceImageFormatProperties(Gpu(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0, |
| &image_format_properties); |
| |
| if ((0 == (VK_SAMPLE_COUNT_2_BIT & image_format_properties.sampleCounts)) || |
| (0 == (VK_SAMPLE_COUNT_4_BIT & image_format_properties.sampleCounts))) { |
| GTEST_SKIP() << "Image multi-sample support not found"; |
| } |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(128, 128, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image1(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.samples = VK_SAMPLE_COUNT_2_BIT; |
| vkt::Image image2(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.samples = VK_SAMPLE_COUNT_4_BIT; |
| vkt::Image image4(*m_device, image_ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = {128, 128, 1}; |
| |
| // Copy a single sample image to/from a multi-sample image |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-00136"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image1.handle(), VK_IMAGE_LAYOUT_GENERAL, image4.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-00136"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image2.handle(), VK_IMAGE_LAYOUT_GENERAL, image1.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Copy between multi-sample images with different sample counts |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-00136"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image2.handle(), VK_IMAGE_LAYOUT_GENERAL, image4.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-00136"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image4.handle(), VK_IMAGE_LAYOUT_GENERAL, image2.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageLayerCount) { |
| TEST_DESCRIPTION("Check layerCount in vkCmdCopyImage"); |
| RETURN_IF_SKIP(Init()); |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(128, 128, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image(*m_device, image_ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0}; |
| copy_region.dstOffset = {32, 32, 0}; |
| copy_region.extent = {16, 16, 1}; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-layerCount-01700"); // src |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-layerCount-01700"); // dst |
| vk::CmdCopyImage(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_region.srcSubresource.layerCount = VK_REMAINING_ARRAY_LAYERS; |
| copy_region.dstSubresource.layerCount = VK_REMAINING_ARRAY_LAYERS; |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-layerCount-09243"); // src |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-layerCount-09243"); // dst |
| vk::CmdCopyImage(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageAspectMismatch) { |
| TEST_DESCRIPTION("Image copies with aspect mask errors"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| auto ds_format = FindSupportedDepthStencilFormat(Gpu()); |
| |
| // Add Transfer support for all used formats |
| if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_R32_SFLOAT, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_R32_SFLOAT features not supported"; |
| } else if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_D32_SFLOAT, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required VK_FORMAT_D32_SFLOAT features not supported"; |
| } else if (!FormatFeaturesAreSupported(Gpu(), ds_format, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required Depth/Stencil Format features not supported"; |
| } |
| |
| vkt::Image color_image(*m_device, 128, 128, 1, VK_FORMAT_R32_SFLOAT, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image depth_image(*m_device, 128, 128, 1, VK_FORMAT_D32_SFLOAT, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image ds_image(*m_device, 128, 128, 1, ds_format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| color_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| depth_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| ds_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0, 1}; |
| copy_region.dstOffset = {64, 0, 0}; |
| copy_region.extent = {64, 128, 1}; |
| |
| // Submitting command before command buffer is in recording state |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-commandBuffer-recording"); |
| vk::CmdCopyImage(m_command_buffer.handle(), depth_image.handle(), VK_IMAGE_LAYOUT_GENERAL, depth_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.Begin(); |
| |
| // Src and dest aspect masks don't match |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01551"); |
| vk::CmdCopyImage(m_command_buffer.handle(), ds_image.handle(), VK_IMAGE_LAYOUT_GENERAL, ds_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; |
| |
| // Illegal combinations of aspect bits |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; // color must be alone |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-aspectMask-00167"); |
| // These aspect/format mismatches are redundant but unavoidable here |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspectMask-00142"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01551"); |
| vk::CmdCopyImage(m_command_buffer.handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| // same test for dstSubresource |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; // color must be alone |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-aspectMask-00167"); |
| // These aspect/format mismatches are redundant but unavoidable here |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspectMask-00143"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01551"); |
| vk::CmdCopyImage(m_command_buffer.handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Metadata aspect is illegal |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-aspectMask-00168"); |
| // These aspect/format mismatches are redundant but unavoidable here |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01551"); |
| vk::CmdCopyImage(m_command_buffer.handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| // same test for dstSubresource |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-aspectMask-00168"); |
| // These aspect/format mismatches are redundant but unavoidable here |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01551"); |
| vk::CmdCopyImage(m_command_buffer.handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Aspect Memory Plane mask is illegal |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-aspectMask-02247"); |
| // These aspect/format mismatches are redundant but unavoidable here |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01551"); |
| vk::CmdCopyImage(m_command_buffer.handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), |
| 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_DEPTH_BIT; |
| |
| // Aspect mask doesn't match source image format |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspectMask-00142"); |
| // Again redundant but unavoidable |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01548"); |
| vk::CmdCopyImage(m_command_buffer.handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, depth_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Aspect mask doesn't match dest image format |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspectMask-00143"); |
| // Again redundant but unavoidable |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-01548"); |
| vk::CmdCopyImage(m_command_buffer.handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, depth_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Check no performance warnings regarding layout are thrown when copying from and to the same image |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; |
| copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; |
| vk::CmdCopyImage(m_command_buffer.handle(), depth_image.handle(), VK_IMAGE_LAYOUT_GENERAL, depth_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, DepthStencilImageCopyNoGraphicsQueueFlags) { |
| TEST_DESCRIPTION( |
| "Allocate a command buffer on a queue that does not support graphics and try to issue a depth/stencil image copy to " |
| "buffer"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| const std::optional<uint32_t> no_gfx = m_device->NonGraphicsQueueFamily(); |
| if (!no_gfx) { |
| GTEST_SKIP() << "Non-graphics queue family not found"; |
| } |
| |
| // Create Depth image |
| const VkFormat ds_format = FindSupportedDepthOnlyFormat(Gpu()); |
| vkt::Image ds_image(*m_device, 64, 64, 1, ds_format, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| ds_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| // 256k to have more then enough to copy |
| vkt::Buffer buffer(*m_device, 262144, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); |
| |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0, 1}; |
| region.imageOffset = {0, 0, 0}; |
| region.imageExtent = {64, 64, 1}; |
| region.bufferOffset = 0; |
| |
| // Create command pool on a non-graphics queue |
| vkt::CommandPool command_pool(*m_device, no_gfx.value()); |
| |
| // Setup command buffer on pool |
| vkt::CommandBuffer command_buffer(*m_device, command_pool); |
| command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-commandBuffer-07739"); |
| vk::CmdCopyBufferToImage(command_buffer.handle(), buffer.handle(), ds_image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageTransferQueueFlags) { |
| TEST_DESCRIPTION( |
| "Allocate a command buffer on a queue that does not support graphics/compute and try to issue an invalid image copy to " |
| "buffer"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| const std::optional<uint32_t> transfer_qfi = m_device->TransferOnlyQueueFamily(); |
| if (!transfer_qfi) { |
| GTEST_SKIP() << "Transfer-only queue family not found"; |
| } |
| |
| vkt::Image image(*m_device, 32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); |
| image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| // 256k to have more then enough to copy |
| vkt::Buffer buffer(*m_device, 262144, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| region.imageSubresource.layerCount = 1; |
| region.imageOffset = {0, 0, 0}; |
| region.imageExtent = {16, 16, 1}; |
| region.bufferOffset = 5; |
| |
| // Create command pool on a non-graphics queue |
| vkt::CommandPool command_pool(*m_device, transfer_qfi.value()); |
| |
| // Setup command buffer on pool |
| vkt::CommandBuffer command_buffer(*m_device, command_pool); |
| command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-dstImage-07975"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-commandBuffer-07737"); |
| vk::CmdCopyBufferToImage(command_buffer.handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| ®ion); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, CopyCommands2V13) { |
| TEST_DESCRIPTION("Ensure copy_commands2 promotions are validated"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| RETURN_IF_SKIP(Init()); |
| vkt::Image image(*m_device, 128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| vkt::Image image2(*m_device, 128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| image2.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| vkt::Buffer dst_buffer(*m_device, 128 * 128, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| vkt::Buffer src_buffer(*m_device, 128 * 128, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| VkImageCopy2 copy_region = vku::InitStructHelper(); |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstOffset = {4, 4, 0}; |
| copy_region.extent = {1, 1, 1}; |
| |
| VkCopyImageInfo2 copy_image_info = vku::InitStructHelper(); |
| copy_image_info.srcImage = image.handle(); |
| copy_image_info.srcImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| copy_image_info.dstImage = image.handle(); |
| copy_image_info.dstImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| copy_image_info.regionCount = 1; |
| copy_image_info.pRegions = ©_region; |
| |
| m_command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspect-06663"); |
| vk::CmdCopyImage2(m_command_buffer.handle(), ©_image_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkBufferCopy2 copy_buffer = vku::InitStructHelper(); |
| copy_buffer.dstOffset = 4; |
| copy_buffer.size = 4; |
| |
| VkCopyBufferInfo2 copy_buffer_info = vku::InitStructHelper(); |
| copy_buffer_info.srcBuffer = dst_buffer.handle(); |
| copy_buffer_info.dstBuffer = dst_buffer.handle(); |
| copy_buffer_info.regionCount = 1; |
| copy_buffer_info.pRegions = ©_buffer; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferInfo2-srcBuffer-00118"); |
| vk::CmdCopyBuffer2(m_command_buffer.handle(), ©_buffer_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkBufferImageCopy2 bic_region = vku::InitStructHelper(); |
| bic_region.bufferRowLength = 128; |
| bic_region.bufferImageHeight = 128; |
| bic_region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| bic_region.imageExtent = {4, 4, 1}; |
| |
| VkCopyBufferToImageInfo2 buffer_image_info = vku::InitStructHelper(); |
| buffer_image_info.srcBuffer = src_buffer.handle(); |
| buffer_image_info.dstImage = image.handle(); |
| buffer_image_info.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| buffer_image_info.regionCount = 1; |
| buffer_image_info.pRegions = &bic_region; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferToImageInfo2-dstImage-00177"); |
| vk::CmdCopyBufferToImage2(m_command_buffer.handle(), &buffer_image_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkCopyImageToBufferInfo2 image_buffer_info = vku::InitStructHelper(); |
| image_buffer_info.dstBuffer = src_buffer.handle(); |
| image_buffer_info.srcImage = image.handle(); |
| image_buffer_info.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| image_buffer_info.regionCount = 1; |
| image_buffer_info.pRegions = &bic_region; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageToBufferInfo2-dstBuffer-00191"); |
| vk::CmdCopyImageToBuffer2(m_command_buffer.handle(), &image_buffer_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkImageBlit2 blit_region = vku::InitStructHelper(); |
| blit_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| blit_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| blit_region.srcOffsets[0] = {0, 0, 0}; |
| blit_region.srcOffsets[1] = {31, 31, 1}; |
| blit_region.dstOffsets[0] = {32, 32, 0}; |
| blit_region.dstOffsets[1] = {64, 64, 1}; |
| |
| VkBlitImageInfo2 blit_image_info = vku::InitStructHelper(); |
| blit_image_info.srcImage = image.handle(); |
| blit_image_info.srcImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| blit_image_info.dstImage = image.handle(); |
| blit_image_info.dstImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| blit_image_info.regionCount = 1; |
| blit_image_info.pRegions = &blit_region; |
| blit_image_info.filter = VK_FILTER_NEAREST; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkBlitImageInfo2-dstImage-00224"); |
| vk::CmdBlitImage2(m_command_buffer.handle(), &blit_image_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkImageResolve2 resolve_region = vku::InitStructHelper(); |
| resolve_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| resolve_region.srcOffset = {0, 0, 0}; |
| resolve_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| resolve_region.dstOffset = {0, 0, 0}; |
| resolve_region.extent = {1, 1, 1}; |
| |
| VkResolveImageInfo2 resolve_image_info = vku::InitStructHelper(); |
| resolve_image_info.srcImage = image.handle(); |
| resolve_image_info.srcImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| resolve_image_info.dstImage = image2.handle(); |
| resolve_image_info.dstImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| resolve_image_info.regionCount = 1; |
| resolve_image_info.pRegions = &resolve_region; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkResolveImageInfo2-srcImage-00257"); |
| vk::CmdResolveImage2(m_command_buffer.handle(), &resolve_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageOverlappingMemory) { |
| TEST_DESCRIPTION("Validate Copy Image from/to Buffer with overlapping memory"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| RETURN_IF_SKIP(Init()); |
| |
| VkDeviceSize buff_size = 32 * 32 * 4; |
| vkt::Buffer buffer(*m_device, |
| vkt::Buffer::CreateInfo(buff_size, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), |
| vkt::no_mem); |
| const auto buffer_memory_requirements = buffer.MemoryRequirements(); |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| vkt::Image image(*m_device, image_ci, vkt::no_mem); |
| const auto image_memory_requirements = image.MemoryRequirements(); |
| |
| vkt::DeviceMemory mem; |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(); |
| alloc_info.allocationSize = (std::max)(buffer_memory_requirements.size, image_memory_requirements.size); |
| bool has_memtype = m_device->Physical().SetMemoryType( |
| buffer_memory_requirements.memoryTypeBits & image_memory_requirements.memoryTypeBits, &alloc_info, 0); |
| if (!has_memtype) { |
| GTEST_SKIP() << "Failed to find a memory type for both a buffer and an image"; |
| } |
| mem.init(*m_device, alloc_info); |
| |
| buffer.BindMemory(mem, 0); |
| image.BindMemory(mem, 0); |
| |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.imageOffset = {0, 0, 0}; |
| region.bufferOffset = 0; |
| |
| region.imageExtent = {32, 32, 1}; |
| m_command_buffer.Begin(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-pRegions-00184"); |
| vk::CmdCopyImageToBuffer(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer.handle(), 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-pRegions-00173"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| VkBufferImageCopy2 bic2_region = vku::InitStructHelper(); |
| bic2_region.bufferRowLength = 0; |
| bic2_region.bufferImageHeight = 0; |
| bic2_region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| bic2_region.imageOffset = {0, 0, 0}; |
| bic2_region.bufferOffset = 0; |
| bic2_region.imageExtent = {32, 32, 1}; |
| |
| VkCopyImageToBufferInfo2 i2b2_info = vku::InitStructHelper(); |
| i2b2_info.dstBuffer = buffer.handle(); |
| i2b2_info.pRegions = &bic2_region; |
| i2b2_info.regionCount = 1; |
| i2b2_info.srcImage = image.handle(); |
| i2b2_info.srcImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageToBufferInfo2-pRegions-00184"); |
| vk::CmdCopyImageToBuffer2(m_command_buffer.handle(), &i2b2_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkCopyBufferToImageInfo2 b2i2_info = vku::InitStructHelper(); |
| b2i2_info.srcBuffer = buffer.handle(); |
| b2i2_info.pRegions = &bic2_region; |
| b2i2_info.regionCount = 1; |
| b2i2_info.dstImage = image.handle(); |
| b2i2_info.dstImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferToImageInfo2-pRegions-00173"); |
| vk::CmdCopyBufferToImage2(m_command_buffer.handle(), &b2i2_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageRemainingLayers) { |
| TEST_DESCRIPTION("Test copying an image with VkImageSubresourceLayers.layerCount = VK_REMAINING_ARRAY_LAYERS"); |
| RETURN_IF_SKIP(Init()); |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| |
| // Copy from a to b |
| image_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| vkt::Image image_a(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image image_b(*m_device, image_ci, vkt::set_layout); |
| |
| ASSERT_TRUE(image_a.initialized()); |
| ASSERT_TRUE(image_b.initialized()); |
| |
| m_command_buffer.Begin(); |
| |
| image_a.SetLayout(m_command_buffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); |
| image_b.SetLayout(m_command_buffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
| |
| VkImageCopy copy_region{}; |
| copy_region.extent = image_ci.extent; |
| copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy_region.srcSubresource.baseArrayLayer = 7; |
| copy_region.srcSubresource.layerCount = VK_REMAINING_ARRAY_LAYERS; // This value is unsupported by VkImageSubresourceLayer |
| copy_region.dstSubresource = copy_region.srcSubresource; |
| |
| // These vuids will trigger a special message stating that VK_REMAINING_ARRAY_LAYERS is unsupported |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-layerCount-09243"); // src |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-layerCount-09243"); // dst |
| vk::CmdCopyImage(m_command_buffer.handle(), image_a.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image_b.handle(), |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| const uint32_t buffer_size = 32 * 32 * 4; |
| vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| VkBufferImageCopy buffer_copy{}; |
| buffer_copy.bufferImageHeight = image_ci.extent.height; |
| buffer_copy.bufferRowLength = image_ci.extent.width; |
| buffer_copy.imageExtent = image_ci.extent; |
| buffer_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| buffer_copy.imageSubresource.layerCount = VK_REMAINING_ARRAY_LAYERS; // This value is unsupported by VkImageSubresourceLayers |
| buffer_copy.imageSubresource.mipLevel = 0; |
| buffer_copy.imageSubresource.baseArrayLayer = 5; |
| |
| // This error will trigger first stating that the copy is too big for the buffer, because of VK_REMAINING_ARRAY_LAYERS |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-pRegions-00171"); |
| // This error will trigger second stating that VK_REMAINING_ARRAY_LAYERS is unsupported here |
| m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceLayers-layerCount-09243"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), image_b.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, |
| &buffer_copy); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, DifferentFormatTexelBlockExtent) { |
| TEST_DESCRIPTION("Copy bewteen compress images with different texel block extent."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| RETURN_IF_SKIP(Init()); |
| |
| VkFormat src_format = VK_FORMAT_BC3_UNORM_BLOCK; |
| VkFormat dst_format = VK_FORMAT_ASTC_12x12_SRGB_BLOCK; |
| |
| VkFormatProperties format_properties; |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), src_format, &format_properties); |
| if ((format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0) { |
| GTEST_SKIP() << "Src transfer for format is not supported"; |
| } |
| vk::GetPhysicalDeviceFormatProperties(m_device->Physical().handle(), dst_format, &format_properties); |
| if ((format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0) { |
| GTEST_SKIP() << "Dst transfer for format is not supported"; |
| } |
| |
| vkt::Image src_image(*m_device, 32, 32, 1, src_format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| src_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| vkt::Image dst_image(*m_device, 32, 32, 1, dst_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| dst_image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkImageCopy region; |
| region.extent = {32, 32, 1}; |
| region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.srcOffset = {0, 0, 0}; |
| region.dstOffset = {0, 0, 0}; |
| m_command_buffer.Begin(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-09247"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1u, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, BufferToCompressedImage) { |
| TEST_DESCRIPTION("Copy buffer to compressed image when buffer is larger than image."); |
| RETURN_IF_SKIP(Init()); |
| |
| // Verify format support |
| if (!FormatFeaturesAreSupported(Gpu(), VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_IMAGE_TILING_OPTIMAL, |
| VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { |
| GTEST_SKIP() << "Required formats/features not supported"; |
| } |
| |
| vkt::Buffer buffer(*m_device, 8 * 4 * 2, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| VkBufferImageCopy region = {}; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.imageExtent = {8, 4, 1}; |
| |
| vkt::Image width_image(*m_device, 5, 4, 1, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image height_image(*m_device, 8, 3, 1, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| if (!width_image.initialized() || (!height_image.initialized())) { |
| GTEST_SKIP() << "Unable to initialize surfaces"; |
| } |
| m_command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageSubresource-07971"); |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), width_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageOffset-09104"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-imageSubresource-07970"); |
| |
| VkResult err; |
| VkImageCreateInfo depth_image_create_info = vku::InitStructHelper(); |
| depth_image_create_info.imageType = VK_IMAGE_TYPE_3D; |
| depth_image_create_info.format = VK_FORMAT_BC1_RGBA_SRGB_BLOCK; |
| depth_image_create_info.extent = {8, 4, 1}; |
| depth_image_create_info.mipLevels = 1; |
| depth_image_create_info.arrayLayers = 1; |
| depth_image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| depth_image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| depth_image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; |
| depth_image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| VkImage depth_image = VK_NULL_HANDLE; |
| err = vk::CreateImage(m_device->handle(), &depth_image_create_info, NULL, &depth_image); |
| ASSERT_EQ(VK_SUCCESS, err); |
| |
| VkDeviceMemory mem1; |
| VkMemoryRequirements mem_reqs; |
| mem_reqs.memoryTypeBits = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; |
| VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper(); |
| mem_alloc.allocationSize = 0; |
| mem_alloc.memoryTypeIndex = 0; |
| mem_alloc.memoryTypeIndex = 1; |
| vk::GetImageMemoryRequirements(device(), depth_image, &mem_reqs); |
| mem_alloc.allocationSize = mem_reqs.size; |
| bool pass = m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &mem_alloc, 0); |
| ASSERT_TRUE(pass); |
| err = vk::AllocateMemory(device(), &mem_alloc, NULL, &mem1); |
| ASSERT_EQ(VK_SUCCESS, err); |
| err = vk::BindImageMemory(device(), depth_image, mem1, 0); |
| |
| region.imageExtent.depth = 2; |
| vk::CmdCopyBufferToImage(m_command_buffer.handle(), buffer.handle(), depth_image, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::DestroyImage(device(), depth_image, NULL); |
| vk::FreeMemory(device(), mem1, NULL); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, SameImage) { |
| TEST_DESCRIPTION("use wrong layout copying to the same image."); |
| RETURN_IF_SKIP(Init()); |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_B8G8R8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image src_image(*m_device, image_ci, vkt::set_layout); |
| |
| m_command_buffer.Begin(); |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {2, 2, 0}; |
| copy_region.extent = {1, 1, 1}; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-09460"); |
| vk::CmdCopyImage(m_command_buffer.handle(), src_image.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_image.handle(), |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageRemainingArrayLayers) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(64, 64, 1, 4, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image(*m_device, image_ci, vkt::set_layout); |
| |
| VkImageCopy copy_region = {}; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, VK_REMAINING_ARRAY_LAYERS}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 3}; // should be 2, not 3 |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {4, 4, 0}; |
| copy_region.extent = {1, 1, 1}; |
| |
| m_command_buffer.Begin(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-08794"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageMemory) { |
| TEST_DESCRIPTION("Validate 4 invalid image memory VUIDs "); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddOptionalExtensions(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| const bool copy_commands2 = IsExtensionsEnabled(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); |
| |
| // Create a small image with a dedicated allocation |
| auto image_ci = vkt::Image::ImageCreateInfo2D(64, 64, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image_no_mem(*m_device, image_ci, vkt::no_mem); |
| vkt::Image image(*m_device, image_ci); |
| |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = {4, 4, 1}; |
| |
| m_command_buffer.Begin(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcImage-07966"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image_no_mem.handle(), VK_IMAGE_LAYOUT_GENERAL, image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstImage-07966"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, image_no_mem.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| if (copy_commands2) { |
| const VkImageCopy2 copy_region2 = {VK_STRUCTURE_TYPE_IMAGE_COPY_2, |
| NULL, |
| copy_region.srcSubresource, |
| copy_region.srcOffset, |
| copy_region.dstSubresource, |
| copy_region.dstOffset, |
| copy_region.extent}; |
| VkCopyImageInfo2 copy_image_info2 = {VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2, |
| NULL, |
| image_no_mem.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, |
| image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, |
| 1, |
| ©_region2}; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-srcImage-07966"); |
| m_errorMonitor->SetUnexpectedError("doesn't match the previously used layout VK_IMAGE_LAYOUT_GENERAL."); |
| vk::CmdCopyImage2KHR(m_command_buffer.handle(), ©_image_info2); |
| m_errorMonitor->VerifyFound(); |
| copy_image_info2.srcImage = image.handle(); |
| copy_image_info2.dstImage = image_no_mem.handle(); |
| m_errorMonitor->SetDesiredError("VUID-VkCopyImageInfo2-dstImage-07966"); |
| m_errorMonitor->SetUnexpectedError("doesn't match the previously used layout VK_IMAGE_LAYOUT_GENERAL.."); |
| vk::CmdCopyImage2KHR(m_command_buffer.handle(), ©_image_info2); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeCopyBufferImage, ImageMissingUsage) { |
| TEST_DESCRIPTION("Test copying from src image without VK_IMAGE_USAGE_TRANSFER_SRC_BIT."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| auto format = FindSupportedDepthStencilFormat(Gpu()); |
| VkImageStencilUsageCreateInfo stencil_usage_ci = vku::InitStructHelper(); |
| stencil_usage_ci.stencilUsage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| |
| auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, format, VK_IMAGE_USAGE_SAMPLED_BIT); |
| vkt::Image sampled_image(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image transfer_image(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.pNext = &stencil_usage_ci; |
| image_ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| vkt::Image separate_stencil_sampled_image(*m_device, image_ci, vkt::set_layout); |
| |
| image_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| stencil_usage_ci.stencilUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image separate_stencil_transfer_image(*m_device, image_ci, vkt::set_layout); |
| |
| VkImageCopy region; |
| region.srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1}; |
| region.srcOffset = {0, 0, 0}; |
| region.dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1}; |
| region.dstOffset = {0, 0, 0}; |
| region.extent = {32, 32, 1}; |
| |
| m_command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspect-06662"); |
| vk::CmdCopyImage(m_command_buffer.handle(), sampled_image.handle(), VK_IMAGE_LAYOUT_GENERAL, transfer_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspect-06663"); |
| vk::CmdCopyImage(m_command_buffer.handle(), transfer_image.handle(), VK_IMAGE_LAYOUT_GENERAL, sampled_image.handle(), |
| VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspect-06664"); |
| vk::CmdCopyImage(m_command_buffer.handle(), separate_stencil_sampled_image.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| separate_stencil_transfer_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-aspect-06665"); |
| vk::CmdCopyImage(m_command_buffer.handle(), separate_stencil_transfer_image.handle(), VK_IMAGE_LAYOUT_GENERAL, |
| separate_stencil_sampled_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, OverlappingImage) { |
| TEST_DESCRIPTION("Copy a range of an image to another overlapping range of the same image"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| vkt::Image image(*m_device, 64, 64, 1, VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); |
| image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); |
| |
| m_command_buffer.Begin(); |
| |
| VkImageCopy image_copy{}; |
| image_copy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| image_copy.srcSubresource.layerCount = 1; |
| image_copy.srcOffset = {0, 0, 0}; |
| image_copy.dstSubresource = image_copy.srcSubresource; |
| image_copy.dstOffset = {0, 0, 0}; |
| image_copy.extent = {64, 64, 1}; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-pRegions-00124"); |
| vk::CmdCopyImage(m_command_buffer.handle(), image, VK_IMAGE_LAYOUT_GENERAL, image, VK_IMAGE_LAYOUT_GENERAL, 1, &image_copy); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, MinImageTransferGranularity) { |
| TEST_DESCRIPTION("Tests for validation of Queue Family property minImageTransferGranularity."); |
| RETURN_IF_SKIP(Init()); |
| |
| auto queue_family_properties = m_device->Physical().queue_properties_; |
| auto large_granularity_family = |
| std::find_if(queue_family_properties.begin(), queue_family_properties.end(), [](VkQueueFamilyProperties family_properties) { |
| VkExtent3D family_granularity = family_properties.minImageTransferGranularity; |
| // We need a queue family that supports copy operations and has a large enough minImageTransferGranularity for the tests |
| // below to make sense. |
| return (family_properties.queueFlags & VK_QUEUE_TRANSFER_BIT || family_properties.queueFlags & VK_QUEUE_GRAPHICS_BIT || |
| family_properties.queueFlags & VK_QUEUE_COMPUTE_BIT) && |
| family_granularity.depth >= 4 && family_granularity.width >= 4 && family_granularity.height >= 4; |
| }); |
| |
| if (large_granularity_family == queue_family_properties.end()) { |
| GTEST_SKIP() << "No queue family has a large enough granularity for this test to be meaningful"; |
| } |
| const size_t queue_family_index = std::distance(queue_family_properties.begin(), large_granularity_family); |
| VkExtent3D granularity = queue_family_properties[queue_family_index].minImageTransferGranularity; |
| vkt::CommandPool command_pool(*m_device, queue_family_index, 0); |
| |
| VkImageCreateInfo image_create_info = vku::InitStructHelper(); |
| image_create_info.imageType = VK_IMAGE_TYPE_3D; |
| image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; |
| image_create_info.extent.width = granularity.width * 2; |
| image_create_info.extent.height = granularity.height * 2; |
| image_create_info.extent.depth = granularity.depth * 2; |
| 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_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| image_create_info.flags = 0; |
| vkt::Image src_image(*m_device, image_create_info, vkt::set_layout); |
| |
| image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| vkt::Image dst_image(*m_device, image_create_info, vkt::set_layout); |
| |
| vkt::CommandBuffer command_buffer(*m_device, command_pool); |
| command_buffer.Begin(); |
| |
| VkImageCopy copy_region; |
| copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.srcOffset = {0, 0, 0}; |
| copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| copy_region.dstOffset = {0, 0, 0}; |
| copy_region.extent = granularity; |
| |
| // Introduce failure by setting srcOffset to a bad granularity value |
| copy_region.srcOffset.y = 3; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); // srcOffset image transfer granularity |
| vk::CmdCopyImage(command_buffer.handle(), src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Introduce failure by setting extent to a granularity value that is bad |
| // for both the source and destination image. |
| copy_region.srcOffset.y = 0; |
| copy_region.extent.width = 3; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-srcOffset-01783"); // src extent image transfer granularity |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImage-dstOffset-01784"); // dst extent image transfer granularity |
| vk::CmdCopyImage(command_buffer.handle(), src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_GENERAL, 1, |
| ©_region); |
| m_errorMonitor->VerifyFound(); |
| |
| // Now do some buffer/image copies |
| VkDeviceSize buffer_size = 8 * granularity.height * granularity.width * granularity.depth; |
| vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| VkBufferImageCopy region = {}; |
| region.bufferOffset = 0; |
| region.bufferRowLength = 0; |
| region.bufferImageHeight = 0; |
| region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; |
| region.imageExtent = granularity; |
| region.imageOffset = {0, 0, 0}; |
| |
| // Introduce failure by setting imageExtent to a bad granularity value |
| region.imageExtent.width = 3; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyImageToBuffer-imageOffset-07747"); // image transfer granularity |
| vk::CmdCopyImageToBuffer(command_buffer.handle(), src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer.handle(), 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| region.imageExtent.width = granularity.width; |
| |
| // Introduce failure by setting imageOffset to a bad granularity value |
| region.imageOffset.z = 3; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-imageOffset-07738"); // image transfer granularity |
| vk::CmdCopyBufferToImage(command_buffer.handle(), buffer.handle(), dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, Extents) { |
| TEST_DESCRIPTION("Perform copies across a buffer, provoking out-of-range errors."); |
| |
| AddOptionalExtensions(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| const bool copy_commands2 = IsExtensionsEnabled(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); |
| |
| vkt::Buffer buffer_one(*m_device, 2048, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| vkt::Buffer buffer_two(*m_device, 2048, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| VkBufferCopy copy_info = {4096, 256, 256}; |
| |
| m_command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-srcOffset-00113"); |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer_one.handle(), buffer_two.handle(), 1, ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // equivalent test using KHR_copy_commands2 |
| if (copy_commands2) { |
| const VkBufferCopy2 copy_info2 = {VK_STRUCTURE_TYPE_BUFFER_COPY_2, NULL, copy_info.srcOffset, copy_info.dstOffset, |
| copy_info.size}; |
| const VkCopyBufferInfo2 copy_buffer_info2 = { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2, NULL, buffer_one.handle(), buffer_two.handle(), 1, ©_info2}; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferInfo2-srcOffset-00113"); |
| vk::CmdCopyBuffer2KHR(m_command_buffer.handle(), ©_buffer_info2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-dstOffset-00114"); |
| copy_info = {256, 4096, 256}; |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer_one.handle(), buffer_two.handle(), 1, ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // equivalent test using KHR_copy_commands2 |
| if (copy_commands2) { |
| const VkBufferCopy2 copy_info2 = {VK_STRUCTURE_TYPE_BUFFER_COPY_2, NULL, copy_info.srcOffset, copy_info.dstOffset, |
| copy_info.size}; |
| const VkCopyBufferInfo2 copy_buffer_info2 = { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2, NULL, buffer_one.handle(), buffer_two.handle(), 1, ©_info2}; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferInfo2-dstOffset-00114"); |
| vk::CmdCopyBuffer2KHR(m_command_buffer.handle(), ©_buffer_info2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-size-00115"); |
| copy_info = {1024, 256, 1280}; |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer_one.handle(), buffer_two.handle(), 1, ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // equivalent test using KHR_copy_commands2 |
| if (copy_commands2) { |
| const VkBufferCopy2 copy_info2 = {VK_STRUCTURE_TYPE_BUFFER_COPY_2, NULL, copy_info.srcOffset, copy_info.dstOffset, |
| copy_info.size}; |
| const VkCopyBufferInfo2 copy_buffer_info2 = { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR, NULL, buffer_one.handle(), buffer_two.handle(), 1, ©_info2}; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferInfo2-size-00115"); |
| vk::CmdCopyBuffer2KHR(m_command_buffer.handle(), ©_buffer_info2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-size-00116"); |
| copy_info = {256, 1024, 1280}; |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer_one.handle(), buffer_two.handle(), 1, ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // equivalent test using KHR_copy_commands2 |
| if (copy_commands2) { |
| const VkBufferCopy2 copy_info2 = {VK_STRUCTURE_TYPE_BUFFER_COPY_2, NULL, copy_info.srcOffset, copy_info.dstOffset, |
| copy_info.size}; |
| const VkCopyBufferInfo2 copy_buffer_info2 = { |
| VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR, NULL, buffer_one.handle(), buffer_two.handle(), 1, ©_info2}; |
| m_errorMonitor->SetDesiredError("VUID-VkCopyBufferInfo2-size-00116"); |
| vk::CmdCopyBuffer2KHR(m_command_buffer.handle(), ©_buffer_info2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-pRegions-00117"); |
| copy_info = {256, 512, 512}; |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer_two.handle(), buffer_two.handle(), 1, ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkBufferCopy-size-01988"); |
| copy_info = {256, 256, 0}; |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer_two.handle(), buffer_two.handle(), 1, ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, CompletelyOverlappingBuffer) { |
| TEST_DESCRIPTION("Test copying between buffers with completely overlapping source and destination regions."); |
| RETURN_IF_SKIP(Init()); |
| |
| VkBufferCopy copy_info; |
| copy_info.srcOffset = 0; |
| copy_info.dstOffset = 0; |
| copy_info.size = 256; |
| vkt::Buffer buffer(*m_device, copy_info.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); |
| |
| vkt::Buffer buffer_shared_memory(*m_device, buffer.CreateInfo(), vkt::no_mem); |
| buffer_shared_memory.BindMemory(buffer.Memory(), 0u); |
| |
| m_command_buffer.Begin(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-pRegions-00117"); |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer.handle(), buffer.handle(), 1, ©_info); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-pRegions-00117"); |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer.handle(), buffer_shared_memory.handle(), 1, ©_info); |
| |
| m_command_buffer.End(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, InterleavedRegions) { |
| TEST_DESCRIPTION("Test copying between interleaved source and destination regions."); |
| RETURN_IF_SKIP(Init()); |
| |
| VkBufferCopy copy_infos[4]; |
| copy_infos[0].srcOffset = 0; |
| copy_infos[0].dstOffset = 4; |
| copy_infos[0].size = 4; |
| copy_infos[1].srcOffset = 8; |
| copy_infos[1].dstOffset = 12; |
| copy_infos[1].size = 4; |
| copy_infos[2].srcOffset = 16; |
| copy_infos[2].dstOffset = 20; |
| copy_infos[2].size = 4; |
| copy_infos[3].srcOffset = 24; |
| copy_infos[3].dstOffset = 28; |
| copy_infos[3].size = 4; |
| |
| vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); |
| |
| vkt::Buffer buffer_shared_memory(*m_device, buffer.CreateInfo(), vkt::no_mem); |
| buffer_shared_memory.BindMemory(buffer.Memory(), 0u); |
| |
| m_command_buffer.Begin(); |
| |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer.handle(), buffer.handle(), 4, copy_infos); |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer.handle(), buffer_shared_memory.handle(), 4, copy_infos); |
| |
| copy_infos[2].dstOffset = 21; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-pRegions-00117"); |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer.handle(), buffer.handle(), 4, copy_infos); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-pRegions-00117"); |
| vk::CmdCopyBuffer(m_command_buffer.handle(), buffer.handle(), buffer_shared_memory.handle(), 4, copy_infos); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, FillBuffer) { |
| TEST_DESCRIPTION("Test vkCmdFillBuffer"); |
| RETURN_IF_SKIP(Init()); |
| |
| vkt::Buffer buffer(*m_device, 32u, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| vkt::Buffer invalid_usage_buffer(*m_device, 32u, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| m_command_buffer.Begin(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdFillBuffer-size-00026"); |
| vk::CmdFillBuffer(m_command_buffer.handle(), buffer.handle(), 0u, 0u, 0u); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdFillBuffer-size-00028"); |
| vk::CmdFillBuffer(m_command_buffer.handle(), buffer.handle(), 0u, 3u, 0u); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdFillBuffer-dstBuffer-00029"); |
| vk::CmdFillBuffer(m_command_buffer.handle(), invalid_usage_buffer.handle(), 0u, 4u, 0u); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdFillBuffer-dstOffset-00025"); |
| vk::CmdFillBuffer(m_command_buffer.handle(), buffer.handle(), 1u, 4u, 0u); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, UpdateBuffer) { |
| TEST_DESCRIPTION("Test vkCmdUpdateBuffer"); |
| RETURN_IF_SKIP(Init()); |
| |
| const uint32_t large_buffer_size = 131072u; |
| vkt::Buffer large_buffer(*m_device, large_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| vkt::Buffer invalid_usage_buffer(*m_device, 32, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| std::vector<uint8_t> data(large_buffer_size); |
| |
| m_command_buffer.Begin(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdUpdateBuffer-dataSize-00037"); |
| vk::CmdUpdateBuffer(m_command_buffer.handle(), large_buffer.handle(), 0u, large_buffer_size, data.data()); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdUpdateBuffer-dataSize-00038"); |
| vk::CmdUpdateBuffer(m_command_buffer.handle(), large_buffer.handle(), 0u, 5u, data.data()); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdUpdateBuffer-dstOffset-00036"); |
| vk::CmdUpdateBuffer(m_command_buffer.handle(), large_buffer.handle(), 1u, 4u, data.data()); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdUpdateBuffer-dstBuffer-00034"); |
| vk::CmdUpdateBuffer(m_command_buffer.handle(), invalid_usage_buffer.handle(), 0u, 4u, data.data()); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeCopyBufferImage, CopyToBufferWithoutMemoryBound) { |
| TEST_DESCRIPTION("Copy to dst buffer that has no memory bound"); |
| RETURN_IF_SKIP(Init()); |
| |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| buffer_ci.size = 32u; |
| vkt::Buffer src_buffer(*m_device, buffer_ci); |
| vkt::Buffer dst_buffer(*m_device, buffer_ci, vkt::no_mem); |
| |
| m_command_buffer.Begin(); |
| |
| VkBufferCopy region; |
| region.srcOffset = 0u; |
| region.dstOffset = 0u; |
| region.size = 32u; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBuffer-dstBuffer-00121"); |
| vk::CmdCopyBuffer(m_command_buffer, src_buffer.handle(), dst_buffer.handle(), 1u, ®ion); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.End(); |
| } |