layers: Add checks&tests to Img-Buf copy - GH284
authorDave Houlton <daveh@lunarg.com>
Fri, 3 Feb 2017 00:26:23 +0000 (17:26 -0700)
committerDave Houlton <daveh@lunarg.com>
Thu, 16 Feb 2017 16:39:59 +0000 (09:39 -0700)
Added 16 VU checks for CmdCopyImageToBuffer and CmdCopyBufferToImage
Fixed 1 test in MiscImageLayerTests
Added 12 test in ImageBufferCopyTests

Individual commits:
GH284 add VUs 1240, 1241, 1258, 1259
GH284 add VUs 1238, 1244
GH284 add 1271 1272 1273 1274 1279 1281 1746 1747 remove 1238 1244 1262 1269
GH284 add 1227 1228 1245 1246
GH284 fix validation test MiscImageLayerTests for VU 1269/1747 swap
GH284 update database with new VU checks
GH284 redo VUs 1227 1246, move them into core validation
GH284 final checks and tests
GH284 fix a rebase merge error
GH284 fix uint64 format specifier that broke the Android build

Change-Id: I5b69eddab945fb09d4cf3645349fa45a61576355

layers/core_validation.cpp
layers/image.cpp
layers/vk_layer_utils.h
layers/vk_validation_error_database.txt

index 883c201..08cb6a8 100644 (file)
@@ -3414,7 +3414,7 @@ static bool checkGraphicsOrComputeBit(const layer_data *dev_data, VkQueueFlags f
     if (!((flags & VK_QUEUE_GRAPHICS_BIT) || (flags & VK_QUEUE_COMPUTE_BIT)))
         return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
                        DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
-                       "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name);
+                       "Cannot call %s on a command buffer allocated from a pool without graphics or compute capabilities.", name);
     return false;
 }
 
@@ -7719,6 +7719,100 @@ VKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage s
     }
 }
 
