layers: More CmdBlitImage VU checks
authorDave Houlton <daveh@lunarg.com>
Fri, 9 Jun 2017 23:08:32 +0000 (17:08 -0600)
committerDave Houlton <daveh@lunarg.com>
Fri, 30 Jun 2017 16:37:09 +0000 (10:37 -0600)
Add 11 more VU checks to CmdBlitImage.  Fix layer_validation_tests
errors exposed by these new checks, add new tests for the new checks.
Update database file and clang-format the modified source files.

Change-Id: I3457dd0a31e04ab001bc8fb5bf638eb3f990f5d9

layers/buffer_validation.cpp
layers/vk_validation_error_database.txt
tests/layer_validation_tests.cpp

index 6f4440b..cafa37e 100644 (file)
@@ -43,7 +43,7 @@ std::string to_string(T var) {
     ss << var;
     return ss.str();
 }
-}
+}  // namespace std
 #endif
 
 void SetLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout) {
@@ -496,7 +496,8 @@ bool ValidateBarriersToImages(layer_data *device_data, VkCommandBuffer cmdBuffer
             // Make sure layout is able to be transitioned, currently only presented shared presentable images are locked
             if (image_state->layout_locked) {
                 // TODO: Add unique id for error when available
-                skip |= log_msg(core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT,
+                skip |= log_msg(
+                    core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT,
                     VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 0, "DS",
                     "Attempting to transition shared presentable image 0x%" PRIxLEAST64
                     " from layout %s to layout %s, but image has already been presented and cannot have its layout transitioned.",
@@ -921,9 +922,9 @@ bool VerifyClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IM
             if (!GetDeviceExtensions(device_data)->vk_khr_shared_presentable_image) {
                 // TODO: Add unique error id when available.
                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
-                    HandleToUint64(image_state->image), __LINE__, 0, "DS",
-                    "Must enable VK_KHR_shared_presentable_image extension before creating images with a layout type "
-                    "of VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR.");
+                                HandleToUint64(image_state->image), __LINE__, 0, "DS",
+                                "Must enable VK_KHR_shared_presentable_image extension before creating images with a layout type "
+                                "of VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR.");
 
             } else {
                 if (image_state->shared_presentable) {
@@ -2213,6 +2214,149 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
         skip |= insideRenderPass(device_data, cb_node, "vkCmdBlitImage()", VALIDATION_ERROR_18400017);
         // TODO: Need to validate image layouts, which will include layout validation for shared presentable images
 
+        VkFormat src_format = src_image_state->createInfo.format;
+        VkFormat dst_format = dst_image_state->createInfo.format;
+        VkImageType src_type = src_image_state->createInfo.imageType;
+        VkImageType dst_type = dst_image_state->createInfo.imageType;
+
+        const VkFormatProperties *props = GetFormatProperties(device_data, src_format);
+        VkImageTiling tiling = src_image_state->createInfo.tiling;
+        VkFormatFeatureFlags flags =
+            (tiling == VK_IMAGE_TILING_LINEAR ? props->linearTilingFeatures : props->optimalTilingFeatures);
+        if (VK_FORMAT_FEATURE_BLIT_SRC_BIT != (flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001b4, "IMAGE",
+                            "vkCmdBlitImage: source image format %s does not support VK_FORMAT_FEATURE_BLIT_SRC_BIT feature. %s",
+                            string_VkFormat(src_format), validation_error_map[VALIDATION_ERROR_184001b4]);
+        }
+
+        if ((VK_FILTER_LINEAR == filter) &&
+            (VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT != (flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001d6, "IMAGE",
+                            "vkCmdBlitImage: source image format %s does not support linear filtering. %s",
+                            string_VkFormat(src_format), validation_error_map[VALIDATION_ERROR_184001d6]);
+        }
+
+        if ((VK_FILTER_CUBIC_IMG == filter) && (VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG !=
+                                                (flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG))) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001d8, "IMAGE",
+                            "vkCmdBlitImage: source image format %s does not support cubic filtering. %s",
+                            string_VkFormat(src_format), validation_error_map[VALIDATION_ERROR_184001d8]);
+        }
+
+        if ((VK_FILTER_CUBIC_IMG == filter) && (VK_IMAGE_TYPE_3D != src_type)) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001da, "IMAGE",
+                            "vkCmdBlitImage: source image type must be VK_IMAGE_TYPE_3D when cubic filtering is specified. %s",
+                            validation_error_map[VALIDATION_ERROR_184001da]);
+        }
+
+        props = GetFormatProperties(device_data, dst_format);
+        tiling = dst_image_state->createInfo.tiling;
+        flags = (tiling == VK_IMAGE_TILING_LINEAR ? props->linearTilingFeatures : props->optimalTilingFeatures);
+        if (VK_FORMAT_FEATURE_BLIT_DST_BIT != (flags & VK_FORMAT_FEATURE_BLIT_DST_BIT)) {
+            skip |=
+                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                        HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001be, "IMAGE",
+                        "vkCmdBlitImage: destination image format %s does not support VK_FORMAT_FEATURE_BLIT_DST_BIT feature. %s",
+                        string_VkFormat(dst_format), validation_error_map[VALIDATION_ERROR_184001be]);
+        }
+
+        if ((VK_SAMPLE_COUNT_1_BIT != src_image_state->createInfo.samples) ||
+            (VK_SAMPLE_COUNT_1_BIT != dst_image_state->createInfo.samples)) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001c8, "IMAGE",
+                            "vkCmdBlitImage: source or dest image has sample count other than VK_SAMPLE_COUNT_1_BIT. %s",
+                            validation_error_map[VALIDATION_ERROR_184001c8]);
+        }
+
+        // Validate consistency for unsigned formats
+        if (FormatIsUInt(src_format) != FormatIsUInt(dst_format)) {
+            std::stringstream ss;
+            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has unsigned integer format, "
+               << "the other one must also have unsigned integer format.  "
+               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001cc, "IMAGE", "%s. %s",
+                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001cc]);
+        }
+
+        // Validate consistency for signed formats
+        if (FormatIsSInt(src_format) != FormatIsSInt(dst_format)) {
+            std::stringstream ss;
+            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed integer format, "
+               << "the other one must also have signed integer format.  "
+               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ca, "IMAGE", "%s. %s",
+                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001ca]);
+        }
+
+        // Validate filter for Depth/Stencil formats
+        if (FormatIsDepthOrStencil(src_format) && (filter != VK_FILTER_NEAREST)) {
+            std::stringstream ss;
+            ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, or depth stencil "
+               << "then filter must be VK_FILTER_NEAREST.";
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001d0, "IMAGE", "%s. %s",
+                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001d0]);
+        }
+
+        // Validate aspect bits and formats for depth/stencil images
+        if (FormatIsDepthOrStencil(src_format) || FormatIsDepthOrStencil(dst_format)) {
+            if (src_format != dst_format) {
+                std::stringstream ss;
+                ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
+                   << "stencil, the other one must have exactly the same format.  "
+                   << "Source format is " << string_VkFormat(src_format) << " Destination format is "
+                   << string_VkFormat(dst_format);
+                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                                HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ce, "IMAGE", "%s. %s",
+                                ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001ce]);
+            }
+
+#if 0  // TODO: Cannot find VU statements or spec language for these in CmdBlitImage. Verify or remove.
+            for (uint32_t i = 0; i < regionCount; i++) {
+                VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
+
+                if (FormatIsDepthAndStencil(src_format)) {
+                    if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
+                        std::stringstream ss;
+                        ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
+                            "VK_IMAGE_ASPECT_DEPTH_BIT "
+                            << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
+                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE",
+                            "%s", ss.str().c_str());
+                    }
+                }
+                else if (FormatIsStencilOnly(src_format)) {
+                    if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
+                        std::stringstream ss;
+                        ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
+                            << "set in both the srcImage and dstImage";
+                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE",
+                            "%s", ss.str().c_str());
+                    }
+                }
+                else if (FormatIsDepthOnly(src_format)) {
+                    if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
+                        std::stringstream ss;
+                        ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
+                            << "set in both the srcImage and dstImage";
+                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                            HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE",
+                            "%s", ss.str().c_str());
+                    }
+                }
+            }
+#endif
+        }  // Depth or Stencil
+
+        // Do per-region checks
         for (uint32_t i = 0; i < regionCount; i++) {
             VkImageBlit rgn = pRegions[i];
 
@@ -2260,9 +2404,26 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
                                 validation_error_map[VALIDATION_ERROR_09a001dc]);
             }
 
