layer:Add unique error ids for memory binding
authorTobin Ehlis <tobine@google.com>
Thu, 22 Dec 2016 19:45:09 +0000 (12:45 -0700)
committerTobin Ehlis <tobine@google.com>
Fri, 23 Dec 2016 21:39:34 +0000 (14:39 -0700)
Update all of the cases to validate that memory is bound to non-sparse
images and buffers to use the correct unique error id.

layers/core_validation.cpp
layers/core_validation_types.h
layers/descriptor_sets.cpp
layers/vk_validation_error_database.txt

index d6bd9ea..583ab8c 100644 (file)
@@ -718,40 +718,42 @@ static bool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VkD
 
 // For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value.
 bool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name,
-                              const char *type_name) {
+                              const char *type_name, UNIQUE_VALIDATION_ERROR_CODE error_code) {
     bool result = false;
     if (VK_NULL_HANDLE == mem) {
         result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
-                         __LINE__, MEMTRACK_OBJECT_NOT_BOUND, "MEM",
+                         __LINE__, error_code, "MEM",
                          "%s: Vk%s object 0x%" PRIxLEAST64 " used with no memory bound. Memory should be bound by calling "
-                         "vkBind%sMemory().",
-                         api_name, type_name, handle, type_name);
+                         "vkBind%sMemory(). %s",
+                         api_name, type_name, handle, type_name, validation_error_map[error_code]);
     } else if (MEMORY_UNBOUND == mem) {
         result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
-                         __LINE__, MEMTRACK_OBJECT_NOT_BOUND, "MEM",
+                         __LINE__, error_code, "MEM",
                          "%s: Vk%s object 0x%" PRIxLEAST64 " used with no memory bound and previously bound memory was freed. "
-                         "Memory must not be freed prior to this operation.",
-                         api_name, type_name, handle);
+                         "Memory must not be freed prior to this operation. %s",
+                         api_name, type_name, handle, validation_error_map[error_code]);
     }
     return result;
 }
 
 // Check to see if memory was ever bound to this image
-bool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name) {
+bool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name,
+                                  UNIQUE_VALIDATION_ERROR_CODE error_code) {
     bool result = false;
     if (0 == (static_cast<uint32_t>(image_state->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
-        result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem, reinterpret_cast<const uint64_t &>(image_state->image),
-                                          api_name, "Image");
+        result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem,
+                                          reinterpret_cast<const uint64_t &>(image_state->image), api_name, "Image", error_code);
     }
     return result;
 }
 
 // Check to see if memory was bound to this buffer
-bool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name) {
+bool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name,
+                                   UNIQUE_VALIDATION_ERROR_CODE error_code) {
     bool result = false;
     if (0 == (static_cast<uint32_t>(buffer_state->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) {
         result = VerifyBoundMemoryIsValid(dev_data, buffer_state->binding.mem,
-                                          reinterpret_cast<const uint64_t &>(buffer_state->buffer), api_name, "Buffer");
+                                          reinterpret_cast<const uint64_t &>(buffer_state->buffer), api_name, "Buffer", error_code);
     }
     return result;
 }
@@ -6483,7 +6485,7 @@ static bool PreCallValidateCreateBufferView(layer_data *dev_data, const VkBuffer
     BUFFER_STATE *buffer_state = getBufferState(dev_data, pCreateInfo->buffer);
     // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time
     if (buffer_state) {
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCreateBufferView()");
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCreateBufferView()", VALIDATION_ERROR_02522);
         // In order to create a valid buffer view, the buffer must have been created with at least one of the
         // following flags:  UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT
         skip_call |= ValidateBufferUsageFlags(
@@ -6639,7 +6641,7 @@ static bool PreCallValidateCreateImageView(layer_data *dev_data, const VkImageVi
             false, -1, "vkCreateImageView()",
             "VK_IMAGE_USAGE_[SAMPLED|STORAGE|COLOR_ATTACHMENT|DEPTH_STENCIL_ATTACHMENT|INPUT_ATTACHMENT]_BIT");
         // If this isn't a sparse image, it needs to have memory backing it at CreateImageView time
-        skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCreateImageView()");
+        skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCreateImageView()", VALIDATION_ERROR_02524);
         // Checks imported from image layer
         if (create_info->subresourceRange.baseMipLevel >= image_state->createInfo.mipLevels) {
             std::stringstream ss;
@@ -7924,7 +7926,7 @@ CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize
     auto buffer_state = getBufferState(dev_data, buffer);
     auto cb_node = getCBNode(dev_data, commandBuffer);
     if (cb_node && buffer_state) {
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()");
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_02543);
         std::function<bool()> function = [=]() {
             return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()");
         };
@@ -7983,7 +7985,7 @@ VKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, u
         for (uint32_t i = 0; i < bindingCount; ++i) {
             auto buffer_state = getBufferState(dev_data, pBuffers[i]);
             assert(buffer_state);
-            skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()");
+            skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_02546);
             std::function<bool()> function = [=]() {
                 return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()");
             };
@@ -8151,7 +8153,7 @@ static bool PreCallValidateCmdDrawIndirect(
     bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state,
                                     active_set_bindings_pairs, active_bindings, caller, VALIDATION_ERROR_01381);
     *buffer_state = getBufferState(dev_data, buffer);
-    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller);
+    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02544);
     return skip;
 }
 
@@ -8195,7 +8197,7 @@ static bool PreCallValidateCmdDrawIndexedIndirect(
     bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state,
                                     active_set_bindings_pairs, active_bindings, caller, VALIDATION_ERROR_01393);
     *buffer_state = getBufferState(dev_data, buffer);
-    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller);
+    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02545);
     return skip;
 }
 
