aboutsummaryrefslogtreecommitdiff
path: root/layers/buffer_validation.cpp
diff options
context:
space:
mode:
authorDave Houlton <daveh@lunarg.com>2017-04-27 14:32:45 -0600
committerDave Houlton <daveh@lunarg.com>2017-05-03 11:58:54 -0600
commita7ef0e0e0f8ade94b0c2cbb7115b17710c203546 (patch)
treec8ce071efd87eaae96735488769c0b06fbe0c9fc /layers/buffer_validation.cpp
parent3d3042c1d602774a738bb3ce2c6c48f4ac5d66e3 (diff)
downloadusermoji-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.cpp107
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(&regions[i].srcOffset, &regions[i].extent, &(src_image_state->createInfo.extent))) {
+ VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource));
+ if (0 != ExceedsBounds(&regions[i].srcOffset, &regions[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(&regions[i].dstOffset, &regions[i].extent, &(dst_image_state->createInfo.extent))) {
+ img_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource));
+ if (0 != ExceedsBounds(&regions[i].dstOffset, &regions[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), &regions[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), &regions[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]);