Skip to content
This repository was archived by the owner on Jul 19, 2018. It is now read-only.

Commit 23c5a20

Browse files
krOozemark-lunarg
authored andcommitted
layers: GH1752, Update ImageSubrange checks
- fix #1752 - handle possible overflow of `level`+`count` - include correct err code in msges - update and add some tests
1 parent db365f5 commit 23c5a20

6 files changed

Lines changed: 430 additions & 158 deletions

layers/buffer_validation.cpp

Lines changed: 88 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
// Allow use of STL min and max functions in Windows
2323
#define NOMINMAX
2424

25+
#include <inttypes.h>
2526
#include <sstream>
27+
#include <string>
2628

2729
#include "vk_enum_string_helper.h"
2830
#include "vk_layer_data.h"
@@ -31,6 +33,19 @@
3133

3234
#include "buffer_validation.h"
3335

36+
// TODO: remove on NDK update (r15 will probably have proper STL impl)
37+
#ifdef __ANDROID__
38+
namespace std {
39+
40+
template <typename T>
41+
std::string to_string(T var) {
42+
std::ostringstream ss;
43+
ss << var;
44+
return ss.str();
45+
}
46+
}
47+
#endif
48+
3449
void SetLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout) {
3550
if (pCB->imageLayoutMap.find(imgpair) != pCB->imageLayoutMap.end()) {
3651
pCB->imageLayoutMap[imgpair].layout = layout;
@@ -990,6 +1005,9 @@ bool PreCallValidateCmdClearColorImage(layer_data *dev_data, VkCommandBuffer com
9901005
skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
9911006
skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_01096);
9921007
for (uint32_t i = 0; i < rangeCount; ++i) {
1008+
std::string param_name = "pRanges[" + std::to_string(i) + "]";
1009+
skip |= ValidateImageSubresourceRange(dev_data, image_state, nullptr, pRanges[i], "vkCmdClearColorImage",
1010+
param_name.c_str());
9931011
skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]);
9941012
skip |= VerifyClearImageLayout(dev_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearColorImage()");
9951013
}
@@ -1032,6 +1050,9 @@ bool PreCallValidateCmdClearDepthStencilImage(layer_data *device_data, VkCommand
10321050
skip |= ValidateCmd(device_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
10331051
skip |= insideRenderPass(device_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_01111);
10341052
for (uint32_t i = 0; i < rangeCount; ++i) {
1053+
std::string param_name = "pRanges[" + std::to_string(i) + "]";
1054+
skip |= ValidateImageSubresourceRange(device_data, image_state, nullptr, pRanges[i], "vkCmdClearDepthStencilImage",
1055+
param_name.c_str());
10351056
skip |=
10361057
VerifyClearImageLayout(device_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()");
10371058
// Image aspect must be depth or stencil or both
@@ -2576,20 +2597,77 @@ bool ValidateImageAspectMask(layer_data *device_data, VkImage image, VkFormat fo
25762597
return skip;
25772598
}
25782599

2579-
bool ValidateImageSubrangeLevelLayerCounts(layer_data *device_data, const VkImageSubresourceRange &subresourceRange,
2580-
const char *func_name) {
2600+
bool ValidateImageSubresourceRange(const layer_data *device_data, const IMAGE_STATE *image_state,
2601+
const VkImageViewCreateInfo *image_view_create_info,
2602+
const VkImageSubresourceRange &subresourceRange, const char *cmd_name, const char *param_name) {
25812603
const debug_report_data *report_data = core_validation::GetReportData(device_data);
25822604
bool skip = false;
2605+
2606+
// Validate mip levels
2607+
const auto image_mip_count = image_state->createInfo.mipLevels;
2608+
25832609
if (subresourceRange.levelCount == 0) {
2584-
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2585-
VALIDATION_ERROR_00768, "IMAGE", "%s called with 0 in subresourceRange.levelCount. %s", func_name,
2586-
validation_error_map[VALIDATION_ERROR_00768]);
2610+
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2611+
HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_00768, "IMAGE", "%s: %s.levelCount is 0. %s",
2612+
cmd_name, param_name, validation_error_map[VALIDATION_ERROR_00768]);
2613+
} else if (subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) {
2614+
// TODO: Not in the spec VUs. Probably missing -- KhronosGroup/Vulkan-Docs#416
2615+
if (subresourceRange.baseMipLevel >= image_mip_count) {
2616+
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2617+
HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_SUBRANGE, "IMAGE",
2618+
"%s: %s.baseMipLevel (= %" PRIu32 ") is greater or equal to the mip level count of the image (i.e. "
2619+
"greater or equal to %" PRIu32 ").",
2620+
cmd_name, param_name, subresourceRange.baseMipLevel, image_mip_count);
2621+
}
2622+
} else {
2623+
const uint64_t necessary_mip_count = uint64_t{subresourceRange.baseMipLevel} + uint64_t{subresourceRange.levelCount};
2624+
2625+
if (necessary_mip_count > image_mip_count) {
2626+
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2627+
HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_00768, "IMAGE",
2628+
"%s: %s.baseMipLevel + .levelCount (= %" PRIu32 " + %" PRIu32 " = %" PRIu64 ") is greater than the "
2629+
"mip level count of the image (i.e. greater than %" PRIu32 "). %s",
2630+
cmd_name, param_name, subresourceRange.baseMipLevel, subresourceRange.levelCount, necessary_mip_count,
2631+
image_mip_count, validation_error_map[VALIDATION_ERROR_00768]);
2632+
}
25872633
}
2634+
2635+
// Validate array layers
2636+
bool is_3D_to_2D_map = image_view_create_info && GetDeviceExtensions(device_data)->khr_maintenance1 &&
2637+
image_state->createInfo.imageType == VK_IMAGE_TYPE_3D &&
2638+
image_view_create_info->viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY;
2639+
2640+
const auto image_layer_count = is_3D_to_2D_map ? image_state->createInfo.extent.depth : image_state->createInfo.arrayLayers;
2641+
const auto image_layer_count_var_name = is_3D_to_2D_map ? "extent.depth" : "arrayLayers";
2642+
const auto invalid_layer_code = is_3D_to_2D_map ? VALIDATION_ERROR_00769 : VALIDATION_ERROR_02931;
2643+
25882644
if (subresourceRange.layerCount == 0) {
2589-
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2590-
VALIDATION_ERROR_00769, "IMAGE", "%s called with 0 in subresourceRange.layerCount. %s", func_name,
2591-
validation_error_map[VALIDATION_ERROR_00769]);
2645+
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2646+
HandleToUint64(image_state->image), __LINE__, invalid_layer_code, "IMAGE", "%s: %s.layerCount is 0. %s",
2647+
cmd_name, param_name, validation_error_map[invalid_layer_code]);
2648+
} else if (subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) {
2649+
// TODO: Not in the spec VUs. Probably missing -- KhronosGroup/Vulkan-Docs#416
2650+
if (subresourceRange.baseArrayLayer >= image_layer_count) {
2651+
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2652+
HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_SUBRANGE, "IMAGE",
2653+
"%s: %s.baseArrayLayer (= %" PRIu32 ") is greater or equal to the %s of the image when it was created "
2654+
"(i.e. greater or equal to %" PRIu32 ").",
2655+
cmd_name, param_name, subresourceRange.baseArrayLayer, image_layer_count_var_name, image_layer_count);
2656+
}
2657+
} else {
2658+
const uint64_t necessary_layer_count = uint64_t{subresourceRange.baseArrayLayer} + uint64_t{subresourceRange.layerCount};
2659+
2660+
if (necessary_layer_count > image_layer_count) {
2661+
skip |=
2662+
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2663+
HandleToUint64(image_state->image), __LINE__, invalid_layer_code, "IMAGE",
2664+
"%s: %s.baseArrayLayer + .layerCount (= %" PRIu32 " + %" PRIu32 " = %" PRIu64 ") is greater than the "
2665+
"%s of the image when it was created (i.e. greater than %" PRIu32 "). %s",
2666+
cmd_name, param_name, subresourceRange.baseArrayLayer, subresourceRange.layerCount, necessary_layer_count,
2667+
image_layer_count_var_name, image_layer_count, validation_error_map[invalid_layer_code]);
2668+
}
25922669
}
2670+
25932671
return skip;
25942672
}
25952673