+            if (!VerifyAspectsPresent(rgn.srcSubresource.aspectMask, src_format)) {
+                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                                HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001e2, "IMAGE",
+                                "vkCmdBlitImage: region [%d] source aspectMask (0x%x) specifies aspects not present in source "
+                                "image format %s. %s",
+                                i, rgn.srcSubresource.aspectMask, string_VkFormat(src_format),
+                                validation_error_map[VALIDATION_ERROR_09a001e2]);
+            }
+
+            if (!VerifyAspectsPresent(rgn.dstSubresource.aspectMask, dst_format)) {
+                skip |= log_msg(
+                    report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                    HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001e4, "IMAGE",
+                    "vkCmdBlitImage: region [%d] dest aspectMask (0x%x) specifies aspects not present in dest image format %s. %s",
+                    i, rgn.dstSubresource.aspectMask, string_VkFormat(dst_format), validation_error_map[VALIDATION_ERROR_09a001e4]);
+            }
+
             // Validate source image offsets
             VkExtent3D src_extent = GetImageSubresourceExtent(src_image_state, &(rgn.srcSubresource));
-            if (VK_IMAGE_TYPE_1D == src_image_state->createInfo.imageType) {
+            if (VK_IMAGE_TYPE_1D == src_type) {
                 if ((0 != rgn.srcOffsets[0].y) || (1 != rgn.srcOffsets[1].y)) {
                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001ea, "IMAGE",
@@ -2272,8 +2433,7 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
                 }
             }
 
-            if ((VK_IMAGE_TYPE_1D == src_image_state->createInfo.imageType) ||
-                (VK_IMAGE_TYPE_2D == src_image_state->createInfo.imageType)) {
+            if ((VK_IMAGE_TYPE_1D == src_type) || (VK_IMAGE_TYPE_2D == src_type)) {
                 if ((0 != rgn.srcOffsets[0].z) || (1 != rgn.srcOffsets[1].z)) {
                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001ee, "IMAGE",
@@ -2283,8 +2443,10 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
                 }
             }
 
+            bool oob = false;
             if ((rgn.srcOffsets[0].x < 0) || (rgn.srcOffsets[0].x > static_cast<int32_t>(src_extent.width)) ||
                 (rgn.srcOffsets[1].x < 0) || (rgn.srcOffsets[1].x > static_cast<int32_t>(src_extent.width))) {
+                oob = true;
                 skip |= log_msg(
                     report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001e6, "IMAGE",
@@ -2293,6 +2455,7 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
             }
             if ((rgn.srcOffsets[0].y < 0) || (rgn.srcOffsets[0].y > static_cast<int32_t>(src_extent.height)) ||
                 (rgn.srcOffsets[1].y < 0) || (rgn.srcOffsets[1].y > static_cast<int32_t>(src_extent.height))) {
+                oob = true;
                 skip |= log_msg(
                     report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001e8, "IMAGE",
@@ -2301,16 +2464,28 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
             }
             if ((rgn.srcOffsets[0].z < 0) || (rgn.srcOffsets[0].z > static_cast<int32_t>(src_extent.depth)) ||
                 (rgn.srcOffsets[1].z < 0) || (rgn.srcOffsets[1].z > static_cast<int32_t>(src_extent.depth))) {
+                oob = true;
                 skip |= log_msg(
                     report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001ec, "IMAGE",
                     "vkCmdBlitImage: region [%d] srcOffset[].z values (%1d, %1d) exceed srcSubresource depth extent (%1d). %s", i,
                     rgn.srcOffsets[0].z, rgn.srcOffsets[1].z, src_extent.depth, validation_error_map[VALIDATION_ERROR_09a001ec]);
             }
+            if (rgn.srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) {
+                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                                HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ae, "IMAGE",
+                                "vkCmdBlitImage: region [%d] source image, attempt to access a non-existant mip level %1d. %s", i,
+                                rgn.srcSubresource.mipLevel, validation_error_map[VALIDATION_ERROR_184001ae]);
+            } else if (oob) {
+                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                                HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ae, "IMAGE",
+                                "vkCmdBlitImage: region [%d] source image blit region exceeds image dimensions. %s", i,
+                                validation_error_map[VALIDATION_ERROR_184001ae]);
+            }
 
             // Validate dest image offsets
             VkExtent3D dst_extent = GetImageSubresourceExtent(dst_image_state, &(rgn.dstSubresource));
-            if (VK_IMAGE_TYPE_1D == dst_image_state->createInfo.imageType) {
+            if (VK_IMAGE_TYPE_1D == dst_type) {
                 if ((0 != rgn.dstOffsets[0].y) || (1 != rgn.dstOffsets[1].y)) {
                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f4, "IMAGE",
@@ -2320,8 +2495,7 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
                 }
             }
 
-            if ((VK_IMAGE_TYPE_1D == dst_image_state->createInfo.imageType) ||
-                (VK_IMAGE_TYPE_2D == dst_image_state->createInfo.imageType)) {
+            if ((VK_IMAGE_TYPE_1D == dst_type) || (VK_IMAGE_TYPE_2D == dst_type)) {
                 if ((0 != rgn.dstOffsets[0].z) || (1 != rgn.dstOffsets[1].z)) {
                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f8, "IMAGE",
@@ -2331,8 +2505,10 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
                 }
             }
 
+            oob = false;
             if ((rgn.dstOffsets[0].x < 0) || (rgn.dstOffsets[0].x > static_cast<int32_t>(dst_extent.width)) ||
                 (rgn.dstOffsets[1].x < 0) || (rgn.dstOffsets[1].x > static_cast<int32_t>(dst_extent.width))) {
+                oob = true;
                 skip |= log_msg(
                     report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f0, "IMAGE",
@@ -2341,6 +2517,7 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
             }
             if ((rgn.dstOffsets[0].y < 0) || (rgn.dstOffsets[0].y > static_cast<int32_t>(dst_extent.height)) ||
                 (rgn.dstOffsets[1].y < 0) || (rgn.dstOffsets[1].y > static_cast<int32_t>(dst_extent.height))) {
+                oob = true;
                 skip |= log_msg(
                     report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f2, "IMAGE",
@@ -2349,98 +2526,36 @@ bool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod
             }
             if ((rgn.dstOffsets[0].z < 0) || (rgn.dstOffsets[0].z > static_cast<int32_t>(dst_extent.depth)) ||
                 (rgn.dstOffsets[1].z < 0) || (rgn.dstOffsets[1].z > static_cast<int32_t>(dst_extent.depth))) {
+                oob = true;
                 skip |= log_msg(
                     report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                     HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f6, "IMAGE",
                     "vkCmdBlitImage: region [%d] dstOffset[].z values (%1d, %1d) exceed dstSubresource depth extent (%1d). %s", i,
                     rgn.dstOffsets[0].z, rgn.dstOffsets[1].z, dst_extent.depth, validation_error_map[VALIDATION_ERROR_09a001f6]);
             }
-        }
-
-        VkFormat src_format = src_image_state->createInfo.format;
-        VkFormat dst_format = dst_image_state->createInfo.format;
-
-        // Validate consistency for unsigned formats
-        if (FormatIsUInt(src_format) != FormatIsUInt(dst_format)) {
-            std::stringstream ss;
-            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has unsigned integer format, "
-               << "the other one must also have unsigned integer format.  "
-               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
-            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001cc, "IMAGE", "%s. %s",
-                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001cc]);
-        }
-
-        // Validate consistency for signed formats
-        if (FormatIsSInt(src_format) != FormatIsSInt(dst_format)) {
-            std::stringstream ss;
-            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed integer format, "
-               << "the other one must also have signed integer format.  "
-               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
-            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ca, "IMAGE", "%s. %s",
-                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001ca]);
-        }
-
-        // Validate aspect bits and formats for depth/stencil images
-        if (FormatIsDepthOrStencil(src_format) || FormatIsDepthOrStencil(dst_format)) {
-            if (src_format != dst_format) {
-                std::stringstream ss;
-                ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
-                   << "stencil, the other one must have exactly the same format.  "
-                   << "Source format is " << string_VkFormat(src_format) << " Destination format is "
-                   << string_VkFormat(dst_format);
+            if (rgn.dstSubresource.mipLevel >= dst_image_state->createInfo.mipLevels) {
                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                                HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ce, "IMAGE", "%s. %s",
-                                ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001ce]);
+                                HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001b0, "IMAGE",
+                                "vkCmdBlitImage: region [%d] destination image, attempt to access a non-existant mip level %1d. %s",
+                                i, rgn.dstSubresource.mipLevel, validation_error_map[VALIDATION_ERROR_184001b0]);
+            } else if (oob) {
+                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                                HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001b0, "IMAGE",
+                                "vkCmdBlitImage: region [%d] destination image blit region exceeds image dimensions. %s", i,
+                                validation_error_map[VALIDATION_ERROR_184001b0]);
             }
 
