Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / vulkan / util / vk_object.c
index 77258ab6879564ab130041edcc0258dc314ce58f..7fed00e42c76d44c5e49a3d6f748dcbc00387ac2 100644 (file)
 
 #include "vk_object.h"
 
+#include "vk_alloc.h"
+#include "util/hash_table.h"
+#include "util/ralloc.h"
+
+void
+vk_object_base_init(UNUSED struct vk_device *device,
+                    struct vk_object_base *base,
+                    UNUSED VkObjectType obj_type)
+{
+   base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
+   base->type = obj_type;
+   util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);
+}
+
+void
+vk_object_base_finish(struct vk_object_base *base)
+{
+   util_sparse_array_finish(&base->private_data);
+}
+
 void
 vk_device_init(struct vk_device *device,
                UNUSED const VkDeviceCreateInfo *pCreateInfo,
                const VkAllocationCallbacks *instance_alloc,
                const VkAllocationCallbacks *device_alloc)
 {
-   device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
+   vk_object_base_init(device, &device->base, VK_OBJECT_TYPE_DEVICE);
    if (device_alloc)
       device->alloc = *device_alloc;
    else
       device->alloc = *instance_alloc;
+
+   p_atomic_set(&device->private_data_next_index, 0);
+
+#ifdef ANDROID
+   mtx_init(&device->swapchain_private_mtx, mtx_plain);
+   device->swapchain_private = NULL;
+#endif /* ANDROID */
 }
 
 void
 vk_device_finish(UNUSED struct vk_device *device)
 {
+#ifdef ANDROID
+   if (device->swapchain_private) {
+      hash_table_foreach(device->swapchain_private, entry)
+         util_sparse_array_finish(entry->data);
+      ralloc_free(device->swapchain_private);
+   }
+#endif /* ANDROID */
+
+   vk_object_base_finish(&device->base);
+}
+
+void *
+vk_object_alloc(struct vk_device *device,
+                const VkAllocationCallbacks *alloc,
+                size_t size,
+                VkObjectType obj_type)
+{
+   void *ptr = vk_alloc2(&device->alloc, alloc, size, 8,
+                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (ptr == NULL)
+      return NULL;
+
+   vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
+
+   return ptr;
+}
+
+void *
+vk_object_zalloc(struct vk_device *device,
+                const VkAllocationCallbacks *alloc,
+                size_t size,
+                VkObjectType obj_type)
+{
+   void *ptr = vk_zalloc2(&device->alloc, alloc, size, 8,
+                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (ptr == NULL)
+      return NULL;
+
+   vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
+
+   return ptr;
+}
+
+void
+vk_object_free(struct vk_device *device,
+               const VkAllocationCallbacks *alloc,
+               void *data)
+{
+   vk_object_base_finish((struct vk_object_base *)data);
+   vk_free2(&device->alloc, alloc, data);
+}
+
+VkResult
+vk_private_data_slot_create(struct vk_device *device,
+                            const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
+                            const VkAllocationCallbacks* pAllocator,
+                            VkPrivateDataSlotEXT* pPrivateDataSlot)
+{
+   struct vk_private_data_slot *slot =
+      vk_alloc2(&device->alloc, pAllocator, sizeof(*slot), 8,
+                VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+   if (slot == NULL)
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+   vk_object_base_init(device, &slot->base,
+                       VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT);
+   slot->index = p_atomic_inc_return(&device->private_data_next_index);
+
+   *pPrivateDataSlot = vk_private_data_slot_to_handle(slot);
+
+   return VK_SUCCESS;
+}
+
+void
+vk_private_data_slot_destroy(struct vk_device *device,
+                             VkPrivateDataSlotEXT privateDataSlot,
+                             const VkAllocationCallbacks *pAllocator)
+{
+   VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
+   if (slot == NULL)
+      return;
+
+   vk_object_base_finish(&slot->base);
+   vk_free2(&device->alloc, pAllocator, slot);
+}
+
+#ifdef ANDROID
+static VkResult
+get_swapchain_private_data_locked(struct vk_device *device,
+                                  uint64_t objectHandle,
+                                  struct vk_private_data_slot *slot,
+                                  uint64_t **private_data)
+{
+   if (unlikely(device->swapchain_private == NULL)) {
+      /* Even though VkSwapchain is a non-dispatchable object, we know a
+       * priori that Android swapchains are actually pointers so we can use
+       * the pointer hash table for them.
+       */
+      device->swapchain_private = _mesa_pointer_hash_table_create(NULL);
+      if (device->swapchain_private == NULL)
+         return VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
+
+   struct hash_entry *entry =
+      _mesa_hash_table_search(device->swapchain_private,
+                              (void *)(uintptr_t)objectHandle);
+   if (unlikely(entry == NULL)) {
+      struct util_sparse_array *swapchain_private =
+         ralloc(device->swapchain_private, struct util_sparse_array);
+      util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8);
+
+      entry = _mesa_hash_table_insert(device->swapchain_private,
+                                      (void *)(uintptr_t)objectHandle,
+                                      swapchain_private);
+      if (entry == NULL)
+         return VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
+
+   struct util_sparse_array *swapchain_private = entry->data;
+   *private_data = util_sparse_array_get(swapchain_private, slot->index);
+
+   return VK_SUCCESS;
+}
+#endif /* ANDROID */
+
+static VkResult
+vk_object_base_private_data(struct vk_device *device,
+                            VkObjectType objectType,
+                            uint64_t objectHandle,
+                            VkPrivateDataSlotEXT privateDataSlot,
+                            uint64_t **private_data)
+{
+   VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
+
+#ifdef ANDROID
+   /* There is an annoying spec corner here on Android.  Because WSI is
+    * implemented in the Vulkan loader which doesn't know about the
+    * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
+    * driver as a special case.  On future versions of Android where the
+    * loader does understand VK_EXT_private_data, we'll never see a
+    * vkGet/SetPrivateDataEXT call on a swapchain because the loader will
+    * handle it.
+    */
+   if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {
+      mtx_lock(&device->swapchain_private_mtx);
+      VkResult result = get_swapchain_private_data_locked(device, objectHandle,
+                                                          slot, private_data);
+      mtx_unlock(&device->swapchain_private_mtx);
+      return result;
+   }
+#endif /* ANDROID */
+
+   struct vk_object_base *obj =
+      vk_object_base_from_u64_handle(objectHandle, objectType);
+   *private_data = util_sparse_array_get(&obj->private_data, slot->index);
+
+   return VK_SUCCESS;
+}
+
+VkResult
+vk_object_base_set_private_data(struct vk_device *device,
+                                VkObjectType objectType,
+                                uint64_t objectHandle,
+                                VkPrivateDataSlotEXT privateDataSlot,
+                                uint64_t data)
+{
+   uint64_t *private_data;
+   VkResult result = vk_object_base_private_data(device,
+                                                 objectType, objectHandle,
+                                                 privateDataSlot,
+                                                 &private_data);
+   if (unlikely(result != VK_SUCCESS))
+      return result;
+
+   *private_data = data;
+   return VK_SUCCESS;
+}
+
+void
+vk_object_base_get_private_data(struct vk_device *device,
+                                VkObjectType objectType,
+                                uint64_t objectHandle,
+                                VkPrivateDataSlotEXT privateDataSlot,
+                                uint64_t *pData)
+{
+   uint64_t *private_data;
+   VkResult result = vk_object_base_private_data(device,
+                                                 objectType, objectHandle,
+                                                 privateDataSlot,
+                                                 &private_data);
+   if (likely(result == VK_SUCCESS)) {
+      *pData = *private_data;
+   } else {
+      *pData = 0;
+   }
 }