@@ -8275,7 +8277,7 @@ static bool PreCallValidateCmdDispatchIndirect(
     bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state,
                                     active_set_bindings_pairs, active_bindings, caller, VALIDATION_ERROR_01569);
     *buffer_state = getBufferState(dev_data, buffer);
-    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller);
+    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02547);
     return skip;
 }
 
@@ -8321,8 +8323,8 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer
     auto src_buff_state = getBufferState(dev_data, srcBuffer);
     auto dst_buff_state = getBufferState(dev_data, dstBuffer);
     if (cb_node && src_buff_state && dst_buff_state) {
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_state, "vkCmdCopyBuffer()");
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyBuffer()");
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02531);
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02532);
         // Update bindings between buffers and cmd buffer
         AddCommandBufferBindingBuffer(dev_data, cb_node, src_buff_state);
         AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
@@ -8701,8 +8703,8 @@ CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcI
     auto src_image_state = getImageState(dev_data, srcImage);
     auto dst_image_state = getImageState(dev_data, dstImage);
     if (cb_node && src_image_state && dst_image_state) {
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdCopyImage()");
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdCopyImage()");
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02533);
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02534);
         // Update bindings between images and cmd buffer
         AddCommandBufferBindingImage(dev_data, cb_node, src_image_state);
         AddCommandBufferBindingImage(dev_data, cb_node, dst_image_state);
@@ -8766,8 +8768,8 @@ CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcI
     if (cb_node && src_image_state && dst_image_state) {
         skip_call |= ValidateImageSampleCount(dev_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): srcImage");
         skip_call |= ValidateImageSampleCount(dev_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): dstImage");
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdBlitImage()");
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdBlitImage()");
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02539);
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02540);
         // Update bindings between images and cmd buffer
         AddCommandBufferBindingImage(dev_data, cb_node, src_image_state);
         AddCommandBufferBindingImage(dev_data, cb_node, dst_image_state);
@@ -8811,8 +8813,8 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, V
     if (cb_node && src_buff_state && dst_image_state) {
         skip_call |=
             ValidateImageSampleCount(dev_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyBufferToImage(): dstImage");
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_state, "vkCmdCopyBufferToImage()");
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdCopyBufferToImage()");
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02535);
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02536);
         AddCommandBufferBindingBuffer(dev_data, cb_node, src_buff_state);
         AddCommandBufferBindingImage(dev_data, cb_node, dst_image_state);
         skip_call |=
@@ -8857,8 +8859,8 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, V
     if (cb_node && src_image_state && dst_buff_state) {
         skip_call |=
             ValidateImageSampleCount(dev_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyImageToBuffer(): srcImage");
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdCopyImageToBuffer()");
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyImageToBuffer()");
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02537);
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02538);
         // Update bindings between buffer/image and cmd buffer
         AddCommandBufferBindingImage(dev_data, cb_node, src_image_state);
         AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
