333 lines
11 KiB
C
333 lines
11 KiB
C
/*
|
|
* Copyright © 2020 Intel Corporation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
* IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "vk_object.h"
|
|
|
|
#include "vk_alloc.h"
|
|
#include "vk_common_entrypoints.h"
|
|
#include "vk_device.h"
|
|
#include "util/hash_table.h"
|
|
#include "util/ralloc.h"
|
|
#include "vk_enum_to_str.h"
|
|
|
|
void
|
|
vk_object_base_init(struct vk_device *device,
|
|
struct vk_object_base *base,
|
|
VkObjectType obj_type)
|
|
{
|
|
base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
|
|
base->type = obj_type;
|
|
base->device = device;
|
|
base->client_visible = false;
|
|
base->object_name = NULL;
|
|
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);
|
|
|
|
if (base->object_name != NULL)
|
|
vk_free(&base->device->alloc, base->object_name);
|
|
}
|
|
|
|
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_multialloc(struct vk_device *device,
|
|
struct vk_multialloc *ma,
|
|
const VkAllocationCallbacks *alloc,
|
|
VkObjectType obj_type)
|
|
{
|
|
void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
|
|
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_multizalloc(struct vk_device *device,
|
|
struct vk_multialloc *ma,
|
|
const VkAllocationCallbacks *alloc,
|
|
VkObjectType obj_type)
|
|
{
|
|
void *ptr = vk_multialloc_zalloc2(ma, &device->alloc, alloc,
|
|
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 VkPrivateDataSlotCreateInfo* pCreateInfo,
|
|
const VkAllocationCallbacks* pAllocator,
|
|
VkPrivateDataSlot* 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);
|
|
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,
|
|
VkPrivateDataSlot 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,
|
|
VkPrivateDataSlot 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,
|
|
VkPrivateDataSlot 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,
|
|
VkPrivateDataSlot 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;
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
vk_common_CreatePrivateDataSlotEXT(VkDevice _device,
|
|
const VkPrivateDataSlotCreateInfo *pCreateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkPrivateDataSlot *pPrivateDataSlot)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
return vk_private_data_slot_create(device, pCreateInfo, pAllocator,
|
|
pPrivateDataSlot);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_DestroyPrivateDataSlotEXT(VkDevice _device,
|
|
VkPrivateDataSlot privateDataSlot,
|
|
const VkAllocationCallbacks *pAllocator)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
vk_private_data_slot_destroy(device, privateDataSlot, pAllocator);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
vk_common_SetPrivateDataEXT(VkDevice _device,
|
|
VkObjectType objectType,
|
|
uint64_t objectHandle,
|
|
VkPrivateDataSlot privateDataSlot,
|
|
uint64_t data)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
return vk_object_base_set_private_data(device,
|
|
objectType, objectHandle,
|
|
privateDataSlot, data);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_GetPrivateDataEXT(VkDevice _device,
|
|
VkObjectType objectType,
|
|
uint64_t objectHandle,
|
|
VkPrivateDataSlot privateDataSlot,
|
|
uint64_t *pData)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
vk_object_base_get_private_data(device,
|
|
objectType, objectHandle,
|
|
privateDataSlot, pData);
|
|
}
|
|
|
|
const char *
|
|
vk_object_base_name(struct vk_object_base *obj)
|
|
{
|
|
if (obj->object_name)
|
|
return obj->object_name;
|
|
|
|
obj->object_name = vk_asprintf(&obj->device->alloc,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE,
|
|
"%s(0x%"PRIx64")",
|
|
vk_ObjectType_to_ObjectName(obj->type),
|
|
(uint64_t)(uintptr_t)obj);
|
|
|
|
return obj->object_name;
|
|
}
|