+static bool ValidateImageBounds(const layer_data *dev_data, const VkImageCreateInfo *image_info, const uint32_t regionCount,
+                                const VkBufferImageCopy *pRegions, const char *func_name, UNIQUE_VALIDATION_ERROR_CODE msg_code) {
+    bool skip = false;
+
+    for (uint32_t i = 0; i < regionCount; i++) {
+        bool overrun = false;
+        VkExtent3D extent = pRegions[i].imageExtent;
+        VkOffset3D offset = pRegions[i].imageOffset;
+        VkExtent3D image_extent = image_info->extent;
+
+        // for compressed images, the image createInfo.extent is in texel blocks
+        // convert to texels here
+        if (vk_format_is_compressed(image_info->format)) {
+            VkExtent2D texel_block_extent = vk_format_compressed_block_size(image_info->format);
+            image_extent.width *= texel_block_extent.width;
+            image_extent.height *= texel_block_extent.height;
+        }
+
+        // Extents/depths cannot be negative but checks left in for clarity
+        switch (image_info->imageType) {
+            case VK_IMAGE_TYPE_3D:  // Validate z and depth
+                if ((offset.z + extent.depth > image_extent.depth) || (offset.z < 0) ||
+                    ((offset.z + static_cast<int32_t>(extent.depth)) < 0)) {
+                    overrun = true;
+                }
+            // Intentionally fall through to 2D case to check height
+            case VK_IMAGE_TYPE_2D:  // Validate y and height
+                if ((offset.y + extent.height > image_extent.height) || (offset.y < 0) ||
+                    ((offset.y + static_cast<int32_t>(extent.height)) < 0)) {
+                    overrun = true;
+                }
+            // Intentionally fall through to 1D case to check width
+            case VK_IMAGE_TYPE_1D:  // Validate x and width
+                if ((offset.x + extent.width > image_extent.width) || (offset.x < 0) ||
+                    ((offset.x + static_cast<int32_t>(extent.width)) < 0)) {
+                    overrun = true;
+                }
+                break;
+            default:
+                assert(false);
+        }
+
+        if (overrun) {
+            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            (uint64_t)0, __LINE__, msg_code, "DS", "%s: pRegion[%d] exceeds image bounds. %s.", func_name, i,
+                            validation_error_map[msg_code]);
+        }
+    }
+
+    return skip;
+}
+
+static inline bool ValidtateBufferBounds(layer_data *dev_data, IMAGE_STATE *image_state, BUFFER_STATE *buff_state,
+                                         uint32_t regionCount, const VkBufferImageCopy *pRegions, const char *func_name,
+                                         UNIQUE_VALIDATION_ERROR_CODE msg_code) {
+    bool skip = false;
+
+    VkDeviceSize buffer_size = buff_state->createInfo.size;
+
+    for (uint32_t i = 0; i < regionCount; i++) {
+        VkExtent3D copy_extent = pRegions[i].imageExtent;
+
+        VkDeviceSize buffer_width = (0 == pRegions[i].bufferRowLength ? copy_extent.width : pRegions[i].bufferRowLength);
+        VkDeviceSize buffer_height = (0 == pRegions[i].bufferImageHeight ? copy_extent.height : pRegions[i].bufferImageHeight);
+        VkDeviceSize unit_size = vk_format_get_size(image_state->createInfo.format);  // size (bytes) of texel or block
+
+        if (vk_format_is_compressed(image_state->createInfo.format)) {
+            VkExtent2D texel_block_extent = vk_format_compressed_block_size(image_state->createInfo.format);
+            buffer_width /= texel_block_extent.width;  // switch to texel block units
+            buffer_height /= texel_block_extent.height;
+            copy_extent.width /= texel_block_extent.width;
+            copy_extent.height /= texel_block_extent.height;
+        }
+
+        // Either depth or layerCount must be 1 (or both). This is the number of 'slices' to copy
+        uint32_t zCopy = max(copy_extent.depth, pRegions[i].imageSubresource.layerCount);
+        assert(zCopy > 0);
+
+        // Calculate buffer offset of final copied byte, + 1.
+        VkDeviceSize max_buffer_offset = (zCopy - 1) * buffer_height * buffer_width;         // offset to slice
+        max_buffer_offset += ((copy_extent.height - 1) * buffer_width) + copy_extent.width;  // add row,col
+        max_buffer_offset *= unit_size;                                                      // convert to bytes
+        max_buffer_offset += pRegions[i].bufferOffset;                                       // add initial offset (bytes)
+
+        if (buffer_size < max_buffer_offset) {
+            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            (uint64_t)0, __LINE__, msg_code, "DS", "%s: pRegion[%d] exceeds buffer bounds. %s.", func_name, i,
+                            validation_error_map[msg_code]);
+        }
+    }
+
+    return skip;
+}
+
 VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
                                                 VkImageLayout dstImageLayout, uint32_t regionCount,
                                                 const VkBufferImageCopy *pRegions) {
@@ -7730,6 +7824,34 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, V
     auto src_buff_state = GetBufferState(dev_data, srcBuffer);
     auto dst_image_state = GetImageState(dev_data, dstImage);
     if (cb_node && src_buff_state && dst_image_state) {
+        // Validate command buffer state
+        if (CB_RECORDING != cb_node->state) {
+            skip_call |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01240, "DS",
+                        "Cannot call vkCmdCopyBufferToImage() on command buffer which is not in recording state. %s.",
+                        validation_error_map[VALIDATION_ERROR_01240]);
+        } else {
+            skip_call |= ValidateCmdSubpassState(dev_data, cb_node, CMD_COPYBUFFERTOIMAGE);
+        }
+
+        // Command pool must support graphics, compute, or transfer operations
+        auto pPool = GetCommandPoolNode(dev_data, cb_node->createInfo.commandPool);
+        VkQueueFlags queue_flags = dev_data->phys_dev_properties.queue_family_properties[pPool->queueFamilyIndex].queueFlags;
+        if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
+            skip_call |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01241, "DS",
+                        "Cannot call vkCmdCopyBufferToImage() on a command buffer allocated from a pool without graphics, compute, "
+                        "or transfer capabilities. %s.",
+                        validation_error_map[VALIDATION_ERROR_01241]);
+        }
+
+        skip_call |= ValidateImageBounds(dev_data, &(dst_image_state->createInfo), regionCount, pRegions,
+                                         "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01228);
+        skip_call |= ValidtateBufferBounds(dev_data, dst_image_state, src_buff_state, regionCount, pRegions,
+                                           "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01227);
+
         skip_call |= ValidateImageSampleCount(dev_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT,
                                               "vkCmdCopyBufferToImage(): dstImage", VALIDATION_ERROR_01232);
         skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02535);
@@ -7749,7 +7871,6 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, V
         function = [=]() { return ValidateBufferMemoryIsValid(dev_data, src_buff_state, "vkCmdCopyBufferToImage()"); };
         cb_node->validate_functions.push_back(function);
 
-        skip_call |= ValidateCmd(dev_data, cb_node, CMD_COPYBUFFERTOIMAGE, "vkCmdCopyBufferToImage()");
         UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFERTOIMAGE);
         skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01242);
         for (uint32_t i = 0; i < regionCount; ++i) {
@@ -7760,6 +7881,8 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, V
         }
     } else {
         assert(0);
+
+        // TODO: report VU01244 here, or put in object tracker?
     }
     lock.unlock();
     if (!skip_call)