-#if 0  // TODO: Cannot find VU statements or spec language for these in CmdBlitImage. Verify or remove.
-            for (uint32_t i = 0; i < regionCount; i++) {
-                VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
-
-                if (FormatIsDepthAndStencil(src_format)) {
-                    if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
-                        std::stringstream ss;
-                        ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
-                              "VK_IMAGE_ASPECT_DEPTH_BIT "
-                           << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
-                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                                        HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE",
-                                        "%s", ss.str().c_str());
-                    }
-                } else if (FormatIsStencilOnly(src_format)) {
-                    if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
-                        std::stringstream ss;
-                        ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
-                           << "set in both the srcImage and dstImage";
-                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                                        HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE",
-                                        "%s", ss.str().c_str());
-                    }
-                } else if (FormatIsDepthOnly(src_format)) {
-                    if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
-                        std::stringstream ss;
-                        ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
-                           << "set in both the srcImage and dstImage";
-                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                                        HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE",
-                                        "%s", ss.str().c_str());
-                    }
+            if ((VK_IMAGE_TYPE_3D == src_type) || (VK_IMAGE_TYPE_3D == dst_type)) {
+                if ((0 != rgn.srcSubresource.baseArrayLayer) || (1 != rgn.srcSubresource.layerCount) ||
+                    (0 != rgn.dstSubresource.baseArrayLayer) || (1 != rgn.dstSubresource.layerCount)) {
+                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+                                    HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001e0, "IMAGE",
+                                    "vkCmdBlitImage: region [%d] blit to/from a 3D image type with a non-zero baseArrayLayer, or a "
+                                    "layerCount other than 1. %s",
+                                    i, validation_error_map[VALIDATION_ERROR_09a001e0]);
                 }
             }
-#endif
-        }  // Depth/Stencil
-
-        // Validate filter
-        if (FormatIsDepthOrStencil(src_format) && (filter != VK_FILTER_NEAREST)) {
-            std::stringstream ss;
-            ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, or depth stencil "
-               << "then filter must be VK_FILTER_NEAREST.";
-            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
-                            HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001d0, "IMAGE", "%s. %s",
-                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001d0]);
-        }
+        }  // per-region checks
     } else {
         assert(0);
     }
@@ -2743,7 +2858,7 @@ bool ValidateLayouts(core_validation::layer_data *device_data, VkDevice device,
             //  as an acceptable layout, but need to make sure shared presentable images ONLY use that layout
             switch (subpass.pColorAttachments[j].layout) {
                 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
-                    // This is ideal.
+                // This is ideal.
                 case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
                     // TODO: See note above, just assuming that attachment is shared presentable and allowing this for now.
                     break;
@@ -3019,7 +3134,8 @@ bool ValidateImageSubresourceRange(const layer_data *device_data, const IMAGE_ST
         if (subresourceRange.baseMipLevel >= image_mip_count) {
             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
                             HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_SUBRANGE, "IMAGE",
-                            "%s: %s.baseMipLevel (= %" PRIu32 ") is greater or equal to the mip level count of the image (i.e. "
+                            "%s: %s.baseMipLevel (= %" PRIu32
+                            ") is greater or equal to the mip level count of the image (i.e. "
                             "greater or equal to %" PRIu32 ").",
                             cmd_name, param_name, subresourceRange.baseMipLevel, image_mip_count);
         }
@@ -3056,7 +3172,8 @@ bool ValidateImageSubresourceRange(const layer_data *device_data, const IMAGE_ST
         if (subresourceRange.baseArrayLayer >= image_layer_count) {
             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
                             HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_SUBRANGE, "IMAGE",
-                            "%s: %s.baseArrayLayer (= %" PRIu32 ") is greater or equal to the %s of the image when it was created "
+                            "%s: %s.baseArrayLayer (= %" PRIu32
+                            ") is greater or equal to the %s of the image when it was created "
                             "(i.e. greater or equal to %" PRIu32 ").",
                             cmd_name, param_name, subresourceRange.baseArrayLayer, image_layer_count_var_name, image_layer_count);
         }
@@ -3067,7 +3184,8 @@ bool ValidateImageSubresourceRange(const layer_data *device_data, const IMAGE_ST
             skip |=
                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
                         HandleToUint64(image_state->image), __LINE__, invalid_layer_code, "IMAGE",
-                        "%s: %s.baseArrayLayer + .layerCount (= %" PRIu32 " + %" PRIu32 " = %" PRIu64 ") is greater than the "
+                        "%s: %s.baseArrayLayer + .layerCount (= %" PRIu32 " + %" PRIu32 " = %" PRIu64
+                        ") is greater than the "
                         "%s of the image when it was created (i.e. greater than %" PRIu32 "). %s",
                         cmd_name, param_name, subresourceRange.baseArrayLayer, subresourceRange.layerCount, necessary_layer_count,
                         image_layer_count_var_name, image_layer_count, validation_error_map[invalid_layer_code]);
@@ -3509,8 +3627,8 @@ static bool ValidateImageBounds(const debug_report_data *report_data, const IMAG
 }
 
 static inline bool ValidateBufferBounds(const debug_report_data *report_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) {
+                                        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;
@@ -3606,7 +3724,7 @@ bool PreCallValidateCmdCopyImageToBuffer(layer_data *device_data, VkImageLayout
     skip |= ValidateImageBounds(report_data, src_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
                                 VALIDATION_ERROR_1920016c);
     skip |= ValidateBufferBounds(report_data, src_image_state, dst_buffer_state, regionCount, pRegions, "vkCmdCopyImageToBuffer()",
-                                  VALIDATION_ERROR_1920016e);
+                                 VALIDATION_ERROR_1920016e);
 
     skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyImageToBuffer(): srcImage",
                                      VALIDATION_ERROR_19200178);
@@ -3650,7 +3768,6 @@ void PreCallRecordCmdCopyImageToBuffer(layer_data *device_data, GLOBAL_CB_NODE *
         return false;
     };
     cb_node->validate_functions.push_back(function);
-
 }
 
 bool PreCallValidateCmdCopyBufferToImage(layer_data *device_data, VkImageLayout dstImageLayout, GLOBAL_CB_NODE *cb_node,
@@ -3682,7 +3799,7 @@ bool PreCallValidateCmdCopyBufferToImage(layer_data *device_data, VkImageLayout
     skip |= ValidateImageBounds(report_data, dst_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
                                 VALIDATION_ERROR_18e00158);
     skip |= ValidateBufferBounds(report_data, dst_image_state, src_buffer_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
-                                  VALIDATION_ERROR_18e00156);
+                                 VALIDATION_ERROR_18e00156);
     skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyBufferToImage(): dstImage",
                                      VALIDATION_ERROR_18e00166);
     skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_18e00160);
@@ -3719,7 +3836,6 @@ void PreCallRecordCmdCopyBufferToImage(layer_data *device_data, GLOBAL_CB_NODE *
     cb_node->validate_functions.push_back(function);
     function = [=]() { return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBufferToImage()"); };
     cb_node->validate_functions.push_back(function);
-
 }
 
 bool PreCallValidateGetImageSubresourceLayout(layer_data *device_data, VkImage image, const VkImageSubresource *pSubresource) {
index 5d2d01e..aeca34b 100644 (file)
@@ -545,9 +545,9 @@ VALIDATION_ERROR_09826a01~^~N~^~Unknown~^~vkCreateIOSSurfaceMVK~^~VUID-VkIOSSurf
 VALIDATION_ERROR_0982b00b~^~Y~^~Unknown~^~vkCreateIOSSurfaceMVK~^~VUID-VkIOSSurfaceCreateInfoMVK-sType-sType~^~core~^~The spec valid usage text states 'sType must be VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkIOSSurfaceCreateInfoMVK-sType-sType)~^~implicit
 VALIDATION_ERROR_09a001dc~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-VkImageBlit-aspectMask-00238~^~core~^~The spec valid usage text states 'The aspectMask member of srcSubresource and dstSubresource must match' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-aspectMask-00238)~^~
 VALIDATION_ERROR_09a001de~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-VkImageBlit-layerCount-00239~^~core~^~The spec valid usage text states 'The layerCount member of srcSubresource and dstSubresource must match' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-layerCount-00239)~^~
