layers: Add VUs 01202..01207
Added checks for 6 CopyImage VUs to buffer validation. Updated copy
size tests to provoke each new VU.
Change-Id: Ice7821b7c1b8aa0c90e68e8386c56bd021a616ed
diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp
index d5b15cb..a0e6df6 100644
--- a/layers/buffer_validation.cpp
+++ b/layers/buffer_validation.cpp
@@ -1054,21 +1054,25 @@
return result;
}
-// Returns true if offset and extent exceed image extents
-static bool ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent) {
- bool result = false;
+// Returns non-zero if offset and extent exceed image extents
+static const uint32_t x_bit = 1;
+static const uint32_t y_bit = 2;
+static const uint32_t z_bit = 4;
+static uint32_t ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent)
+{
+ uint32_t result = 0;
// Extents/depths cannot be negative but checks left in for clarity
if ((offset->z + extent->depth > image_extent->depth) || (offset->z < 0) ||
((offset->z + static_cast<int32_t>(extent->depth)) < 0)) {
- result = true;
+ result |= z_bit;
}
if ((offset->y + extent->height > image_extent->height) || (offset->y < 0) ||
((offset->y + static_cast<int32_t>(extent->height)) < 0)) {
- result = true;
+ result |= y_bit;
}
if ((offset->x + extent->width > image_extent->width) || (offset->x < 0) ||
((offset->x + static_cast<int32_t>(extent->width)) < 0)) {
- result = true;
+ result |= x_bit;
}
return result;
}
@@ -1086,11 +1090,26 @@
// Returns the image extent of a specific subresource.
static inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) {
const uint32_t mip = subresource->mipLevel;
- VkExtent3D extent = img->createInfo.extent;
+
+ // Return zero extent if mip level doesn't exist
+ if (mip >= img->createInfo.mipLevels)
+ {
+ return VkExtent3D{ 0, 0, 0 };
+ }
+
// Don't allow mip adjustment to create 0 dim, but pass along a 0 if that's what subresource specified
+ VkExtent3D extent = img->createInfo.extent;
extent.width = (0 == extent.width ? 0 : std::max(1U, extent.width >> mip));
extent.height = (0 == extent.height ? 0 : std::max(1U, extent.height >> mip));
extent.depth = (0 == extent.depth ? 0 : std::max(1U, extent.depth >> mip));
+
+ // For 2D images, the number of layers present becomes the effective depth (for 2D <-> 3D copies)
+ // In this case the depth extent is not diminished with mip level
+ if (VK_IMAGE_TYPE_2D == img->createInfo.imageType)
+ {
+ extent.depth = img->createInfo.arrayLayers;
+ }
+
return extent;
}
@@ -1426,24 +1445,88 @@
// Check region extents for 1D-1D, 2D-2D, and 3D-3D copies
if (src_image_state->createInfo.imageType == dst_image_state->createInfo.imageType) {
// The source region specified by a given element of regions must be a region that is contained within srcImage
- if (ExceedsBounds(®ions[i].srcOffset, ®ions[i].extent, &(src_image_state->createInfo.extent))) {
+ VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource));
+ if (0 != ExceedsBounds(®ions[i].srcOffset, ®ions[i].extent, &img_extent)) {
std::stringstream ss;
- ss << "vkCmdCopyImage: srcSubResource in pRegions[" << i << "] exceeds extents srcImage was created with";
+ ss << "vkCmdCopyImage: Source pRegion[" << i << "] with mipLevel [ " << regions[i].srcSubresource.mipLevel
+ << " ], offset [ " << regions[i].srcOffset.x << ", " << regions[i].srcOffset.y << ", " << regions[i].srcOffset.z
+ << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", "
+ << regions[i].extent.depth << " ] exceeds the source image dimensions";
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01175, "IMAGE", "%s. %s",
ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01175]);
}
// The destination region specified by a given element of regions must be a region that is contained within dst_image
- if (ExceedsBounds(®ions[i].dstOffset, ®ions[i].extent, &(dst_image_state->createInfo.extent))) {
+ img_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource));
+ if (0 != ExceedsBounds(®ions[i].dstOffset, ®ions[i].extent, &img_extent)) {
std::stringstream ss;
- ss << "vkCmdCopyImage: dstSubResource in pRegions[" << i << "] exceeds extents dstImage was created with";
+ ss << "vkCmdCopyImage: Dest pRegion[" << i << "] with mipLevel [ " << regions[i].dstSubresource.mipLevel
+ << " ], offset [ " << regions[i].dstOffset.x << ", " << regions[i].dstOffset.y << ", " << regions[i].dstOffset.z
+ << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", "
+ << regions[i].extent.depth << " ] exceeds the destination image dimensions";
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01176, "IMAGE", "%s. %s",
ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01176]);
}
}
+ // Each dimension offset + extent limits must fall with image subresource extent
+ VkExtent3D subresource_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource));
+ uint32_t extent_check = ExceedsBounds(&(regions[i].srcOffset), ®ions[i].extent, &subresource_extent);
+ if (extent_check & x_bit) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01202, "IMAGE",
+ "vkCmdCopyImage: Source image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource "
+ "width [%1d]. %s",
+ i, regions[i].srcOffset.x, regions[i].extent.width, subresource_extent.width,
+ validation_error_map[VALIDATION_ERROR_01202]);
+ }
+
+ if (extent_check & y_bit) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01203, "IMAGE",
+ "vkCmdCopyImage: Source image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource "
+ "height [%1d]. %s",
+ i, regions[i].srcOffset.y, regions[i].extent.height, subresource_extent.height,
+ validation_error_map[VALIDATION_ERROR_01203]);
+ }
+ if (extent_check & z_bit) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01204, "IMAGE",
+ "vkCmdCopyImage: Source image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource "
+ "depth [%1d]. %s",
+ i, regions[i].srcOffset.z, regions[i].extent.depth, subresource_extent.depth,
+ validation_error_map[VALIDATION_ERROR_01204]);
+ }
+
+ subresource_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource));
+ extent_check = ExceedsBounds(&(regions[i].dstOffset), ®ions[i].extent, &subresource_extent);
+ if (extent_check & x_bit) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01205, "IMAGE",
+ "vkCmdCopyImage: Dest image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource "
+ "width [%1d]. %s",
+ i, regions[i].dstOffset.x, regions[i].extent.width, subresource_extent.width,
+ validation_error_map[VALIDATION_ERROR_01205]);
+ }
+ if (extent_check & y_bit) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01206, "IMAGE",
+ "vkCmdCopyImage: Dest image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource "
+ "height [%1d]. %s",
+ i, regions[i].dstOffset.y, regions[i].extent.height, subresource_extent.height,
+ validation_error_map[VALIDATION_ERROR_01206]);
+ }
+ if (extent_check & z_bit) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01207, "IMAGE",
+ "vkCmdCopyImage: Dest image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource "
+ "depth [%1d]. %s",
+ i, regions[i].dstOffset.z, regions[i].extent.depth, subresource_extent.depth,
+ validation_error_map[VALIDATION_ERROR_01207]);
+ }
+
// The union of all source regions, and the union of all destination regions, specified by the elements of regions,
// must not overlap in memory
if (src_image_state->image == dst_image_state->image) {
@@ -2888,7 +2971,7 @@
}
}
- if (ExceedsBounds(&offset, &extent, &image_extent)) {
+ if (0 != ExceedsBounds(&offset, &extent, &image_extent)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0,
__LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds image bounds. %s.", func_name, i,
validation_error_map[msg_code]);
diff --git a/layers/vk_validation_error_database.txt b/layers/vk_validation_error_database.txt
index 9fde6e5..5b3997d 100644
--- a/layers/vk_validation_error_database.txt
+++ b/layers/vk_validation_error_database.txt
@@ -1163,12 +1163,12 @@
VALIDATION_ERROR_01199~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If either of the calling commands srcImage or dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer and layerCount members of the corresponding subresource must be 0 and 1, respectively' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
VALIDATION_ERROR_01200~^~Y~^~CopyImageAspectMismatch~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'The aspectMask member of srcSubresource must specify aspects present in the calling commands srcImage' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
VALIDATION_ERROR_01201~^~Y~^~CopyImageAspectMismatch~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'The aspectMask member of dstSubresource must specify aspects present in the calling commands dstImage' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
-VALIDATION_ERROR_01202~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcOffset.x and (extent.width + srcOffset.x) must both be greater than or equal to 0 and less than or equal to the source image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
-VALIDATION_ERROR_01203~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcOffset.y and (extent.height + srcOffset.y) must both be greater than or equal to 0 and less than or equal to the source image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
-VALIDATION_ERROR_01204~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcOffset.z and (extent.depth + srcOffset.z) must both be greater than or equal to 0 and less than or equal to the source image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
-VALIDATION_ERROR_01205~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.x and (extent.width + dstOffset.x) must both be greater than or equal to 0 and less than or equal to the destination image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
-VALIDATION_ERROR_01206~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.y and (extent.height + dstOffset.y) must both be greater than or equal to 0 and less than or equal to the destination image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
-VALIDATION_ERROR_01207~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.z and (extent.depth + dstOffset.z) must both be greater than or equal to 0 and less than or equal to the destination image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
+VALIDATION_ERROR_01202~^~Y~^~CopyImageSrcSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcOffset.x and (extent.width + srcOffset.x) must both be greater than or equal to 0 and less than or equal to the source image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
+VALIDATION_ERROR_01203~^~Y~^~CopyImageSrcSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcOffset.y and (extent.height + srcOffset.y) must both be greater than or equal to 0 and less than or equal to the source image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
+VALIDATION_ERROR_01204~^~Y~^~CopyImageSrcSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcOffset.z and (extent.depth + srcOffset.z) must both be greater than or equal to 0 and less than or equal to the source image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
+VALIDATION_ERROR_01205~^~Y~^~CopyImageDstSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.x and (extent.width + dstOffset.x) must both be greater than or equal to 0 and less than or equal to the destination image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
+VALIDATION_ERROR_01206~^~Y~^~CopyImageDstSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.y and (extent.height + dstOffset.y) must both be greater than or equal to 0 and less than or equal to the destination image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
+VALIDATION_ERROR_01207~^~Y~^~CopyImageDstSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.z and (extent.depth + dstOffset.z) must both be greater than or equal to 0 and less than or equal to the destination image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
VALIDATION_ERROR_01209~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'all members of srcOffset must be a multiple of the corresponding dimensions of the compressed texel block' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
VALIDATION_ERROR_01210~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'extent.width must be a multiple of the compressed texel block width or (extent.width + srcOffset.x) must equal the source image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
VALIDATION_ERROR_01211~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'extent.height must be a multiple of the compressed texel block height or (extent.height + srcOffset.y) must equal the source image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index c32a637..a548ec4 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -17126,76 +17126,186 @@
TEST_F(VkLayerTest, CopyImageSrcSizeExceeded) {
// Image copy with source region specified greater than src image size
- m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01175);
-
ASSERT_NO_FATAL_FAILURE(Init());
+ uint32_t queue_count = 1;
+ VkQueueFamilyProperties queue_props;
+ vkGetPhysicalDeviceQueueFamilyProperties(gpu(), &queue_count, &queue_props);
+ if (0 == queue_props.minImageTransferGranularity.width || 0 == queue_props.minImageTransferGranularity.height ||
+ 0 == queue_props.minImageTransferGranularity.depth) {
+ printf(" Image transfer granularity of 0, not supported; skipped.\n");
+ return;
+ }
+
+ // Create images with full mip chain
+ VkImageCreateInfo ci;
+ ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ ci.pNext = NULL;
+ 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;
+ ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ ci.queueFamilyIndexCount = 0;
+ ci.pQueueFamilyIndices = NULL;
+ ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
VkImageObj src_image(m_device);
- src_image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR, 0);
+ src_image.init(&ci);
+ ASSERT_TRUE(src_image.initialized());
+
+ // Dest image with one more mip level
+ ci.extent = {64, 64, 16};
+ ci.mipLevels = 7;
+ ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkImageObj dst_image(m_device);
- dst_image.Init(64, 64, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, 0);
+ dst_image.init(&ci);
+ ASSERT_TRUE(dst_image.initialized());
m_commandBuffer->BeginCommandBuffer();
+
VkImageCopy copy_region;
+ copy_region.extent = {32, 32, 8};
copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copy_region.srcSubresource.mipLevel = 0;
- copy_region.srcSubresource.baseArrayLayer = 0;
- copy_region.srcSubresource.layerCount = 0;
- copy_region.srcOffset.x = 0;
- copy_region.srcOffset.y = 0;
- copy_region.srcOffset.z = 0;
copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copy_region.dstSubresource.mipLevel = 0;
+ copy_region.srcSubresource.mipLevel = 0; // invalid for source
+ copy_region.dstSubresource.mipLevel = 0; // ok
+ copy_region.srcSubresource.baseArrayLayer = 0;
copy_region.dstSubresource.baseArrayLayer = 0;
- copy_region.dstSubresource.layerCount = 0;
- copy_region.dstOffset.x = 0;
- copy_region.dstOffset.y = 0;
- copy_region.dstOffset.z = 0;
- copy_region.extent.width = 64;
- copy_region.extent.height = 64;
- copy_region.extent.depth = 1;
+ copy_region.srcSubresource.layerCount = 1;
+ copy_region.dstSubresource.layerCount = 1;
+ copy_region.srcOffset = {0, 0, 0};
+ copy_region.dstOffset = {0, 0, 0};
+
+ m_errorMonitor->ExpectSuccess();
m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
©_region);
- m_commandBuffer->EndCommandBuffer();
+ m_errorMonitor->VerifyNotFound();
+ // Source exceeded in x-dim, VU 01202
+ copy_region.srcOffset.x = 4;
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01175); // General "contained within" VU
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01202);
+ m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
+ ©_region);
m_errorMonitor->VerifyFound();
+
+ // Source exceeded in y-dim, VU 01203
+ copy_region.srcOffset.x = 0;
+ copy_region.extent.height = 48;
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01175);
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01203);
+ m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
+ ©_region);
+ m_errorMonitor->VerifyFound();
+
+ // Source exceeded in z-dim, VU 01204
+ copy_region.extent = {4, 4, 4};
+ copy_region.srcSubresource.mipLevel = 2;
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01175);
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01204);
+ m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
+ ©_region);
+ m_errorMonitor->VerifyFound();
+
+ m_commandBuffer->EndCommandBuffer();
}
TEST_F(VkLayerTest, CopyImageDstSizeExceeded) {
// Image copy with dest region specified greater than dest image size
- m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01176);
-
ASSERT_NO_FATAL_FAILURE(Init());
- VkImageObj src_image(m_device);
- src_image.Init(64, 64, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR, 0);
+ uint32_t queue_count = 1;
+ VkQueueFamilyProperties queue_props;
+ vkGetPhysicalDeviceQueueFamilyProperties(gpu(), &queue_count, &queue_props);
+ if (0 == queue_props.minImageTransferGranularity.width || 0 == queue_props.minImageTransferGranularity.height ||
+ 0 == queue_props.minImageTransferGranularity.depth) {
+ printf(" Image transfer granularity of 0, not supported; skipped.\n");
+ return;
+ }
+
+ // Create images with full mip chain
+ VkImageCreateInfo ci;
+ ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ ci.pNext = NULL;
+ 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;
+ ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ ci.queueFamilyIndexCount = 0;
+ ci.pQueueFamilyIndices = NULL;
+ ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
VkImageObj dst_image(m_device);
- dst_image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, 0);
+ dst_image.init(&ci);
+ ASSERT_TRUE(dst_image.initialized());
+
+ // Src image with one more mip level
+ ci.extent = {64, 64, 16};
+ ci.mipLevels = 7;
+ ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ VkImageObj src_image(m_device);
+ src_image.init(&ci);
+ ASSERT_TRUE(src_image.initialized());
m_commandBuffer->BeginCommandBuffer();
+
VkImageCopy copy_region;
+ copy_region.extent = {32, 32, 8};
copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copy_region.srcSubresource.mipLevel = 0;
- copy_region.srcSubresource.baseArrayLayer = 0;
- copy_region.srcSubresource.layerCount = 0;
- copy_region.srcOffset.x = 0;
- copy_region.srcOffset.y = 0;
- copy_region.srcOffset.z = 0;
copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copy_region.dstSubresource.mipLevel = 0;
+ copy_region.srcSubresource.mipLevel = 0; // invalid for source
+ copy_region.dstSubresource.mipLevel = 0; // ok
+ copy_region.srcSubresource.baseArrayLayer = 0;
copy_region.dstSubresource.baseArrayLayer = 0;
- copy_region.dstSubresource.layerCount = 0;
- copy_region.dstOffset.x = 0;
- copy_region.dstOffset.y = 0;
- copy_region.dstOffset.z = 0;
- copy_region.extent.width = 64;
- copy_region.extent.height = 64;
- copy_region.extent.depth = 1;
+ copy_region.srcSubresource.layerCount = 1;
+ copy_region.dstSubresource.layerCount = 1;
+ copy_region.srcOffset = {0, 0, 0};
+ copy_region.dstOffset = {0, 0, 0};
+
+ m_errorMonitor->ExpectSuccess();
m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
©_region);
- m_commandBuffer->EndCommandBuffer();
+ m_errorMonitor->VerifyNotFound();
+ // Dest exceeded in x-dim, VU 01205
+ copy_region.dstOffset.x = 4;
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01176); // General "contained within" VU
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01205);
+ m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
+ ©_region);
m_errorMonitor->VerifyFound();
+
+ // Dest exceeded in y-dim, VU 01206
+ copy_region.dstOffset.x = 0;
+ copy_region.extent.height = 48;
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01176);
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01206);
+ m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
+ ©_region);
+ m_errorMonitor->VerifyFound();
+
+ // Dest exceeded in z-dim, VU 01207
+ copy_region.extent = {4, 4, 4};
+ copy_region.dstSubresource.mipLevel = 2;
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01176);
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_01207);
+ m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1,
+ ©_region);
+ m_errorMonitor->VerifyFound();
+
+ m_commandBuffer->EndCommandBuffer();
}
TEST_F(VkLayerTest, CopyImageFormatSizeMismatch) {