@@ -8903,7 +8905,7 @@ VKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuff
     auto cb_node = getCBNode(dev_data, commandBuffer);
     auto dst_buff_state = getBufferState(dev_data, dstBuffer);
     if (cb_node && dst_buff_state) {
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdUpdateBuffer()");
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_02530);
         // Update bindings between buffer and cmd buffer
         AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
         // Validate that DST buffer has correct usage flags set
@@ -8935,7 +8937,7 @@ CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize ds
     auto cb_node = getCBNode(dev_data, commandBuffer);
     auto dst_buff_state = getBufferState(dev_data, dstBuffer);
     if (cb_node && dst_buff_state) {
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdFillBuffer()");
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdFillBuffer()", VALIDATION_ERROR_02529);
         // Update bindings between buffer and cmd buffer
         AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
         // Validate that DST buffer has correct usage flags set
@@ -9060,7 +9062,7 @@ VKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkI
     auto cb_node = getCBNode(dev_data, commandBuffer);
     auto image_state = getImageState(dev_data, image);
     if (cb_node && image_state) {
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()");
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_02527);
         AddCommandBufferBindingImage(dev_data, cb_node, image_state);
         std::function<bool()> function = [=]() {
             SetImageMemoryValid(dev_data, image_state, true);
@@ -9094,7 +9096,7 @@ CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageL
     auto cb_node = getCBNode(dev_data, commandBuffer);
     auto image_state = getImageState(dev_data, image);
     if (cb_node && image_state) {
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearDepthStencilImage()");
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_02528);
         AddCommandBufferBindingImage(dev_data, cb_node, image_state);
         std::function<bool()> function = [=]() {
             SetImageMemoryValid(dev_data, image_state, true);
@@ -9127,8 +9129,8 @@ CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout s
     auto src_image_state = getImageState(dev_data, srcImage);
     auto dst_image_state = getImageState(dev_data, dstImage);
     if (cb_node && src_image_state && dst_image_state) {
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdResolveImage()");
-        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdResolveImage()");
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02541);
+        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02542);
         // Update bindings between images and cmd buffer
         AddCommandBufferBindingImage(dev_data, cb_node, src_image_state);
         AddCommandBufferBindingImage(dev_data, cb_node, dst_image_state);
@@ -9876,7 +9878,7 @@ CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, ui
     auto cb_node = getCBNode(dev_data, commandBuffer);
     auto dst_buff_state = getBufferState(dev_data, dstBuffer);
     if (cb_node && dst_buff_state) {
-        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()");
+        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_02526);
         // Update bindings between buffer and cmd buffer
         AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
         // Validate that DST buffer has correct usage flags set
index 43d0212..5417a0a 100644 (file)
@@ -654,8 +654,8 @@ IMAGE_VIEW_STATE *getImageViewState(const layer_data *, VkImageView);
 VkSwapchainKHR getSwapchainFromImage(const layer_data *, VkImage);
 SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, VkSwapchainKHR);
 void invalidateCommandBuffers(const layer_data *, std::unordered_set<GLOBAL_CB_NODE *> const &, VK_OBJECT);
-bool ValidateMemoryIsBoundToBuffer(const layer_data *, const BUFFER_STATE *, const char *);
-bool ValidateMemoryIsBoundToImage(const layer_data *, const IMAGE_STATE *, const char *);
+bool ValidateMemoryIsBoundToBuffer(const layer_data *, const BUFFER_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE);
+bool ValidateMemoryIsBoundToImage(const layer_data *, const IMAGE_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE);
 void AddCommandBufferBindingSampler(GLOBAL_CB_NODE *, SAMPLER_STATE *);
 void AddCommandBufferBindingImage(const layer_data *, GLOBAL_CB_NODE *, IMAGE_STATE *);
 void AddCommandBufferBindingImageView(const layer_data *, GLOBAL_CB_NODE *, IMAGE_VIEW_STATE *);
index ba5c481..7f14801 100644 (file)
@@ -762,7 +762,7 @@ bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout
         format = image_node->createInfo.format;
         usage = image_node->createInfo.usage;
         // Validate that memory is bound to image
-        if (ValidateMemoryIsBoundToImage(dev_data, image_node, "vkUpdateDescriptorSets()")) {
+        if (ValidateMemoryIsBoundToImage(dev_data, image_node, "vkUpdateDescriptorSets()", VALIDATION_ERROR_02524)) {
             *error_code = VALIDATION_ERROR_02524;
             *error_msg = "No memory bound to image.";
             return false;
@@ -1297,7 +1297,7 @@ bool cvdescriptorset::DescriptorSet::ValidateBufferUpdate(VkDescriptorBufferInfo
         *error_msg = error_str.str();
         return false;
     }
-    if (ValidateMemoryIsBoundToBuffer(device_data_, buffer_node, "vkUpdateDescriptorSets()")) {
+    if (ValidateMemoryIsBoundToBuffer(device_data_, buffer_node, "vkUpdateDescriptorSets()", VALIDATION_ERROR_02525)) {
         *error_code = VALIDATION_ERROR_02525;
         *error_msg = "No memory bound to buffer.";
         return false;
index 2b08a41..7e1e840 100644 (file)
@@ -2451,32 +2451,32 @@ VALIDATION_ERROR_02518~^~U~^~Unknown~^~vkCreateRenderPass~^~For more information
 VALIDATION_ERROR_02519~^~U~^~Unknown~^~vkCreateRenderPass~^~For more information refer to Vulkan Spec Section '7.1. Render Pass Creation' which states 'Any access flag included in dstAccessMask must be supported by one of the pipeline stages in dstStageMask, as specified in the table of supported access types.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkSubpassDependency)~^~
 VALIDATION_ERROR_02520~^~U~^~Unknown~^~vkCmdBeginRenderPass~^~For more information refer to Vulkan Spec Section '7.4. Render Pass Commands' which states 'The srcStageMask and dstStageMask members of any element of the pDependencies member of VkRenderPassCreateInfo used to create renderpass must be supported by the capabilities of the queue family identified by the queueFamilyIndex member of the VkCommandPoolCreateInfo used to create the command pool which commandBuffer was allocated from.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkSubpassContents)~^~
 VALIDATION_ERROR_02521~^~U~^~Unknown~^~vkCreatePipelineLayout~^~For more information refer to Vulkan Spec Section '13.2.2. Pipeline Layouts' which states 'offset must be a multiple of 4' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkPushConstantRange)~^~
-VALIDATION_ERROR_02522~^~U~^~Unknown~^~vkCreateBufferView~^~For more information refer to Vulkan Spec Section '11.2. Buffer Views' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferViewCreateInfo)~^~
+VALIDATION_ERROR_02522~^~Y~^~Unknown~^~vkCreateBufferView~^~For more information refer to Vulkan Spec Section '11.2. Buffer Views' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkBufferViewCreateInfo)~^~
 VALIDATION_ERROR_02523~^~U~^~Unknown~^~vkCreateImage~^~For more information refer to Vulkan Spec Section '11.3. Images' which states 'The combination of format, type, tiling, usage, and flags must be supported, as indicated by a VK_SUCCESS return value from vkGetPhysicalDeviceImageFormatProperties invoked with the same values passed to the corresponding parameters.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageCreateInfo)~^~
 VALIDATION_ERROR_02524~^~Y~^~Unknown~^~vkCreateImageView~^~For more information refer to Vulkan Spec Section '11.5. Image Views' which states 'If image is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#resources-image-views-compatibility)~^~
 VALIDATION_ERROR_02525~^~Y~^~Unknown~^~vkUpdateDescriptorSets~^~For more information refer to Vulkan Spec Section '13.2.4. Descriptor Set Updates' which states 'If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, the buffer member of any given element of pBufferInfo that is non-sparse must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#descriptorsets-updates-consecutive)~^~
-VALIDATION_ERROR_02526~^~U~^~Unknown~^~vkCmdCopyQueryPoolResults~^~For more information refer to Vulkan Spec Section '16.2. Query Operation' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyQueryPoolResults)~^~
-VALIDATION_ERROR_02527~^~U~^~Unknown~^~vkCmdClearColorImage~^~For more information refer to Vulkan Spec Section '17.1. Clearing Images Outside A Render Pass Instance' which states 'If image is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdClearColorImage)~^~
-VALIDATION_ERROR_02528~^~U~^~Unknown~^~vkCmdClearDepthStencilImage~^~For more information refer to Vulkan Spec Section '17.1. Clearing Images Outside A Render Pass Instance' which states 'If image is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdClearDepthStencilImage)~^~
-VALIDATION_ERROR_02529~^~U~^~Unknown~^~vkCmdFillBuffer~^~For more information refer to Vulkan Spec Section '17.4. Filling Buffers' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdFillBuffer)~^~
-VALIDATION_ERROR_02530~^~U~^~Unknown~^~vkCmdUpdateBuffer~^~For more information refer to Vulkan Spec Section '17.5. Updating Buffers' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdUpdateBuffer)~^~
-VALIDATION_ERROR_02531~^~U~^~Unknown~^~vkCmdCopyBuffer~^~For more information refer to Vulkan Spec Section '18.2. Copying Data Between Buffers' which states 'If srcBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBuffer)~^~
-VALIDATION_ERROR_02532~^~U~^~Unknown~^~vkCmdCopyBuffer~^~For more information refer to Vulkan Spec Section '18.2. Copying Data Between Buffers' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBuffer)~^~
-VALIDATION_ERROR_02533~^~U~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#copies-images-format-compatibility)~^~
-VALIDATION_ERROR_02534~^~U~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#copies-images-format-compatibility)~^~
-VALIDATION_ERROR_02535~^~U~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If srcBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
-VALIDATION_ERROR_02536~^~U~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
-VALIDATION_ERROR_02537~^~U~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
-VALIDATION_ERROR_02538~^~U~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
-VALIDATION_ERROR_02539~^~U~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBlitImage)~^~
-VALIDATION_ERROR_02540~^~U~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBlitImage)~^~
-VALIDATION_ERROR_02541~^~U~^~Unknown~^~vkCmdResolveImage~^~For more information refer to Vulkan Spec Section '18.6. Resolving Multisample Images' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdResolveImage)~^~
-VALIDATION_ERROR_02542~^~U~^~Unknown~^~vkCmdResolveImage~^~For more information refer to Vulkan Spec Section '18.6. Resolving Multisample Images' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdResolveImage)~^~
-VALIDATION_ERROR_02543~^~U~^~Unknown~^~vkCmdBindIndexBuffer~^~For more information refer to Vulkan Spec Section '19.2. Programmable Primitive Shading' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkIndexType)~^~
-VALIDATION_ERROR_02544~^~U~^~Unknown~^~vkCmdDrawIndirect~^~For more information refer to Vulkan Spec Section '19.2. Programmable Primitive Shading' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdDrawIndirect)~^~
-VALIDATION_ERROR_02545~^~U~^~Unknown~^~vkCmdDrawIndexedIndirect~^~For more information refer to Vulkan Spec Section '19.2. Programmable Primitive Shading' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdDrawIndexedIndirect)~^~
-VALIDATION_ERROR_02546~^~U~^~Unknown~^~vkCmdBindVertexBuffers~^~For more information refer to Vulkan Spec Section '20.2. Vertex Input Description' which states 'Each element of pBuffers that is non-sparse must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBindVertexBuffers)~^~
-VALIDATION_ERROR_02547~^~U~^~Unknown~^~vkCmdDispatchIndirect~^~For more information refer to Vulkan Spec Section '26.2. Logical Operations' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdDispatchIndirect)~^~
+VALIDATION_ERROR_02526~^~Y~^~Unknown~^~vkCmdCopyQueryPoolResults~^~For more information refer to Vulkan Spec Section '16.2. Query Operation' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyQueryPoolResults)~^~
+VALIDATION_ERROR_02527~^~Y~^~Unknown~^~vkCmdClearColorImage~^~For more information refer to Vulkan Spec Section '17.1. Clearing Images Outside A Render Pass Instance' which states 'If image is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdClearColorImage)~^~
+VALIDATION_ERROR_02528~^~Y~^~Unknown~^~vkCmdClearDepthStencilImage~^~For more information refer to Vulkan Spec Section '17.1. Clearing Images Outside A Render Pass Instance' which states 'If image is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdClearDepthStencilImage)~^~
+VALIDATION_ERROR_02529~^~Y~^~Unknown~^~vkCmdFillBuffer~^~For more information refer to Vulkan Spec Section '17.4. Filling Buffers' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdFillBuffer)~^~
+VALIDATION_ERROR_02530~^~Y~^~Unknown~^~vkCmdUpdateBuffer~^~For more information refer to Vulkan Spec Section '17.5. Updating Buffers' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdUpdateBuffer)~^~
+VALIDATION_ERROR_02531~^~Y~^~Unknown~^~vkCmdCopyBuffer~^~For more information refer to Vulkan Spec Section '18.2. Copying Data Between Buffers' which states 'If srcBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBuffer)~^~
+VALIDATION_ERROR_02532~^~Y~^~Unknown~^~vkCmdCopyBuffer~^~For more information refer to Vulkan Spec Section '18.2. Copying Data Between Buffers' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBuffer)~^~
+VALIDATION_ERROR_02533~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#copies-images-format-compatibility)~^~
+VALIDATION_ERROR_02534~^~Y~^~Unknown~^~vkCmdCopyImage~^~For more information refer to Vulkan Spec Section '18.3. Copying Data Between Images' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#copies-images-format-compatibility)~^~
+VALIDATION_ERROR_02535~^~Y~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If srcBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
+VALIDATION_ERROR_02536~^~Y~^~Unknown~^~vkCmdCopyBufferToImage~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyBufferToImage)~^~
+VALIDATION_ERROR_02537~^~Y~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
+VALIDATION_ERROR_02538~^~Y~^~Unknown~^~vkCmdCopyImageToBuffer~^~For more information refer to Vulkan Spec Section '18.4. Copying Data Between Buffers and Images' which states 'If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdCopyImageToBuffer)~^~
+VALIDATION_ERROR_02539~^~Y~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBlitImage)~^~
+VALIDATION_ERROR_02540~^~Y~^~Unknown~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBlitImage)~^~
+VALIDATION_ERROR_02541~^~Y~^~Unknown~^~vkCmdResolveImage~^~For more information refer to Vulkan Spec Section '18.6. Resolving Multisample Images' which states 'If srcImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdResolveImage)~^~
+VALIDATION_ERROR_02542~^~Y~^~Unknown~^~vkCmdResolveImage~^~For more information refer to Vulkan Spec Section '18.6. Resolving Multisample Images' which states 'If dstImage is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdResolveImage)~^~
+VALIDATION_ERROR_02543~^~Y~^~Unknown~^~vkCmdBindIndexBuffer~^~For more information refer to Vulkan Spec Section '19.2. Programmable Primitive Shading' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkIndexType)~^~
+VALIDATION_ERROR_02544~^~Y~^~Unknown~^~vkCmdDrawIndirect~^~For more information refer to Vulkan Spec Section '19.2. Programmable Primitive Shading' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdDrawIndirect)~^~
+VALIDATION_ERROR_02545~^~Y~^~Unknown~^~vkCmdDrawIndexedIndirect~^~For more information refer to Vulkan Spec Section '19.2. Programmable Primitive Shading' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdDrawIndexedIndirect)~^~
+VALIDATION_ERROR_02546~^~Y~^~Unknown~^~vkCmdBindVertexBuffers~^~For more information refer to Vulkan Spec Section '20.2. Vertex Input Description' which states 'Each element of pBuffers that is non-sparse must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBindVertexBuffers)~^~
+VALIDATION_ERROR_02547~^~Y~^~Unknown~^~vkCmdDispatchIndirect~^~For more information refer to Vulkan Spec Section '26.2. Logical Operations' which states 'If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdDispatchIndirect)~^~
 VALIDATION_ERROR_02548~^~U~^~Unknown~^~vkCmdProcessCommandsNVX~^~For more information refer to Vulkan Spec Section '28.4. Indirect Commands Generation' which states 'indirectCommandsTokenCount must be greater than 0' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkCmdProcessCommandsInfoNVX)~^~
 VALIDATION_ERROR_02549~^~U~^~Unknown~^~vkQueueSubmit~^~For more information refer to Vulkan Spec Section '5.4. Command Buffer Submission' which states 'All elements of the pWaitSemaphores member of all elements of pSubmits must be semaphores that are signaled, or have semaphore signal operations previously submitted for execution.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkQueueSubmit)~^~
 VALIDATION_ERROR_02550~^~U~^~Unknown~^~vkQueueSubmit~^~For more information refer to Vulkan Spec Section '5.4. Command Buffer Submission' which states 'Any given element of pWaitDstStageMask must not include VK_PIPELINE_STAGE_HOST_BIT.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkSubmitInfo)~^~