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_object_alloc(struct vk_device
*device
,
82 const VkAllocationCallbacks
*alloc
,
84 VkObjectType obj_type
)
86 void *ptr
= vk_alloc2(&device
->alloc
, alloc
, size
, 8,
87 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
91 vk_object_base_init(device
, (struct vk_object_base
*)ptr
, obj_type
);
97 vk_object_zalloc(struct vk_device
*device
,
98 const VkAllocationCallbacks
*alloc
,
100 VkObjectType obj_type
)
102 void *ptr
= vk_zalloc2(&device
->alloc
, alloc
, size
, 8,
103 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
107 vk_object_base_init(device
, (struct vk_object_base
*)ptr
, obj_type
);
113 vk_object_free(struct vk_device
*device
,
114 const VkAllocationCallbacks
*alloc
,
117 vk_object_base_finish((struct vk_object_base
*)data
);
118 vk_free2(&device
->alloc
, alloc
, data
);
122 vk_private_data_slot_create(struct vk_device
*device
,
123 const VkPrivateDataSlotCreateInfoEXT
* pCreateInfo
,
124 const VkAllocationCallbacks
* pAllocator
,
125 VkPrivateDataSlotEXT
* pPrivateDataSlot
)
127 struct vk_private_data_slot
*slot
=
128 vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*slot
), 8,
129 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
131 return VK_ERROR_OUT_OF_HOST_MEMORY
;
133 vk_object_base_init(device
, &slot
->base
,
134 VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT
);
135 slot
->index
= p_atomic_inc_return(&device
->private_data_next_index
);
137 *pPrivateDataSlot
= vk_private_data_slot_to_handle(slot
);
143 vk_private_data_slot_destroy(struct vk_device
*device
,
144 VkPrivateDataSlotEXT privateDataSlot
,
145 const VkAllocationCallbacks
*pAllocator
)
147 VK_FROM_HANDLE(vk_private_data_slot
, slot
, privateDataSlot
);
151 vk_object_base_finish(&slot
->base
);
152 vk_free2(&device
->alloc
, pAllocator
, slot
);
157 get_swapchain_private_data_locked(struct vk_device
*device
,
158 uint64_t objectHandle
,
159 struct vk_private_data_slot
*slot
,
160 uint64_t **private_data
)
162 if (unlikely(device
->swapchain_private
== NULL
)) {
163 /* Even though VkSwapchain is a non-dispatchable object, we know a
164 * priori that Android swapchains are actually pointers so we can use
165 * the pointer hash table for them.
167 device
->swapchain_private
= _mesa_pointer_hash_table_create(NULL
);
168 if (device
->swapchain_private
== NULL
)
169 return VK_ERROR_OUT_OF_HOST_MEMORY
;
172 struct hash_entry
*entry
=
173 _mesa_hash_table_search(device
->swapchain_private
,
174 (void *)(uintptr_t)objectHandle
);
175 if (unlikely(entry
== NULL
)) {
176 struct util_sparse_array
*swapchain_private
=
177 ralloc(device
->swapchain_private
, struct util_sparse_array
);
178 util_sparse_array_init(swapchain_private
, sizeof(uint64_t), 8);
180 entry
= _mesa_hash_table_insert(device
->swapchain_private
,
181 (void *)(uintptr_t)objectHandle
,
184 return VK_ERROR_OUT_OF_HOST_MEMORY
;
187 struct util_sparse_array
*swapchain_private
= entry
->data
;
188 *private_data
= util_sparse_array_get(swapchain_private
, slot
->index
);
195 vk_object_base_private_data(struct vk_device
*device
,
196 VkObjectType objectType
,
197 uint64_t objectHandle
,
198 VkPrivateDataSlotEXT privateDataSlot
,
199 uint64_t **private_data
)
201 VK_FROM_HANDLE(vk_private_data_slot
, slot
, privateDataSlot
);
204 /* There is an annoying spec corner here on Android. Because WSI is
205 * implemented in the Vulkan loader which doesn't know about the
206 * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
207 * driver as a special case. On future versions of Android where the
208 * loader does understand VK_EXT_private_data, we'll never see a
209 * vkGet/SetPrivateDataEXT call on a swapchain because the loader will
212 if (objectType
== VK_OBJECT_TYPE_SWAPCHAIN_KHR
) {
213 mtx_lock(&device
->swapchain_private_mtx
);
214 VkResult result
= get_swapchain_private_data_locked(device
, objectHandle
,
216 mtx_unlock(&device
->swapchain_private_mtx
);
221 struct vk_object_base
*obj
=
222 vk_object_base_from_u64_handle(objectHandle
, objectType
);
223 *private_data
= util_sparse_array_get(&obj
->private_data
, slot
->index
);
229 vk_object_base_set_private_data(struct vk_device
*device
,
230 VkObjectType objectType
,
231 uint64_t objectHandle
,
232 VkPrivateDataSlotEXT privateDataSlot
,
235 uint64_t *private_data
;
236 VkResult result
= vk_object_base_private_data(device
,
237 objectType
, objectHandle
,
240 if (unlikely(result
!= VK_SUCCESS
))
243 *private_data
= data
;
248 vk_object_base_get_private_data(struct vk_device
*device
,
249 VkObjectType objectType
,
250 uint64_t objectHandle
,
251 VkPrivateDataSlotEXT privateDataSlot
,
254 uint64_t *private_data
;
255 VkResult result
= vk_object_base_private_data(device
,
256 objectType
, objectHandle
,
259 if (likely(result
== VK_SUCCESS
)) {
260 *pData
= *private_data
;