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