-VALIDATION_ERROR_09a001e0~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-VkImageBlit-srcImage-00240~^~core~^~The spec valid usage text states 'If either of the calling command's srcImage or dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-srcImage-00240)~^~
-VALIDATION_ERROR_09a001e2~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-VkImageBlit-aspectMask-00241~^~core~^~The spec valid usage text states 'The aspectMask member of srcSubresource must specify aspects present in the calling command's srcImage' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-aspectMask-00241)~^~
-VALIDATION_ERROR_09a001e4~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-VkImageBlit-aspectMask-00242~^~core~^~The spec valid usage text states 'The aspectMask member of dstSubresource must specify aspects present in the calling command's dstImage' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-aspectMask-00242)~^~
+VALIDATION_ERROR_09a001e0~^~Y~^~MiscBlitImageTests~^~vkCmdBlitImage~^~VUID-VkImageBlit-srcImage-00240~^~core~^~The spec valid usage text states 'If either of the calling command's srcImage or dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-srcImage-00240)~^~
+VALIDATION_ERROR_09a001e2~^~Y~^~MiscBlitImageTests~^~vkCmdBlitImage~^~VUID-VkImageBlit-aspectMask-00241~^~core~^~The spec valid usage text states 'The aspectMask member of srcSubresource must specify aspects present in the calling command's srcImage' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-aspectMask-00241)~^~
+VALIDATION_ERROR_09a001e4~^~Y~^~MiscBlitImageTests~^~vkCmdBlitImage~^~VUID-VkImageBlit-aspectMask-00242~^~core~^~The spec valid usage text states 'The aspectMask member of dstSubresource must specify aspects present in the calling command's dstImage' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-aspectMask-00242)~^~
 VALIDATION_ERROR_09a001e6~^~Y~^~BlitImageOffsets~^~vkCmdBlitImage~^~VUID-VkImageBlit-srcOffset-00243~^~core~^~The spec valid usage text states 'srcOffset[0].x and srcOffset[1].x must both be greater than or equal to 0 and less than or equal to the source image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-srcOffset-00243)~^~
 VALIDATION_ERROR_09a001e8~^~Y~^~BlitImageOffsets~^~vkCmdBlitImage~^~VUID-VkImageBlit-srcOffset-00244~^~core~^~The spec valid usage text states 'srcOffset[0].y and srcOffset[1].y must both be greater than or equal to 0 and less than or equal to the source image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageBlit-srcOffset-00244)~^~
 VALIDATION_ERROR_09a001ea~^~Y~^~BlitImageOffsets~^~vkCmdBlitImage~^~VUID-VkImageBlit-srcImage-00245~^~core~^~The spec valid usage text states 'If the calling command's 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/html/vkspec.html#VUID-VkImageBlit-srcImage-00245)~^~
@@ -1545,29 +1545,29 @@ VALIDATION_ERROR_18210601~^~Y~^~None~^~vkCmdBindVertexBuffers~^~VUID-vkCmdBindVe
 VALIDATION_ERROR_1821d201~^~N~^~Unknown~^~vkCmdBindVertexBuffers~^~VUID-vkCmdBindVertexBuffers-pOffsets-parameter~^~core~^~The spec valid usage text states 'pOffsets must be a pointer to an array of bindingCount VkDeviceSize values' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBindVertexBuffers-pOffsets-parameter)~^~implicit
 VALIDATION_ERROR_18400009~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-commonparent~^~core~^~The spec valid usage text states 'Each of commandBuffer, dstImage, and srcImage must have been created, allocated, or retrieved from the same VkDevice' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-commonparent)~^~implicit
 VALIDATION_ERROR_18400017~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-renderpass~^~core~^~The spec valid usage text states 'This command must only be called outside of a render pass instance' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-renderpass)~^~implicit
-VALIDATION_ERROR_184001ae~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-pRegions-00215~^~core~^~The spec valid usage text 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/html/vkspec.html#VUID-vkCmdBlitImage-pRegions-00215)~^~
-VALIDATION_ERROR_184001b0~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-pRegions-00216~^~core~^~The spec valid usage text states 'The destination 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/html/vkspec.html#VUID-vkCmdBlitImage-pRegions-00216)~^~
+VALIDATION_ERROR_184001ae~^~Y~^~BlitImageOffsets~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-pRegions-00215~^~core~^~The spec valid usage text 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/html/vkspec.html#VUID-vkCmdBlitImage-pRegions-00215)~^~
+VALIDATION_ERROR_184001b0~^~Y~^~BlitImageOffsets~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-pRegions-00216~^~core~^~The spec valid usage text states 'The destination 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/html/vkspec.html#VUID-vkCmdBlitImage-pRegions-00216)~^~
 VALIDATION_ERROR_184001b2~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-pRegions-00217~^~core~^~The spec valid usage text states 'The union of all destination regions, specified by the elements of pRegions, must not overlap in memory with any texel that may be sampled during the blit operation' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-pRegions-00217)~^~
-VALIDATION_ERROR_184001b4~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00218~^~core~^~The spec valid usage text states 'srcImage must use a format that supports VK_FORMAT_FEATURE_BLIT_SRC_BIT, which is indicated by VkFormatProperties::linearTilingFeatures (for linearly tiled images) or VkFormatProperties::optimalTilingFeatures (for optimally tiled images) - as returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00218)~^~
+VALIDATION_ERROR_184001b4~^~Y~^~NotTestable~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00218~^~core~^~The spec valid usage text states 'srcImage must use a format that supports VK_FORMAT_FEATURE_BLIT_SRC_BIT, which is indicated by VkFormatProperties::linearTilingFeatures (for linearly tiled images) or VkFormatProperties::optimalTilingFeatures (for optimally tiled images) - as returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00218)~^~
 VALIDATION_ERROR_184001b6~^~Y~^~None~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00219~^~core~^~The spec valid usage text states 'srcImage must have been created with VK_IMAGE_USAGE_TRANSFER_SRC_BIT usage flag' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00219)~^~
 VALIDATION_ERROR_184001b8~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00220~^~core~^~The spec valid usage text states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00220)~^~
 VALIDATION_ERROR_184001ba~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImageLayout-00221~^~core~^~The spec valid usage text states 'srcImageLayout must specify the layout of the image subresources of srcImage specified in pRegions at the time this command is executed on a VkDevice' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImageLayout-00221)~^~
 VALIDATION_ERROR_184001bc~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImageLayout-00222~^~core~^~The spec valid usage text states 'srcImageLayout must be' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImageLayout-00222)~^~
-VALIDATION_ERROR_184001be~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImage-00223~^~core~^~The spec valid usage text states 'dstImage must use a format that supports VK_FORMAT_FEATURE_BLIT_DST_BIT, which is indicated by VkFormatProperties::linearTilingFeatures (for linearly tiled images) or VkFormatProperties::optimalTilingFeatures (for optimally tiled images) - as returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImage-00223)~^~
+VALIDATION_ERROR_184001be~^~Y~^~MiscBlitImageTests~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImage-00223~^~core~^~The spec valid usage text states 'dstImage must use a format that supports VK_FORMAT_FEATURE_BLIT_DST_BIT, which is indicated by VkFormatProperties::linearTilingFeatures (for linearly tiled images) or VkFormatProperties::optimalTilingFeatures (for optimally tiled images) - as returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImage-00223)~^~
 VALIDATION_ERROR_184001c0~^~Y~^~None~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImage-00224~^~core~^~The spec valid usage text states 'dstImage must have been created with VK_IMAGE_USAGE_TRANSFER_DST_BIT usage flag' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImage-00224)~^~
 VALIDATION_ERROR_184001c2~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImage-00225~^~core~^~The spec valid usage text states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImage-00225)~^~
 VALIDATION_ERROR_184001c4~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImageLayout-00226~^~core~^~The spec valid usage text states 'dstImageLayout must specify the layout of the image subresources of dstImage specified in pRegions at the time this command is executed on a VkDevice' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImageLayout-00226)~^~
 VALIDATION_ERROR_184001c6~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImageLayout-00227~^~core~^~The spec valid usage text states 'dstImageLayout must be' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImageLayout-00227)~^~
