Mesa (master): vulkan: Handle vkGet/SetPrivateDataEXT on Android swapchains

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue May 12 18:13:57 UTC 2020


Module: Mesa
Branch: master
Commit: 3c87618d357a4f75a4f47b2638c8f89939fd6c61
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3c87618d357a4f75a4f47b2638c8f89939fd6c61

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Fri May  8 02:06:26 2020 -0500

vulkan: Handle vkGet/SetPrivateDataEXT on Android swapchains

There is an annoying spec corner on Android.  Because VkSwapchain is
implemented in the Vulkan loader on Android which may not know about
this extension, we have to handle it as a special case inside the
driver.  We only have to do this on Android and only for VkSwapchainKHR.

Acked-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4882>

---

 src/vulkan/util/vk_object.c | 108 ++++++++++++++++++++++++++++++++++++++++----
 src/vulkan/util/vk_object.h |   8 ++++
 2 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/src/vulkan/util/vk_object.c b/src/vulkan/util/vk_object.c
index 789cf12b15c..25e42f397e3 100644
--- a/src/vulkan/util/vk_object.c
+++ b/src/vulkan/util/vk_object.c
@@ -24,6 +24,8 @@
 #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,
@@ -54,11 +56,24 @@ vk_device_init(struct vk_device *device,
       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);
 }
 
@@ -96,15 +111,77 @@ vk_private_data_slot_destroy(struct vk_device *device,
    vk_free2(&device->alloc, pAllocator, slot);
 }
 
-static uint64_t *
-vk_object_base_private_data(VkObjectType objectType,
+#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)
+                            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);
-   return util_sparse_array_get(&obj->private_data, slot->index);
+   *private_data = util_sparse_array_get(&obj->private_data, slot->index);
+
+   return VK_SUCCESS;
 }
 
 VkResult
@@ -114,8 +191,14 @@ vk_object_base_set_private_data(struct vk_device *device,
                                 VkPrivateDataSlotEXT privateDataSlot,
                                 uint64_t data)
 {
-   uint64_t *private_data =
-      vk_object_base_private_data(objectType, objectHandle, privateDataSlot);
+   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;
 }
@@ -127,7 +210,14 @@ vk_object_base_get_private_data(struct vk_device *device,
                                 VkPrivateDataSlotEXT privateDataSlot,
                                 uint64_t *pData)
 {
-   uint64_t *private_data =
-      vk_object_base_private_data(objectType, objectHandle, privateDataSlot);
-   *pData = *private_data;
+   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;
+   }
 }
diff --git a/src/vulkan/util/vk_object.h b/src/vulkan/util/vk_object.h
index 8ae539bd556..7550b6a422b 100644
--- a/src/vulkan/util/vk_object.h
+++ b/src/vulkan/util/vk_object.h
@@ -26,6 +26,7 @@
 #include <vulkan/vulkan.h>
 #include <vulkan/vk_icd.h>
 
+#include "c11/threads.h"
 #include "util/macros.h"
 #include "util/sparse_array.h"
 
@@ -33,6 +34,8 @@
 extern "C" {
 #endif
 
+struct hash_table;
+
 struct vk_device;
 
 struct vk_object_base {
@@ -70,6 +73,11 @@ struct vk_device {
 
    /* For VK_EXT_private_data */
    uint32_t private_data_next_index;
+
+#ifdef ANDROID
+   mtx_t swapchain_private_mtx;
+   struct hash_table *swapchain_private;
+#endif
 };
 
 void vk_device_init(struct vk_device *device,



More information about the mesa-commit mailing list