2 * Copyright © 2020 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "vk_object.h"
27 #include "util/hash_table.h"
28 #include "util/ralloc.h"
31 vk_object_base_init(UNUSED
struct vk_device
*device
,
32 struct vk_object_base
*base
,
33 UNUSED VkObjectType obj_type
)
35 base
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
36 base
->type
= obj_type
;
37 util_sparse_array_init(&base
->private_data
, sizeof(uint64_t), 8);
41 vk_object_base_finish(struct vk_object_base
*base
)
43 util_sparse_array_finish(&base
->private_data
);
47 vk_device_init(struct vk_device
*device
,
48 UNUSED
const VkDeviceCreateInfo
*pCreateInfo
,
49 const VkAllocationCallbacks
*instance_alloc
,
50 const VkAllocationCallbacks
*device_alloc
)
52 vk_object_base_init(device
, &device
->base
, VK_OBJECT_TYPE_DEVICE
);
54 device
->alloc
= *device_alloc
;
56 device
->alloc
= *instance_alloc
;
58 p_atomic_set(&device
->private_data_next_index
, 0);
61 mtx_init(&device
->swapchain_private_mtx
, mtx_plain
);
62 device
->swapchain_private
= NULL
;
67 vk_device_finish(UNUSED
struct vk_device
*device
)
70 if (device
->swapchain_private
) {
71 hash_table_foreach(device
->swapchain_private
, entry
)
72 util_sparse_array_finish(entry
->data
);
73 ralloc_free(device
->swapchain_private
);
77 vk_object_base_finish(&device
->base
);
81 vk_private_data_slot_create(struct vk_device
*device
,
82 const VkPrivateDataSlotCreateInfoEXT
* pCreateInfo
,
83 const VkAllocationCallbacks
* pAllocator
,
84 VkPrivateDataSlotEXT
* pPrivateDataSlot
)
86 struct vk_private_data_slot
*slot
=
87 vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*slot
), 8,
88 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
90 return VK_ERROR_OUT_OF_HOST_MEMORY
;
92 vk_object_base_init(device
, &slot
->base
,
93 VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT
);
94 slot
->index
= p_atomic_inc_return(&device
->private_data_next_index
);
96 *pPrivateDataSlot
= vk_private_data_slot_to_handle(slot
);
102 vk_private_data_slot_destroy(struct vk_device
*device
,
103 VkPrivateDataSlotEXT privateDataSlot
,
104 const VkAllocationCallbacks
*pAllocator
)
106 VK_FROM_HANDLE(vk_private_data_slot
, slot
, privateDataSlot
);
110 vk_object_base_finish(&slot
->base
);
111 vk_free2(&device
->alloc
, pAllocator
, slot
);
116 get_swapchain_private_data_locked(struct vk_device
*device
,
117 uint64_t objectHandle
,
118 struct vk_private_data_slot
*slot
,
119 uint64_t **private_data
)
121 if (unlikely(device
->swapchain_private
== NULL
)) {
122 /* Even though VkSwapchain is a non-dispatchable object, we know a
123 * priori that Android swapchains are actually pointers so we can use
124 * the pointer hash table for them.
126 device
->swapchain_private
= _mesa_pointer_hash_table_create(NULL
);
127 if (device
->swapchain_private
== NULL
)
128 return VK_ERROR_OUT_OF_HOST_MEMORY
;
131 struct hash_entry
*entry
=
132 _mesa_hash_table_search(device
->swapchain_private
,
133 (void *)(uintptr_t)objectHandle
);
134 if (unlikely(entry
== NULL
)) {
135 struct util_sparse_array
*swapchain_private
=
136 ralloc(device
->swapchain_private
, struct util_sparse_array
);
137 util_sparse_array_init(swapchain_private
, sizeof(uint64_t), 8);
139 entry
= _mesa_hash_table_insert(device
->swapchain_private
,
140 (void *)(uintptr_t)objectHandle
,
143 return VK_ERROR_OUT_OF_HOST_MEMORY
;
146 struct util_sparse_array
*swapchain_private
= entry
->data
;
147 *private_data
= util_sparse_array_get(swapchain_private
, slot
->index
);
154 vk_object_base_private_data(struct vk_device
*device
,
155 VkObjectType objectType
,
156 uint64_t objectHandle
,
157 VkPrivateDataSlotEXT privateDataSlot
,
158 uint64_t **private_data
)
160 VK_FROM_HANDLE(vk_private_data_slot
, slot
, privateDataSlot
);
163 /* There is an annoying spec corner here on Android. Because WSI is
164 * implemented in the Vulkan loader which doesn't know about the
165 * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
166 * driver as a special case. On future versions of Android where the
167 * loader does understand VK_EXT_private_data, we'll never see a
168 * vkGet/SetPrivateDataEXT call on a swapchain because the loader will
171 if (objectType
== VK_OBJECT_TYPE_SWAPCHAIN_KHR
) {
172 mtx_lock(&device
->swapchain_private_mtx
);
173 VkResult result
= get_swapchain_private_data_locked(device
, objectHandle
,
175 mtx_unlock(&device
->swapchain_private_mtx
);
180 struct vk_object_base
*obj
=
181 vk_object_base_from_u64_handle(objectHandle
, objectType
);
182 *private_data
= util_sparse_array_get(&obj
->private_data
, slot
->index
);
188 vk_object_base_set_private_data(struct vk_device
*device
,
189 VkObjectType objectType
,
190 uint64_t objectHandle
,
191 VkPrivateDataSlotEXT privateDataSlot
,
194 uint64_t *private_data
;
195 VkResult result
= vk_object_base_private_data(device
,
196 objectType
, objectHandle
,
199 if (unlikely(result
!= VK_SUCCESS
))
202 *private_data
= data
;
207 vk_object_base_get_private_data(struct vk_device
*device
,
208 VkObjectType objectType
,
209 uint64_t objectHandle
,
210 VkPrivateDataSlotEXT privateDataSlot
,
213 uint64_t *private_data
;
214 VkResult result
= vk_object_base_private_data(device
,
215 objectType
, objectHandle
,
218 if (likely(result
== VK_SUCCESS
)) {
219 *pData
= *private_data
;