-VALIDATION_ERROR_184001c8~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00228~^~core~^~The spec valid usage text states 'The sample count of srcImage and dstImage must both be equal to VK_SAMPLE_COUNT_1_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00228)~^~
-VALIDATION_ERROR_184001ca~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00229~^~core~^~The spec valid usage text states 'If either of srcImage or dstImage was created with a signed integer VkFormat, the other must also have been created with a signed integer VkFormat' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00229)~^~
-VALIDATION_ERROR_184001cc~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00230~^~core~^~The spec valid usage text states 'If either of srcImage or dstImage was created with an unsigned integer VkFormat, the other must also have been created with an unsigned integer VkFormat' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00230)~^~
-VALIDATION_ERROR_184001ce~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00231~^~core~^~The spec valid usage text states 'If either of srcImage or dstImage was created with a depth/stencil format, the other must have exactly the same format' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00231)~^~
+VALIDATION_ERROR_184001c8~^~Y~^~MiscBlitImageTests~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00228~^~core~^~The spec valid usage text states 'The sample count of srcImage and dstImage must both be equal to VK_SAMPLE_COUNT_1_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00228)~^~
+VALIDATION_ERROR_184001ca~^~Y~^~BlitImageFormatTypes~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00229~^~core~^~The spec valid usage text states 'If either of srcImage or dstImage was created with a signed integer VkFormat, the other must also have been created with a signed integer VkFormat' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00229)~^~
+VALIDATION_ERROR_184001cc~^~Y~^~BlitImageFormatTypes~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00230~^~core~^~The spec valid usage text states 'If either of srcImage or dstImage was created with an unsigned integer VkFormat, the other must also have been created with an unsigned integer VkFormat' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00230)~^~
+VALIDATION_ERROR_184001ce~^~Y~^~BlitImageFormatTypes~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00231~^~core~^~The spec valid usage text states 'If either of srcImage or dstImage was created with a depth/stencil format, the other must have exactly the same format' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00231)~^~
 VALIDATION_ERROR_184001d0~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00232~^~core~^~The spec valid usage text states 'If srcImage was created with a depth/stencil format, filter must be VK_FILTER_NEAREST' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00232)~^~
-VALIDATION_ERROR_184001d2~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00233~^~core~^~The spec valid usage text states 'srcImage must have been created with a samples value of VK_SAMPLE_COUNT_1_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00233)~^~
-VALIDATION_ERROR_184001d4~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImage-00234~^~core~^~The spec valid usage text states 'dstImage must have been created with a samples value of VK_SAMPLE_COUNT_1_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImage-00234)~^~
-VALIDATION_ERROR_184001d6~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-filter-00235~^~core~^~The spec valid usage text states 'If filter is VK_FILTER_LINEAR, srcImage must be of a format which supports linear filtering, as specified by the VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT flag in VkFormatProperties::linearTilingFeatures (for a linear image) or VkFormatProperties::optimalTilingFeatures(for an optimally tiled image) returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-filter-00235)~^~
-VALIDATION_ERROR_184001d8~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-filter-00236~^~(VK_IMG_filter_cubic)~^~The spec valid usage text states 'If filter is VK_FILTER_CUBIC_IMG, srcImage must be of a format which supports cubic filtering, as specified by the VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG flag in VkFormatProperties::linearTilingFeatures (for a linear image) or VkFormatProperties::optimalTilingFeatures(for an optimally tiled image) returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkCmdBlitImage-filter-00236)~^~
-VALIDATION_ERROR_184001da~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-filter-00237~^~(VK_IMG_filter_cubic)~^~The spec valid usage text states 'If filter is VK_FILTER_CUBIC_IMG, srcImage must have a VkImageType of VK_IMAGE_TYPE_3D' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkCmdBlitImage-filter-00237)~^~
+VALIDATION_ERROR_184001d2~^~Y~^~MiscBlitImageTests~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-srcImage-00233~^~core~^~The spec valid usage text states 'srcImage must have been created with a samples value of VK_SAMPLE_COUNT_1_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-srcImage-00233)~^~
+VALIDATION_ERROR_184001d4~^~Y~^~MiscBlitImageTests~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-dstImage-00234~^~core~^~The spec valid usage text states 'dstImage must have been created with a samples value of VK_SAMPLE_COUNT_1_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-dstImage-00234)~^~
+VALIDATION_ERROR_184001d6~^~Y~^~BlitImageFilters~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-filter-00235~^~core~^~The spec valid usage text states 'If filter is VK_FILTER_LINEAR, srcImage must be of a format which supports linear filtering, as specified by the VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT flag in VkFormatProperties::linearTilingFeatures (for a linear image) or VkFormatProperties::optimalTilingFeatures(for an optimally tiled image) returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-filter-00235)~^~
+VALIDATION_ERROR_184001d8~^~Y~^~BlitImageFilters~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-filter-00236~^~(VK_IMG_filter_cubic)~^~The spec valid usage text states 'If filter is VK_FILTER_CUBIC_IMG, srcImage must be of a format which supports cubic filtering, as specified by the VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG flag in VkFormatProperties::linearTilingFeatures (for a linear image) or VkFormatProperties::optimalTilingFeatures(for an optimally tiled image) returned by vkGetPhysicalDeviceFormatProperties' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkCmdBlitImage-filter-00236)~^~
+VALIDATION_ERROR_184001da~^~Y~^~BlitImageFilters~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-filter-00237~^~(VK_IMG_filter_cubic)~^~The spec valid usage text states 'If filter is VK_FILTER_CUBIC_IMG, srcImage must have a VkImageType of VK_IMAGE_TYPE_3D' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkCmdBlitImage-filter-00237)~^~
 VALIDATION_ERROR_18402401~^~Y~^~None~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-commandBuffer-parameter~^~core~^~The spec valid usage text states 'commandBuffer must be a valid VkCommandBuffer handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-commandBuffer-parameter)~^~implicit
 VALIDATION_ERROR_18402413~^~N~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-commandBuffer-recording~^~core~^~The spec valid usage text states 'commandBuffer must be in the recording state' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-commandBuffer-recording)~^~implicit
 VALIDATION_ERROR_18402415~^~Y~^~Unknown~^~vkCmdBlitImage~^~VUID-vkCmdBlitImage-commandBuffer-cmdpool~^~core~^~The spec valid usage text states 'The VkCommandPool that commandBuffer was allocated from must support graphics operations' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdBlitImage-commandBuffer-cmdpool)~^~implicit
index 602e254..ebe43c7 100644 (file)
@@ -113,6 +113,27 @@ VkFormat FindSupportedDepthStencilFormat(VkPhysicalDevice phy) {
     return (VkFormat)0;
 }
 
+// Returns true if *any* requested features are available.
+// Assumption is that the framework can successfully create an image as
+// long as at least one of the feature bits is present (excepting VTX_BUF).
+bool ImageFormatIsSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling,
+                            VkFormatFeatureFlags features = ~VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) {
+    VkFormatProperties format_props;
+    vkGetPhysicalDeviceFormatProperties(phy, format, &format_props);
+    VkFormatFeatureFlags phy_features =
+        (VK_IMAGE_TILING_OPTIMAL == tiling ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures);
+    return (0 != (phy_features & features));
+}
+
+// Returns true if *all* requested features are available.
+bool ImageFeatureIsSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling, VkFormatFeatureFlags features) {
+    VkFormatProperties format_props;
+    vkGetPhysicalDeviceFormatProperties(phy, format, &format_props);
+    VkFormatFeatureFlags phy_features =
+        (VK_IMAGE_TILING_OPTIMAL == tiling ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures);
+    return (features == (phy_features & features));
+}
+
 // Validation report callback prototype
 static VKAPI_ATTR VkBool32 VKAPI_CALL myDbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
                                                 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg,
