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