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"
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+
3449void 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 ;
0 commit comments