From 8a32fccc761d508b4d6329fbfd8e7eda4589d73c Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 2 May 2017 17:15:13 -0600 Subject: layers: Add VU checks to CmdCopyImage Added 16 image copy checks called from PreCallValidateCmdCopyImage() in buffer_validation.cpp. VUs 1209-1217, 1742-1745, and 2603-2604. Change-Id: I5f63862a4451458b054c4b10cd218293d9e16289 --- layers/buffer_validation.cpp | 364 +++++++++++++++++++++++++++++--- layers/vk_validation_error_database.txt | 28 +-- 2 files changed, 346 insertions(+), 46 deletions(-) diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp index e0c3b81b..a6903dfa 100644 --- a/layers/buffer_validation.cpp +++ b/layers/buffer_validation.cpp @@ -1144,7 +1144,7 @@ static inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *oth return result; } -// Returns the image extent of a specific subresource. +// Returns the effective extent of an image subresource, adjusted for mip level and array depth. static inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) { const uint32_t mip = subresource->mipLevel; @@ -1159,9 +1159,8 @@ static inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const extent.height = (0 == extent.height ? 0 : std::max(1U, extent.height >> mip)); extent.depth = (0 == extent.depth ? 0 : std::max(1U, extent.depth >> mip)); - // For 2D images, the number of layers present becomes the effective depth (for 2D <-> 3D copies) - // In this case the depth extent is not diminished with mip level - if (VK_IMAGE_TYPE_2D == img->createInfo.imageType) { + // Image arrays have an effective z extent that isn't diminished by mip level + if (VK_IMAGE_TYPE_3D != img->createInfo.imageType) { extent.depth = img->createInfo.arrayLayers; } @@ -1263,7 +1262,15 @@ static inline bool CheckItgExtent(layer_data *device_data, const GLOBAL_CB_NODE offset_extent_sum.width = static_cast(abs(offset->x)) + extent->width; offset_extent_sum.height = static_cast(abs(offset->y)) + extent->height; offset_extent_sum.depth = static_cast(abs(offset->z)) + extent->depth; - if ((IsExtentAligned(extent, granularity) == false) && (IsExtentEqual(&offset_extent_sum, subresource_extent) == false)) { + + bool x_ok = + ((0 == SafeModulo(extent->width, granularity->width)) || (subresource_extent->width == offset_extent_sum.width)); + bool y_ok = + ((0 == SafeModulo(extent->height, granularity->height)) || (subresource_extent->height == offset_extent_sum.height)); + bool z_ok = + ((0 == SafeModulo(extent->depth, granularity->depth)) || (subresource_extent->depth == offset_extent_sum.depth)); + + if (!(x_ok && y_ok && z_ok)) { 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_IMAGE_TRANSFER_GRANULARITY, "DS", @@ -1343,26 +1350,311 @@ bool ValidateCopyBufferImageTransferGranularityRequirements(layer_data *device_d // Check valid usage Image Tranfer Granularity requirements for elements of a VkImageCopy structure bool ValidateCopyImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, - const IMAGE_STATE *img, const VkImageCopy *region, const uint32_t i, - const char *function) { + const IMAGE_STATE *src_img, const IMAGE_STATE *dst_img, + const VkImageCopy *region, const uint32_t i, const char *function) { bool skip = false; - VkExtent3D granularity = GetScaledItg(device_data, cb_node, img); + VkExtent3D granularity = GetScaledItg(device_data, cb_node, src_img); skip |= CheckItgOffset(device_data, cb_node, ®ion->srcOffset, &granularity, i, function, "srcOffset"); + VkExtent3D subresource_extent = GetImageSubresourceExtent(src_img, ®ion->srcSubresource); + skip |= CheckItgExtent(device_data, cb_node, ®ion->extent, ®ion->srcOffset, &granularity, &subresource_extent, i, + function, "extent"); + + granularity = GetScaledItg(device_data, cb_node, dst_img); skip |= CheckItgOffset(device_data, cb_node, ®ion->dstOffset, &granularity, i, function, "dstOffset"); - VkExtent3D subresource_extent = GetImageSubresourceExtent(img, ®ion->dstSubresource); + subresource_extent = GetImageSubresourceExtent(dst_img, ®ion->dstSubresource); skip |= CheckItgExtent(device_data, cb_node, ®ion->extent, ®ion->dstOffset, &granularity, &subresource_extent, i, function, "extent"); return skip; } +// Validate contents of a VkImageCopy struct +bool ValidateImageCopyData(const layer_data *device_data, const debug_report_data *report_data, const uint32_t regionCount, + const VkImageCopy *ic_regions, const IMAGE_STATE *src_state, const IMAGE_STATE *dst_state) { + bool skip = false; + + for (uint32_t i = 0; i < regionCount; i++) { + VkImageCopy image_copy = ic_regions[i]; + bool slice_override = false; + uint32_t depth_slices = 0; + + // Special case for copying between a 1D/2D array and a 3D image + // TBD: This seems like the only way to reconcile 3 mutually-exclusive VU checks for 2D/3D copies. Heads up. + if ((VK_IMAGE_TYPE_3D == src_state->createInfo.imageType) && (VK_IMAGE_TYPE_3D != dst_state->createInfo.imageType)) { + depth_slices = image_copy.dstSubresource.layerCount; // Slice count from 2D subresource + slice_override = (depth_slices != 1); + } else if ((VK_IMAGE_TYPE_3D == dst_state->createInfo.imageType) && (VK_IMAGE_TYPE_3D != src_state->createInfo.imageType)) { + depth_slices = image_copy.srcSubresource.layerCount; // Slice count from 2D subresource + slice_override = (depth_slices != 1); + } + + // Do all checks on source image + // + if (src_state->createInfo.imageType == VK_IMAGE_TYPE_1D) { + if ((0 != image_copy.srcOffset.y) || (1 != image_copy.extent.height)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01742, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] srcOffset.y is %d and extent.height is %d. For 1D images these must " + "be 0 and 1, respectively. %s", + i, image_copy.srcOffset.y, image_copy.extent.height, validation_error_map[VALIDATION_ERROR_01742]); + } + } + + if ((src_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (src_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) { + if ((0 != image_copy.srcOffset.z) || (1 != image_copy.extent.depth)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01743, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] srcOffset.z is %d and extent.depth is %d. For 1D and 2D images " + "these must be 0 and 1, respectively. %s", + i, image_copy.srcOffset.z, image_copy.extent.depth, validation_error_map[VALIDATION_ERROR_01743]); + } + } + + // VU01199 changed with mnt1 + if (GetDeviceExtensions(device_data)->khr_maintenance1) { + if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { + if ((0 != image_copy.srcSubresource.baseArrayLayer) || (1 != image_copy.srcSubresource.layerCount)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01199, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer is %d and srcSubresource.layerCount " + "is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s", + i, image_copy.srcSubresource.baseArrayLayer, image_copy.srcSubresource.layerCount, + validation_error_map[VALIDATION_ERROR_01199]); + } + } + } else { // Pre maint 1 + if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D || dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { + if ((0 != image_copy.srcSubresource.baseArrayLayer) || (1 != image_copy.srcSubresource.layerCount)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01199, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer is %d and " + "srcSubresource.layerCount is %d. For copies with either source or dest of type " + "VK_IMAGE_TYPE_3D, these must be 0 and 1, respectively. %s", + i, image_copy.srcSubresource.baseArrayLayer, image_copy.srcSubresource.layerCount, + validation_error_map[VALIDATION_ERROR_01199]); + } + } + } + + // TODO: this VU is redundant with VU01224. Gitlab issue 812 submitted to get it removed from the spec. + if ((image_copy.srcSubresource.baseArrayLayer >= src_state->createInfo.arrayLayers) || + (image_copy.srcSubresource.baseArrayLayer + image_copy.srcSubresource.layerCount > src_state->createInfo.arrayLayers)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_02603, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer (%d) must be less than the source image's " + "arrayLayers (%d), and the sum of baseArrayLayer and srcSubresource.layerCount (%d) must be less than " + "or equal to the source image's arrayLayers. %s", + i, image_copy.srcSubresource.baseArrayLayer, src_state->createInfo.arrayLayers, + image_copy.srcSubresource.layerCount, validation_error_map[VALIDATION_ERROR_02603]); + } + + // Checks that apply only to compressed images + if (FormatIsCompressed(src_state->createInfo.format)) { + VkExtent3D block_size = FormatCompressedTexelBlockExtent(src_state->createInfo.format); + + // image offsets must be multiples of block dimensions + if ((SafeModulo(image_copy.srcOffset.x, block_size.width) != 0) || + (SafeModulo(image_copy.srcOffset.y, block_size.height) != 0) || + (SafeModulo(image_copy.srcOffset.z, block_size.depth) != 0)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01209, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] srcOffset (%d, %d) must be multiples of the compressed image's " + "texel width & height (%d, %d). %s.", + i, image_copy.srcOffset.x, image_copy.srcOffset.y, block_size.width, block_size.height, + validation_error_map[VALIDATION_ERROR_01209]); + } + + // extent width must be a multiple of block width, or extent+offset width must equal subresource width + VkExtent3D mip_extent = GetImageSubresourceExtent(src_state, &(image_copy.srcSubresource)); + if ((SafeModulo(image_copy.extent.width, block_size.width) != 0) && + (image_copy.extent.width + image_copy.srcOffset.x != mip_extent.width)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01210, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " + "width (%d), or when added to srcOffset.x (%d) must equal the image subresource width (%d). %s.", + i, image_copy.extent.width, block_size.width, image_copy.srcOffset.x, mip_extent.width, + validation_error_map[VALIDATION_ERROR_01210]); + } + + // extent height must be a multiple of block height, or extent+offset height must equal subresource height + if ((SafeModulo(image_copy.extent.height, block_size.height) != 0) && + (image_copy.extent.height + image_copy.srcOffset.y != mip_extent.height)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01211, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block " + "height (%d), or when added to srcOffset.y (%d) must equal the image subresource height (%d). %s.", + i, image_copy.extent.height, block_size.height, image_copy.srcOffset.y, mip_extent.height, + validation_error_map[VALIDATION_ERROR_01211]); + } + + // extent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth + uint32_t copy_depth = (slice_override ? depth_slices : image_copy.extent.depth); + if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + image_copy.srcOffset.z != mip_extent.depth)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(src_state->image), __LINE__, VALIDATION_ERROR_01212, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " + "depth (%d), or when added to srcOffset.z (%d) must equal the image subresource depth (%d). %s.", + i, image_copy.extent.depth, block_size.depth, image_copy.srcOffset.z, mip_extent.depth, + validation_error_map[VALIDATION_ERROR_01212]); + } + } // Compressed + + // Do all checks on dest image + // + if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_1D) { + if ((0 != image_copy.dstOffset.y) || (1 != image_copy.extent.height)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01744, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] dstOffset.y is %d and extent.height is %d. For 1D images these must " + "be 0 and 1, respectively. %s", + i, image_copy.dstOffset.y, image_copy.extent.height, validation_error_map[VALIDATION_ERROR_01744]); + } + } + + if ((dst_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (dst_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) { + if ((0 != image_copy.dstOffset.z) || (1 != image_copy.extent.depth)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01745, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] dstOffset.z is %d and extent.depth is %d. For 1D and 2D images " + "these must be 0 and 1, respectively. %s", + i, image_copy.dstOffset.z, image_copy.extent.depth, validation_error_map[VALIDATION_ERROR_01745]); + } + } + + if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { + if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01199, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and dstSubresource.layerCount " + "is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s", + i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount, + validation_error_map[VALIDATION_ERROR_01199]); + } + } + // VU01199 changed with mnt1 + if (GetDeviceExtensions(device_data)->khr_maintenance1) { + if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { + if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01199, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and dstSubresource.layerCount " + "is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s", + i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount, + validation_error_map[VALIDATION_ERROR_01199]); + } + } + } else { // Pre maint 1 + if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D || dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { + if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01199, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and " + "dstSubresource.layerCount is %d. For copies with either source or dest of type " + "VK_IMAGE_TYPE_3D, these must be 0 and 1, respectively. %s", + i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount, + validation_error_map[VALIDATION_ERROR_01199]); + } + } + } + + // TODO: this VU is redundant with VU01224. Gitlab issue 812 submitted to get it removed from the spec. + if ((image_copy.dstSubresource.baseArrayLayer >= dst_state->createInfo.arrayLayers) || + (image_copy.dstSubresource.baseArrayLayer + image_copy.dstSubresource.layerCount > dst_state->createInfo.arrayLayers)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_02604, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer (%d) must be less than the dest image's " + "arrayLayers (%d), and the sum of baseArrayLayer and dstSubresource.layerCount (%d) must be less than " + "or equal to the dest image's arrayLayers. %s", + i, image_copy.dstSubresource.baseArrayLayer, dst_state->createInfo.arrayLayers, + image_copy.dstSubresource.layerCount, validation_error_map[VALIDATION_ERROR_02604]); + } + + // Checks that apply only to compressed images + if (FormatIsCompressed(dst_state->createInfo.format)) { + VkExtent3D block_size = FormatCompressedTexelBlockExtent(dst_state->createInfo.format); + + // image offsets must be multiples of block dimensions + if ((SafeModulo(image_copy.dstOffset.x, block_size.width) != 0) || + (SafeModulo(image_copy.dstOffset.y, block_size.height) != 0) || + (SafeModulo(image_copy.dstOffset.z, block_size.depth) != 0)) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01214, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] dstOffset (%d, %d) must be multiples of the compressed image's " + "texel width & height (%d, %d). %s.", + i, image_copy.dstOffset.x, image_copy.dstOffset.y, block_size.width, block_size.height, + validation_error_map[VALIDATION_ERROR_01214]); + } + + // extent width must be a multiple of block width, or extent+offset width must equal subresource width + VkExtent3D mip_extent = GetImageSubresourceExtent(dst_state, &(image_copy.dstSubresource)); + if ((SafeModulo(image_copy.extent.width, block_size.width) != 0) && + (image_copy.extent.width + image_copy.dstOffset.x != mip_extent.width)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01215, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " + "width (%d), or when added to dstOffset.x (%d) must equal the image subresource width (%d). %s.", + i, image_copy.extent.width, block_size.width, image_copy.dstOffset.x, mip_extent.width, + validation_error_map[VALIDATION_ERROR_01215]); + } + + // extent height must be a multiple of block height, or extent+offset height must equal subresource height + if ((SafeModulo(image_copy.extent.height, block_size.height) != 0) && + (image_copy.extent.height + image_copy.dstOffset.y != mip_extent.height)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01216, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block " + "height (%d), or when added to dstOffset.y (%d) must equal the image subresource height (%d). %s.", + i, image_copy.extent.height, block_size.height, image_copy.dstOffset.y, mip_extent.height, + validation_error_map[VALIDATION_ERROR_01216]); + } + + // extent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth + uint32_t copy_depth = (slice_override ? depth_slices : image_copy.extent.depth); + if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + image_copy.dstOffset.z != mip_extent.depth)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + reinterpret_cast(dst_state->image), __LINE__, VALIDATION_ERROR_01217, "IMAGE", + "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " + "depth (%d), or when added to dstOffset.z (%d) must equal the image subresource depth (%d). %s.", + i, image_copy.extent.depth, block_size.depth, image_copy.dstOffset.z, mip_extent.depth, + validation_error_map[VALIDATION_ERROR_01217]); + } + } // Compressed + } + return skip; +} + bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, IMAGE_STATE *dst_image_state, uint32_t region_count, const VkImageCopy *regions, VkImageLayout src_image_layout, VkImageLayout dst_image_layout) { bool skip = false; const debug_report_data *report_data = core_validation::GetReportData(device_data); + skip = ValidateImageCopyData(device_data, report_data, region_count, regions, src_image_state, dst_image_state); + VkCommandBuffer command_buffer = cb_node->commandBuffer; for (uint32_t i = 0; i < region_count; i++) { + bool slice_override = false; + uint32_t depth_slices = 0; + + // Special case for copying between a 1D/2D array and a 3D image + // TBD: This seems like the only way to reconcile 3 mutually-exclusive VU checks for 2D/3D copies. Heads up. + if ((VK_IMAGE_TYPE_3D == src_image_state->createInfo.imageType) && + (VK_IMAGE_TYPE_3D != dst_image_state->createInfo.imageType)) { + depth_slices = regions[i].dstSubresource.layerCount; // Slice count from 2D subresource + slice_override = (depth_slices != 1); + } else if ((VK_IMAGE_TYPE_3D == dst_image_state->createInfo.imageType) && + (VK_IMAGE_TYPE_3D != src_image_state->createInfo.imageType)) { + depth_slices = regions[i].srcSubresource.layerCount; // Slice count from 2D subresource + slice_override = (depth_slices != 1); + } + if (regions[i].srcSubresource.layerCount == 0) { std::stringstream ss; ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero"; @@ -1379,7 +1671,27 @@ bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod HandleToUint64(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str()); } - if (!GetDeviceExtensions(device_data)->khr_maintenance1) { + if (GetDeviceExtensions(device_data)->khr_maintenance1) { + // No chance of mismatch if we're overriding depth slice count + if (!slice_override) { + // The number of depth slices in srcSubresource and dstSubresource must match + // Depth comes from layerCount for 1D,2D resources, from extent.depth for 3D + uint32_t src_slices = + (VK_IMAGE_TYPE_3D == src_image_state->createInfo.imageType ? regions[i].extent.depth + : regions[i].srcSubresource.layerCount); + uint32_t dst_slices = + (VK_IMAGE_TYPE_3D == dst_image_state->createInfo.imageType ? regions[i].extent.depth + : regions[i].dstSubresource.layerCount); + if (src_slices != dst_slices) { + std::stringstream ss; + ss << "vkCmdCopyImage: number of depth slices in source and destination subresources for pRegions[" << i + << "] do not match"; + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + reinterpret_cast(command_buffer), __LINE__, VALIDATION_ERROR_01198, "IMAGE", + "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01198]); + } + } + } else { // For each region the layerCount member of srcSubresource and dstSubresource must match if (regions[i].srcSubresource.layerCount != regions[i].dstSubresource.layerCount) { std::stringstream ss; @@ -1438,22 +1750,6 @@ bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod validation_error_map[VALIDATION_ERROR_01221]); } - if (!GetDeviceExtensions(device_data)->khr_maintenance1) { - // If either of the calling command's src_image or dst_image parameters are of VkImageType VK_IMAGE_TYPE_3D, - // the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively - if (((src_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) || - (dst_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D)) && - ((regions[i].srcSubresource.baseArrayLayer != 0) || (regions[i].srcSubresource.layerCount != 1) || - (regions[i].dstSubresource.baseArrayLayer != 0) || (regions[i].dstSubresource.layerCount != 1))) { - std::stringstream ss; - ss << "vkCmdCopyImage: src or dstImage type was IMAGE_TYPE_3D, but in subRegion[" << i - << "] baseArrayLayer was not zero or layerCount was not 1."; - skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, - HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_01199, "IMAGE", "%s. %s", - ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01199]); - } - } - // MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created if (regions[i].srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) { std::stringstream ss; @@ -1526,7 +1822,9 @@ bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod // Each dimension offset + extent limits must fall with image subresource extent VkExtent3D subresource_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource)); - uint32_t extent_check = ExceedsBounds(&(regions[i].srcOffset), ®ions[i].extent, &subresource_extent); + VkExtent3D copy_extent = regions[i].extent; + if (slice_override) copy_extent.depth = depth_slices; + uint32_t extent_check = ExceedsBounds(&(regions[i].srcOffset), ©_extent, &subresource_extent); if (extent_check & x_bit) { skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_01202, "IMAGE", @@ -1549,12 +1847,14 @@ bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_01204, "IMAGE", "vkCmdCopyImage: Source image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource " "depth [%1d]. %s", - i, regions[i].srcOffset.z, regions[i].extent.depth, subresource_extent.depth, + i, regions[i].srcOffset.z, copy_extent.depth, subresource_extent.depth, validation_error_map[VALIDATION_ERROR_01204]); } subresource_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource)); - extent_check = ExceedsBounds(&(regions[i].dstOffset), ®ions[i].extent, &subresource_extent); + copy_extent = regions[i].extent; + if (slice_override) copy_extent.depth = depth_slices; + extent_check = ExceedsBounds(&(regions[i].dstOffset), ©_extent, &subresource_extent); if (extent_check & x_bit) { skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_01205, "IMAGE", @@ -1576,7 +1876,7 @@ bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_01207, "IMAGE", "vkCmdCopyImage: Dest image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource " "depth [%1d]. %s", - i, regions[i].dstOffset.z, regions[i].extent.depth, subresource_extent.depth, + i, regions[i].dstOffset.z, copy_extent.depth, subresource_extent.depth, validation_error_map[VALIDATION_ERROR_01207]); } @@ -1640,8 +1940,8 @@ bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "vkCmdCopyImage()", VALIDATION_ERROR_01180, &hit_error); skip |= VerifyImageLayout(device_data, cb_node, dst_image_state, regions[i].dstSubresource, dst_image_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "vkCmdCopyImage()", VALIDATION_ERROR_01183, &hit_error); - skip |= ValidateCopyImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, ®ions[i], i, - "vkCmdCopyImage()"); + skip |= ValidateCopyImageTransferGranularityRequirements(device_data, cb_node, src_image_state, dst_image_state, + ®ions[i], i, "vkCmdCopyImage()"); } return skip; diff --git a/layers/vk_validation_error_database.txt b/layers/vk_validation_error_database.txt index 31f051cd..710d7f36 100644 --- a/layers/vk_validation_error_database.txt +++ b/layers/vk_validation_error_database.txt @@ -1161,14 +1161,14 @@ VALIDATION_ERROR_01204~^~Y~^~CopyImageSrcSizeExceeded~^~vkCmdCopyImage~^~For mor VALIDATION_ERROR_01205~^~Y~^~CopyImageDstSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.x and (extent.width + dstOffset.x) must both be greater than or equal to 0 and less than or equal to the destination image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ VALIDATION_ERROR_01206~^~Y~^~CopyImageDstSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.y and (extent.height + dstOffset.y) must both be greater than or equal to 0 and less than or equal to the destination image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ VALIDATION_ERROR_01207~^~Y~^~CopyImageDstSizeExceeded~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstOffset.z and (extent.depth + dstOffset.z) must both be greater than or equal to 0 and less than or equal to the destination image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01209~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is a compressed format image, all members of srcOffset must be a multiple of the corresponding dimensions of the compressed texel block' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01210~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is a compressed format image, extent.width must be a multiple of the compressed texel block width or (extent.width + srcOffset.x) must equal the source image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01211~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is a compressed format image, extent.height must be a multiple of the compressed texel block height or (extent.height + srcOffset.y) must equal the source image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01212~^~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 a compressed format image, extent.depth must be a multiple of the compressed texel block depth or (extent.depth + srcOffset.z) must equal the source image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01214~^~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 a compressed format image, all members of dstOffset must be a multiple of the corresponding dimensions of the compressed texel block' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01215~^~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 a compressed format image, extent.width must be a multiple of the compressed texel block width or (extent.width + dstOffset.x) must equal the destination image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01216~^~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 a compressed format image, extent.height must be a multiple of the compressed texel block height or (extent.height + dstOffset.y) must equal the destination image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_01217~^~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 a compressed format image, extent.depth must be a multiple of the compressed texel block depth or (extent.depth + dstOffset.z) must equal the destination image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01209~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is a compressed format image, all members of srcOffset must be a multiple of the corresponding dimensions of the compressed texel block' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01210~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is a compressed format image, extent.width must be a multiple of the compressed texel block width or (extent.width + srcOffset.x) must equal the source image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01211~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is a compressed format image, extent.height must be a multiple of the compressed texel block height or (extent.height + srcOffset.y) must equal the source image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01212~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands srcImage is a compressed format image, extent.depth must be a multiple of the compressed texel block depth or (extent.depth + srcOffset.z) must equal the source image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01214~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands dstImage is a compressed format image, all members of dstOffset must be a multiple of the corresponding dimensions of the compressed texel block' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01215~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands dstImage is a compressed format image, extent.width must be a multiple of the compressed texel block width or (extent.width + dstOffset.x) must equal the destination image subresource width' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01216~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands dstImage is a compressed format image, extent.height must be a multiple of the compressed texel block height or (extent.height + dstOffset.y) must equal the destination image subresource height' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01217~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If the calling commands dstImage is a compressed format image, extent.depth must be a multiple of the compressed texel block depth or (extent.depth + dstOffset.z) must equal the destination image subresource depth' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ VALIDATION_ERROR_01218~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcOffset, dstOffset, and extent 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/html/vkspec.html#VkImageCopy)~^~ VALIDATION_ERROR_01219~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcSubresource must be a valid VkImageSubresourceLayers structure' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkImageCopy-srcOffset-00166)~^~implicit VALIDATION_ERROR_01220~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstSubresource must be a valid VkImageSubresourceLayers structure' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkImageCopy-srcOffset-00166)~^~implicit @@ -1611,10 +1611,10 @@ VALIDATION_ERROR_01737~^~N~^~Unknown~^~vkCreateImage~^~For more information refe VALIDATION_ERROR_01738~^~N~^~Unknown~^~vkCreateImage~^~For more information refer to Vulkan Spec Section '11.3. Images' which states 'pNext must be NULL' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkExternalMemoryImageCreateInfoNV)~^~implicit, TBD in parameter validation layer. VALIDATION_ERROR_01739~^~N~^~Unknown~^~vkCreateImage~^~For more information refer to Vulkan Spec Section '11.3. Images' which states 'handleTypes must be a valid combination of VkExternalMemoryHandleTypeFlagBitsNV values' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkExternalMemoryImageCreateInfoNV)~^~implicit VALIDATION_ERROR_01741~^~N~^~Unknown~^~vkCreateSampler~^~For more information refer to Vulkan Spec Section '12. Samplers' which states 'If either magFilter or minFilter is VK_FILTER_CUBIC_IMG, anisotropyEnable must be VK_FALSE' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkSamplerAddressMode)~^~ -VALIDATION_ERROR_01742~^~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, then srcOffset.y must be 0 and extent.height must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -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/html/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/html/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/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01742~^~Y~^~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, then srcOffset.y must be 0 and extent.height must be 1.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01743~^~Y~^~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/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01744~^~Y~^~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/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_01745~^~Y~^~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/html/vkspec.html#VkImageCopy)~^~ 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/html/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/html/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/html/vkspec.html#VkImageBlit)~^~ @@ -2416,8 +2416,8 @@ VALIDATION_ERROR_02599~^~N~^~Unknown~^~vkCmdClearColorImage~^~For more informati VALIDATION_ERROR_02600~^~N~^~Unknown~^~vkCmdClearDepthStencilImage~^~For more information refer to Vulkan Spec Section '17.1. Clearing Images Outside A Render Pass Instance' which states 'image must use a format that supports VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR, 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-extensions/html/vkspec.html#vkCmdClearDepthStencilImage)~^~ VALIDATION_ERROR_02601~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcImage must use a format that supports VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR, 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-extensions/html/vkspec.html#vkCmdCopyImage)~^~ VALIDATION_ERROR_02602~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstImage must use a format that supports VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR, 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-extensions/html/vkspec.html#vkCmdCopyImage)~^~ -VALIDATION_ERROR_02603~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcSubresource.baseArrayLayer must be less than and (srcSubresource.layerCount + srcSubresource.baseArrayLayer) must be less than or equal to the number of layers in the source image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ -VALIDATION_ERROR_02604~^~N~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstSubresource.baseArrayLayer must be less than and (dstSubresource.layerCount + dstSubresource.baseArrayLayer) must be less than or equal to the number of layers in the destination image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_02603~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'srcSubresource.baseArrayLayer must be less than and (srcSubresource.layerCount + srcSubresource.baseArrayLayer) must be less than or equal to the number of layers in the source image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ +VALIDATION_ERROR_02604~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'dstSubresource.baseArrayLayer must be less than and (dstSubresource.layerCount + dstSubresource.baseArrayLayer) must be less than or equal to the number of layers in the destination image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkImageCopy)~^~ VALIDATION_ERROR_02605~^~N~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'dstImage must use a format that supports VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR, 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-extensions/html/vkspec.html#vkCmdCopyBufferToImage)~^~ VALIDATION_ERROR_02606~^~N~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'srcImage must use a format that supports VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR, 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-extensions/html/vkspec.html#vkCmdCopyImageToBuffer)~^~ VALIDATION_ERROR_02607~^~N~^~Unknown~^~vkCmdSetViewport~^~For more information refer to Vulkan Spec Section '23.7. Controlling the Viewport' which states 'If the multiple viewports feature is not enabled, firstViewport must be 0' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#vkCmdSetViewport)~^~ -- cgit v1.2.3