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@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4882>
This commit is contained in:
Jason Ekstrand 2020-05-08 02:06:26 -05:00 committed by Marge Bot
parent 51c6bc13ce
commit 3c87618d35
2 changed files with 107 additions and 9 deletions

View file

@ -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;
}
}

View file

@ -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,