Path: blob/21.2-virgl/src/vulkan/util/vk_object.c
7130 views
/*1* Copyright © 2020 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "vk_object.h"2425#include "vk_alloc.h"26#include "vk_common_entrypoints.h"27#include "vk_device.h"28#include "util/hash_table.h"29#include "util/ralloc.h"3031static void32vk_object_base_reinit(struct vk_object_base *base)33{34base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;35util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);36}3738void39vk_object_base_init(struct vk_device *device,40struct vk_object_base *base,41UNUSED VkObjectType obj_type)42{43vk_object_base_reinit(base);44base->type = obj_type;45base->device = device;46}4748void49vk_object_base_finish(struct vk_object_base *base)50{51util_sparse_array_finish(&base->private_data);52}5354void55vk_object_base_reset(struct vk_object_base *base)56{57vk_object_base_finish(base);58vk_object_base_reinit(base);59}6061void *62vk_object_alloc(struct vk_device *device,63const VkAllocationCallbacks *alloc,64size_t size,65VkObjectType obj_type)66{67void *ptr = vk_alloc2(&device->alloc, alloc, size, 8,68VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);69if (ptr == NULL)70return NULL;7172vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);7374return ptr;75}7677void *78vk_object_zalloc(struct vk_device *device,79const VkAllocationCallbacks *alloc,80size_t size,81VkObjectType obj_type)82{83void *ptr = vk_zalloc2(&device->alloc, alloc, size, 8,84VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);85if (ptr == NULL)86return NULL;8788vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);8990return ptr;91}9293void *94vk_object_multialloc(struct vk_device *device,95struct vk_multialloc *ma,96const VkAllocationCallbacks *alloc,97VkObjectType obj_type)98{99void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,100VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);101if (ptr == NULL)102return NULL;103104vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);105106return ptr;107}108109void *110vk_object_multizalloc(struct vk_device *device,111struct vk_multialloc *ma,112const VkAllocationCallbacks *alloc,113VkObjectType obj_type)114{115void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,116VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);117if (ptr == NULL)118return NULL;119120memset(ptr, 0, ma->size);121vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);122123return ptr;124}125126void127vk_object_free(struct vk_device *device,128const VkAllocationCallbacks *alloc,129void *data)130{131vk_object_base_finish((struct vk_object_base *)data);132vk_free2(&device->alloc, alloc, data);133}134135VkResult136vk_private_data_slot_create(struct vk_device *device,137const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,138const VkAllocationCallbacks* pAllocator,139VkPrivateDataSlotEXT* pPrivateDataSlot)140{141struct vk_private_data_slot *slot =142vk_alloc2(&device->alloc, pAllocator, sizeof(*slot), 8,143VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);144if (slot == NULL)145return VK_ERROR_OUT_OF_HOST_MEMORY;146147vk_object_base_init(device, &slot->base,148VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT);149slot->index = p_atomic_inc_return(&device->private_data_next_index);150151*pPrivateDataSlot = vk_private_data_slot_to_handle(slot);152153return VK_SUCCESS;154}155156void157vk_private_data_slot_destroy(struct vk_device *device,158VkPrivateDataSlotEXT privateDataSlot,159const VkAllocationCallbacks *pAllocator)160{161VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);162if (slot == NULL)163return;164165vk_object_base_finish(&slot->base);166vk_free2(&device->alloc, pAllocator, slot);167}168169#ifdef ANDROID170static VkResult171get_swapchain_private_data_locked(struct vk_device *device,172uint64_t objectHandle,173struct vk_private_data_slot *slot,174uint64_t **private_data)175{176if (unlikely(device->swapchain_private == NULL)) {177/* Even though VkSwapchain is a non-dispatchable object, we know a178* priori that Android swapchains are actually pointers so we can use179* the pointer hash table for them.180*/181device->swapchain_private = _mesa_pointer_hash_table_create(NULL);182if (device->swapchain_private == NULL)183return VK_ERROR_OUT_OF_HOST_MEMORY;184}185186struct hash_entry *entry =187_mesa_hash_table_search(device->swapchain_private,188(void *)(uintptr_t)objectHandle);189if (unlikely(entry == NULL)) {190struct util_sparse_array *swapchain_private =191ralloc(device->swapchain_private, struct util_sparse_array);192util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8);193194entry = _mesa_hash_table_insert(device->swapchain_private,195(void *)(uintptr_t)objectHandle,196swapchain_private);197if (entry == NULL)198return VK_ERROR_OUT_OF_HOST_MEMORY;199}200201struct util_sparse_array *swapchain_private = entry->data;202*private_data = util_sparse_array_get(swapchain_private, slot->index);203204return VK_SUCCESS;205}206#endif /* ANDROID */207208static VkResult209vk_object_base_private_data(struct vk_device *device,210VkObjectType objectType,211uint64_t objectHandle,212VkPrivateDataSlotEXT privateDataSlot,213uint64_t **private_data)214{215VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);216217#ifdef ANDROID218/* There is an annoying spec corner here on Android. Because WSI is219* implemented in the Vulkan loader which doesn't know about the220* VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the221* driver as a special case. On future versions of Android where the222* loader does understand VK_EXT_private_data, we'll never see a223* vkGet/SetPrivateDataEXT call on a swapchain because the loader will224* handle it.225*/226if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {227mtx_lock(&device->swapchain_private_mtx);228VkResult result = get_swapchain_private_data_locked(device, objectHandle,229slot, private_data);230mtx_unlock(&device->swapchain_private_mtx);231return result;232}233#endif /* ANDROID */234235struct vk_object_base *obj =236vk_object_base_from_u64_handle(objectHandle, objectType);237*private_data = util_sparse_array_get(&obj->private_data, slot->index);238239return VK_SUCCESS;240}241242VkResult243vk_object_base_set_private_data(struct vk_device *device,244VkObjectType objectType,245uint64_t objectHandle,246VkPrivateDataSlotEXT privateDataSlot,247uint64_t data)248{249uint64_t *private_data;250VkResult result = vk_object_base_private_data(device,251objectType, objectHandle,252privateDataSlot,253&private_data);254if (unlikely(result != VK_SUCCESS))255return result;256257*private_data = data;258return VK_SUCCESS;259}260261void262vk_object_base_get_private_data(struct vk_device *device,263VkObjectType objectType,264uint64_t objectHandle,265VkPrivateDataSlotEXT privateDataSlot,266uint64_t *pData)267{268uint64_t *private_data;269VkResult result = vk_object_base_private_data(device,270objectType, objectHandle,271privateDataSlot,272&private_data);273if (likely(result == VK_SUCCESS)) {274*pData = *private_data;275} else {276*pData = 0;277}278}279280VKAPI_ATTR VkResult VKAPI_CALL281vk_common_CreatePrivateDataSlotEXT(VkDevice _device,282const VkPrivateDataSlotCreateInfoEXT *pCreateInfo,283const VkAllocationCallbacks *pAllocator,284VkPrivateDataSlotEXT *pPrivateDataSlot)285{286VK_FROM_HANDLE(vk_device, device, _device);287return vk_private_data_slot_create(device, pCreateInfo, pAllocator,288pPrivateDataSlot);289}290291VKAPI_ATTR void VKAPI_CALL292vk_common_DestroyPrivateDataSlotEXT(VkDevice _device,293VkPrivateDataSlotEXT privateDataSlot,294const VkAllocationCallbacks *pAllocator)295{296VK_FROM_HANDLE(vk_device, device, _device);297vk_private_data_slot_destroy(device, privateDataSlot, pAllocator);298}299300VKAPI_ATTR VkResult VKAPI_CALL301vk_common_SetPrivateDataEXT(VkDevice _device,302VkObjectType objectType,303uint64_t objectHandle,304VkPrivateDataSlotEXT privateDataSlot,305uint64_t data)306{307VK_FROM_HANDLE(vk_device, device, _device);308return vk_object_base_set_private_data(device,309objectType, objectHandle,310privateDataSlot, data);311}312313VKAPI_ATTR void VKAPI_CALL314vk_common_GetPrivateDataEXT(VkDevice _device,315VkObjectType objectType,316uint64_t objectHandle,317VkPrivateDataSlotEXT privateDataSlot,318uint64_t *pData)319{320VK_FROM_HANDLE(vk_device, device, _device);321vk_object_base_get_private_data(device,322objectType, objectHandle,323privateDataSlot, pData);324}325326327