xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_object.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2020 Intel Corporation
3  *
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:
10  *
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
13  * Software.
14  *
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
21  * IN THE SOFTWARE.
22  */
23 
24 #include "vk_object.h"
25 
26 #include "vk_alloc.h"
27 #include "vk_common_entrypoints.h"
28 #include "vk_instance.h"
29 #include "vk_device.h"
30 #include "util/hash_table.h"
31 #include "util/ralloc.h"
32 #include "vk_enum_to_str.h"
33 
34 void
vk_object_base_init(struct vk_device * device,struct vk_object_base * base,VkObjectType obj_type)35 vk_object_base_init(struct vk_device *device,
36                     struct vk_object_base *base,
37                     VkObjectType obj_type)
38 {
39    base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
40    base->type = obj_type;
41    base->client_visible = false;
42    base->device = device;
43    base->instance = NULL;
44    base->object_name = NULL;
45    util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);
46 }
47 
vk_object_base_instance_init(struct vk_instance * instance,struct vk_object_base * base,VkObjectType obj_type)48 void vk_object_base_instance_init(struct vk_instance *instance,
49                                   struct vk_object_base *base,
50                                   VkObjectType obj_type)
51 {
52    base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
53    base->type = obj_type;
54    base->client_visible = false;
55    base->device = NULL;
56    base->instance = instance;
57    base->object_name = NULL;
58    util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);
59 }
60 
61 void
vk_object_base_finish(struct vk_object_base * base)62 vk_object_base_finish(struct vk_object_base *base)
63 {
64    util_sparse_array_finish(&base->private_data);
65 
66    if (base->object_name == NULL)
67       return;
68 
69    assert(base->device != NULL || base->instance != NULL);
70    if (base->device)
71       vk_free(&base->device->alloc, base->object_name);
72    else
73       vk_free(&base->instance->alloc, base->object_name);
74 }
75 
76 void
vk_object_base_recycle(struct vk_object_base * base)77 vk_object_base_recycle(struct vk_object_base *base)
78 {
79    struct vk_device *device = base->device;
80    VkObjectType obj_type = base->type;
81    vk_object_base_finish(base);
82    vk_object_base_init(device, base, obj_type);
83 }
84 
85 void *
vk_object_alloc(struct vk_device * device,const VkAllocationCallbacks * alloc,size_t size,VkObjectType obj_type)86 vk_object_alloc(struct vk_device *device,
87                 const VkAllocationCallbacks *alloc,
88                 size_t size,
89                 VkObjectType obj_type)
90 {
91    void *ptr = vk_alloc2(&device->alloc, alloc, size, 8,
92                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
93    if (ptr == NULL)
94       return NULL;
95 
96    vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
97 
98    return ptr;
99 }
100 
101 void *
vk_object_zalloc(struct vk_device * device,const VkAllocationCallbacks * alloc,size_t size,VkObjectType obj_type)102 vk_object_zalloc(struct vk_device *device,
103                 const VkAllocationCallbacks *alloc,
104                 size_t size,
105                 VkObjectType obj_type)
106 {
107    void *ptr = vk_zalloc2(&device->alloc, alloc, size, 8,
108                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
109    if (ptr == NULL)
110       return NULL;
111 
112    vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
113 
114    return ptr;
115 }
116 
117 void *
vk_object_multialloc(struct vk_device * device,struct vk_multialloc * ma,const VkAllocationCallbacks * alloc,VkObjectType obj_type)118 vk_object_multialloc(struct vk_device *device,
119                      struct vk_multialloc *ma,
120                      const VkAllocationCallbacks *alloc,
121                      VkObjectType obj_type)
122 {
123    void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
124                                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
125    if (ptr == NULL)
126       return NULL;
127 
128    vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
129 
130    return ptr;
131 }
132 
133 void *
vk_object_multizalloc(struct vk_device * device,struct vk_multialloc * ma,const VkAllocationCallbacks * alloc,VkObjectType obj_type)134 vk_object_multizalloc(struct vk_device *device,
135                       struct vk_multialloc *ma,
136                       const VkAllocationCallbacks *alloc,
137                       VkObjectType obj_type)
138 {
139    void *ptr = vk_multialloc_zalloc2(ma, &device->alloc, alloc,
140                                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
141    if (ptr == NULL)
142       return NULL;
143 
144    vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
145 
146    return ptr;
147 }
148 
149 void
vk_object_free(struct vk_device * device,const VkAllocationCallbacks * alloc,void * data)150 vk_object_free(struct vk_device *device,
151                const VkAllocationCallbacks *alloc,
152                void *data)
153 {
154    vk_object_base_finish((struct vk_object_base *)data);
155    vk_free2(&device->alloc, alloc, data);
156 }
157 
158 VkResult
vk_private_data_slot_create(struct vk_device * device,const VkPrivateDataSlotCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPrivateDataSlot * pPrivateDataSlot)159 vk_private_data_slot_create(struct vk_device *device,
160                             const VkPrivateDataSlotCreateInfo* pCreateInfo,
161                             const VkAllocationCallbacks* pAllocator,
162                             VkPrivateDataSlot* pPrivateDataSlot)
163 {
164    struct vk_private_data_slot *slot =
165       vk_alloc2(&device->alloc, pAllocator, sizeof(*slot), 8,
166                 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
167    if (slot == NULL)
168       return VK_ERROR_OUT_OF_HOST_MEMORY;
169 
170    vk_object_base_init(device, &slot->base,
171                        VK_OBJECT_TYPE_PRIVATE_DATA_SLOT);
172    slot->index = p_atomic_inc_return(&device->private_data_next_index);
173 
174    *pPrivateDataSlot = vk_private_data_slot_to_handle(slot);
175 
176    return VK_SUCCESS;
177 }
178 
179 void
vk_private_data_slot_destroy(struct vk_device * device,VkPrivateDataSlot privateDataSlot,const VkAllocationCallbacks * pAllocator)180 vk_private_data_slot_destroy(struct vk_device *device,
181                              VkPrivateDataSlot privateDataSlot,
182                              const VkAllocationCallbacks *pAllocator)
183 {
184    VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
185    if (slot == NULL)
186       return;
187 
188    vk_object_base_finish(&slot->base);
189    vk_free2(&device->alloc, pAllocator, slot);
190 }
191 
192 static VkResult
get_swapchain_private_data_locked(struct vk_device * device,uint64_t objectHandle,struct vk_private_data_slot * slot,uint64_t ** private_data)193 get_swapchain_private_data_locked(struct vk_device *device,
194                                   uint64_t objectHandle,
195                                   struct vk_private_data_slot *slot,
196                                   uint64_t **private_data)
197 {
198    if (unlikely(device->swapchain_private == NULL)) {
199       /* Even though VkSwapchain/Surface are non-dispatchable objects, we know
200        * a priori that these are actually pointers so we can use
201        * the pointer hash table for them.
202        */
203       device->swapchain_private = _mesa_pointer_hash_table_create(NULL);
204       if (device->swapchain_private == NULL)
205          return VK_ERROR_OUT_OF_HOST_MEMORY;
206    }
207 
208    struct hash_entry *entry =
209       _mesa_hash_table_search(device->swapchain_private,
210                               (void *)(uintptr_t)objectHandle);
211    if (unlikely(entry == NULL)) {
212       struct util_sparse_array *swapchain_private =
213          ralloc(device->swapchain_private, struct util_sparse_array);
214       util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8);
215 
216       entry = _mesa_hash_table_insert(device->swapchain_private,
217                                       (void *)(uintptr_t)objectHandle,
218                                       swapchain_private);
219       if (entry == NULL)
220          return VK_ERROR_OUT_OF_HOST_MEMORY;
221    }
222 
223    struct util_sparse_array *swapchain_private = entry->data;
224    *private_data = util_sparse_array_get(swapchain_private, slot->index);
225 
226    return VK_SUCCESS;
227 }
228 
229 static VkResult
vk_object_base_private_data(struct vk_device * device,VkObjectType objectType,uint64_t objectHandle,VkPrivateDataSlot privateDataSlot,uint64_t ** private_data)230 vk_object_base_private_data(struct vk_device *device,
231                             VkObjectType objectType,
232                             uint64_t objectHandle,
233                             VkPrivateDataSlot privateDataSlot,
234                             uint64_t **private_data)
235 {
236    VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
237 
238    /* There is an annoying spec corner here on Android.  Because WSI is
239     * implemented in the Vulkan loader which doesn't know about the
240     * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
241     * driver as a special case.  On future versions of Android where the
242     * loader does understand VK_EXT_private_data, we'll never see a
243     * vkGet/SetPrivateData call on a swapchain because the loader will
244     * handle it.
245     */
246 #if DETECT_OS_ANDROID
247    if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR ||
248        objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
249 #else
250    if (objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
251 #endif
252       mtx_lock(&device->swapchain_private_mtx);
253       VkResult result = get_swapchain_private_data_locked(device, objectHandle,
254                                                           slot, private_data);
255       mtx_unlock(&device->swapchain_private_mtx);
256       return result;
257    }
258 
259    struct vk_object_base *obj =
260       vk_object_base_from_u64_handle(objectHandle, objectType);
261    *private_data = util_sparse_array_get(&obj->private_data, slot->index);
262 
263    return VK_SUCCESS;
264 }
265 
266 VkResult
267 vk_object_base_set_private_data(struct vk_device *device,
268                                 VkObjectType objectType,
269                                 uint64_t objectHandle,
270                                 VkPrivateDataSlot privateDataSlot,
271                                 uint64_t data)
272 {
273    uint64_t *private_data;
274    VkResult result = vk_object_base_private_data(device,
275                                                  objectType, objectHandle,
276                                                  privateDataSlot,
277                                                  &private_data);
278    if (unlikely(result != VK_SUCCESS))
279       return result;
280 
281    *private_data = data;
282    return VK_SUCCESS;
283 }
284 
285 void
286 vk_object_base_get_private_data(struct vk_device *device,
287                                 VkObjectType objectType,
288                                 uint64_t objectHandle,
289                                 VkPrivateDataSlot privateDataSlot,
290                                 uint64_t *pData)
291 {
292    uint64_t *private_data;
293    VkResult result = vk_object_base_private_data(device,
294                                                  objectType, objectHandle,
295                                                  privateDataSlot,
296                                                  &private_data);
297    if (likely(result == VK_SUCCESS)) {
298       *pData = *private_data;
299    } else {
300       *pData = 0;
301    }
302 }
303 
304 VKAPI_ATTR VkResult VKAPI_CALL
305 vk_common_CreatePrivateDataSlot(VkDevice _device,
306                                 const VkPrivateDataSlotCreateInfo *pCreateInfo,
307                                 const VkAllocationCallbacks *pAllocator,
308                                 VkPrivateDataSlot *pPrivateDataSlot)
309 {
310    VK_FROM_HANDLE(vk_device, device, _device);
311    return vk_private_data_slot_create(device, pCreateInfo, pAllocator,
312                                       pPrivateDataSlot);
313 }
314 
315 VKAPI_ATTR void VKAPI_CALL
316 vk_common_DestroyPrivateDataSlot(VkDevice _device,
317                                  VkPrivateDataSlot privateDataSlot,
318                                  const VkAllocationCallbacks *pAllocator)
319 {
320    VK_FROM_HANDLE(vk_device, device, _device);
321    vk_private_data_slot_destroy(device, privateDataSlot, pAllocator);
322 }
323 
324 VKAPI_ATTR VkResult VKAPI_CALL
325 vk_common_SetPrivateData(VkDevice _device,
326                          VkObjectType objectType,
327                          uint64_t objectHandle,
328                          VkPrivateDataSlot privateDataSlot,
329                          uint64_t data)
330 {
331    VK_FROM_HANDLE(vk_device, device, _device);
332    return vk_object_base_set_private_data(device,
333                                           objectType, objectHandle,
334                                           privateDataSlot, data);
335 }
336 
337 VKAPI_ATTR void VKAPI_CALL
338 vk_common_GetPrivateData(VkDevice _device,
339                          VkObjectType objectType,
340                          uint64_t objectHandle,
341                          VkPrivateDataSlot privateDataSlot,
342                          uint64_t *pData)
343 {
344    VK_FROM_HANDLE(vk_device, device, _device);
345    vk_object_base_get_private_data(device,
346                                    objectType, objectHandle,
347                                    privateDataSlot, pData);
348 }
349 
350 const char *
351 vk_object_base_name(struct vk_object_base *obj)
352 {
353    if (obj->object_name)
354       return obj->object_name;
355 
356    obj->object_name = vk_asprintf(&obj->device->alloc,
357                                   VK_SYSTEM_ALLOCATION_SCOPE_DEVICE,
358                                   "%s(0x%"PRIx64")",
359                                   vk_ObjectType_to_ObjectName(obj->type),
360                                   (uint64_t)(uintptr_t)obj);
361 
362    return obj->object_name;
363 }
364