@@ -7776,6 +7899,34 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, V
     auto src_image_state = GetImageState(dev_data, srcImage);
     auto dst_buff_state = GetBufferState(dev_data, dstBuffer);
     if (cb_node && src_image_state && dst_buff_state) {
+        // Validate command buffer state
+        if (CB_RECORDING != cb_node->state) {
+            skip_call |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01258, "DS",
+                        "Cannot call vkCmdCopyImageToBuffer() on command buffer which is not in recording state. %s.",
+                        validation_error_map[VALIDATION_ERROR_01258]);
+        } else {
+            skip_call |= ValidateCmdSubpassState(dev_data, cb_node, CMD_COPYIMAGETOBUFFER);
+        }
+
+        // Command pool must support graphics, compute, or transfer operations
+        auto pPool = GetCommandPoolNode(dev_data, cb_node->createInfo.commandPool);
+        VkQueueFlags queue_flags = dev_data->phys_dev_properties.queue_family_properties[pPool->queueFamilyIndex].queueFlags;
+        if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
+            skip_call |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01259, "DS",
+                        "Cannot call vkCmdCopyImageToBuffer() on a command buffer allocated from a pool without graphics, compute, "
+                        "or transfer capabilities. %s.",
+                        validation_error_map[VALIDATION_ERROR_01259]);
+        }
+
+        skip_call |= ValidateImageBounds(dev_data, &(src_image_state->createInfo), regionCount, pRegions,
+                                         "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01245);
+        skip_call |= ValidtateBufferBounds(dev_data, src_image_state, dst_buff_state, regionCount, pRegions,
+                                           "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_01246);
+
         skip_call |= ValidateImageSampleCount(dev_data, src_image_state, VK_SAMPLE_COUNT_1_BIT,
                                               "vkCmdCopyImageToBuffer(): srcImage", VALIDATION_ERROR_01249);
         skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02537);
@@ -7799,7 +7950,6 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, V
         };
         cb_node->validate_functions.push_back(function);
 
-        skip_call |= ValidateCmd(dev_data, cb_node, CMD_COPYIMAGETOBUFFER, "vkCmdCopyImageToBuffer()");
         UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGETOBUFFER);
         skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_01260);
         for (uint32_t i = 0; i < regionCount; ++i) {
@@ -7810,6 +7960,8 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, V
         }
     } else {
         assert(0);
+
+        // TODO: report VU01262 here, or put in object tracker?
     }
     lock.unlock();
     if (!skip_call)
index 8487b0c..cec9e7b 100644 (file)
@@ -1,7 +1,7 @@
-/* Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
- * Copyright (C) 2015-2016 Google Inc.
+/* Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (C) 2015-2017 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
  * Author: Mark Lobodzinski <mark@lunarg.com>
  * Author: Mike Stroyan <mike@LunarG.com>
  * Author: Tobin Ehlis <tobin@lunarg.com>
+ * Author: Dave Houlton <daveh@lunarg.com>
  */
 
 // Allow use of STL min and max functions in Windows