@@ -2860,9 +2881,9 @@ TEST_F(VkLayerTest, ImageSampleCounts) {
         vk_testing::Image dst_image;
         dst_image.init(*m_device, (const VkImageCreateInfo &)image_create_info, reqs);
         m_commandBuffer->begin();
-        m_errorMonitor->SetDesiredFailureMsg(
-            VK_DEBUG_REPORT_ERROR_BIT_EXT,
-            "was created with a sample count of VK_SAMPLE_COUNT_2_BIT but must be VK_SAMPLE_COUNT_1_BIT");
+        // TODO: These 2 VUs are redundant - expect one of them to go away
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001d2);
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001c8);
         vkCmdBlitImage(m_commandBuffer->handle(), src_image.handle(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, dst_image.handle(),
                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, &blit_region, VK_FILTER_NEAREST);
         m_errorMonitor->VerifyFound();
@@ -2881,9 +2902,9 @@ TEST_F(VkLayerTest, ImageSampleCounts) {
         vk_testing::Image dst_image;
         dst_image.init(*m_device, (const VkImageCreateInfo &)image_create_info, reqs);
         m_commandBuffer->begin();
-        m_errorMonitor->SetDesiredFailureMsg(
-            VK_DEBUG_REPORT_ERROR_BIT_EXT,
-            "was created with a sample count of VK_SAMPLE_COUNT_4_BIT but must be VK_SAMPLE_COUNT_1_BIT");
+        // TODO: These 2 VUs are redundant - expect one of them to go away
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001d4);
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001c8);
         vkCmdBlitImage(m_commandBuffer->handle(), src_image.handle(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, dst_image.handle(),
                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, &blit_region, VK_FILTER_NEAREST);
         m_errorMonitor->VerifyFound();
@@ -2938,15 +2959,55 @@ TEST_F(VkLayerTest, ImageSampleCounts) {
     }
 }
 
-TEST_F(VkLayerTest, BlitImageFormats) {
+TEST_F(VkLayerTest, BlitImageFormatTypes) {
     ASSERT_NO_FATAL_FAILURE(Init());
 
-    VkImageObj src_image(m_device);
-    src_image.Init(64, 64, 1, VK_FORMAT_A2B10G10R10_UINT_PACK32, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR, 0);
-    VkImageObj dst_image(m_device);
-    dst_image.Init(64, 64, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, 0);
-    VkImageObj dst_image2(m_device);
-    dst_image2.Init(64, 64, 1, VK_FORMAT_R8G8B8A8_SINT, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, 0);
+    VkFormat f_unsigned = VK_FORMAT_R8G8B8A8_UINT;
+    VkFormat f_signed = VK_FORMAT_R8G8B8A8_SINT;
+    VkFormat f_float = VK_FORMAT_R32_SFLOAT;
+    VkFormat f_depth = VK_FORMAT_D32_SFLOAT_S8_UINT;
+    VkFormat f_depth2 = VK_FORMAT_D32_SFLOAT;
+
+    if (!ImageFormatIsSupported(gpu(), f_unsigned, VK_IMAGE_TILING_OPTIMAL) ||
+        !ImageFormatIsSupported(gpu(), f_signed, VK_IMAGE_TILING_OPTIMAL) ||
+        !ImageFormatIsSupported(gpu(), f_float, VK_IMAGE_TILING_OPTIMAL) ||
+        !ImageFormatIsSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL) ||
+        !ImageFormatIsSupported(gpu(), f_depth2, VK_IMAGE_TILING_OPTIMAL)) {
+        printf("             Requested formats not supported - BlitImageFormatTypes skipped.\n");
+        return;
+    }
+
+    // Note any missing feature bits
+    bool usrc = !ImageFeatureIsSupported(gpu(), f_unsigned, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
+    bool udst = !ImageFeatureIsSupported(gpu(), f_unsigned, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT);
+    bool ssrc = !ImageFeatureIsSupported(gpu(), f_signed, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
+    bool sdst = !ImageFeatureIsSupported(gpu(), f_signed, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT);
+    bool fsrc = !ImageFeatureIsSupported(gpu(), f_float, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
+    bool fdst = !ImageFeatureIsSupported(gpu(), f_float, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT);
+    bool d1dst = !ImageFeatureIsSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT);
+    bool d2src = !ImageFeatureIsSupported(gpu(), f_depth2, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
+
+    VkImageObj unsigned_image(m_device);
+    unsigned_image.Init(64, 64, 1, f_unsigned, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+                        VK_IMAGE_TILING_OPTIMAL, 0);
+    ASSERT_TRUE(unsigned_image.initialized());
+    VkImageObj signed_image(m_device);
+    signed_image.Init(64, 64, 1, f_signed, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+                      VK_IMAGE_TILING_OPTIMAL, 0);
+    ASSERT_TRUE(signed_image.initialized());
+    VkImageObj float_image(m_device);
+    float_image.Init(64, 64, 1, f_float, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL,
+                     0);
+    ASSERT_TRUE(float_image.initialized());
+
+    VkImageObj depth_image(m_device);
+    depth_image.Init(64, 64, 1, f_depth, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL,
+                     0);
+    ASSERT_TRUE(depth_image.initialized());
+    VkImageObj depth_image2(m_device);
+    depth_image2.Init(64, 64, 1, f_depth2, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+                      VK_IMAGE_TILING_OPTIMAL, 0);
+    ASSERT_TRUE(depth_image2.initialized());
 
     VkImageBlit blitRegion = {};
     blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -2957,45 +3018,164 @@ TEST_F(VkLayerTest, BlitImageFormats) {
     blitRegion.dstSubresource.baseArrayLayer = 0;
     blitRegion.dstSubresource.layerCount = 1;
     blitRegion.dstSubresource.mipLevel = 0;
-    blitRegion.srcOffsets[0] = {64, 64, 0};
-    blitRegion.srcOffsets[1] = {0, 0, 1};
+    blitRegion.srcOffsets[0] = {0, 0, 0};
+    blitRegion.srcOffsets[1] = {64, 64, 1};
     blitRegion.dstOffsets[0] = {0, 0, 0};
     blitRegion.dstOffsets[1] = {32, 32, 1};
 
-    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001cc);
-
-    // TODO: there are 9 permutations of signed, unsigned, & other for source and dest
-    //       this test is only checking 2 of them at the moment
+    m_commandBuffer->begin();
 
     // Unsigned int vs not an int
-    m_commandBuffer->begin();
-    vkCmdBlitImage(m_commandBuffer->handle(), src_image.image(), src_image.Layout(), dst_image.image(), dst_image.Layout(), 1,
-                   &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001cc);
+    if (usrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b4);
+    if (fdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), unsigned_image.image(), unsigned_image.Layout(), float_image.image(),
+                   float_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001cc);
+    if (fsrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b4);
+    if (udst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), float_image.image(), float_image.Layout(), unsigned_image.image(),
+                   unsigned_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
 
+    // Signed int vs not an int,
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ca);
+    if (ssrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b4);
+    if (fdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), signed_image.image(), signed_image.Layout(), float_image.image(),
+                   float_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ca);
+    if (fsrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b4);
+    if (sdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), float_image.image(), float_image.Layout(), signed_image.image(),
+                   signed_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
 
-    // Test should generate 2 VU failures
+    // Signed vs Unsigned int - generates both VUs
     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ca);
     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001cc);
+    if (ssrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b4);
+    if (udst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), signed_image.image(), signed_image.Layout(), unsigned_image.image(),
+                   unsigned_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ca);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001cc);
+    if (usrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b4);
+    if (sdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), unsigned_image.image(), unsigned_image.Layout(), signed_image.image(),
+                   signed_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
 
-    // Unsigned int vs signed int
-    vkCmdBlitImage(m_commandBuffer->handle(), src_image.image(), src_image.Layout(), dst_image2.image(), dst_image2.Layout(), 1,
-                   &blitRegion, VK_FILTER_NEAREST);
-
-    // TODO: Note that this only verifies that at least one of the VU enums was found
-    //       Also, if any were not seen, they'll remain in the target list (Soln TBD, JIRA task: VL-72)
+    // Depth vs any non-identical depth format
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ce);
+    blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+    blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+    if (d2src) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b4);
+    if (d1dst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), depth_image2.image(), depth_image2.Layout(), depth_image.image(),
+                   depth_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
 
     m_commandBuffer->end();
 }
 
