layers: Add VU checks for dedicated buffers/images
authorJohn Zulauf <jzulauf@lunarg.com>
Fri, 2 Mar 2018 16:13:09 +0000 (09:13 -0700)
committerjzulauf-lunarg <32470354+jzulauf-lunarg@users.noreply.github.com>
Mon, 5 Mar 2018 18:48:31 +0000 (11:48 -0700)
Add validation for the following valid usage for binding dedicated
allocations to buffers and images.

VALIDATION_ERROR_17000bc8    VUID-vkBindBufferMemory-memory-01508
VALIDATION_ERROR_17400bca    VUID-vkBindImageMemory-memory-01509

The same code path checks the BindImage2/BufferMemory2, but there are no
matching VUID at this time.

Change-Id: I8b700059d8c0acdfabf0b30be3dca20f616b3be1

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

index 74eae32..8f51546 100644 (file)
@@ -353,18 +353,20 @@ static void add_mem_obj_info(layer_data *dev_data, void *object, const VkDeviceM
                              const VkMemoryAllocateInfo *pAllocateInfo) {
     assert(object != NULL);
 
-    dev_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo));
-
-    if (pAllocateInfo->pNext) {
-        auto struct_header = reinterpret_cast<const GENERIC_HEADER *>(pAllocateInfo->pNext);
-        while (struct_header) {
-            if (VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR == struct_header->sType ||
-                VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR == struct_header->sType) {
-                dev_data->memObjMap[mem]->global_valid = true;
-                break;
-            }
-            struct_header = reinterpret_cast<const GENERIC_HEADER *>(struct_header->pNext);
-        }
+    auto *mem_info = new DEVICE_MEM_INFO(object, mem, pAllocateInfo);
+    dev_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(mem_info);
+
+    // TODO: If the number of things we search for goes much higher, need a map...
+    mem_info->global_valid = nullptr != lvl_find_in_chain<VkImportMemoryFdInfoKHR>(pAllocateInfo->pNext);
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+    mem_info->global_valid |= nullptr != lvl_find_in_chain<VkImportMemoryWin32HandleInfoKHR>(pAllocateInfo->pNext);
+#endif
+
+    auto dedicated = lvl_find_in_chain<VkMemoryDedicatedAllocateInfoKHR>(pAllocateInfo->pNext);
+    if (dedicated) {
+        mem_info->is_dedicated = true;
+        mem_info->dedicated_buffer = dedicated->buffer;
+        mem_info->dedicated_image = dedicated->image;
     }
 }
 
@@ -3825,7 +3827,7 @@ static bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffe
         }
 
         // Validate bound memory range information
-        auto mem_info = GetMemObjInfo(dev_data, mem);
+        const auto mem_info = GetMemObjInfo(dev_data, mem);
         if (mem_info) {
             skip |= ValidateInsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements, api_name);
             skip |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, api_name,
@@ -3843,8 +3845,8 @@ static bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffe
                             validation_error_map[VALIDATION_ERROR_17000818]);
         }
 
-        // Validate memory requirements size
         if (mem_info) {
+            // Validate memory requirements size
             if (buffer_state->requirements.size > (mem_info->alloc_info.allocationSize - memoryOffset)) {
                 skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
                                 buffer_handle, __LINE__, VALIDATION_ERROR_1700081a, "DS",
@@ -3854,6 +3856,24 @@ static bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffe
                                 api_name, mem_info->alloc_info.allocationSize - memoryOffset, buffer_state->requirements.size,
                                 validation_error_map[VALIDATION_ERROR_1700081a]);
             }
+
+            // Validate dedicated allocation
+            if (mem_info->is_dedicated && ((mem_info->dedicated_buffer != buffer) || (memoryOffset != 0))) {
+                // TODO: Add vkBindBufferMemory2KHR error message when added to spec.
+                auto validation_error = VALIDATION_ERROR_UNDEFINED;
+                const char *validation_error_msg = "";
+                if (strcmp(api_name, "vkBindBufferMemory()") == 0) {
+                    validation_error = VALIDATION_ERROR_17000bc8;
+                    validation_error_msg = validation_error_map[validation_error];
+                }
+                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
+                                buffer_handle, __LINE__, validation_error, "DS",
+                                "%s: for dedicated memory allocation 0x%" PRIxLEAST64
+                                ", VkMemoryDedicatedAllocateInfoKHR::buffer 0x%" PRIXLEAST64
+                                " must be equal to buffer 0x%" PRIxLEAST64 " and memoryOffset 0x%" PRIxLEAST64 " must be zero. %s",
+                                api_name, HandleToUint64(mem), HandleToUint64(mem_info->dedicated_buffer), buffer_handle,
+                                memoryOffset, validation_error_msg);
+            }
         }
 
         // Validate device limits alignments
@@ -9513,8 +9533,8 @@ static bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image,
                             validation_error_map[VALIDATION_ERROR_17400830]);
         }
 