@@ -248,14 +249,36 @@ static bool ValidateBufferImageCopyData(layer_data *dev_data, uint32_t regionCou
     for (uint32_t i = 0; i < regionCount; i++) {
         auto image_info = GetImageState(dev_data, image);
         if (image_info) {
+            if (image_info->imageType == VK_IMAGE_TYPE_1D) {
+                if ((pRegions[i].imageOffset.y != 0) || (pRegions[i].imageExtent.height != 1)) {
+                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01746, "IMAGE",
+                                    "%s(): pRegion[%d] imageOffset.y is %d and imageExtent.height is %d. For 1D images these "
+                                    "must be 0 and 1, respectively. %s",
+                                    function, i, pRegions[i].imageOffset.y, pRegions[i].imageExtent.height,
+                                    validation_error_map[VALIDATION_ERROR_01746]);
+                }
+            }
+
             if ((image_info->imageType == VK_IMAGE_TYPE_1D) || (image_info->imageType == VK_IMAGE_TYPE_2D)) {
                 if ((pRegions[i].imageOffset.z != 0) || (pRegions[i].imageExtent.depth != 1)) {
                     skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
-                                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01269, "IMAGE",
-                                    "%s(): pRegion[%d] imageOffset.z is %d and imageExtent.depth is %d.  These must be 0 and 1, "
-                                    "respectively. %s",
+                                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01747, "IMAGE",
+                                    "%s(): pRegion[%d] imageOffset.z is %d and imageExtent.depth is %d. For 1D and 2D images these "
+                                    "must be 0 and 1, respectively. %s",
                                     function, i, pRegions[i].imageOffset.z, pRegions[i].imageExtent.depth,
-                                    validation_error_map[VALIDATION_ERROR_01269]);
+                                    validation_error_map[VALIDATION_ERROR_01747]);
+                }
+            }
+
+            if (image_info->imageType == VK_IMAGE_TYPE_3D) {
+                if ((0 != pRegions[i].imageSubresource.baseArrayLayer) || (1 != pRegions[i].imageSubresource.layerCount)) {
+                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01281, "IMAGE",
+                                    "%s(): pRegion[%d] imageSubresource.baseArrayLayer is %d and imageSubresource.layerCount is "
+                                    "%d. For 3D images these must be 0 and 1, respectively. %s",
+                                    function, i, pRegions[i].imageSubresource.baseArrayLayer,
+                                    pRegions[i].imageSubresource.layerCount, validation_error_map[VALIDATION_ERROR_01281]);
                 }
             }
 
@@ -298,14 +321,78 @@ static bool ValidateBufferImageCopyData(layer_data *dev_data, uint32_t regionCou
                     validation_error_map[VALIDATION_ERROR_01266]);
             }
 