+TEST_F(VkLayerTest, BlitImageFilters) {
+    bool cubic_support = false;
+    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+    if (DeviceExtensionSupported(gpu(), nullptr, "VK_IMG_filter_cubic")) {
+        m_device_extension_names.push_back("VK_IMG_filter_cubic");
+        cubic_support = true;
+    }
+    ASSERT_NO_FATAL_FAILURE(InitState());
+
+    VkFormat fmt = VK_FORMAT_R8_UINT;
+    if (!ImageFormatIsSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL)) {
+        printf("             No R8_UINT format support - BlitImageFilters skipped.\n");
+        return;
+    }
+
+    // Create 2D images
+    VkImageObj src2D(m_device);
+    VkImageObj dst2D(m_device);
+    src2D.Init(64, 64, 1, fmt, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
+    dst2D.Init(64, 64, 1, fmt, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
+    ASSERT_TRUE(src2D.initialized());
+    ASSERT_TRUE(dst2D.initialized());
+
+    // Create 3D image
+    VkImageCreateInfo ci;
+    ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+    ci.pNext = NULL;
+    ci.flags = 0;
+    ci.imageType = VK_IMAGE_TYPE_3D;
+    ci.format = fmt;
+    ci.extent = {64, 64, 4};
+    ci.mipLevels = 1;
+    ci.arrayLayers = 1;
+    ci.samples = VK_SAMPLE_COUNT_1_BIT;
+    ci.tiling = VK_IMAGE_TILING_OPTIMAL;
+    ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+    ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    ci.queueFamilyIndexCount = 0;
+    ci.pQueueFamilyIndices = NULL;
+    ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+    VkImageObj src3D(m_device);
+    src3D.init(&ci);
+    ASSERT_TRUE(src3D.initialized());
+
+    VkImageBlit blitRegion = {};
+    blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    blitRegion.srcSubresource.baseArrayLayer = 0;
+    blitRegion.srcSubresource.layerCount = 1;
+    blitRegion.srcSubresource.mipLevel = 0;
+    blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    blitRegion.dstSubresource.baseArrayLayer = 0;
+    blitRegion.dstSubresource.layerCount = 1;
+    blitRegion.dstSubresource.mipLevel = 0;
+    blitRegion.srcOffsets[0] = {0, 0, 0};
+    blitRegion.srcOffsets[1] = {48, 48, 1};
+    blitRegion.dstOffsets[0] = {0, 0, 0};
+    blitRegion.dstOffsets[1] = {64, 64, 1};
+
+    m_commandBuffer->begin();
+
+    // UINT format should not support linear filtering, but check to be sure
+    if (!ImageFeatureIsSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001d6);
+        vkCmdBlitImage(m_commandBuffer->handle(), src2D.image(), src2D.Layout(), dst2D.image(), dst2D.Layout(), 1, &blitRegion,
+                       VK_FILTER_LINEAR);
+        m_errorMonitor->VerifyFound();
+    }
+
+    if (cubic_support &&
+        !ImageFeatureIsSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG)) {
+        // Invalid filter CUBIC_IMG
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001d8);
+        vkCmdBlitImage(m_commandBuffer->handle(), src3D.image(), src3D.Layout(), dst2D.image(), dst2D.Layout(), 1, &blitRegion,
+                       VK_FILTER_CUBIC_IMG);
+        m_errorMonitor->VerifyFound();
+
+        // Invalid filter CUBIC_IMG + invalid 2D source image
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001d8);
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001da);
+        vkCmdBlitImage(m_commandBuffer->handle(), src2D.image(), src2D.Layout(), dst2D.image(), dst2D.Layout(), 1, &blitRegion,
+                       VK_FILTER_CUBIC_IMG);
+        m_errorMonitor->VerifyFound();
+    }
+
+    m_commandBuffer->end();
+}
+
 TEST_F(VkLayerTest, BlitImageOffsets) {
     ASSERT_NO_FATAL_FAILURE(Init());
 
-    VkFormatProperties format_properties;
-    vkGetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_R8G8B8A8_UNORM, &format_properties);
-    if (0 == (format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||
-        0 == (format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) {
+    VkFormat fmt = VK_FORMAT_R8G8B8A8_UNORM;
+    if (!ImageFeatureIsSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL,
+                                 VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT)) {
         printf("             No blit feature bits - BlitImageOffsets skipped.\n");
         return;
     }
@@ -3005,7 +3185,7 @@ TEST_F(VkLayerTest, BlitImageOffsets) {
     ci.pNext = NULL;
     ci.flags = 0;
     ci.imageType = VK_IMAGE_TYPE_1D;
-    ci.format = VK_FORMAT_R8G8B8A8_UNORM;
+    ci.format = fmt;
     ci.extent = {64, 1, 1};
     ci.mipLevels = 1;
     ci.arrayLayers = 1;
@@ -3084,20 +3264,23 @@ TEST_F(VkLayerTest, BlitImageOffsets) {
     blit_region.srcOffsets[1] = {65, 64, 1};  // src x
     blit_region.dstOffsets[0] = {0, 0, 0};
     blit_region.dstOffsets[1] = {64, 64, 1};
-    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e6);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e6);  // x
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ae);  // src region
     vkCmdBlitImage(m_commandBuffer->handle(), image_3D.image(), image_3D.Layout(), image_2D.image(), image_2D.Layout(), 1,
                    &blit_region, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
 
-    blit_region.srcOffsets[1] = {64, 65, 1};  // src y
-    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e8);
+    blit_region.srcOffsets[1] = {64, 65, 1};                                                         // src y
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e8);  // y
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ae);  // src region
     vkCmdBlitImage(m_commandBuffer->handle(), image_3D.image(), image_3D.Layout(), image_2D.image(), image_2D.Layout(), 1,
                    &blit_region, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
 
     blit_region.srcOffsets[0] = {0, 0, 65};  // src z
     blit_region.srcOffsets[1] = {64, 64, 64};
-    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001ec);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001ec);  // z
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001ae);  // src region
     vkCmdBlitImage(m_commandBuffer->handle(), image_3D.image(), image_3D.Layout(), image_2D.image(), image_2D.Layout(), 1,
                    &blit_region, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
@@ -3107,20 +3290,23 @@ TEST_F(VkLayerTest, BlitImageOffsets) {
     blit_region.srcOffsets[1] = {64, 64, 1};
     blit_region.dstOffsets[0] = {96, 64, 32};  // dst x
     blit_region.dstOffsets[1] = {64, 0, 33};
-    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001f0);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001f0);  // x
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b0);  // dst region
     vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_3D.image(), image_3D.Layout(), 1,
                    &blit_region, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
 
-    blit_region.dstOffsets[0] = {0, 65, 32};  // dst y
-    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001f2);
+    blit_region.dstOffsets[0] = {0, 65, 32};                                                         // dst y
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001f2);  // y
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b0);  // dst region
     vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_3D.image(), image_3D.Layout(), 1,
                    &blit_region, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
 
     blit_region.dstOffsets[0] = {0, 64, 65};  // dst z
     blit_region.dstOffsets[1] = {64, 0, 64};
-    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001f6);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001f6);  // z
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001b0);  // dst region
     vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_3D.image(), image_3D.Layout(), 1,
                    &blit_region, VK_FILTER_NEAREST);
     m_errorMonitor->VerifyFound();
@@ -3128,6 +3314,126 @@ TEST_F(VkLayerTest, BlitImageOffsets) {
     m_commandBuffer->end();
 }
 