-        // Validate memory requirements size
         if (mem_info) {
+            // Validate memory requirements size
             if (image_state->requirements.size > mem_info->alloc_info.allocationSize - memoryOffset) {
                 skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
                                 image_handle, __LINE__, VALIDATION_ERROR_17400832, "DS",
@@ -9524,6 +9544,24 @@ static bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image,
                                 api_name, mem_info->alloc_info.allocationSize - memoryOffset, image_state->requirements.size,
                                 validation_error_map[VALIDATION_ERROR_17400832]);
             }
+
+            // Validate dedicated allocation
+            if (mem_info->is_dedicated && ((mem_info->dedicated_image != image) || (memoryOffset != 0))) {
+                // TODO: Add vkBindImageMemory2KHR error message when added to spec.
+                auto validation_error = VALIDATION_ERROR_UNDEFINED;
+                const char *validation_error_msg = "";
+                if (strcmp(api_name, "vkBindImageMemory()") == 0) {
+                    validation_error = VALIDATION_ERROR_17400bca;
+                    validation_error_msg = validation_error_map[validation_error];
+                }
+                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
+                                image_handle, __LINE__, validation_error, "DS",
+                                "%s: for dedicated memory allocation 0x%" PRIxLEAST64
+                                ", VkMemoryDedicatedAllocateInfoKHR::image 0x%" PRIXLEAST64
+                                " must be equal to image 0x%" PRIxLEAST64 " and memoryOffset 0x%" PRIxLEAST64 " must be zero. %s",
+                                api_name, HandleToUint64(mem), HandleToUint64(mem_info->dedicated_image), image_handle,
+                                memoryOffset, validation_error_msg);
+            }
         }
     }
     return skip;
index de1aeac..79330d5 100644 (file)
 // TODO : Is there a way to track when Cmd Buffer finishes & remove mem references at that point?
 // TODO : Could potentially store a list of freed mem allocs to flag when they're incorrectly used
 