+            // subresource aspectMask must have exactly 1 bit set
             const int num_bits = sizeof(VkFlags) * CHAR_BIT;
             std::bitset<num_bits> aspect_mask_bits(pRegions[i].imageSubresource.aspectMask);
             if (aspect_mask_bits.count() != 1) {
-                skip |=
-                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                            reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01280, "IMAGE",
-                            "%s: aspectMasks for imageSubresource in each region must have only a single bit set. %s", function,
-                            validation_error_map[VALIDATION_ERROR_01280]);
+                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                                reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01280, "IMAGE",
+                                "%s: aspectMasks for imageSubresource in each region must have only a single bit set. %s", function,
+                                validation_error_map[VALIDATION_ERROR_01280]);
+            }
+
+            // image subresource aspect bit must match format
+            if (((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)) &&
+                 (!vk_format_is_color(image_info->format))) ||
+                ((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)) &&
+                 (!vk_format_has_depth(image_info->format))) ||
+                ((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) &&
+                 (!vk_format_has_stencil(image_info->format)))) {
+                skip |= log_msg(
+                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01279, "IMAGE",
+                    "%s(): pRegion[%d] subresource aspectMask 0x%x specifies aspects that are not present in image format 0x%x. %s",
+                    function, i, pRegions[i].imageSubresource.aspectMask, image_info->format,
+                    validation_error_map[VALIDATION_ERROR_01279]);
+            }
+
+            // Checks that apply only to compressed images
+            // TODO: there is a comment in ValidateCopyBufferImageTransferGranularityRequirements() in core_validation.cpp that
+            //       reserves a place for these compressed image checks.  This block of code could move there once the image
+            //       stuff is moved into core validation.
+            if (vk_format_is_compressed(image_info->format)) {
+                VkExtent2D block_size = vk_format_compressed_block_size(image_info->format);
+
+                //  BufferRowLength must be a multiple of block width
+                if (vk_safe_modulo(pRegions[i].bufferRowLength, block_size.width) != 0) {
+                    skip |= log_msg(
+                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                        reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01271, "IMAGE",
+                        "%s(): pRegion[%d] bufferRowLength (%d) must be a multiple of the compressed image's texel width (%d). %s.",
+                        function, i, pRegions[i].bufferRowLength, block_size.width, validation_error_map[VALIDATION_ERROR_01271]);
+                }
+
+                //  BufferRowHeight must be a multiple of block height
+                if (vk_safe_modulo(pRegions[i].bufferImageHeight, block_size.height) != 0) {
+                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01272, "IMAGE",
+                                    "%s(): pRegion[%d] bufferImageHeight (%d) must be a multiple of the compressed image's texel "
+                                    "height (%d). %s.",
+                                    function, i, pRegions[i].bufferImageHeight, block_size.height,
+                                    validation_error_map[VALIDATION_ERROR_01272]);
+                }
+
+                //  image offsets must be multiples of block dimensions
+                if ((vk_safe_modulo(pRegions[i].imageOffset.x, block_size.width) != 0) ||
+                    (vk_safe_modulo(pRegions[i].imageOffset.y, block_size.height) != 0)) {
+                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01273, "IMAGE",
+                                    "%s(): pRegion[%d] imageOffset(x,y) (%d, %d) must be multiples of the compressed image's texel "
+                                    "width & height (%d, %d). %s.",
+                                    function, i, pRegions[i].imageOffset.x, pRegions[i].imageOffset.y, block_size.width,
+                                    block_size.height, validation_error_map[VALIDATION_ERROR_01273]);
+                }
+
+                // bufferOffset must be a multiple of block size (linear bytes)
+                int block_size_in_bytes = block_size.width * block_size.height;
+                if (vk_safe_modulo(pRegions[i].bufferOffset, block_size_in_bytes) != 0) {
+                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+                                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01274, "IMAGE",
+                                    "%s(): pRegion[%d] bufferOffset (0x%" PRIxLEAST64 ") must be a multiple of the compressed image's texel block "
+                                    "size (0x%x). %s.",
+                                    function, i, pRegions[i].bufferOffset, block_size_in_bytes,
+                                    validation_error_map[VALIDATION_ERROR_01274]);
+                }
             }
         }
     }
@@ -315,7 +402,8 @@ static bool ValidateBufferImageCopyData(layer_data *dev_data, uint32_t regionCou
 
 static bool PreCallValidateCmdCopyImageToBuffer(layer_data *dev_data, VkImage srcImage, uint32_t regionCount,
                                                 const VkBufferImageCopy *pRegions, const char *func_name) {
-    return ValidateBufferImageCopyData(dev_data, regionCount, pRegions, srcImage, "vkCmdCopyImageToBuffer");
+    bool skip = ValidateBufferImageCopyData(dev_data, regionCount, pRegions, srcImage, "vkCmdCopyImageToBuffer");
+    return skip;
 }
 
 VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
@@ -330,7 +418,8 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, V
 
 static bool PreCallValidateCmdCopyBufferToImage(layer_data *dev_data, VkImage dstImage, uint32_t regionCount,
                                                 const VkBufferImageCopy *pRegions, const char *func_name) {
-    return ValidateBufferImageCopyData(dev_data, regionCount, pRegions, dstImage, "vkCmdCopyBufferToImage");
+    bool skip = ValidateBufferImageCopyData(dev_data, regionCount, pRegions, dstImage, "vkCmdCopyBufferToImage");
+    return skip;
 }
 
 VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
index 943f846..4151ffe 100644 (file)
@@ -1,6 +1,6 @@
-/* Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
+/* Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
  *
  * Author: Mark Lobodzinski <mark@lunarg.com>
  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Dave Houlton <daveh@lunarg.com>
  */
 
 #pragma once
@@ -104,6 +105,14 @@ static inline bool vk_format_is_color(VkFormat format) {
     return !(vk_format_is_undef(format) || vk_format_is_depth_or_stencil(format));
 }
 
+static inline bool vk_format_has_depth(VkFormat format) {
+    return (vk_format_is_depth_only(format) || vk_format_is_depth_and_stencil(format));
+}
+
+static inline bool vk_format_has_stencil(VkFormat format) {
+    return (vk_format_is_stencil_only(format) || vk_format_is_depth_and_stencil(format));
+}
+
 VK_LAYER_EXPORT bool vk_format_is_norm(VkFormat format);
 VK_LAYER_EXPORT bool vk_format_is_int(VkFormat format);
 VK_LAYER_EXPORT bool vk_format_is_sint(VkFormat format);
index 4df7040..979fd83 100644 (file)
@@ -1215,8 +1215,8 @@ VALIDATION_ERROR_01223~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information ref
 VALIDATION_ERROR_01224~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states '(baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the image was created' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageSubresourceLayers)~^~
 VALIDATION_ERROR_01225~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'aspectMask must be a valid combination of VkImageAspectFlagBits values' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageSubresourceLayers)~^~implicit
 VALIDATION_ERROR_01226~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'aspectMask must not be 0' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageSubresourceLayers)~^~implicit