+TEST_F(VkLayerTest, MiscBlitImageTests) {
+    ASSERT_NO_FATAL_FAILURE(Init());
+
+    VkFormat f_color = VK_FORMAT_R32_SFLOAT;  // Need features ..BLIT_SRC_BIT & ..BLIT_DST_BIT
+    VkFormat f_depth = VK_FORMAT_D32_SFLOAT;  // Need feature ..BLIT_SRC_BIT but not ..BLIT_DST_BIT
+
+    if (!ImageFeatureIsSupported(gpu(), f_color, VK_IMAGE_TILING_OPTIMAL,
+                                 VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT) ||
+        !ImageFeatureIsSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||
+        ImageFeatureIsSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT)) {
+        printf("             Requested format features unavailable - MiscBlitImageTests skipped.\n");
+        return;
+    }
+
+    VkImageCreateInfo ci;
+    ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+    ci.pNext = NULL;
+    ci.flags = 0;
+    ci.imageType = VK_IMAGE_TYPE_2D;
+    ci.format = f_color;
+    ci.extent = {64, 64, 1};
+    ci.mipLevels = 1;
+    ci.arrayLayers = 1;
+    ci.samples = VK_SAMPLE_COUNT_1_BIT;
+    ci.tiling = VK_IMAGE_TILING_OPTIMAL;
+    ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    ci.queueFamilyIndexCount = 0;
+    ci.pQueueFamilyIndices = NULL;
+    ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+    // 2D color image
+    VkImageObj color_img(m_device);
+    color_img.init(&ci);
+    ASSERT_TRUE(color_img.initialized());
+
+    // 2D multi-sample image
+    ci.samples = VK_SAMPLE_COUNT_4_BIT;
+    VkImageObj ms_img(m_device);
+    ms_img.init(&ci);
+    ASSERT_TRUE(ms_img.initialized());
+
+    // 2D depth image
+    ci.format = f_depth;
+    ci.samples = VK_SAMPLE_COUNT_1_BIT;
+    VkImageObj depth_img(m_device);
+    depth_img.init(&ci);
+    ASSERT_TRUE(depth_img.initialized());
+
+    // 3D color image
+    ci.format = f_color;
+    ci.imageType = VK_IMAGE_TYPE_3D;
+    ci.extent = {64, 64, 8};
+    VkImageObj color_3D_img(m_device);
+    color_3D_img.init(&ci);
+    ASSERT_TRUE(color_3D_img.initialized());
+
+    VkImageBlit blitRegion = {};
+    blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    blitRegion.srcSubresource.baseArrayLayer = 0;
+    blitRegion.srcSubresource.layerCount = 1;
+    blitRegion.srcSubresource.mipLevel = 0;
+    blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    blitRegion.dstSubresource.baseArrayLayer = 0;
+    blitRegion.dstSubresource.layerCount = 1;
+    blitRegion.dstSubresource.mipLevel = 0;
+    blitRegion.srcOffsets[0] = {0, 0, 0};
+    blitRegion.srcOffsets[1] = {16, 16, 1};
+    blitRegion.dstOffsets[0] = {32, 32, 0};
+    blitRegion.dstOffsets[1] = {64, 64, 1};
+
+    m_commandBuffer->begin();
+
+    // Blit depth image - has SRC_BIT but not DST_BIT
+    blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+    blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001be);
+    vkCmdBlitImage(m_commandBuffer->handle(), depth_img.image(), depth_img.Layout(), depth_img.image(), depth_img.Layout(), 1,
+                   &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+
+    // Blit with aspectMask errors
+    blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+    blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e2);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e4);
+    vkCmdBlitImage(m_commandBuffer->handle(), color_img.image(), color_img.Layout(), color_img.image(), color_img.Layout(), 1,
+                   &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+
+    // Blit multi-sample image
+    blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    // TODO: redundant VUs, one (1c8) or two (1d2 & 1d4) should be eliminated.
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001c8);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001d2);
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_184001d4);
+    vkCmdBlitImage(m_commandBuffer->handle(), ms_img.image(), ms_img.Layout(), ms_img.image(), ms_img.Layout(), 1, &blitRegion,
+                   VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+
+    // Blit 3D with baseArrayLayer != 0 or layerCount != 1
+    blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    blitRegion.srcSubresource.baseArrayLayer = 1;
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e0);
+    vkCmdBlitImage(m_commandBuffer->handle(), color_3D_img.image(), color_3D_img.Layout(), color_3D_img.image(),
+                   color_3D_img.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+    blitRegion.srcSubresource.baseArrayLayer = 0;
+    blitRegion.srcSubresource.layerCount = 0;
+    blitRegion.dstSubresource.layerCount = 0;
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09a001e0);
+    vkCmdBlitImage(m_commandBuffer->handle(), color_3D_img.image(), color_3D_img.Layout(), color_3D_img.image(),
+                   color_3D_img.Layout(), 1, &blitRegion, VK_FILTER_NEAREST);
+    m_errorMonitor->VerifyFound();
+
+    m_commandBuffer->end();
+}
+
 TEST_F(VkLayerTest, DSImageTransferGranularityTests) {
     VkResult err;
     bool pass;
@@ -12362,8 +12668,7 @@ TEST_F(VkLayerTest, VertexBufferInvalid) {
         // Create and bind a vertex buffer in a reduced scope, which will cause
         // it to be deleted upon leaving this scope
         const float vbo_data[3] = {1.f, 0.f, 1.f};
-        VkVerticesObj draw_verticies(m_device, 1, 1,
-            sizeof(vbo_data[0]), sizeof(vbo_data) / sizeof(vbo_data[0]), vbo_data);
+        VkVerticesObj draw_verticies(m_device, 1, 1, sizeof(vbo_data[0]), sizeof(vbo_data) / sizeof(vbo_data[0]), vbo_data);
         draw_verticies.BindVertexBuffers(m_commandBuffer->handle());
         draw_verticies.AddVertexInputToPipe(pipe);
     }
@@ -17651,10 +17956,10 @@ TEST_F(VkLayerTest, MiscImageLayerTests) {
 
     region.bufferImageHeight = 128;
     VkImageObj intImage1(m_device);
-    intImage1.Init(128, 128, 1, VK_FORMAT_R8_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+    intImage1.Init(128, 128, 1, VK_FORMAT_R8_SNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
                    VK_IMAGE_TILING_OPTIMAL, 0);
     VkImageObj intImage2(m_device);
-    intImage2.Init(128, 128, 1, VK_FORMAT_R8_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+    intImage2.Init(128, 128, 1, VK_FORMAT_R8_SNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
                    VK_IMAGE_TILING_OPTIMAL, 0);
     VkImageBlit blitRegion = {};
     blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -17896,7 +18201,6 @@ TEST_F(VkLayerTest, CopyImageTypeExtentMismatch) {
     m_errorMonitor->VerifyFound();
     copy_region.dstOffset.z = 0;
 
-
     // 2D texture w/ extent.depth > 1. Source = VU 09c00128, dest = 09c00134
     copy_region.extent.depth = 8;
     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_09c00128);
@@ -17943,7 +18247,7 @@ TEST_F(VkLayerTest, CopyImageTypeExtentMismatchMaintenance1) {
     ci.flags = 0;
     ci.imageType = VK_IMAGE_TYPE_1D;
     ci.format = VK_FORMAT_R8G8B8A8_UNORM;
-    ci.extent = { 32, 1, 1 };
+    ci.extent = {32, 1, 1};
     ci.mipLevels = 1;
     ci.arrayLayers = 1;
     ci.samples = VK_SAMPLE_COUNT_1_BIT;
@@ -17961,21 +18265,21 @@ TEST_F(VkLayerTest, CopyImageTypeExtentMismatchMaintenance1) {
 
     // 2D image
     ci.imageType = VK_IMAGE_TYPE_2D;
-    ci.extent = { 32, 32, 1 };
+    ci.extent = {32, 32, 1};
     VkImageObj image_2D(m_device);
     image_2D.init(&ci);
     ASSERT_TRUE(image_2D.initialized());
 
     // 3D image
     ci.imageType = VK_IMAGE_TYPE_3D;
-    ci.extent = { 32, 32, 8 };
+    ci.extent = {32, 32, 8};
     VkImageObj image_3D(m_device);
     image_3D.init(&ci);
     ASSERT_TRUE(image_3D.initialized());
 
     // 2D image array
     ci.imageType = VK_IMAGE_TYPE_2D;
-    ci.extent = { 32, 32, 1 };
+    ci.extent = {32, 32, 1};
     ci.arrayLayers = 8;
     VkImageObj image_2D_array(m_device);
     image_2D_array.init(&ci);
@@ -17984,7 +18288,7 @@ TEST_F(VkLayerTest, CopyImageTypeExtentMismatchMaintenance1) {
     m_commandBuffer->begin();
 
     VkImageCopy copy_region;
-    copy_region.extent = { 32, 1, 1 };
+    copy_region.extent = {32, 1, 1};
     copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     copy_region.srcSubresource.mipLevel = 0;
@@ -17993,8 +18297,8 @@ TEST_F(VkLayerTest, CopyImageTypeExtentMismatchMaintenance1) {
     copy_region.dstSubresource.baseArrayLayer = 0;
     copy_region.srcSubresource.layerCount = 1;
     copy_region.dstSubresource.layerCount = 1;
-    copy_region.srcOffset = { 0, 0, 0 };
-    copy_region.dstOffset = { 0, 0, 0 };
+    copy_region.srcOffset = {0, 0, 0};
+    copy_region.dstOffset = {0, 0, 0};
 
     // Copy from layer not present - VU 09c0012a
     // TODO: this VU is redundant with VU 0a600154. Gitlab issue 812 submitted to have it removed.
@@ -18022,9 +18326,6 @@ TEST_F(VkLayerTest, CopyImageTypeExtentMismatchMaintenance1) {
     m_commandBuffer->end();
 }
 
-
-
-
 TEST_F(VkLayerTest, CopyImageCompressedBlockAlignment) {
     // Image copy tests on compressed images with block alignment errors