@@ -2607,28 +2685,8 @@ bool PreCallValidateCreateImageView(layer_data *device_data, const VkImageViewCr
26072685
// If this isn't a sparse image, it needs to have memory backing it at CreateImageView time
26082686
skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCreateImageView()", VALIDATION_ERROR_02524);
26092687
// Checks imported from image layer
2610-
if ((create_info->subresourceRange.baseMipLevel + create_info->subresourceRange.levelCount) >
2611-
image_state->createInfo.mipLevels) {
2612-
std::stringstream ss;
2613-
ss << "vkCreateImageView called with baseMipLevel " << create_info->subresourceRange.baseMipLevel << " for image "
2614-
<< create_info->image << " that only has " << image_state->createInfo.mipLevels << " mip levels.";
2615-
skip |=
2616-
log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2617-
VALIDATION_ERROR_00768, "IMAGE", "%s %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_00768]);
2618-
}
2619-
if (!GetDeviceExtensions(device_data)->khr_maintenance1) {
2620-
if (create_info->subresourceRange.baseArrayLayer >= image_state->createInfo.arrayLayers) {
2621-
std::stringstream ss;
2622-
ss << "vkCreateImageView called with baseArrayLayer " << create_info->subresourceRange.baseArrayLayer
2623-
<< " for image " << create_info->image << " that only has " << image_state->createInfo.arrayLayers
2624-
<< " array layers.";
2625-
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2626-
VALIDATION_ERROR_00769, "IMAGE", "%s %s", ss.str().c_str(),
2627-
validation_error_map[VALIDATION_ERROR_00769]);
2628-
}
2629-
}
2630-
// TODO: Need new valid usage language for levelCount == 0 & layerCount == 0
2631-
skip |= ValidateImageSubrangeLevelLayerCounts(device_data, create_info->subresourceRange, "vkCreateImageView()");
2688+
skip |= ValidateImageSubresourceRange(device_data, image_state, create_info, create_info->subresourceRange,
2689+
"vkCreateImageView", "pCreateInfo->subresourceRange");
26322690