-VALIDATION_ERROR_01227~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The buffer region specified by a given element of pRegions must be a region that is contained within srcBuffer' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
-VALIDATION_ERROR_01228~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The image region specified by a given element of pRegions must be a region that is contained within dstImage' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
+VALIDATION_ERROR_01227~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The buffer region specified by a given element of pRegions must be a region that is contained within srcBuffer' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
+VALIDATION_ERROR_01228~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The image region specified by a given element of pRegions must be a region that is contained within dstImage' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
 VALIDATION_ERROR_01229~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The union of all source regions, and the union of all destination regions, specified by the elements of pRegions, must not overlap in memory' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
 VALIDATION_ERROR_01230~^~Y~^~None~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'srcBuffer must have been created with VK_BUFFER_USAGE_TRANSFER_SRC_BIT usage flag' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
 VALIDATION_ERROR_01231~^~Y~^~None~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'dstImage must have been created with VK_IMAGE_USAGE_TRANSFER_DST_BIT usage flag' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
@@ -1228,13 +1228,13 @@ VALIDATION_ERROR_01236~^~Y~^~None~^~vkCmdCopyBufferToImage~^~For more informatio
 VALIDATION_ERROR_01237~^~Y~^~None~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'dstImage must be a valid VkImage handle' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
 VALIDATION_ERROR_01238~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'dstImageLayout must be a valid VkImageLayout value' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
 VALIDATION_ERROR_01239~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'pRegions must be a pointer to an array of regionCount valid VkBufferImageCopy structures' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
-VALIDATION_ERROR_01240~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'commandBuffer must be in the recording state' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
-VALIDATION_ERROR_01241~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The VkCommandPool that commandBuffer was allocated from must support transfer, graphics, or compute operations' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
+VALIDATION_ERROR_01240~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'commandBuffer must be in the recording state' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
+VALIDATION_ERROR_01241~^~Y~^~None~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The VkCommandPool that commandBuffer was allocated from must support transfer, graphics, or compute operations' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
 VALIDATION_ERROR_01242~^~Y~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'This command must only be called outside of a render pass instance' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
 VALIDATION_ERROR_01243~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'regionCount must be greater than 0' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
 VALIDATION_ERROR_01244~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'Each of commandBuffer, dstImage, and srcBuffer must have been created, allocated, or retrieved from the same VkDevice' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~implicit
-VALIDATION_ERROR_01245~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The image region specified by a given element of pRegions must be a region that is contained within srcImage' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
-VALIDATION_ERROR_01246~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The buffer region specified by a given element of pRegions must be a region that is contained within dstBuffer' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
+VALIDATION_ERROR_01245~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The image region specified by a given element of pRegions must be a region that is contained within srcImage' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
+VALIDATION_ERROR_01246~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The buffer region specified by a given element of pRegions must be a region that is contained within dstBuffer' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
 VALIDATION_ERROR_01247~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The union of all source regions, and the union of all destination regions, specified by the elements of pRegions, must not overlap in memory' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
 VALIDATION_ERROR_01248~^~Y~^~None~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'srcImage must have been created with VK_IMAGE_USAGE_TRANSFER_SRC_BIT usage flag' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
 VALIDATION_ERROR_01249~^~Y~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'srcImage must have a sample count equal to VK_SAMPLE_COUNT_1_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
