layers: Repro and fix GH 2239
Modified positive test UncompressedToCompressedImageCopy to provoke
the issue reported in GH 2239
Fixed destination extents calculations in buffer_validation.cpp to
avoid the erroneous errors
Change-Id: I268f14a6be678d767df14f0a6694aca479854c3
diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp
index 3f0b525..cd13f24 100644
--- a/layers/buffer_validation.cpp
+++ b/layers/buffer_validation.cpp
@@ -1190,6 +1190,24 @@
return result;
}
+// For image copies between compressed/uncompressed formats, the extent is provided in source image texels
+// Destination image texel extents must be adjusted by block size for the dest validation checks
+VkExtent3D GetAdjustedDestImageExtent(VkFormat src_format, VkFormat dst_format, VkExtent3D extent) {
+ VkExtent3D adjusted_extent = extent;
+ if ((FormatIsCompressed(src_format) && (!FormatIsCompressed(dst_format)))) {
+ VkExtent3D block_size = FormatCompressedTexelBlockExtent(src_format);
+ adjusted_extent.width /= block_size.width;
+ adjusted_extent.height /= block_size.height;
+ adjusted_extent.depth /= block_size.depth;
+ } else if ((!FormatIsCompressed(src_format) && (FormatIsCompressed(dst_format)))) {
+ VkExtent3D block_size = FormatCompressedTexelBlockExtent(dst_format);
+ adjusted_extent.width *= block_size.width;
+ adjusted_extent.height *= block_size.height;
+ adjusted_extent.depth *= block_size.depth;
+ }
+ return adjusted_extent;
+}
+
// Returns the effective extent of an image subresource, adjusted for mip level and array depth.
static inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) {
const uint32_t mip = subresource->mipLevel;
@@ -1416,26 +1434,16 @@
skip |= CheckItgOffset(device_data, cb_node, ®ion->srcOffset, &granularity, i, function, "srcOffset");
VkExtent3D subresource_extent = GetImageSubresourceExtent(src_img, ®ion->srcSubresource);
VkExtent3D extent = region->extent;
- if (FormatIsCompressed(src_img->createInfo.format) && !FormatIsCompressed(dst_img->createInfo.format)) {
- // Src is compressed and dest is uncompressed, adjust extent:
- VkExtent3D block_size = FormatCompressedTexelBlockExtent(src_img->createInfo.format);
- extent.width /= block_size.width;
- extent.height /= block_size.height;
- }
skip |= CheckItgExtent(device_data, cb_node, &extent, ®ion->srcOffset, &granularity, &subresource_extent,
src_img->createInfo.imageType, i, function, "extent");
// Destination image checks
granularity = GetScaledItg(device_data, cb_node, dst_img);
skip |= CheckItgOffset(device_data, cb_node, ®ion->dstOffset, &granularity, i, function, "dstOffset");
+ // Adjust dest extent, if necessary
+ VkExtent3D dest_effective_extent = GetAdjustedDestImageExtent(src_img->createInfo.format, dst_img->createInfo.format, extent);
subresource_extent = GetImageSubresourceExtent(dst_img, ®ion->dstSubresource);
- if (!FormatIsCompressed(src_img->createInfo.format) && FormatIsCompressed(dst_img->createInfo.format)) {
- // Src is uncompressed and dest is compressed, adjust extent:
- VkExtent3D block_size = FormatCompressedTexelBlockExtent(dst_img->createInfo.format);
- extent.width *= block_size.width;
- extent.height *= block_size.height;
- }
- skip |= CheckItgExtent(device_data, cb_node, &extent, ®ion->dstOffset, &granularity, &subresource_extent,
+ skip |= CheckItgExtent(device_data, cb_node, &dest_effective_extent, ®ion->dstOffset, &granularity, &subresource_extent,
dst_img->createInfo.imageType, i, function, "extent");
return skip;
}
@@ -1446,81 +1454,85 @@
bool skip = false;
for (uint32_t i = 0; i < regionCount; i++) {
- VkImageCopy image_copy = ic_regions[i];
+ VkImageCopy region = ic_regions[i];
+
+ // For comp<->uncomp copies, the copy extent for the dest image must be adjusted
+ VkExtent3D src_copy_extent = region.extent;
+ VkExtent3D dst_copy_extent =
+ GetAdjustedDestImageExtent(src_state->createInfo.format, dst_state->createInfo.format, region.extent);
+
bool slice_override = false;
uint32_t depth_slices = 0;
// Special case for copying between a 1D/2D array and a 3D image
// TBD: This seems like the only way to reconcile 3 mutually-exclusive VU checks for 2D/3D copies. Heads up.
if ((VK_IMAGE_TYPE_3D == src_state->createInfo.imageType) && (VK_IMAGE_TYPE_3D != dst_state->createInfo.imageType)) {
- depth_slices = image_copy.dstSubresource.layerCount; // Slice count from 2D subresource
+ depth_slices = region.dstSubresource.layerCount; // Slice count from 2D subresource
slice_override = (depth_slices != 1);
} else if ((VK_IMAGE_TYPE_3D == dst_state->createInfo.imageType) && (VK_IMAGE_TYPE_3D != src_state->createInfo.imageType)) {
- depth_slices = image_copy.srcSubresource.layerCount; // Slice count from 2D subresource
+ depth_slices = region.srcSubresource.layerCount; // Slice count from 2D subresource
slice_override = (depth_slices != 1);
}
// Do all checks on source image
//
if (src_state->createInfo.imageType == VK_IMAGE_TYPE_1D) {
- if ((0 != image_copy.srcOffset.y) || (1 != image_copy.extent.height)) {
- skip |=
- log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c00124, "IMAGE",
- "vkCmdCopyImage(): pRegion[%d] srcOffset.y is %d and extent.height is %d. For 1D images these must "
- "be 0 and 1, respectively. %s",
- i, image_copy.srcOffset.y, image_copy.extent.height, validation_error_map[VALIDATION_ERROR_09c00124]);
+ if ((0 != region.srcOffset.y) || (1 != src_copy_extent.height)) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c00124, "IMAGE",
+ "vkCmdCopyImage(): pRegion[%d] srcOffset.y is %d and extent.height is %d. For 1D images these must "
+ "be 0 and 1, respectively. %s",
+ i, region.srcOffset.y, src_copy_extent.height, validation_error_map[VALIDATION_ERROR_09c00124]);
}
}
if ((src_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (src_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) {
- if ((0 != image_copy.srcOffset.z) || (1 != image_copy.extent.depth)) {
- skip |=
- log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c00128, "IMAGE",
- "vkCmdCopyImage(): pRegion[%d] srcOffset.z is %d and extent.depth is %d. For 1D and 2D images "
- "these must be 0 and 1, respectively. %s",
- i, image_copy.srcOffset.z, image_copy.extent.depth, validation_error_map[VALIDATION_ERROR_09c00128]);
+ if ((0 != region.srcOffset.z) || (1 != src_copy_extent.depth)) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c00128, "IMAGE",
+ "vkCmdCopyImage(): pRegion[%d] srcOffset.z is %d and extent.depth is %d. For 1D and 2D images "
+ "these must be 0 and 1, respectively. %s",
+ i, region.srcOffset.z, src_copy_extent.depth, validation_error_map[VALIDATION_ERROR_09c00128]);
}
}
// VU01199 changed with mnt1
if (GetDeviceExtensions(device_data)->vk_khr_maintenance1) {
if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
- if ((0 != image_copy.srcSubresource.baseArrayLayer) || (1 != image_copy.srcSubresource.layerCount)) {
+ if ((0 != region.srcSubresource.baseArrayLayer) || (1 != region.srcSubresource.layerCount)) {
skip |=
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer is %d and srcSubresource.layerCount "
"is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s",
- i, image_copy.srcSubresource.baseArrayLayer, image_copy.srcSubresource.layerCount,
+ i, region.srcSubresource.baseArrayLayer, region.srcSubresource.layerCount,
validation_error_map[VALIDATION_ERROR_09c0011a]);
}
}
} else { // Pre maint 1
if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D || dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
- if ((0 != image_copy.srcSubresource.baseArrayLayer) || (1 != image_copy.srcSubresource.layerCount)) {
+ if ((0 != region.srcSubresource.baseArrayLayer) || (1 != region.srcSubresource.layerCount)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer is %d and "
"srcSubresource.layerCount is %d. For copies with either source or dest of type "
"VK_IMAGE_TYPE_3D, these must be 0 and 1, respectively. %s",
- i, image_copy.srcSubresource.baseArrayLayer, image_copy.srcSubresource.layerCount,
+ i, region.srcSubresource.baseArrayLayer, region.srcSubresource.layerCount,
validation_error_map[VALIDATION_ERROR_09c0011a]);
}
}
}
// TODO: this VU is redundant with VU01224. Gitlab issue 812 submitted to get it removed from the spec.
- if ((image_copy.srcSubresource.baseArrayLayer >= src_state->createInfo.arrayLayers) ||
- (image_copy.srcSubresource.baseArrayLayer + image_copy.srcSubresource.layerCount > src_state->createInfo.arrayLayers)) {
+ if ((region.srcSubresource.baseArrayLayer >= src_state->createInfo.arrayLayers) ||
+ (region.srcSubresource.baseArrayLayer + region.srcSubresource.layerCount > src_state->createInfo.arrayLayers)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c0012a, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer (%d) must be less than the source image's "
"arrayLayers (%d), and the sum of baseArrayLayer and srcSubresource.layerCount (%d) must be less than "
"or equal to the source image's arrayLayers. %s",
- i, image_copy.srcSubresource.baseArrayLayer, src_state->createInfo.arrayLayers,
- image_copy.srcSubresource.layerCount, validation_error_map[VALIDATION_ERROR_09c0012a]);
+ i, region.srcSubresource.baseArrayLayer, src_state->createInfo.arrayLayers,
+ region.srcSubresource.layerCount, validation_error_map[VALIDATION_ERROR_09c0012a]);
}
// Checks that apply only to compressed images
@@ -1528,58 +1540,50 @@
VkExtent3D block_size = FormatCompressedTexelBlockExtent(src_state->createInfo.format);
// image offsets must be multiples of block dimensions
- if ((SafeModulo(image_copy.srcOffset.x, block_size.width) != 0) ||
- (SafeModulo(image_copy.srcOffset.y, block_size.height) != 0) ||
- (SafeModulo(image_copy.srcOffset.z, block_size.depth) != 0)) {
+ if ((SafeModulo(region.srcOffset.x, block_size.width) != 0) ||
+ (SafeModulo(region.srcOffset.y, block_size.height) != 0) ||
+ (SafeModulo(region.srcOffset.z, block_size.depth) != 0)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c0013a, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] srcOffset (%d, %d) must be multiples of the compressed image's "
"texel width & height (%d, %d). %s.",
- i, image_copy.srcOffset.x, image_copy.srcOffset.y, block_size.width, block_size.height,
+ i, region.srcOffset.x, region.srcOffset.y, block_size.width, block_size.height,
validation_error_map[VALIDATION_ERROR_09c0013a]);
}
- // Extent width must be a multiple of block width, or extent+offset width must equal subresource width
- VkExtent3D adj_extent = image_copy.extent;
- if (!FormatIsCompressed(dst_state->createInfo.format)) {
- // Copying from compressed source. Modify extent to be extent / texel block size
- adj_extent.width /= block_size.width;
- adj_extent.height /= block_size.height;
- }
-
- VkExtent3D mip_extent = GetImageSubresourceExtent(src_state, &(image_copy.srcSubresource));
- if ((SafeModulo(adj_extent.width, block_size.width) != 0) &&
- (adj_extent.width + image_copy.srcOffset.x != mip_extent.width)) {
+ VkExtent3D mip_extent = GetImageSubresourceExtent(src_state, &(region.srcSubresource));
+ if ((SafeModulo(src_copy_extent.width, block_size.width) != 0) &&
+ (src_copy_extent.width + region.srcOffset.x != mip_extent.width)) {
skip |=
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c0013c, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block "
"width (%d), or when added to srcOffset.x (%d) must equal the image subresource width (%d). %s.",
- i, adj_extent.width, block_size.width, image_copy.srcOffset.x, mip_extent.width,
+ i, src_copy_extent.width, block_size.width, region.srcOffset.x, mip_extent.width,
validation_error_map[VALIDATION_ERROR_09c0013c]);
}
// Extent height must be a multiple of block height, or extent+offset height must equal subresource height
- if ((SafeModulo(adj_extent.height, block_size.height) != 0) &&
- (adj_extent.height + image_copy.srcOffset.y != mip_extent.height)) {
+ if ((SafeModulo(src_copy_extent.height, block_size.height) != 0) &&
+ (src_copy_extent.height + region.srcOffset.y != mip_extent.height)) {
skip |=
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c0013e, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block "
"height (%d), or when added to srcOffset.y (%d) must equal the image subresource height (%d). %s.",
- i, adj_extent.height, block_size.height, image_copy.srcOffset.y, mip_extent.height,
+ i, src_copy_extent.height, block_size.height, region.srcOffset.y, mip_extent.height,
validation_error_map[VALIDATION_ERROR_09c0013e]);
}
// Extent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth
- uint32_t copy_depth = (slice_override ? depth_slices : image_copy.extent.depth);
- if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + image_copy.srcOffset.z != mip_extent.depth)) {
+ uint32_t copy_depth = (slice_override ? depth_slices : src_copy_extent.depth);
+ if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + region.srcOffset.z != mip_extent.depth)) {
skip |=
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(src_state->image), __LINE__, VALIDATION_ERROR_09c00140, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block "
"depth (%d), or when added to srcOffset.z (%d) must equal the image subresource depth (%d). %s.",
- i, image_copy.extent.depth, block_size.depth, image_copy.srcOffset.z, mip_extent.depth,
+ i, src_copy_extent.depth, block_size.depth, region.srcOffset.z, mip_extent.depth,
validation_error_map[VALIDATION_ERROR_09c00140]);
}
} // Compressed
@@ -1587,74 +1591,74 @@
// Do all checks on dest image
//
if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_1D) {
- if ((0 != image_copy.dstOffset.y) || (1 != image_copy.extent.height)) {
- skip |=
- log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00130, "IMAGE",
- "vkCmdCopyImage(): pRegion[%d] dstOffset.y is %d and extent.height is %d. For 1D images these must "
- "be 0 and 1, respectively. %s",
- i, image_copy.dstOffset.y, image_copy.extent.height, validation_error_map[VALIDATION_ERROR_09c00130]);
+ if ((0 != region.dstOffset.y) || (1 != dst_copy_extent.height)) {
+ skip |= log_msg(
+ report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00130, "IMAGE",
+ "vkCmdCopyImage(): pRegion[%d] dstOffset.y is %d and dst_copy_extent.height is %d. For 1D images these must "
+ "be 0 and 1, respectively. %s",
+ i, region.dstOffset.y, dst_copy_extent.height, validation_error_map[VALIDATION_ERROR_09c00130]);
}
}
if ((dst_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (dst_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) {
- if ((0 != image_copy.dstOffset.z) || (1 != image_copy.extent.depth)) {
+ if ((0 != region.dstOffset.z) || (1 != dst_copy_extent.depth)) {
skip |=
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00134, "IMAGE",
- "vkCmdCopyImage(): pRegion[%d] dstOffset.z is %d and extent.depth is %d. For 1D and 2D images "
+ "vkCmdCopyImage(): pRegion[%d] dstOffset.z is %d and dst_copy_extent.depth is %d. For 1D and 2D images "
"these must be 0 and 1, respectively. %s",
- i, image_copy.dstOffset.z, image_copy.extent.depth, validation_error_map[VALIDATION_ERROR_09c00134]);
+ i, region.dstOffset.z, dst_copy_extent.depth, validation_error_map[VALIDATION_ERROR_09c00134]);
}
}
if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
- if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) {
+ if ((0 != region.dstSubresource.baseArrayLayer) || (1 != region.dstSubresource.layerCount)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and dstSubresource.layerCount "
"is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s",
- i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount,
+ i, region.dstSubresource.baseArrayLayer, region.dstSubresource.layerCount,
validation_error_map[VALIDATION_ERROR_09c0011a]);
}
}
// VU01199 changed with mnt1
if (GetDeviceExtensions(device_data)->vk_khr_maintenance1) {
if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
- if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) {
+ if ((0 != region.dstSubresource.baseArrayLayer) || (1 != region.dstSubresource.layerCount)) {
skip |=
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and dstSubresource.layerCount "
"is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s",
- i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount,
+ i, region.dstSubresource.baseArrayLayer, region.dstSubresource.layerCount,
validation_error_map[VALIDATION_ERROR_09c0011a]);
}
}
} else { // Pre maint 1
if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D || dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
- if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) {
+ if ((0 != region.dstSubresource.baseArrayLayer) || (1 != region.dstSubresource.layerCount)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and "
"dstSubresource.layerCount is %d. For copies with either source or dest of type "
"VK_IMAGE_TYPE_3D, these must be 0 and 1, respectively. %s",
- i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount,
+ i, region.dstSubresource.baseArrayLayer, region.dstSubresource.layerCount,
validation_error_map[VALIDATION_ERROR_09c0011a]);
}
}
}
// TODO: this VU is redundant with VU01224. Gitlab issue 812 submitted to get it removed from the spec.
- if ((image_copy.dstSubresource.baseArrayLayer >= dst_state->createInfo.arrayLayers) ||
- (image_copy.dstSubresource.baseArrayLayer + image_copy.dstSubresource.layerCount > dst_state->createInfo.arrayLayers)) {
+ if ((region.dstSubresource.baseArrayLayer >= dst_state->createInfo.arrayLayers) ||
+ (region.dstSubresource.baseArrayLayer + region.dstSubresource.layerCount > dst_state->createInfo.arrayLayers)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00136, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer (%d) must be less than the dest image's "
"arrayLayers (%d), and the sum of baseArrayLayer and dstSubresource.layerCount (%d) must be less than "
"or equal to the dest image's arrayLayers. %s",
- i, image_copy.dstSubresource.baseArrayLayer, dst_state->createInfo.arrayLayers,
- image_copy.dstSubresource.layerCount, validation_error_map[VALIDATION_ERROR_09c00136]);
+ i, region.dstSubresource.baseArrayLayer, dst_state->createInfo.arrayLayers,
+ region.dstSubresource.layerCount, validation_error_map[VALIDATION_ERROR_09c00136]);
}
// Checks that apply only to compressed images
@@ -1662,59 +1666,51 @@
VkExtent3D block_size = FormatCompressedTexelBlockExtent(dst_state->createInfo.format);
// image offsets must be multiples of block dimensions
- if ((SafeModulo(image_copy.dstOffset.x, block_size.width) != 0) ||
- (SafeModulo(image_copy.dstOffset.y, block_size.height) != 0) ||
- (SafeModulo(image_copy.dstOffset.z, block_size.depth) != 0)) {
+ if ((SafeModulo(region.dstOffset.x, block_size.width) != 0) ||
+ (SafeModulo(region.dstOffset.y, block_size.height) != 0) ||
+ (SafeModulo(region.dstOffset.z, block_size.depth) != 0)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00144, "IMAGE",
"vkCmdCopyImage(): pRegion[%d] dstOffset (%d, %d) must be multiples of the compressed image's "
"texel width & height (%d, %d). %s.",
- i, image_copy.dstOffset.x, image_copy.dstOffset.y, block_size.width, block_size.height,
+ i, region.dstOffset.x, region.dstOffset.y, block_size.width, block_size.height,
validation_error_map[VALIDATION_ERROR_09c00144]);
}
- // Extent width must be a multiple of block width, or extent+offset width must equal subresource width
- VkExtent3D adj_extent = image_copy.extent;
- if (!FormatIsCompressed(src_state->createInfo.format)) {
- // Copying from uncompressed source. Modify extent to be extent * texel block size
- adj_extent.width *= block_size.width;
- adj_extent.height *= block_size.height;
+ VkExtent3D mip_extent = GetImageSubresourceExtent(dst_state, &(region.dstSubresource));
+ if ((SafeModulo(dst_copy_extent.width, block_size.width) != 0) &&
+ (dst_copy_extent.width + region.dstOffset.x != mip_extent.width)) {
+ skip |= log_msg(
+ report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00146, "IMAGE",
+ "vkCmdCopyImage(): pRegion[%d] dst_copy_extent width (%d) must be a multiple of the compressed texture block "
+ "width (%d), or when added to dstOffset.x (%d) must equal the image subresource width (%d). %s.",
+ i, dst_copy_extent.width, block_size.width, region.dstOffset.x, mip_extent.width,
+ validation_error_map[VALIDATION_ERROR_09c00146]);
}
- VkExtent3D mip_extent = GetImageSubresourceExtent(dst_state, &(image_copy.dstSubresource));
- if ((SafeModulo(adj_extent.width, block_size.width) != 0) &&
- (adj_extent.width + image_copy.dstOffset.x != mip_extent.width)) {
- skip |=
- log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00146, "IMAGE",
- "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block "
- "width (%d), or when added to dstOffset.x (%d) must equal the image subresource width (%d). %s.",
- i, adj_extent.width, block_size.width, image_copy.dstOffset.x, mip_extent.width,
- validation_error_map[VALIDATION_ERROR_09c00146]);
+ // Extent height must be a multiple of block height, or dst_copy_extent+offset height must equal subresource height
+ if ((SafeModulo(dst_copy_extent.height, block_size.height) != 0) &&
+ (dst_copy_extent.height + region.dstOffset.y != mip_extent.height)) {
+ skip |= log_msg(
+ report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00148, "IMAGE",
+ "vkCmdCopyImage(): pRegion[%d] dst_copy_extent height (%d) must be a multiple of the compressed texture block "
+ "height (%d), or when added to dstOffset.y (%d) must equal the image subresource height (%d). %s.",
+ i, dst_copy_extent.height, block_size.height, region.dstOffset.y, mip_extent.height,
+ validation_error_map[VALIDATION_ERROR_09c00148]);
}
- // Extent height must be a multiple of block height, or extent+offset height must equal subresource height
- if ((SafeModulo(adj_extent.height, block_size.height) != 0) &&
- (adj_extent.height + image_copy.dstOffset.y != mip_extent.height)) {
- skip |=
- log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c00148, "IMAGE",
- "vkCmdCopyImage(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block "
- "height (%d), or when added to dstOffset.y (%d) must equal the image subresource height (%d). %s.",
- i, adj_extent.height, block_size.height, image_copy.dstOffset.y, mip_extent.height,
- validation_error_map[VALIDATION_ERROR_09c00148]);
- }
-
- // Extent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth
- uint32_t copy_depth = (slice_override ? depth_slices : image_copy.extent.depth);
- if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + image_copy.dstOffset.z != mip_extent.depth)) {
- skip |=
- log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c0014a, "IMAGE",
- "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block "
- "depth (%d), or when added to dstOffset.z (%d) must equal the image subresource depth (%d). %s.",
- i, image_copy.extent.depth, block_size.depth, image_copy.dstOffset.z, mip_extent.depth,
- validation_error_map[VALIDATION_ERROR_09c0014a]);
+ // Extent depth must be a multiple of block depth, or dst_copy_extent+offset depth must equal subresource depth
+ uint32_t copy_depth = (slice_override ? depth_slices : dst_copy_extent.depth);
+ if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + region.dstOffset.z != mip_extent.depth)) {
+ skip |= log_msg(
+ report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ HandleToUint64(dst_state->image), __LINE__, VALIDATION_ERROR_09c0014a, "IMAGE",
+ "vkCmdCopyImage(): pRegion[%d] dst_copy_extent width (%d) must be a multiple of the compressed texture block "
+ "depth (%d), or when added to dstOffset.z (%d) must equal the image subresource depth (%d). %s.",
+ i, dst_copy_extent.depth, block_size.depth, region.dstOffset.z, mip_extent.depth,
+ validation_error_map[VALIDATION_ERROR_09c0014a]);
}
} // Compressed
}
@@ -1731,6 +1727,13 @@
VkCommandBuffer command_buffer = cb_node->commandBuffer;
for (uint32_t i = 0; i < region_count; i++) {
+ VkImageCopy region = regions[i];
+
+ // For comp/uncomp copies, the copy extent for the dest image must be adjusted
+ VkExtent3D src_copy_extent = region.extent;
+ VkExtent3D dst_copy_extent =
+ GetAdjustedDestImageExtent(src_image_state->createInfo.format, dst_image_state->createInfo.format, region.extent);
+
bool slice_override = false;
uint32_t depth_slices = 0;
@@ -1738,15 +1741,15 @@
// TBD: This seems like the only way to reconcile 3 mutually-exclusive VU checks for 2D/3D copies. Heads up.
if ((VK_IMAGE_TYPE_3D == src_image_state->createInfo.imageType) &&
(VK_IMAGE_TYPE_3D != dst_image_state->createInfo.imageType)) {
- depth_slices = regions[i].dstSubresource.layerCount; // Slice count from 2D subresource
+ depth_slices = region.dstSubresource.layerCount; // Slice count from 2D subresource
slice_override = (depth_slices != 1);
} else if ((VK_IMAGE_TYPE_3D == dst_image_state->createInfo.imageType) &&
(VK_IMAGE_TYPE_3D != src_image_state->createInfo.imageType)) {
- depth_slices = regions[i].srcSubresource.layerCount; // Slice count from 2D subresource
+ depth_slices = region.srcSubresource.layerCount; // Slice count from 2D subresource
slice_override = (depth_slices != 1);
}
- if (regions[i].srcSubresource.layerCount == 0) {
+ if (region.srcSubresource.layerCount == 0) {
std::stringstream ss;
ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero";
skip |=
@@ -1754,7 +1757,7 @@
HandleToUint64(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
}
- if (regions[i].dstSubresource.layerCount == 0) {
+ if (region.dstSubresource.layerCount == 0) {
std::stringstream ss;
ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] dstSubresource is zero";
skip |=
@@ -1768,11 +1771,11 @@
// The number of depth slices in srcSubresource and dstSubresource must match
// Depth comes from layerCount for 1D,2D resources, from extent.depth for 3D
uint32_t src_slices =
- (VK_IMAGE_TYPE_3D == src_image_state->createInfo.imageType ? regions[i].extent.depth
- : regions[i].srcSubresource.layerCount);
+ (VK_IMAGE_TYPE_3D == src_image_state->createInfo.imageType ? src_copy_extent.depth
+ : region.srcSubresource.layerCount);
uint32_t dst_slices =
- (VK_IMAGE_TYPE_3D == dst_image_state->createInfo.imageType ? regions[i].extent.depth
- : regions[i].dstSubresource.layerCount);
+ (VK_IMAGE_TYPE_3D == dst_image_state->createInfo.imageType ? dst_copy_extent.depth
+ : region.dstSubresource.layerCount);
if (src_slices != dst_slices) {
std::stringstream ss;
ss << "vkCmdCopyImage: number of depth slices in source and destination subresources for pRegions[" << i
@@ -1784,7 +1787,7 @@
}
} else {
// For each region the layerCount member of srcSubresource and dstSubresource must match
- if (regions[i].srcSubresource.layerCount != regions[i].dstSubresource.layerCount) {
+ if (region.srcSubresource.layerCount != region.dstSubresource.layerCount) {
std::stringstream ss;
ss << "vkCmdCopyImage: number of layers in source and destination subresources for pRegions[" << i
<< "] do not match";
@@ -1795,7 +1798,7 @@
}
// For each region, the aspectMask member of srcSubresource and dstSubresource must match
- if (regions[i].srcSubresource.aspectMask != regions[i].dstSubresource.aspectMask) {
+ if (region.srcSubresource.aspectMask != region.dstSubresource.aspectMask) {
char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00112, "IMAGE", "%s. %s", str,
@@ -1803,7 +1806,7 @@
}
// For each region, the aspectMask member of srcSubresource must be present in the source image
- if (!VerifyAspectsPresent(regions[i].srcSubresource.aspectMask, src_image_state->createInfo.format)) {
+ if (!VerifyAspectsPresent(region.srcSubresource.aspectMask, src_image_state->createInfo.format)) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegion[" << i
<< "] srcSubresource.aspectMask cannot specify aspects not present in source image";
@@ -1813,7 +1816,7 @@
}
// For each region, the aspectMask member of dstSubresource must be present in the destination image
- if (!VerifyAspectsPresent(regions[i].dstSubresource.aspectMask, dst_image_state->createInfo.format)) {
+ if (!VerifyAspectsPresent(region.dstSubresource.aspectMask, dst_image_state->createInfo.format)) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegion[" << i << "] dstSubresource.aspectMask cannot specify aspects not present in dest image";
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -1822,8 +1825,8 @@
}
// AspectMask must not contain VK_IMAGE_ASPECT_METADATA_BIT
- if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) ||
- (regions[i].dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) {
+ if ((region.srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) ||
+ (region.dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegions[" << i << "] may not specify aspectMask containing VK_IMAGE_ASPECT_METADATA_BIT";
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -1833,8 +1836,8 @@
// For each region, if aspectMask contains VK_IMAGE_ASPECT_COLOR_BIT, it must not contain either of
// VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
- if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
- (regions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
+ if ((region.srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
+ (region.srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a60014e, "IMAGE", "%s. %s", str,
@@ -1842,7 +1845,7 @@
}
// MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
- if (regions[i].srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) {
+ if (region.srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegions[" << i
<< "] specifies a src mipLevel greater than the number specified when the srcImage was created.";
@@ -1850,7 +1853,7 @@
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600152, "IMAGE", "%s. %s",
ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600152]);
}
- if (regions[i].dstSubresource.mipLevel >= dst_image_state->createInfo.mipLevels) {
+ if (region.dstSubresource.mipLevel >= dst_image_state->createInfo.mipLevels) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegions[" << i
<< "] specifies a dst mipLevel greater than the number specified when the dstImage was created.";
@@ -1861,22 +1864,18 @@
// (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the
// image was created
- if ((regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount) >
- src_image_state->createInfo.arrayLayers) {
+ if ((region.srcSubresource.baseArrayLayer + region.srcSubresource.layerCount) > src_image_state->createInfo.arrayLayers) {
std::stringstream ss;
ss << "vkCmdCopyImage: srcImage arrayLayers was " << src_image_state->createInfo.arrayLayers << " but subRegion[" << i
- << "] baseArrayLayer + layerCount is "
- << (regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount);
+ << "] baseArrayLayer + layerCount is " << (region.srcSubresource.baseArrayLayer + region.srcSubresource.layerCount);
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600154, "IMAGE", "%s. %s",
ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600154]);
}
- if ((regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount) >
- dst_image_state->createInfo.arrayLayers) {
+ if ((region.dstSubresource.baseArrayLayer + region.dstSubresource.layerCount) > dst_image_state->createInfo.arrayLayers) {
std::stringstream ss;
ss << "vkCmdCopyImage: dstImage arrayLayers was " << dst_image_state->createInfo.arrayLayers << " but subRegion[" << i
- << "] baseArrayLayer + layerCount is "
- << (regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount);
+ << "] baseArrayLayer + layerCount is " << (region.dstSubresource.baseArrayLayer + region.dstSubresource.layerCount);
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600154, "IMAGE", "%s. %s",
ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600154]);
@@ -1885,26 +1884,26 @@
// 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
- VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource));
- if (0 != ExceedsBounds(®ions[i].srcOffset, ®ions[i].extent, &img_extent)) {
+ VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(region.srcSubresource));
+ if (0 != ExceedsBounds(®ion.srcOffset, &src_copy_extent, &img_extent)) {
std::stringstream ss;
- 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";
+ ss << "vkCmdCopyImage: Source pRegion[" << i << "] with mipLevel [ " << region.srcSubresource.mipLevel
+ << " ], offset [ " << region.srcOffset.x << ", " << region.srcOffset.y << ", " << region.srcOffset.z
+ << " ], extent [ " << src_copy_extent.width << ", " << src_copy_extent.height << ", " << src_copy_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,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_190000f4, "IMAGE", "%s. %s",
ss.str().c_str(), validation_error_map[VALIDATION_ERROR_190000f4]);
}
// The destination region specified by a given element of regions must be a region that is contained within dst_image
- img_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource));
- if (0 != ExceedsBounds(®ions[i].dstOffset, ®ions[i].extent, &img_extent)) {
+ img_extent = GetImageSubresourceExtent(dst_image_state, &(region.dstSubresource));
+ if (0 != ExceedsBounds(®ion.dstOffset, &dst_copy_extent, &img_extent)) {
std::stringstream ss;
- 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";
+ ss << "vkCmdCopyImage: Dest pRegion[" << i << "] with mipLevel [ " << region.dstSubresource.mipLevel
+ << " ], offset [ " << region.dstOffset.x << ", " << region.dstOffset.y << ", " << region.dstOffset.z
+ << " ], extent [ " << dst_copy_extent.width << ", " << dst_copy_extent.height << ", " << dst_copy_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,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_190000f6, "IMAGE", "%s. %s",
ss.str().c_str(), validation_error_map[VALIDATION_ERROR_190000f6]);
@@ -1912,16 +1911,15 @@
}
// Each dimension offset + extent limits must fall with image subresource extent
- VkExtent3D subresource_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource));
- VkExtent3D copy_extent = regions[i].extent;
- if (slice_override) copy_extent.depth = depth_slices;
- uint32_t extent_check = ExceedsBounds(&(regions[i].srcOffset), ©_extent, &subresource_extent);
+ VkExtent3D subresource_extent = GetImageSubresourceExtent(src_image_state, &(region.srcSubresource));
+ if (slice_override) src_copy_extent.depth = depth_slices;
+ uint32_t extent_check = ExceedsBounds(&(region.srcOffset), &src_copy_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,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00120, "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,
+ i, region.srcOffset.x, src_copy_extent.width, subresource_extent.width,
validation_error_map[VALIDATION_ERROR_09c00120]);
}
@@ -1930,7 +1928,7 @@
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00122, "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,
+ i, region.srcOffset.y, src_copy_extent.height, subresource_extent.height,
validation_error_map[VALIDATION_ERROR_09c00122]);
}
if (extent_check & z_bit) {
@@ -1938,20 +1936,21 @@
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00126, "IMAGE",
"vkCmdCopyImage: Source image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource "
"depth [%1d]. %s",
- i, regions[i].srcOffset.z, copy_extent.depth, subresource_extent.depth,
+ i, region.srcOffset.z, src_copy_extent.depth, subresource_extent.depth,
validation_error_map[VALIDATION_ERROR_09c00126]);
}
- subresource_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource));
- copy_extent = regions[i].extent;
- if (slice_override) copy_extent.depth = depth_slices;
- extent_check = ExceedsBounds(&(regions[i].dstOffset), ©_extent, &subresource_extent);
+ // Adjust dest extent if necessary
+ subresource_extent = GetImageSubresourceExtent(dst_image_state, &(region.dstSubresource));
+ if (slice_override) dst_copy_extent.depth = depth_slices;
+
+ extent_check = ExceedsBounds(&(region.dstOffset), &dst_copy_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,
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c0012c, "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,
+ i, region.dstOffset.x, dst_copy_extent.width, subresource_extent.width,
validation_error_map[VALIDATION_ERROR_09c0012c]);
}
if (extent_check & y_bit) {
@@ -1959,7 +1958,7 @@
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c0012e, "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,
+ i, region.dstOffset.y, dst_copy_extent.height, subresource_extent.height,
validation_error_map[VALIDATION_ERROR_09c0012e]);
}
if (extent_check & z_bit) {
@@ -1967,7 +1966,7 @@
HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00132, "IMAGE",
"vkCmdCopyImage: Dest image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource "
"depth [%1d]. %s",
- i, regions[i].dstOffset.z, copy_extent.depth, subresource_extent.depth,
+ i, region.dstOffset.z, dst_copy_extent.depth, subresource_extent.depth,
validation_error_map[VALIDATION_ERROR_09c00132]);
}
@@ -1975,7 +1974,7 @@
// must not overlap in memory
if (src_image_state->image == dst_image_state->image) {
for (uint32_t j = 0; j < region_count; j++) {
- if (RegionIntersects(®ions[i], ®ions[j], src_image_state->createInfo.imageType)) {
+ if (RegionIntersects(®ion, ®ions[j], src_image_state->createInfo.imageType)) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "].";
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,