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, &region->srcOffset, &granularity, i, function, "srcOffset");
     VkExtent3D subresource_extent = GetImageSubresourceExtent(src_img, &region->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, &region->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, &region->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, &region->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, &region->dstOffset, &granularity, &subresource_extent,
+    skip |= CheckItgExtent(device_data, cb_node, &dest_effective_extent, &region->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(&regions[i].srcOffset, &regions[i].extent, &img_extent)) {
+            VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(region.srcSubresource));
+            if (0 != ExceedsBounds(&region.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(&regions[i].dstOffset, &regions[i].extent, &img_extent)) {
+            img_extent = GetImageSubresourceExtent(dst_image_state, &(region.dstSubresource));
+            if (0 != ExceedsBounds(&region.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), &copy_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), &copy_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(&regions[i], &regions[j], src_image_state->createInfo.imageType)) {
+                if (RegionIntersects(&region, &regions[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,