@@ -1246,8 +1246,8 @@ VALIDATION_ERROR_01254~^~Y~^~None~^~vkCmdCopyImageToBuffer~^~For more informatio
 VALIDATION_ERROR_01255~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'srcImageLayout must be a valid VkImageLayout value' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
 VALIDATION_ERROR_01256~^~Y~^~None~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'dstBuffer must be a valid VkBuffer handle' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
 VALIDATION_ERROR_01257~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'pRegions must be a pointer to an array of regionCount valid VkBufferImageCopy structures' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
-VALIDATION_ERROR_01258~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'commandBuffer must be in the recording state' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
-VALIDATION_ERROR_01259~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The VkCommandPool that commandBuffer was allocated from must support transfer, graphics, or compute operations' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
+VALIDATION_ERROR_01258~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'commandBuffer must be in the recording state' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
+VALIDATION_ERROR_01259~^~Y~^~None~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The VkCommandPool that commandBuffer was allocated from must support transfer, graphics, or compute operations' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
 VALIDATION_ERROR_01260~^~Y~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'This command must only be called outside of a render pass instance' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
 VALIDATION_ERROR_01261~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'regionCount must be greater than 0' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
 VALIDATION_ERROR_01262~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'Each of commandBuffer, dstBuffer, and srcImage must have been created, allocated, or retrieved from the same VkDevice' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~implicit
@@ -1257,19 +1257,19 @@ VALIDATION_ERROR_01265~^~Y~^~MiscImageLayerTests~^~vkCmdCopyImageToBuffer~^~For
 VALIDATION_ERROR_01266~^~Y~^~MiscImageLayerTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferImageHeight must be 0, or greater than or equal to the height member of imageExtent' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01267~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and less than or equal to the image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01268~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and less than or equal to the image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01269~^~Y~^~MiscImageLayerTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~This VU has two distinct conditions and the implemented check looks at both, but there are two distinct test cases for this enum
-VALIDATION_ERROR_01270~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands VkImage parameter is a compressed format image:bufferRowLength must be a multiple of the compressed texel block widthbufferImageHeight must be a multiple of the compressed texel block heightall members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel blockbufferOffset must be a multiple of the compressed texel block size in bytesimageExtent.width must be a multiple of the compressed texel block width or (imageExtent.width + imageOffset.x) must equal the image subresource widthimageExtent.height must be a multiple of the compressed texel block height or (imageExtent.height + imageOffset.y) must equal the image subresource heightimageExtent.depth must be a multiple of the compressed texel block depth or (imageExtent.depth + imageOffset.z) must equal the image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01271~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferRowLength must be a multiple of the compressed texel block width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01272~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferImageHeight must be a multiple of the compressed texel block height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01273~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'all members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel block' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01274~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferOffset must be a multiple of the compressed texel block size in bytes' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01269~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageOffset.z and (imageExtent.depth + imageOffset.z) must both be greater than or equal to 0 and less than or equal to the image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~This VU has two distinct conditions and the implemented check looks at both, but there are two distinct test cases for this enum
+VALIDATION_ERROR_01270~^~N~^~None~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands VkImage parameter is a compressed format image:bufferRowLength must be a multiple of the compressed texel block widthbufferImageHeight must be a multiple of the compressed texel block heightall members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel blockbufferOffset must be a multiple of the compressed texel block size in bytesimageExtent.width must be a multiple of the compressed texel block width or (imageExtent.width + imageOffset.x) must equal the image subresource widthimageExtent.height must be a multiple of the compressed texel block height or (imageExtent.height + imageOffset.y) must equal the image subresource heightimageExtent.depth must be a multiple of the compressed texel block depth or (imageExtent.depth + imageOffset.z) must equal the image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01271~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferRowLength must be a multiple of the compressed texel block width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01272~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferImageHeight must be a multiple of the compressed texel block height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01273~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'all members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel block' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01274~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferOffset must be a multiple of the compressed texel block size in bytes' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01275~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageExtent.width must be a multiple of the compressed texel block width or (imageExtent.width + imageOffset.x) must equal the image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01276~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageExtent.height must be a multiple of the compressed texel block height or (imageExtent.height + imageOffset.y) must equal the image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01277~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageExtent.depth must be a multiple of the compressed texel block depth or (imageExtent.depth + imageOffset.z) must equal the image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01278~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'bufferOffset, bufferRowLength, bufferImageHeight and all members of imageOffset and imageExtent must respect the image transfer granularity requirements of the queue family that it will be submitted against, as described in Physical Device Enumeration' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01279~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The aspectMask member of imageSubresource must specify aspects present in the calling commands VkImage parameter' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01280~^~Y~^~None~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The aspectMask member of imageSubresource must only have a single bit set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01281~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands VkImage parameter is of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer and layerCount members of imageSubresource must be 0 and 1, respectively' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01279~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The aspectMask member of imageSubresource must specify aspects present in the calling commands VkImage parameter' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01280~^~Y~^~ImageBufferCopyTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'The aspectMask member of imageSubresource must only have a single bit set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01281~^~Y~^~None~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands VkImage parameter is of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer and layerCount members of imageSubresource must be 0 and 1, respectively' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01282~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'When copying to the depth aspect of an image subresource, the data in the source buffer must be in the range [0,1]' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01283~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'imageSubresource must be a valid VkImageSubresourceLayers structure' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~implicit
 VALIDATION_ERROR_01287~^~N~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'The source region specified by a given element of pRegions must be a region that is contained within srcImage' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBlitImage)~^~