26332691
VkImageCreateFlags image_flags = image_state->createInfo.flags;
26342692
VkFormat image_format = image_state->createInfo.format;

layers/buffer_validation.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,9 @@ void PostCallRecordCreateBufferView(layer_data *device_data, const VkBufferViewC
185185
bool ValidateImageAspectMask(layer_data *device_data, VkImage image, VkFormat format, VkImageAspectFlags aspect_mask,
186186
const char *func_name);
187187

188-
bool ValidateImageSubrangeLevelLayerCounts(layer_data *device_data, const VkImageSubresourceRange &subresourceRange,
189-
const char *func_name);
188+
bool ValidateImageSubresourceRange(const layer_data *device_data, const IMAGE_STATE *image_state,
189+
const VkImageViewCreateInfo *image_view_create_info,
190+
const VkImageSubresourceRange &subresourceRange, const char *cmd_name, const char *param_name);
190191

191192
bool PreCallValidateCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info);
192193

layers/core_validation.cpp

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7766,29 +7766,12 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui
77667766
funcName);
77677767
}
77687768
if (image_data) {
7769-
skip |= ValidateImageSubrangeLevelLayerCounts(dev_data, mem_barrier->subresourceRange, funcName);
77707769
auto aspect_mask = mem_barrier->subresourceRange.aspectMask;
77717770
skip |= ValidateImageAspectMask(dev_data, image_data->image, image_data->createInfo.format, aspect_mask, funcName);
77727771

7773-
uint32_t layer_count = ResolveRemainingLayers(&mem_barrier->subresourceRange, image_data->createInfo.arrayLayers);
7774-
if ((mem_barrier->subresourceRange.baseArrayLayer + layer_count) > image_data->createInfo.arrayLayers) {
7775-
skip |= log_msg(
7776-
dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7777-
HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
7778-
"%s: Subresource must have the sum of the baseArrayLayer (%d) and layerCount (%d) be less "
7779-
"than or equal to the total number of layers (%d).",
7780-
funcName, mem_barrier->subresourceRange.baseArrayLayer, layer_count, image_data->createInfo.arrayLayers);
7781-
}
7782-
7783-
uint32_t level_count = ResolveRemainingLevels(&mem_barrier->subresourceRange, image_data->createInfo.mipLevels);
7784-
if ((mem_barrier->subresourceRange.baseMipLevel + level_count) > image_data->createInfo.mipLevels) {
7785-
skip |= log_msg(
7786-
dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7787-
HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
7788-
"%s: Subresource must have the sum of the baseMipLevel (%d) and levelCount (%d) be less than or equal to "
7789-
"the total number of levels (%d).",
7790-
funcName, mem_barrier->subresourceRange.baseMipLevel, level_count, image_data->createInfo.mipLevels);
7791-
}
7772+
std::string param_name = "pImageMemoryBarriers[" + std::to_string(i) + "].subresourceRange";
7773+
skip |= ValidateImageSubresourceRange(dev_data, image_data, nullptr, mem_barrier->subresourceRange, funcName,
7774+
param_name.c_str());
77927775
}
77937776
}
77947777

layers/core_validation_error_enums.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ enum DRAW_STATE_ERROR {
160160
DRAWSTATE_SWAPCHAIN_REPLACED,
161161
DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND,
162162
DRAWSTATE_EXTENSION_NOT_ENABLED,
163+
DRAWSTATE_INVALID_IMAGE_SUBRANGE,
163164
};
164165

165166
// Shader Checker ERROR codes

0 commit comments

Comments
 (0)