diff options
| author | Dave Houlton <daveh@lunarg.com> | 2017-04-27 14:32:45 -0600 |
|---|---|---|
| committer | Dave Houlton <daveh@lunarg.com> | 2017-05-03 11:58:54 -0600 |
| commit | a7ef0e0e0f8ade94b0c2cbb7115b17710c203546 (patch) | |
| tree | c8ce071efd87eaae96735488769c0b06fbe0c9fc /layers/buffer_validation.cpp | |
| parent | 3d3042c1d602774a738bb3ce2c6c48f4ac5d66e3 (diff) | |
| download | usermoji-a7ef0e0e0f8ade94b0c2cbb7115b17710c203546.tar.xz | |
layers: Add VUs 01202..01207
Added checks for 6 CopyImage VUs to buffer validation. Updated copy
size tests to provoke each new VU.
Change-Id: Ice7821b7c1b8aa0c90e68e8386c56bd021a616ed
Diffstat (limited to 'layers/buffer_validation.cpp')
| -rw-r--r-- | layers/buffer_validation.cpp | 107 |
1 files changed, 95 insertions, 12 deletions
diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp index d5b15cb8..a0e6df6b 100644 --- a/layers/buffer_validation.cpp +++ b/layers/buffer_validation.cpp @@ -1054,21 +1054,25 @@ static bool RegionIntersects(const VkImageCopy *src, const VkImageCopy *dst, VkI return result; } -// Returns true if offset and extent exceed image extents -static bool ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent) { - bool result = false; +// Returns non-zero if offset and extent exceed image extents +static const uint32_t x_bit = 1; +static const uint32_t y_bit = 2; +static const uint32_t z_bit = 4; +static uint32_t ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent) +{ + uint32_t result = 0; // Extents/depths cannot be negative but checks left in for clarity if ((offset->z + extent->depth > image_extent->depth) || (offset->z < 0) || ((offset->z + static_cast<int32_t>(extent->depth)) < 0)) { - result = true; + result |= z_bit; } if ((offset->y + extent->height > image_extent->height) || (offset->y < 0) || ((offset->y + static_cast<int32_t>(extent->height)) < 0)) { - result = true; + result |= y_bit; } if ((offset->x + extent->width > image_extent->width) || (offset->x < 0) || ((offset->x + static_cast<int32_t>(extent->width)) < 0)) { - result = true; + result |= x_bit; } return result; } @@ -1086,11 +1090,26 @@ static inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *oth // Returns the image extent of a specific subresource. static inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) { const uint32_t mip = subresource->mipLevel; - VkExtent3D extent = img->createInfo.extent; + + // Return zero extent if mip level doesn't exist + if (mip >= img->createInfo.mipLevels) + { + return VkExtent3D{ 0, 0, 0 }; + } + // Don't allow mip adjustment to create 0 dim, but pass along a 0 if that's what subresource specified + VkExtent3D extent = img->createInfo.extent; extent.width = (0 == extent.width ? 0 : std::max(1U, extent.width >> mip)); 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) + { + extent.depth = img->createInfo.arrayLayers; + } + return extent; } @@ -1426,24 +1445,88 @@ bool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_nod // Check region extents for 1D-1D, 2D-2D, and 3D-3D copies if (src_image_state->createInfo.imageType == dst_image_state->createInfo.imageType) { // The source region specified by a given element of regions must be a region that is contained within srcImage - if (ExceedsBounds(®ions[i].srcOffset, ®ions[i].extent, &(src_image_state->createInfo.extent))) { + VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource)); + if (0 != ExceedsBounds(®ions[i].srcOffset, ®ions[i].extent, &img_extent)) { std::stringstream ss; - ss << "vkCmdCopyImage: srcSubResource in pRegions[" << i << "] exceeds extents srcImage was created with"; + ss << "vkCmdCopyImage: Source pRegion[" << i << "] with mipLevel [ " << regions[i].srcSubresource.mipLevel + << " ], offset [ " << regions[i].srcOffset.x << ", " << regions[i].srcOffset.y << ", " << regions[i].srcOffset.z + << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", " + << regions[i].extent.depth << " ] exceeds the source image dimensions"; skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01175, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01175]); } // The destination region specified by a given element of regions must be a region that is contained within dst_image - if (ExceedsBounds(®ions[i].dstOffset, ®ions[i].extent, &(dst_image_state->createInfo.extent))) { + img_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource)); + if (0 != ExceedsBounds(®ions[i].dstOffset, ®ions[i].extent, &img_extent)) { std::stringstream ss; - ss << "vkCmdCopyImage: dstSubResource in pRegions[" << i << "] exceeds extents dstImage was created with"; + ss << "vkCmdCopyImage: Dest pRegion[" << i << "] with mipLevel [ " << regions[i].dstSubresource.mipLevel + << " ], offset [ " << regions[i].dstOffset.x << ", " << regions[i].dstOffset.y << ", " << regions[i].dstOffset.z + << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", " + << regions[i].extent.depth << " ] exceeds the destination image dimensions"; skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01176, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01176]); } } + // 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); + if (extent_check & x_bit) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01202, "IMAGE", + "vkCmdCopyImage: Source image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource " + "width [%1d]. %s", + i, regions[i].srcOffset.x, regions[i].extent.width, subresource_extent.width, + validation_error_map[VALIDATION_ERROR_01202]); + } + + if (extent_check & y_bit) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01203, "IMAGE", + "vkCmdCopyImage: Source image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource " + "height [%1d]. %s", + i, regions[i].srcOffset.y, regions[i].extent.height, subresource_extent.height, + validation_error_map[VALIDATION_ERROR_01203]); + } + if (extent_check & z_bit) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + reinterpret_cast<uint64_t &>(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, + 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); + if (extent_check & x_bit) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01205, "IMAGE", + "vkCmdCopyImage: Dest image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource " + "width [%1d]. %s", + i, regions[i].dstOffset.x, regions[i].extent.width, subresource_extent.width, + validation_error_map[VALIDATION_ERROR_01205]); + } + if (extent_check & y_bit) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01206, "IMAGE", + "vkCmdCopyImage: Dest image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource " + "height [%1d]. %s", + i, regions[i].dstOffset.y, regions[i].extent.height, subresource_extent.height, + validation_error_map[VALIDATION_ERROR_01206]); + } + if (extent_check & z_bit) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + reinterpret_cast<uint64_t &>(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, + validation_error_map[VALIDATION_ERROR_01207]); + } + // The union of all source regions, and the union of all destination regions, specified by the elements of regions, // must not overlap in memory if (src_image_state->image == dst_image_state->image) { @@ -2888,7 +2971,7 @@ static bool ValidateImageBounds(const debug_report_data *report_data, const IMAG } } - if (ExceedsBounds(&offset, &extent, &image_extent)) { + if (0 != ExceedsBounds(&offset, &extent, &image_extent)) { skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0, __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds image bounds. %s.", func_name, i, validation_error_map[msg_code]); |