@@ -1689,8 +1689,8 @@ VALIDATION_ERROR_01742~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information ref
 VALIDATION_ERROR_01743~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is of type VK_IMAGE_TYPE_1D or VK_IMAGE_TYPE_2D, then srcOffset.z must be 0 and extent.depth must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageCopy)~^~
 VALIDATION_ERROR_01744~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands dstImage is of type VK_IMAGE_TYPE_1D, then dstOffset.y must be 0 and extent.height must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageCopy)~^~
 VALIDATION_ERROR_01745~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands dstImage is of type VK_IMAGE_TYPE_1D or VK_IMAGE_TYPE_2D, then dstOffset.z must be 0 and extent.depth must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageCopy)~^~
-VALIDATION_ERROR_01746~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands srcImage (vkCmdCopyImageToBuffer) or dstImage (vkCmdCopyBufferToImage) is of type VK_IMAGE_TYPE_1D, then imageOffset.y must be 0 and imageExtent.height must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
-VALIDATION_ERROR_01747~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands srcImage (vkCmdCopyImageToBuffer) or dstImage (vkCmdCopyBufferToImage) is of type VK_IMAGE_TYPE_1D or VK_IMAGE_TYPE_2D, then imageOffset.z must be 0 and imageExtent.depth must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01746~^~Y~^~None~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands srcImage (vkCmdCopyImageToBuffer) or dstImage (vkCmdCopyBufferToImage) is of type VK_IMAGE_TYPE_1D, then imageOffset.y must be 0 and imageExtent.height must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
+VALIDATION_ERROR_01747~^~Y~^~MiscImageLayerTests~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If the calling commands srcImage (vkCmdCopyImageToBuffer) or dstImage (vkCmdCopyBufferToImage) is of type VK_IMAGE_TYPE_1D or VK_IMAGE_TYPE_2D, then imageOffset.z must be 0 and imageExtent.depth must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferImageCopy)~^~
 VALIDATION_ERROR_01748~^~N~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'If the calling commands srcImage is of type VK_IMAGE_TYPE_1D, then srcOffset[0].y must be 0 and srcOffset[1].y must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageBlit)~^~
 VALIDATION_ERROR_01749~^~N~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'If the calling commands srcImage is of type VK_IMAGE_TYPE_1D or VK_IMAGE_TYPE_2D, then srcOffset[0].z must be 0 and srcOffset[1].z must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageBlit)~^~
 VALIDATION_ERROR_01750~^~N~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'If the calling commands dstImage is of type VK_IMAGE_TYPE_1D, then dstOffset[0].y must be 0 and dstOffset[1].y must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageBlit)~^~