vk_util.h revision 01e04c3f
1/* 2 * Copyright © 2017 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_UTIL_H 24#define VK_UTIL_H 25 26/* common inlines and macros for vulkan drivers */ 27 28#include <vulkan/vulkan.h> 29 30struct vk_struct_common { 31 VkStructureType sType; 32 struct vk_struct_common *pNext; 33}; 34 35#define vk_foreach_struct(__iter, __start) \ 36 for (struct vk_struct_common *__iter = (struct vk_struct_common *)(__start); \ 37 __iter; __iter = __iter->pNext) 38 39#define vk_foreach_struct_const(__iter, __start) \ 40 for (const struct vk_struct_common *__iter = (const struct vk_struct_common *)(__start); \ 41 __iter; __iter = __iter->pNext) 42 43/** 44 * A wrapper for a Vulkan output array. A Vulkan output array is one that 45 * follows the convention of the parameters to 46 * vkGetPhysicalDeviceQueueFamilyProperties(). 47 * 48 * Example Usage: 49 * 50 * VkResult 51 * vkGetPhysicalDeviceQueueFamilyProperties( 52 * VkPhysicalDevice physicalDevice, 53 * uint32_t* pQueueFamilyPropertyCount, 54 * VkQueueFamilyProperties* pQueueFamilyProperties) 55 * { 56 * VK_OUTARRAY_MAKE(props, pQueueFamilyProperties, 57 * pQueueFamilyPropertyCount); 58 * 59 * vk_outarray_append(&props, p) { 60 * p->queueFlags = ...; 61 * p->queueCount = ...; 62 * } 63 * 64 * vk_outarray_append(&props, p) { 65 * p->queueFlags = ...; 66 * p->queueCount = ...; 67 * } 68 * 69 * return vk_outarray_status(&props); 70 * } 71 */ 72struct __vk_outarray { 73 /** May be null. */ 74 void *data; 75 76 /** 77 * Capacity, in number of elements. Capacity is unlimited (UINT32_MAX) if 78 * data is null. 79 */ 80 uint32_t cap; 81 82 /** 83 * Count of elements successfully written to the array. Every write is 84 * considered successful if data is null. 85 */ 86 uint32_t *filled_len; 87 88 /** 89 * Count of elements that would have been written to the array if its 90 * capacity were sufficient. Vulkan functions often return VK_INCOMPLETE 91 * when `*filled_len < wanted_len`. 92 */ 93 uint32_t wanted_len; 94}; 95 96static inline void 97__vk_outarray_init(struct __vk_outarray *a, 98 void *data, uint32_t *restrict len) 99{ 100 a->data = data; 101 a->cap = *len; 102 a->filled_len = len; 103 *a->filled_len = 0; 104 a->wanted_len = 0; 105 106 if (a->data == NULL) 107 a->cap = UINT32_MAX; 108} 109 110static inline VkResult 111__vk_outarray_status(const struct __vk_outarray *a) 112{ 113 if (*a->filled_len < a->wanted_len) 114 return VK_INCOMPLETE; 115 else 116 return VK_SUCCESS; 117} 118 119static inline void * 120__vk_outarray_next(struct __vk_outarray *a, size_t elem_size) 121{ 122 void *p = NULL; 123 124 a->wanted_len += 1; 125 126 if (*a->filled_len >= a->cap) 127 return NULL; 128 129 if (a->data != NULL) 130 p = a->data + (*a->filled_len) * elem_size; 131 132 *a->filled_len += 1; 133 134 return p; 135} 136 137#define vk_outarray(elem_t) \ 138 struct { \ 139 struct __vk_outarray base; \ 140 elem_t meta[]; \ 141 } 142 143#define vk_outarray_typeof_elem(a) __typeof__((a)->meta[0]) 144#define vk_outarray_sizeof_elem(a) sizeof((a)->meta[0]) 145 146#define vk_outarray_init(a, data, len) \ 147 __vk_outarray_init(&(a)->base, (data), (len)) 148 149#define VK_OUTARRAY_MAKE(name, data, len) \ 150 vk_outarray(__typeof__((data)[0])) name; \ 151 vk_outarray_init(&name, (data), (len)) 152 153#define vk_outarray_status(a) \ 154 __vk_outarray_status(&(a)->base) 155 156#define vk_outarray_next(a) \ 157 ((vk_outarray_typeof_elem(a) *) \ 158 __vk_outarray_next(&(a)->base, vk_outarray_sizeof_elem(a))) 159 160/** 161 * Append to a Vulkan output array. 162 * 163 * This is a block-based macro. For example: 164 * 165 * vk_outarray_append(&a, elem) { 166 * elem->foo = ...; 167 * elem->bar = ...; 168 * } 169 * 170 * The array `a` has type `vk_outarray(elem_t) *`. It is usually declared with 171 * VK_OUTARRAY_MAKE(). The variable `elem` is block-scoped and has type 172 * `elem_t *`. 173 * 174 * The macro unconditionally increments the array's `wanted_len`. If the array 175 * is not full, then the macro also increment its `filled_len` and then 176 * executes the block. When the block is executed, `elem` is non-null and 177 * points to the newly appended element. 178 */ 179#define vk_outarray_append(a, elem) \ 180 for (vk_outarray_typeof_elem(a) *elem = vk_outarray_next(a); \ 181 elem != NULL; elem = NULL) 182 183static inline void * 184__vk_find_struct(void *start, VkStructureType sType) 185{ 186 vk_foreach_struct(s, start) { 187 if (s->sType == sType) 188 return s; 189 } 190 191 return NULL; 192} 193 194#define vk_find_struct(__start, __sType) \ 195 __vk_find_struct((__start), VK_STRUCTURE_TYPE_##__sType) 196 197#define vk_find_struct_const(__start, __sType) \ 198 (const void *)__vk_find_struct((void *)(__start), VK_STRUCTURE_TYPE_##__sType) 199 200uint32_t vk_get_driver_version(void); 201 202uint32_t vk_get_version_override(void); 203 204#define VK_EXT_OFFSET (1000000000UL) 205#define VK_ENUM_EXTENSION(__enum) \ 206 ((__enum) >= VK_EXT_OFFSET ? ((((__enum) - VK_EXT_OFFSET) / 1000UL) + 1) : 0) 207#define VK_ENUM_OFFSET(__enum) \ 208 ((__enum) >= VK_EXT_OFFSET ? ((__enum) % 1000) : (__enum)) 209 210#endif /* VK_UTIL_H */ 211