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#ifndef VK_OBJECT_H
24bf215546Sopenharmony_ci#define VK_OBJECT_H
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include <vulkan/vulkan.h>
27bf215546Sopenharmony_ci#include <vulkan/vk_icd.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "c11/threads.h"
30bf215546Sopenharmony_ci#include "util/macros.h"
31bf215546Sopenharmony_ci#include "util/sparse_array.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#ifdef __cplusplus
34bf215546Sopenharmony_ciextern "C" {
35bf215546Sopenharmony_ci#endif
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cistruct hash_table;
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_cistruct vk_device;
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci/** Base struct for all Vulkan objects */
42bf215546Sopenharmony_cistruct vk_object_base {
43bf215546Sopenharmony_ci   VK_LOADER_DATA _loader_data;
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   /** Type of this object
46bf215546Sopenharmony_ci    *
47bf215546Sopenharmony_ci    * This is used for runtime type checking when casting to and from Vulkan
48bf215546Sopenharmony_ci    * handle types since compile-time type checking doesn't always work.
49bf215546Sopenharmony_ci    */
50bf215546Sopenharmony_ci   VkObjectType type;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   /** Pointer to the device in which this object exists, if any
53bf215546Sopenharmony_ci    *
54bf215546Sopenharmony_ci    * This is NULL for instances and physical devices but should point to a
55bf215546Sopenharmony_ci    * valid vk_device for almost everything else.  (There are a few WSI
56bf215546Sopenharmony_ci    * objects that don't inherit from a device.)
57bf215546Sopenharmony_ci    */
58bf215546Sopenharmony_ci   struct vk_device *device;
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   /* True if this object is fully constructed and visible to the client */
61bf215546Sopenharmony_ci   bool client_visible;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   /* For VK_EXT_private_data */
64bf215546Sopenharmony_ci   struct util_sparse_array private_data;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   /* VK_EXT_debug_utils */
67bf215546Sopenharmony_ci   char *object_name;
68bf215546Sopenharmony_ci};
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci/** Initialize a vk_base_object
71bf215546Sopenharmony_ci *
72bf215546Sopenharmony_ci * @param[in]  device   The vk_device this object was created from or NULL
73bf215546Sopenharmony_ci * @param[out] base     The vk_object_base to initialize
74bf215546Sopenharmony_ci * @param[in]  obj_type The VkObjectType of the object being initialized
75bf215546Sopenharmony_ci */
76bf215546Sopenharmony_civoid vk_object_base_init(struct vk_device *device,
77bf215546Sopenharmony_ci                         struct vk_object_base *base,
78bf215546Sopenharmony_ci                         VkObjectType obj_type);
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci/** Tear down a vk_object_base
81bf215546Sopenharmony_ci *
82bf215546Sopenharmony_ci * @param[out] base     The vk_object_base being torn down
83bf215546Sopenharmony_ci */
84bf215546Sopenharmony_civoid vk_object_base_finish(struct vk_object_base *base);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_cistatic inline void
87bf215546Sopenharmony_civk_object_base_assert_valid(ASSERTED struct vk_object_base *base,
88bf215546Sopenharmony_ci                            ASSERTED VkObjectType obj_type)
89bf215546Sopenharmony_ci{
90bf215546Sopenharmony_ci   assert(base == NULL || base->type == obj_type);
91bf215546Sopenharmony_ci}
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_cistatic inline struct vk_object_base *
94bf215546Sopenharmony_civk_object_base_from_u64_handle(uint64_t handle, VkObjectType obj_type)
95bf215546Sopenharmony_ci{
96bf215546Sopenharmony_ci   struct vk_object_base *base = (struct vk_object_base *)(uintptr_t)handle;
97bf215546Sopenharmony_ci   vk_object_base_assert_valid(base, obj_type);
98bf215546Sopenharmony_ci   return base;
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci/** Define handle cast macros for the given dispatchable handle type
102bf215546Sopenharmony_ci *
103bf215546Sopenharmony_ci * For a given `driver_struct`, this defines `driver_struct_to_handle()` and
104bf215546Sopenharmony_ci * `driver_struct_from_handle()` helpers which provide type-safe (as much as
105bf215546Sopenharmony_ci * possible with Vulkan handle types) casts to and from the `driver_struct`
106bf215546Sopenharmony_ci * type.  As an added layer of protection, these casts use the provided
107bf215546Sopenharmony_ci * `VkObjectType` to assert that the object is of the correct type when
108bf215546Sopenharmony_ci * running with a debug build.
109bf215546Sopenharmony_ci *
110bf215546Sopenharmony_ci * @param __driver_type The name of the driver struct; it is assumed this is
111bf215546Sopenharmony_ci *                      the name of a struct type and `struct` will be
112bf215546Sopenharmony_ci *                      prepended automatically
113bf215546Sopenharmony_ci *
114bf215546Sopenharmony_ci * @param __base        The name of the vk_base_object member
115bf215546Sopenharmony_ci *
116bf215546Sopenharmony_ci * @param __VkType      The Vulkan object type such as VkImage
117bf215546Sopenharmony_ci *
118bf215546Sopenharmony_ci * @param __VK_TYPE     The VkObjectType corresponding to __VkType, such as
119bf215546Sopenharmony_ci *                      VK_OBJECT_TYPE_IMAGE
120bf215546Sopenharmony_ci */
121bf215546Sopenharmony_ci#define VK_DEFINE_HANDLE_CASTS(__driver_type, __base, __VkType, __VK_TYPE) \
122bf215546Sopenharmony_ci   static inline struct __driver_type *                                    \
123bf215546Sopenharmony_ci   __driver_type ## _from_handle(__VkType _handle)                         \
124bf215546Sopenharmony_ci   {                                                                       \
125bf215546Sopenharmony_ci      struct vk_object_base *base = (struct vk_object_base *)_handle;      \
126bf215546Sopenharmony_ci      vk_object_base_assert_valid(base, __VK_TYPE);                        \
127bf215546Sopenharmony_ci      STATIC_ASSERT(offsetof(struct __driver_type, __base) == 0);          \
128bf215546Sopenharmony_ci      return (struct __driver_type *) base;                                \
129bf215546Sopenharmony_ci   }                                                                       \
130bf215546Sopenharmony_ci                                                                           \
131bf215546Sopenharmony_ci   static inline __VkType                                                  \
132bf215546Sopenharmony_ci   __driver_type ## _to_handle(struct __driver_type *_obj)                 \
133bf215546Sopenharmony_ci   {                                                                       \
134bf215546Sopenharmony_ci      vk_object_base_assert_valid(&_obj->__base, __VK_TYPE);               \
135bf215546Sopenharmony_ci      if (_obj != NULL)                                                    \
136bf215546Sopenharmony_ci         _obj->__base.client_visible = true;                               \
137bf215546Sopenharmony_ci      return (__VkType) _obj;                                              \
138bf215546Sopenharmony_ci   }
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci/** Define handle cast macros for the given non-dispatchable handle type
141bf215546Sopenharmony_ci *
142bf215546Sopenharmony_ci * For a given `driver_struct`, this defines `driver_struct_to_handle()` and
143bf215546Sopenharmony_ci * `driver_struct_from_handle()` helpers which provide type-safe (as much as
144bf215546Sopenharmony_ci * possible with Vulkan handle types) casts to and from the `driver_struct`
145bf215546Sopenharmony_ci * type.  As an added layer of protection, these casts use the provided
146bf215546Sopenharmony_ci * `VkObjectType` to assert that the object is of the correct type when
147bf215546Sopenharmony_ci * running with a debug build.
148bf215546Sopenharmony_ci *
149bf215546Sopenharmony_ci * @param __driver_type The name of the driver struct; it is assumed this is
150bf215546Sopenharmony_ci *                      the name of a struct type and `struct` will be
151bf215546Sopenharmony_ci *                      prepended automatically
152bf215546Sopenharmony_ci *
153bf215546Sopenharmony_ci * @param __base        The name of the vk_base_object member
154bf215546Sopenharmony_ci *
155bf215546Sopenharmony_ci * @param __VkType      The Vulkan object type such as VkImage
156bf215546Sopenharmony_ci *
157bf215546Sopenharmony_ci * @param __VK_TYPE     The VkObjectType corresponding to __VkType, such as
158bf215546Sopenharmony_ci *                      VK_OBJECT_TYPE_IMAGE
159bf215546Sopenharmony_ci */
160bf215546Sopenharmony_ci#define VK_DEFINE_NONDISP_HANDLE_CASTS(__driver_type, __base, __VkType, __VK_TYPE) \
161bf215546Sopenharmony_ci   static inline struct __driver_type *                                    \
162bf215546Sopenharmony_ci   __driver_type ## _from_handle(__VkType _handle)                         \
163bf215546Sopenharmony_ci   {                                                                       \
164bf215546Sopenharmony_ci      struct vk_object_base *base =                                        \
165bf215546Sopenharmony_ci         (struct vk_object_base *)(uintptr_t)_handle;                      \
166bf215546Sopenharmony_ci      vk_object_base_assert_valid(base, __VK_TYPE);                        \
167bf215546Sopenharmony_ci      STATIC_ASSERT(offsetof(struct __driver_type, __base) == 0);          \
168bf215546Sopenharmony_ci      return (struct __driver_type *)base;                                 \
169bf215546Sopenharmony_ci   }                                                                       \
170bf215546Sopenharmony_ci                                                                           \
171bf215546Sopenharmony_ci   static inline __VkType                                                  \
172bf215546Sopenharmony_ci   __driver_type ## _to_handle(struct __driver_type *_obj)                 \
173bf215546Sopenharmony_ci   {                                                                       \
174bf215546Sopenharmony_ci      vk_object_base_assert_valid(&_obj->__base, __VK_TYPE);               \
175bf215546Sopenharmony_ci      if (_obj != NULL)                                                    \
176bf215546Sopenharmony_ci         _obj->__base.client_visible = true;                               \
177bf215546Sopenharmony_ci      return (__VkType)(uintptr_t) _obj;                                   \
178bf215546Sopenharmony_ci   }
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci/** Declares a __driver_type pointer which represents __handle
181bf215546Sopenharmony_ci *
182bf215546Sopenharmony_ci * @param __driver_type The name of the driver struct; it is assumed this is
183bf215546Sopenharmony_ci *                      the name of a struct type and `struct` will be
184bf215546Sopenharmony_ci *                      prepended automatically
185bf215546Sopenharmony_ci *
186bf215546Sopenharmony_ci * @param __name        The name of the declared pointer
187bf215546Sopenharmony_ci *
188bf215546Sopenharmony_ci * @param __handle      The Vulkan object handle with which to initialize
189bf215546Sopenharmony_ci *                      `__name`
190bf215546Sopenharmony_ci */
191bf215546Sopenharmony_ci#define VK_FROM_HANDLE(__driver_type, __name, __handle) \
192bf215546Sopenharmony_ci   struct __driver_type *__name = __driver_type ## _from_handle(__handle)
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci/* Helpers for vk object (de)allocation and (de)initialization */
195bf215546Sopenharmony_civoid *
196bf215546Sopenharmony_civk_object_alloc(struct vk_device *device,
197bf215546Sopenharmony_ci                const VkAllocationCallbacks *alloc,
198bf215546Sopenharmony_ci                size_t size,
199bf215546Sopenharmony_ci                VkObjectType vk_obj_type);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_civoid *
202bf215546Sopenharmony_civk_object_zalloc(struct vk_device *device,
203bf215546Sopenharmony_ci                const VkAllocationCallbacks *alloc,
204bf215546Sopenharmony_ci                size_t size,
205bf215546Sopenharmony_ci                VkObjectType vk_obj_type);
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_cistruct vk_multialloc;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_civoid *
210bf215546Sopenharmony_civk_object_multialloc(struct vk_device *device,
211bf215546Sopenharmony_ci                     struct vk_multialloc *ma,
212bf215546Sopenharmony_ci                     const VkAllocationCallbacks *alloc,
213bf215546Sopenharmony_ci                     VkObjectType vk_obj_type);
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_civoid *
216bf215546Sopenharmony_civk_object_multizalloc(struct vk_device *device,
217bf215546Sopenharmony_ci                      struct vk_multialloc *ma,
218bf215546Sopenharmony_ci                      const VkAllocationCallbacks *alloc,
219bf215546Sopenharmony_ci                      VkObjectType vk_obj_type);
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_civoid
222bf215546Sopenharmony_civk_object_free(struct vk_device *device,
223bf215546Sopenharmony_ci               const VkAllocationCallbacks *alloc,
224bf215546Sopenharmony_ci               void *data);
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_cistruct vk_private_data_slot {
228bf215546Sopenharmony_ci   struct vk_object_base base;
229bf215546Sopenharmony_ci   uint32_t index;
230bf215546Sopenharmony_ci};
231bf215546Sopenharmony_ciVK_DEFINE_NONDISP_HANDLE_CASTS(vk_private_data_slot, base,
232bf215546Sopenharmony_ci                               VkPrivateDataSlot,
233bf215546Sopenharmony_ci                               VK_OBJECT_TYPE_PRIVATE_DATA_SLOT);
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ciVkResult
236bf215546Sopenharmony_civk_private_data_slot_create(struct vk_device *device,
237bf215546Sopenharmony_ci                            const VkPrivateDataSlotCreateInfo* pCreateInfo,
238bf215546Sopenharmony_ci                            const VkAllocationCallbacks* pAllocator,
239bf215546Sopenharmony_ci                            VkPrivateDataSlot* pPrivateDataSlot);
240bf215546Sopenharmony_civoid
241bf215546Sopenharmony_civk_private_data_slot_destroy(struct vk_device *device,
242bf215546Sopenharmony_ci                             VkPrivateDataSlot privateDataSlot,
243bf215546Sopenharmony_ci                             const VkAllocationCallbacks *pAllocator);
244bf215546Sopenharmony_ciVkResult
245bf215546Sopenharmony_civk_object_base_set_private_data(struct vk_device *device,
246bf215546Sopenharmony_ci                                VkObjectType objectType,
247bf215546Sopenharmony_ci                                uint64_t objectHandle,
248bf215546Sopenharmony_ci                                VkPrivateDataSlot privateDataSlot,
249bf215546Sopenharmony_ci                                uint64_t data);
250bf215546Sopenharmony_civoid
251bf215546Sopenharmony_civk_object_base_get_private_data(struct vk_device *device,
252bf215546Sopenharmony_ci                                VkObjectType objectType,
253bf215546Sopenharmony_ci                                uint64_t objectHandle,
254bf215546Sopenharmony_ci                                VkPrivateDataSlot privateDataSlot,
255bf215546Sopenharmony_ci                                uint64_t *pData);
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ciconst char *
258bf215546Sopenharmony_civk_object_base_name(struct vk_object_base *obj);
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci#ifdef __cplusplus
261bf215546Sopenharmony_ci}
262bf215546Sopenharmony_ci#endif
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci#endif /* VK_OBJECT_H */
265