1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2020 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "vk_object.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "vk_alloc.h" 27bf215546Sopenharmony_ci#include "vk_common_entrypoints.h" 28bf215546Sopenharmony_ci#include "vk_device.h" 29bf215546Sopenharmony_ci#include "util/hash_table.h" 30bf215546Sopenharmony_ci#include "util/ralloc.h" 31bf215546Sopenharmony_ci#include "vk_enum_to_str.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_civoid 34bf215546Sopenharmony_civk_object_base_init(struct vk_device *device, 35bf215546Sopenharmony_ci struct vk_object_base *base, 36bf215546Sopenharmony_ci VkObjectType obj_type) 37bf215546Sopenharmony_ci{ 38bf215546Sopenharmony_ci base->_loader_data.loaderMagic = ICD_LOADER_MAGIC; 39bf215546Sopenharmony_ci base->type = obj_type; 40bf215546Sopenharmony_ci base->device = device; 41bf215546Sopenharmony_ci base->client_visible = false; 42bf215546Sopenharmony_ci base->object_name = NULL; 43bf215546Sopenharmony_ci util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8); 44bf215546Sopenharmony_ci} 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_civoid 47bf215546Sopenharmony_civk_object_base_finish(struct vk_object_base *base) 48bf215546Sopenharmony_ci{ 49bf215546Sopenharmony_ci util_sparse_array_finish(&base->private_data); 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci if (base->object_name != NULL) 52bf215546Sopenharmony_ci vk_free(&base->device->alloc, base->object_name); 53bf215546Sopenharmony_ci} 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_civoid * 56bf215546Sopenharmony_civk_object_alloc(struct vk_device *device, 57bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 58bf215546Sopenharmony_ci size_t size, 59bf215546Sopenharmony_ci VkObjectType obj_type) 60bf215546Sopenharmony_ci{ 61bf215546Sopenharmony_ci void *ptr = vk_alloc2(&device->alloc, alloc, size, 8, 62bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 63bf215546Sopenharmony_ci if (ptr == NULL) 64bf215546Sopenharmony_ci return NULL; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci return ptr; 69bf215546Sopenharmony_ci} 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_civoid * 72bf215546Sopenharmony_civk_object_zalloc(struct vk_device *device, 73bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 74bf215546Sopenharmony_ci size_t size, 75bf215546Sopenharmony_ci VkObjectType obj_type) 76bf215546Sopenharmony_ci{ 77bf215546Sopenharmony_ci void *ptr = vk_zalloc2(&device->alloc, alloc, size, 8, 78bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 79bf215546Sopenharmony_ci if (ptr == NULL) 80bf215546Sopenharmony_ci return NULL; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci return ptr; 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_civoid * 88bf215546Sopenharmony_civk_object_multialloc(struct vk_device *device, 89bf215546Sopenharmony_ci struct vk_multialloc *ma, 90bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 91bf215546Sopenharmony_ci VkObjectType obj_type) 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc, 94bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 95bf215546Sopenharmony_ci if (ptr == NULL) 96bf215546Sopenharmony_ci return NULL; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type); 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci return ptr; 101bf215546Sopenharmony_ci} 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_civoid * 104bf215546Sopenharmony_civk_object_multizalloc(struct vk_device *device, 105bf215546Sopenharmony_ci struct vk_multialloc *ma, 106bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 107bf215546Sopenharmony_ci VkObjectType obj_type) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci void *ptr = vk_multialloc_zalloc2(ma, &device->alloc, alloc, 110bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 111bf215546Sopenharmony_ci if (ptr == NULL) 112bf215546Sopenharmony_ci return NULL; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type); 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci return ptr; 117bf215546Sopenharmony_ci} 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_civoid 120bf215546Sopenharmony_civk_object_free(struct vk_device *device, 121bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 122bf215546Sopenharmony_ci void *data) 123bf215546Sopenharmony_ci{ 124bf215546Sopenharmony_ci vk_object_base_finish((struct vk_object_base *)data); 125bf215546Sopenharmony_ci vk_free2(&device->alloc, alloc, data); 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ciVkResult 129bf215546Sopenharmony_civk_private_data_slot_create(struct vk_device *device, 130bf215546Sopenharmony_ci const VkPrivateDataSlotCreateInfo* pCreateInfo, 131bf215546Sopenharmony_ci const VkAllocationCallbacks* pAllocator, 132bf215546Sopenharmony_ci VkPrivateDataSlot* pPrivateDataSlot) 133bf215546Sopenharmony_ci{ 134bf215546Sopenharmony_ci struct vk_private_data_slot *slot = 135bf215546Sopenharmony_ci vk_alloc2(&device->alloc, pAllocator, sizeof(*slot), 8, 136bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 137bf215546Sopenharmony_ci if (slot == NULL) 138bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci vk_object_base_init(device, &slot->base, 141bf215546Sopenharmony_ci VK_OBJECT_TYPE_PRIVATE_DATA_SLOT); 142bf215546Sopenharmony_ci slot->index = p_atomic_inc_return(&device->private_data_next_index); 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci *pPrivateDataSlot = vk_private_data_slot_to_handle(slot); 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci return VK_SUCCESS; 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_civoid 150bf215546Sopenharmony_civk_private_data_slot_destroy(struct vk_device *device, 151bf215546Sopenharmony_ci VkPrivateDataSlot privateDataSlot, 152bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 153bf215546Sopenharmony_ci{ 154bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot); 155bf215546Sopenharmony_ci if (slot == NULL) 156bf215546Sopenharmony_ci return; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci vk_object_base_finish(&slot->base); 159bf215546Sopenharmony_ci vk_free2(&device->alloc, pAllocator, slot); 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci#ifdef ANDROID 163bf215546Sopenharmony_cistatic VkResult 164bf215546Sopenharmony_ciget_swapchain_private_data_locked(struct vk_device *device, 165bf215546Sopenharmony_ci uint64_t objectHandle, 166bf215546Sopenharmony_ci struct vk_private_data_slot *slot, 167bf215546Sopenharmony_ci uint64_t **private_data) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci if (unlikely(device->swapchain_private == NULL)) { 170bf215546Sopenharmony_ci /* Even though VkSwapchain is a non-dispatchable object, we know a 171bf215546Sopenharmony_ci * priori that Android swapchains are actually pointers so we can use 172bf215546Sopenharmony_ci * the pointer hash table for them. 173bf215546Sopenharmony_ci */ 174bf215546Sopenharmony_ci device->swapchain_private = _mesa_pointer_hash_table_create(NULL); 175bf215546Sopenharmony_ci if (device->swapchain_private == NULL) 176bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci struct hash_entry *entry = 180bf215546Sopenharmony_ci _mesa_hash_table_search(device->swapchain_private, 181bf215546Sopenharmony_ci (void *)(uintptr_t)objectHandle); 182bf215546Sopenharmony_ci if (unlikely(entry == NULL)) { 183bf215546Sopenharmony_ci struct util_sparse_array *swapchain_private = 184bf215546Sopenharmony_ci ralloc(device->swapchain_private, struct util_sparse_array); 185bf215546Sopenharmony_ci util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci entry = _mesa_hash_table_insert(device->swapchain_private, 188bf215546Sopenharmony_ci (void *)(uintptr_t)objectHandle, 189bf215546Sopenharmony_ci swapchain_private); 190bf215546Sopenharmony_ci if (entry == NULL) 191bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci struct util_sparse_array *swapchain_private = entry->data; 195bf215546Sopenharmony_ci *private_data = util_sparse_array_get(swapchain_private, slot->index); 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci return VK_SUCCESS; 198bf215546Sopenharmony_ci} 199bf215546Sopenharmony_ci#endif /* ANDROID */ 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_cistatic VkResult 202bf215546Sopenharmony_civk_object_base_private_data(struct vk_device *device, 203bf215546Sopenharmony_ci VkObjectType objectType, 204bf215546Sopenharmony_ci uint64_t objectHandle, 205bf215546Sopenharmony_ci VkPrivateDataSlot privateDataSlot, 206bf215546Sopenharmony_ci uint64_t **private_data) 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci#ifdef ANDROID 211bf215546Sopenharmony_ci /* There is an annoying spec corner here on Android. Because WSI is 212bf215546Sopenharmony_ci * implemented in the Vulkan loader which doesn't know about the 213bf215546Sopenharmony_ci * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the 214bf215546Sopenharmony_ci * driver as a special case. On future versions of Android where the 215bf215546Sopenharmony_ci * loader does understand VK_EXT_private_data, we'll never see a 216bf215546Sopenharmony_ci * vkGet/SetPrivateDataEXT call on a swapchain because the loader will 217bf215546Sopenharmony_ci * handle it. 218bf215546Sopenharmony_ci */ 219bf215546Sopenharmony_ci if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR) { 220bf215546Sopenharmony_ci mtx_lock(&device->swapchain_private_mtx); 221bf215546Sopenharmony_ci VkResult result = get_swapchain_private_data_locked(device, objectHandle, 222bf215546Sopenharmony_ci slot, private_data); 223bf215546Sopenharmony_ci mtx_unlock(&device->swapchain_private_mtx); 224bf215546Sopenharmony_ci return result; 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci#endif /* ANDROID */ 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci struct vk_object_base *obj = 229bf215546Sopenharmony_ci vk_object_base_from_u64_handle(objectHandle, objectType); 230bf215546Sopenharmony_ci *private_data = util_sparse_array_get(&obj->private_data, slot->index); 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci return VK_SUCCESS; 233bf215546Sopenharmony_ci} 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ciVkResult 236bf215546Sopenharmony_civk_object_base_set_private_data(struct vk_device *device, 237bf215546Sopenharmony_ci VkObjectType objectType, 238bf215546Sopenharmony_ci uint64_t objectHandle, 239bf215546Sopenharmony_ci VkPrivateDataSlot privateDataSlot, 240bf215546Sopenharmony_ci uint64_t data) 241bf215546Sopenharmony_ci{ 242bf215546Sopenharmony_ci uint64_t *private_data; 243bf215546Sopenharmony_ci VkResult result = vk_object_base_private_data(device, 244bf215546Sopenharmony_ci objectType, objectHandle, 245bf215546Sopenharmony_ci privateDataSlot, 246bf215546Sopenharmony_ci &private_data); 247bf215546Sopenharmony_ci if (unlikely(result != VK_SUCCESS)) 248bf215546Sopenharmony_ci return result; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci *private_data = data; 251bf215546Sopenharmony_ci return VK_SUCCESS; 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_civoid 255bf215546Sopenharmony_civk_object_base_get_private_data(struct vk_device *device, 256bf215546Sopenharmony_ci VkObjectType objectType, 257bf215546Sopenharmony_ci uint64_t objectHandle, 258bf215546Sopenharmony_ci VkPrivateDataSlot privateDataSlot, 259bf215546Sopenharmony_ci uint64_t *pData) 260bf215546Sopenharmony_ci{ 261bf215546Sopenharmony_ci uint64_t *private_data; 262bf215546Sopenharmony_ci VkResult result = vk_object_base_private_data(device, 263bf215546Sopenharmony_ci objectType, objectHandle, 264bf215546Sopenharmony_ci privateDataSlot, 265bf215546Sopenharmony_ci &private_data); 266bf215546Sopenharmony_ci if (likely(result == VK_SUCCESS)) { 267bf215546Sopenharmony_ci *pData = *private_data; 268bf215546Sopenharmony_ci } else { 269bf215546Sopenharmony_ci *pData = 0; 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci} 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 274bf215546Sopenharmony_civk_common_CreatePrivateDataSlotEXT(VkDevice _device, 275bf215546Sopenharmony_ci const VkPrivateDataSlotCreateInfo *pCreateInfo, 276bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 277bf215546Sopenharmony_ci VkPrivateDataSlot *pPrivateDataSlot) 278bf215546Sopenharmony_ci{ 279bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 280bf215546Sopenharmony_ci return vk_private_data_slot_create(device, pCreateInfo, pAllocator, 281bf215546Sopenharmony_ci pPrivateDataSlot); 282bf215546Sopenharmony_ci} 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 285bf215546Sopenharmony_civk_common_DestroyPrivateDataSlotEXT(VkDevice _device, 286bf215546Sopenharmony_ci VkPrivateDataSlot privateDataSlot, 287bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 290bf215546Sopenharmony_ci vk_private_data_slot_destroy(device, privateDataSlot, pAllocator); 291bf215546Sopenharmony_ci} 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 294bf215546Sopenharmony_civk_common_SetPrivateDataEXT(VkDevice _device, 295bf215546Sopenharmony_ci VkObjectType objectType, 296bf215546Sopenharmony_ci uint64_t objectHandle, 297bf215546Sopenharmony_ci VkPrivateDataSlot privateDataSlot, 298bf215546Sopenharmony_ci uint64_t data) 299bf215546Sopenharmony_ci{ 300bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 301bf215546Sopenharmony_ci return vk_object_base_set_private_data(device, 302bf215546Sopenharmony_ci objectType, objectHandle, 303bf215546Sopenharmony_ci privateDataSlot, data); 304bf215546Sopenharmony_ci} 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 307bf215546Sopenharmony_civk_common_GetPrivateDataEXT(VkDevice _device, 308bf215546Sopenharmony_ci VkObjectType objectType, 309bf215546Sopenharmony_ci uint64_t objectHandle, 310bf215546Sopenharmony_ci VkPrivateDataSlot privateDataSlot, 311bf215546Sopenharmony_ci uint64_t *pData) 312bf215546Sopenharmony_ci{ 313bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 314bf215546Sopenharmony_ci vk_object_base_get_private_data(device, 315bf215546Sopenharmony_ci objectType, objectHandle, 316bf215546Sopenharmony_ci privateDataSlot, pData); 317bf215546Sopenharmony_ci} 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ciconst char * 320bf215546Sopenharmony_civk_object_base_name(struct vk_object_base *obj) 321bf215546Sopenharmony_ci{ 322bf215546Sopenharmony_ci if (obj->object_name) 323bf215546Sopenharmony_ci return obj->object_name; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci obj->object_name = vk_asprintf(&obj->device->alloc, 326bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE, 327bf215546Sopenharmony_ci "%s(0x%"PRIx64")", 328bf215546Sopenharmony_ci vk_ObjectType_to_ObjectName(obj->type), 329bf215546Sopenharmony_ci (uint64_t)(uintptr_t)obj); 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci return obj->object_name; 332bf215546Sopenharmony_ci} 333