-struct GENERIC_HEADER {
-    VkStructureType sType;
-    const void *pNext;
-};
-
 enum SyncScope {
     kSyncScopeInternal,
     kSyncScopeExternalTemporary,
index bc5a554..c7f0bea 100644 (file)
@@ -318,6 +318,9 @@ struct DEVICE_MEM_INFO : public BASE_NODE {
     bool global_valid;  // If allocation is mapped or external, set to "true" to be picked up by subsequently bound ranges
     VkDeviceMemory mem;
     VkMemoryAllocateInfo alloc_info;
+    bool is_dedicated;
+    VkBuffer dedicated_buffer;
+    VkImage dedicated_image;
     std::unordered_set<VK_OBJECT> obj_bindings;               // objects bound to this memory
     std::unordered_map<uint64_t, MEMORY_RANGE> bound_ranges;  // Map of object to its binding range
     // Convenience vectors image/buff handles to speed up iterating over images or buffers independently
@@ -336,6 +339,9 @@ struct DEVICE_MEM_INFO : public BASE_NODE {
           global_valid(false),
           mem(in_mem),
           alloc_info(*p_alloc_info),
+          is_dedicated(false),
+          dedicated_buffer(VK_NULL_HANDLE),
+          dedicated_image(VK_NULL_HANDLE),
           mem_range{},
           shadow_copy_base(0),
           shadow_copy(0),
index d71ef06..4e1a8e0 100644 (file)
@@ -1688,7 +1688,7 @@ VALIDATION_ERROR_1700081a~^~Y~^~BindInvalidMemory~^~vkBindBufferMemory~^~VUID-vk
 VALIDATION_ERROR_1700081c~^~N~^~Unknown~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-buffer-01038~^~(VK_NV_dedicated_allocation)~^~The spec valid usage text states 'If buffer was created with VkDedicatedAllocationBufferCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must have been created with VkDedicatedAllocationMemoryAllocateInfoNV::buffer equal to a buffer handle created with identical creation parameters to buffer and memoryOffset must be zero' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindBufferMemory-buffer-01038)~^~
 VALIDATION_ERROR_1700081e~^~N~^~Unknown~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-buffer-01039~^~(VK_NV_dedicated_allocation)+!(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If buffer was not created with VkDedicatedAllocationBufferCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must not have been allocated dedicated for a specific buffer or image' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkBindBufferMemory-buffer-01039)~^~
 VALIDATION_ERROR_17000b48~^~N~^~None~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-buffer-01444~^~(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If buffer requires a dedicated allocation(as reported by vkGetBufferMemoryRequirements2KHR in VkMemoryDedicatedRequirementsKHR::requiresDedicatedAllocation for image), memory must have been created with VkMemoryDedicatedAllocateInfoKHR::buffer equal to buffer' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindBufferMemory-buffer-01444)~^~
-VALIDATION_ERROR_17000bc8~^~N~^~None~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-memory-01508~^~(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If the VkmemoryAllocateInfo provided when memory was allocated included an instance of VkMemoryDedicatedAllocateInfoKHR in its pNext chain, and VkMemoryDedicatedAllocateInfoKHR::buffer was not VK_NULL_HANDLE, then buffer must equal VkMemoryDedicatedAllocateInfoKHR::buffer and memoryOffset must be zero.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindBufferMemory-memory-01508)~^~
+VALIDATION_ERROR_17000bc8~^~Y~^~None~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-memory-01508~^~(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If the VkmemoryAllocateInfo provided when memory was allocated included an instance of VkMemoryDedicatedAllocateInfoKHR in its pNext chain, and VkMemoryDedicatedAllocateInfoKHR::buffer was not VK_NULL_HANDLE, then buffer must equal VkMemoryDedicatedAllocateInfoKHR::buffer and memoryOffset must be zero.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindBufferMemory-memory-01508)~^~
 VALIDATION_ERROR_17001a01~^~Y~^~VertexBufferInvalid~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-buffer-parameter~^~core~^~The spec valid usage text states 'buffer must be a valid VkBuffer handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkBindBufferMemory-buffer-parameter)~^~implicit
 VALIDATION_ERROR_17001a07~^~Y~^~Unknown~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-buffer-parent~^~core~^~The spec valid usage text states 'buffer must have been created, allocated, or retrieved from device' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkBindBufferMemory-buffer-parent)~^~implicit
 VALIDATION_ERROR_17005601~^~Y~^~None~^~vkBindBufferMemory~^~VUID-vkBindBufferMemory-device-parameter~^~core~^~The spec valid usage text states 'device must be a valid VkDevice handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkBindBufferMemory-device-parameter)~^~implicit
@@ -1706,7 +1706,7 @@ VALIDATION_ERROR_17400832~^~Y~^~BindInvalidMemory~^~vkBindImageMemory~^~VUID-vkB
 VALIDATION_ERROR_17400834~^~N~^~Unknown~^~vkBindImageMemory~^~VUID-vkBindImageMemory-image-01050~^~(VK_NV_dedicated_allocation)~^~The spec valid usage text states 'If image was created with VkDedicatedAllocationImageCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must have been created with VkDedicatedAllocationMemoryAllocateInfoNV::image equal to an image handle created with identical creation parameters to image and memoryOffset must be zero' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindImageMemory-image-01050)~^~
 VALIDATION_ERROR_17400836~^~N~^~Unknown~^~vkBindImageMemory~^~VUID-vkBindImageMemory-image-01051~^~(VK_NV_dedicated_allocation)+!(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If image was not created with VkDedicatedAllocationImageCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must not have been allocated dedicated for a specific buffer or image' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkBindImageMemory-image-01051)~^~
 VALIDATION_ERROR_17400b4a~^~N~^~None~^~vkBindImageMemory~^~VUID-vkBindImageMemory-image-01445~^~(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If image requires a dedicated allocation (as reported by vkGetImageMemoryRequirements2KHR in VkMemoryDedicatedRequirementsKHR::requiresDedicatedAllocation for image), memory must have been created with VkMemoryDedicatedAllocateInfoKHR::image equal to image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindImageMemory-image-01445)~^~
-VALIDATION_ERROR_17400bca~^~N~^~None~^~vkBindImageMemory~^~VUID-vkBindImageMemory-memory-01509~^~(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If the VkmemoryAllocateInfo provided when memory was allocated included an instance of VkMemoryDedicatedAllocateInfoKHR in its pNext chain, and VkMemoryDedicatedAllocateInfoKHR::image was not VK_NULL_HANDLE, then image must equal VkMemoryDedicatedAllocateInfoKHR::image and memoryOffset must be zero.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindImageMemory-memory-01509)~^~
+VALIDATION_ERROR_17400bca~^~Y~^~None~^~vkBindImageMemory~^~VUID-vkBindImageMemory-memory-01509~^~(VK_KHR_dedicated_allocation)~^~The spec valid usage text states 'If the VkmemoryAllocateInfo provided when memory was allocated included an instance of VkMemoryDedicatedAllocateInfoKHR in its pNext chain, and VkMemoryDedicatedAllocateInfoKHR::image was not VK_NULL_HANDLE, then image must equal VkMemoryDedicatedAllocateInfoKHR::image and memoryOffset must be zero.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindImageMemory-memory-01509)~^~
 VALIDATION_ERROR_17400c90~^~N~^~None~^~vkBindImageMemory~^~VUID-vkBindImageMemory-image-01608~^~(VK_KHR_sampler_ycbcr_conversion)~^~The spec valid usage text states 'image must not have been created with the VK_IMAGE_CREATE_DISJOINT_BIT_KHR set.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkBindImageMemory-image-01608)~^~
 VALIDATION_ERROR_17405601~^~Y~^~None~^~vkBindImageMemory~^~VUID-vkBindImageMemory-device-parameter~^~core~^~The spec valid usage text states 'device must be a valid VkDevice handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkBindImageMemory-device-parameter)~^~implicit
 VALIDATION_ERROR_1740a001~^~Y~^~BindMemoryToDestroyedObject~^~vkBindImageMemory~^~VUID-vkBindImageMemory-image-parameter~^~core~^~The spec valid usage text states 'image must be a valid VkImage handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkBindImageMemory-image-parameter)~^~implicit