1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2020 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "vk_object.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "vk_alloc.h"
27bf215546Sopenharmony_ci#include "vk_common_entrypoints.h"
28bf215546Sopenharmony_ci#include "vk_device.h"
29bf215546Sopenharmony_ci#include "util/hash_table.h"
30bf215546Sopenharmony_ci#include "util/ralloc.h"
31bf215546Sopenharmony_ci#include "vk_enum_to_str.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_civoid
34bf215546Sopenharmony_civk_object_base_init(struct vk_device *device,
35bf215546Sopenharmony_ci                    struct vk_object_base *base,
36bf215546Sopenharmony_ci                    VkObjectType obj_type)
37bf215546Sopenharmony_ci{
38bf215546Sopenharmony_ci   base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
39bf215546Sopenharmony_ci   base->type = obj_type;
40bf215546Sopenharmony_ci   base->device = device;
41bf215546Sopenharmony_ci   base->client_visible = false;
42bf215546Sopenharmony_ci   base->object_name = NULL;
43bf215546Sopenharmony_ci   util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);
44bf215546Sopenharmony_ci}
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_civoid
47bf215546Sopenharmony_civk_object_base_finish(struct vk_object_base *base)
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci   util_sparse_array_finish(&base->private_data);
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   if (base->object_name != NULL)
52bf215546Sopenharmony_ci      vk_free(&base->device->alloc, base->object_name);
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_civoid *
56bf215546Sopenharmony_civk_object_alloc(struct vk_device *device,
57bf215546Sopenharmony_ci                const VkAllocationCallbacks *alloc,
58bf215546Sopenharmony_ci                size_t size,
59bf215546Sopenharmony_ci                VkObjectType obj_type)
60bf215546Sopenharmony_ci{
61bf215546Sopenharmony_ci   void *ptr = vk_alloc2(&device->alloc, alloc, size, 8,
62bf215546Sopenharmony_ci                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
63bf215546Sopenharmony_ci   if (ptr == NULL)
64bf215546Sopenharmony_ci      return NULL;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   return ptr;
69bf215546Sopenharmony_ci}
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_civoid *
72bf215546Sopenharmony_civk_object_zalloc(struct vk_device *device,
73bf215546Sopenharmony_ci                const VkAllocationCallbacks *alloc,
74bf215546Sopenharmony_ci                size_t size,
75bf215546Sopenharmony_ci                VkObjectType obj_type)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   void *ptr = vk_zalloc2(&device->alloc, alloc, size, 8,
78bf215546Sopenharmony_ci                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
79bf215546Sopenharmony_ci   if (ptr == NULL)
80bf215546Sopenharmony_ci      return NULL;
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   return ptr;
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_civoid *
88bf215546Sopenharmony_civk_object_multialloc(struct vk_device *device,
89bf215546Sopenharmony_ci                     struct vk_multialloc *ma,
90bf215546Sopenharmony_ci                     const VkAllocationCallbacks *alloc,
91bf215546Sopenharmony_ci                     VkObjectType obj_type)
92bf215546Sopenharmony_ci{
93bf215546Sopenharmony_ci   void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
94bf215546Sopenharmony_ci                                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
95bf215546Sopenharmony_ci   if (ptr == NULL)
96bf215546Sopenharmony_ci      return NULL;
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   return ptr;
101bf215546Sopenharmony_ci}
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_civoid *
104bf215546Sopenharmony_civk_object_multizalloc(struct vk_device *device,
105bf215546Sopenharmony_ci                      struct vk_multialloc *ma,
106bf215546Sopenharmony_ci                      const VkAllocationCallbacks *alloc,
107bf215546Sopenharmony_ci                      VkObjectType obj_type)
108bf215546Sopenharmony_ci{
109bf215546Sopenharmony_ci   void *ptr = vk_multialloc_zalloc2(ma, &device->alloc, alloc,
110bf215546Sopenharmony_ci                                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
111bf215546Sopenharmony_ci   if (ptr == NULL)
112bf215546Sopenharmony_ci      return NULL;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   return ptr;
117bf215546Sopenharmony_ci}
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_civoid
120bf215546Sopenharmony_civk_object_free(struct vk_device *device,
121bf215546Sopenharmony_ci               const VkAllocationCallbacks *alloc,
122bf215546Sopenharmony_ci               void *data)
123bf215546Sopenharmony_ci{
124bf215546Sopenharmony_ci   vk_object_base_finish((struct vk_object_base *)data);
125bf215546Sopenharmony_ci   vk_free2(&device->alloc, alloc, data);
126bf215546Sopenharmony_ci}
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ciVkResult
129bf215546Sopenharmony_civk_private_data_slot_create(struct vk_device *device,
130bf215546Sopenharmony_ci                            const VkPrivateDataSlotCreateInfo* pCreateInfo,
131bf215546Sopenharmony_ci                            const VkAllocationCallbacks* pAllocator,
132bf215546Sopenharmony_ci                            VkPrivateDataSlot* pPrivateDataSlot)
133bf215546Sopenharmony_ci{
134bf215546Sopenharmony_ci   struct vk_private_data_slot *slot =
135bf215546Sopenharmony_ci      vk_alloc2(&device->alloc, pAllocator, sizeof(*slot), 8,
136bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
137bf215546Sopenharmony_ci   if (slot == NULL)
138bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   vk_object_base_init(device, &slot->base,
141bf215546Sopenharmony_ci                       VK_OBJECT_TYPE_PRIVATE_DATA_SLOT);
142bf215546Sopenharmony_ci   slot->index = p_atomic_inc_return(&device->private_data_next_index);
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   *pPrivateDataSlot = vk_private_data_slot_to_handle(slot);
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   return VK_SUCCESS;
147bf215546Sopenharmony_ci}
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_civoid
150bf215546Sopenharmony_civk_private_data_slot_destroy(struct vk_device *device,
151bf215546Sopenharmony_ci                             VkPrivateDataSlot privateDataSlot,
152bf215546Sopenharmony_ci                             const VkAllocationCallbacks *pAllocator)
153bf215546Sopenharmony_ci{
154bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
155bf215546Sopenharmony_ci   if (slot == NULL)
156bf215546Sopenharmony_ci      return;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   vk_object_base_finish(&slot->base);
159bf215546Sopenharmony_ci   vk_free2(&device->alloc, pAllocator, slot);
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci#ifdef ANDROID
163bf215546Sopenharmony_cistatic VkResult
164bf215546Sopenharmony_ciget_swapchain_private_data_locked(struct vk_device *device,
165bf215546Sopenharmony_ci                                  uint64_t objectHandle,
166bf215546Sopenharmony_ci                                  struct vk_private_data_slot *slot,
167bf215546Sopenharmony_ci                                  uint64_t **private_data)
168bf215546Sopenharmony_ci{
169bf215546Sopenharmony_ci   if (unlikely(device->swapchain_private == NULL)) {
170bf215546Sopenharmony_ci      /* Even though VkSwapchain is a non-dispatchable object, we know a
171bf215546Sopenharmony_ci       * priori that Android swapchains are actually pointers so we can use
172bf215546Sopenharmony_ci       * the pointer hash table for them.
173bf215546Sopenharmony_ci       */
174bf215546Sopenharmony_ci      device->swapchain_private = _mesa_pointer_hash_table_create(NULL);
175bf215546Sopenharmony_ci      if (device->swapchain_private == NULL)
176bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_HOST_MEMORY;
177bf215546Sopenharmony_ci   }
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   struct hash_entry *entry =
180bf215546Sopenharmony_ci      _mesa_hash_table_search(device->swapchain_private,
181bf215546Sopenharmony_ci                              (void *)(uintptr_t)objectHandle);
182bf215546Sopenharmony_ci   if (unlikely(entry == NULL)) {
183bf215546Sopenharmony_ci      struct util_sparse_array *swapchain_private =
184bf215546Sopenharmony_ci         ralloc(device->swapchain_private, struct util_sparse_array);
185bf215546Sopenharmony_ci      util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8);
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci      entry = _mesa_hash_table_insert(device->swapchain_private,
188bf215546Sopenharmony_ci                                      (void *)(uintptr_t)objectHandle,
189bf215546Sopenharmony_ci                                      swapchain_private);
190bf215546Sopenharmony_ci      if (entry == NULL)
191bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_HOST_MEMORY;
192bf215546Sopenharmony_ci   }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   struct util_sparse_array *swapchain_private = entry->data;
195bf215546Sopenharmony_ci   *private_data = util_sparse_array_get(swapchain_private, slot->index);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   return VK_SUCCESS;
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci#endif /* ANDROID */
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_cistatic VkResult
202bf215546Sopenharmony_civk_object_base_private_data(struct vk_device *device,
203bf215546Sopenharmony_ci                            VkObjectType objectType,
204bf215546Sopenharmony_ci                            uint64_t objectHandle,
205bf215546Sopenharmony_ci                            VkPrivateDataSlot privateDataSlot,
206bf215546Sopenharmony_ci                            uint64_t **private_data)
207bf215546Sopenharmony_ci{
208bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci#ifdef ANDROID
211bf215546Sopenharmony_ci   /* There is an annoying spec corner here on Android.  Because WSI is
212bf215546Sopenharmony_ci    * implemented in the Vulkan loader which doesn't know about the
213bf215546Sopenharmony_ci    * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
214bf215546Sopenharmony_ci    * driver as a special case.  On future versions of Android where the
215bf215546Sopenharmony_ci    * loader does understand VK_EXT_private_data, we'll never see a
216bf215546Sopenharmony_ci    * vkGet/SetPrivateDataEXT call on a swapchain because the loader will
217bf215546Sopenharmony_ci    * handle it.
218bf215546Sopenharmony_ci    */
219bf215546Sopenharmony_ci   if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {
220bf215546Sopenharmony_ci      mtx_lock(&device->swapchain_private_mtx);
221bf215546Sopenharmony_ci      VkResult result = get_swapchain_private_data_locked(device, objectHandle,
222bf215546Sopenharmony_ci                                                          slot, private_data);
223bf215546Sopenharmony_ci      mtx_unlock(&device->swapchain_private_mtx);
224bf215546Sopenharmony_ci      return result;
225bf215546Sopenharmony_ci   }
226bf215546Sopenharmony_ci#endif /* ANDROID */
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   struct vk_object_base *obj =
229bf215546Sopenharmony_ci      vk_object_base_from_u64_handle(objectHandle, objectType);
230bf215546Sopenharmony_ci   *private_data = util_sparse_array_get(&obj->private_data, slot->index);
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   return VK_SUCCESS;
233bf215546Sopenharmony_ci}
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ciVkResult
236bf215546Sopenharmony_civk_object_base_set_private_data(struct vk_device *device,
237bf215546Sopenharmony_ci                                VkObjectType objectType,
238bf215546Sopenharmony_ci                                uint64_t objectHandle,
239bf215546Sopenharmony_ci                                VkPrivateDataSlot privateDataSlot,
240bf215546Sopenharmony_ci                                uint64_t data)
241bf215546Sopenharmony_ci{
242bf215546Sopenharmony_ci   uint64_t *private_data;
243bf215546Sopenharmony_ci   VkResult result = vk_object_base_private_data(device,
244bf215546Sopenharmony_ci                                                 objectType, objectHandle,
245bf215546Sopenharmony_ci                                                 privateDataSlot,
246bf215546Sopenharmony_ci                                                 &private_data);
247bf215546Sopenharmony_ci   if (unlikely(result != VK_SUCCESS))
248bf215546Sopenharmony_ci      return result;
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   *private_data = data;
251bf215546Sopenharmony_ci   return VK_SUCCESS;
252bf215546Sopenharmony_ci}
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_civoid
255bf215546Sopenharmony_civk_object_base_get_private_data(struct vk_device *device,
256bf215546Sopenharmony_ci                                VkObjectType objectType,
257bf215546Sopenharmony_ci                                uint64_t objectHandle,
258bf215546Sopenharmony_ci                                VkPrivateDataSlot privateDataSlot,
259bf215546Sopenharmony_ci                                uint64_t *pData)
260bf215546Sopenharmony_ci{
261bf215546Sopenharmony_ci   uint64_t *private_data;
262bf215546Sopenharmony_ci   VkResult result = vk_object_base_private_data(device,
263bf215546Sopenharmony_ci                                                 objectType, objectHandle,
264bf215546Sopenharmony_ci                                                 privateDataSlot,
265bf215546Sopenharmony_ci                                                 &private_data);
266bf215546Sopenharmony_ci   if (likely(result == VK_SUCCESS)) {
267bf215546Sopenharmony_ci      *pData = *private_data;
268bf215546Sopenharmony_ci   } else {
269bf215546Sopenharmony_ci      *pData = 0;
270bf215546Sopenharmony_ci   }
271bf215546Sopenharmony_ci}
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
274bf215546Sopenharmony_civk_common_CreatePrivateDataSlotEXT(VkDevice _device,
275bf215546Sopenharmony_ci                                   const VkPrivateDataSlotCreateInfo *pCreateInfo,
276bf215546Sopenharmony_ci                                   const VkAllocationCallbacks *pAllocator,
277bf215546Sopenharmony_ci                                   VkPrivateDataSlot *pPrivateDataSlot)
278bf215546Sopenharmony_ci{
279bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
280bf215546Sopenharmony_ci   return vk_private_data_slot_create(device, pCreateInfo, pAllocator,
281bf215546Sopenharmony_ci                                      pPrivateDataSlot);
282bf215546Sopenharmony_ci}
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
285bf215546Sopenharmony_civk_common_DestroyPrivateDataSlotEXT(VkDevice _device,
286bf215546Sopenharmony_ci                                    VkPrivateDataSlot privateDataSlot,
287bf215546Sopenharmony_ci                                    const VkAllocationCallbacks *pAllocator)
288bf215546Sopenharmony_ci{
289bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
290bf215546Sopenharmony_ci   vk_private_data_slot_destroy(device, privateDataSlot, pAllocator);
291bf215546Sopenharmony_ci}
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
294bf215546Sopenharmony_civk_common_SetPrivateDataEXT(VkDevice _device,
295bf215546Sopenharmony_ci                            VkObjectType objectType,
296bf215546Sopenharmony_ci                            uint64_t objectHandle,
297bf215546Sopenharmony_ci                            VkPrivateDataSlot privateDataSlot,
298bf215546Sopenharmony_ci                            uint64_t data)
299bf215546Sopenharmony_ci{
300bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
301bf215546Sopenharmony_ci   return vk_object_base_set_private_data(device,
302bf215546Sopenharmony_ci                                          objectType, objectHandle,
303bf215546Sopenharmony_ci                                          privateDataSlot, data);
304bf215546Sopenharmony_ci}
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
307bf215546Sopenharmony_civk_common_GetPrivateDataEXT(VkDevice _device,
308bf215546Sopenharmony_ci                            VkObjectType objectType,
309bf215546Sopenharmony_ci                            uint64_t objectHandle,
310bf215546Sopenharmony_ci                            VkPrivateDataSlot privateDataSlot,
311bf215546Sopenharmony_ci                            uint64_t *pData)
312bf215546Sopenharmony_ci{
313bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
314bf215546Sopenharmony_ci   vk_object_base_get_private_data(device,
315bf215546Sopenharmony_ci                                   objectType, objectHandle,
316bf215546Sopenharmony_ci                                   privateDataSlot, pData);
317bf215546Sopenharmony_ci}
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ciconst char *
320bf215546Sopenharmony_civk_object_base_name(struct vk_object_base *obj)
321bf215546Sopenharmony_ci{
322bf215546Sopenharmony_ci   if (obj->object_name)
323bf215546Sopenharmony_ci      return obj->object_name;
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   obj->object_name = vk_asprintf(&obj->device->alloc,
326bf215546Sopenharmony_ci                                  VK_SYSTEM_ALLOCATION_SCOPE_DEVICE,
327bf215546Sopenharmony_ci                                  "%s(0x%"PRIx64")",
328bf215546Sopenharmony_ci                                  vk_ObjectType_to_ObjectName(obj->type),
329bf215546Sopenharmony_ci                                  (uint64_t)(uintptr_t)obj);
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   return obj->object_name;
332bf215546Sopenharmony_ci}
333