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