layers: NV_dedicated_allocation support for unique_objects
authorDustin Graves <dustin@lunarg.com>
Thu, 14 Jul 2016 23:28:11 +0000 (17:28 -0600)
committerDustin Graves <dustin@lunarg.com>
Mon, 18 Jul 2016 19:09:19 +0000 (13:09 -0600)
Add ID substitution support for the
VkDedicatedAllocationMemoryAllocateInfoNV extension structure to the
unique_objects layer.  The current implementation is specific to the
case where the vkAllocateMemory pAllocateInfo parameter references
a single VkDedicatedAllocationMemoryAllocateInfoNV struct.

Issues-Addressed: GitHub #755
Change-Id: I33c3f00d32149044694ecafe808673e5d90107b4

layers/unique_objects.h
vk-layer-generate.py

index 18a07ac..962985e 100644 (file)
 #include "vk_loader_platform.h"
 #include "vulkan/vulkan.h"
 
+#include <cinttypes>
+#include <memory>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <cinttypes>
 
 #include <unordered_map>
 #include <vector>
@@ -71,6 +72,27 @@ static device_table_map unique_objects_device_table_map;
 static instance_table_map unique_objects_instance_table_map;
 static std::mutex global_lock; // Protect map accesses and unique_id increments
 
+struct GenericHeader {
+    VkStructureType sType;
+    void *pNext;
+};
+
+template <typename T> bool ContainsExtStruct(const T *target, VkStructureType ext_type) {
+    assert(target != nullptr);
+
+    const GenericHeader *ext_struct = reinterpret_cast<const GenericHeader *>(target->pNext);
+
+    while (ext_struct != nullptr) {
+        if (ext_struct->sType == ext_type) {
+            return true;
+        }
+
+        ext_struct = reinterpret_cast<const GenericHeader *>(ext_struct->pNext);
+    }
+
+    return false;
+}
+
 // Handle CreateInstance
 static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
     uint32_t i;
@@ -253,6 +275,68 @@ void explicit_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAlloc
     layer_data_map.erase(key);
 }
 
+VkResult explicit_AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
+                                 const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
+    const VkMemoryAllocateInfo *input_allocate_info = pAllocateInfo;
+    std::unique_ptr<safe_VkMemoryAllocateInfo> safe_allocate_info;
+    std::unique_ptr<safe_VkDedicatedAllocationMemoryAllocateInfoNV> safe_dedicated_allocate_info;
+    layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
+    if ((pAllocateInfo != nullptr) &&
+        ContainsExtStruct(pAllocateInfo, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV)) {
+        // Assuming there is only one extension struct of this type in the list for now
+        safe_dedicated_allocate_info =
+            std::unique_ptr<safe_VkDedicatedAllocationMemoryAllocateInfoNV>(new safe_VkDedicatedAllocationMemoryAllocateInfoNV);
+        safe_allocate_info = std::unique_ptr<safe_VkMemoryAllocateInfo>(new safe_VkMemoryAllocateInfo);
+
+        safe_allocate_info->initialize(pAllocateInfo);
+        input_allocate_info = reinterpret_cast<const VkMemoryAllocateInfo *>(safe_allocate_info.get());
+
+        const GenericHeader *orig_pnext = reinterpret_cast<const GenericHeader *>(pAllocateInfo->pNext);
+        GenericHeader *input_pnext = reinterpret_cast<GenericHeader *>(safe_allocate_info.get());
+        while (orig_pnext != nullptr) {
+            if (orig_pnext->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV) {
+                safe_dedicated_allocate_info->initialize(
+                    reinterpret_cast<const VkDedicatedAllocationMemoryAllocateInfoNV *>(orig_pnext));
+
+                std::unique_lock<std::mutex> lock(global_lock);
+
+                if (safe_dedicated_allocate_info->buffer != VK_NULL_HANDLE) {
+                    uint64_t local_buffer = reinterpret_cast<uint64_t &>(safe_dedicated_allocate_info->buffer);
+                    safe_dedicated_allocate_info->buffer =
+                        reinterpret_cast<VkBuffer &>(my_map_data->unique_id_mapping[local_buffer]);
+                }
+
+                if (safe_dedicated_allocate_info->image != VK_NULL_HANDLE) {
+                    uint64_t local_image = reinterpret_cast<uint64_t &>(safe_dedicated_allocate_info->image);
+                    safe_dedicated_allocate_info->image = reinterpret_cast<VkImage &>(my_map_data->unique_id_mapping[local_image]);
+                }
+
+                lock.unlock();
+
+                input_pnext->pNext = reinterpret_cast<GenericHeader *>(safe_dedicated_allocate_info.get());
+                input_pnext = reinterpret_cast<GenericHeader *>(input_pnext->pNext);
+            } else {
+                // TODO: generic handling of pNext copies
+            }
+
+            orig_pnext = reinterpret_cast<const GenericHeader *>(orig_pnext->pNext);
+        }
+    }
+
+    VkResult result = get_dispatch_table(unique_objects_device_table_map, device)
+                          ->AllocateMemory(device, input_allocate_info, pAllocator, pMemory);
+
+    if (VK_SUCCESS == result) {
+        std::lock_guard<std::mutex> lock(global_lock);
+        uint64_t unique_id = global_unique_id++;
+        my_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(*pMemory);
+        *pMemory = reinterpret_cast<VkDeviceMemory &>(unique_id);
+    }
+
+    return result;
+}
+
 VkResult explicit_CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
                                          const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
                                          VkPipeline *pPipelines) {
index 29b3281..bde7e34 100755 (executable)
@@ -1557,6 +1557,7 @@ class UniqueObjectsSubcommand(Subcommand):
                                              'DestroyInstance',
                                              'CreateDevice',
                                              'DestroyDevice',
+                                             'AllocateMemory',
                                              'CreateComputePipelines',
                                              'CreateGraphicsPipelines',
                                              'GetPhysicalDeviceDisplayPropertiesKHR',