1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2017 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg#ifndef VK_UTIL_H 24b8e80941Smrg#define VK_UTIL_H 25b8e80941Smrg 26b8e80941Smrg#ifdef __cplusplus 27b8e80941Smrgextern "C" { 28b8e80941Smrg#endif 29b8e80941Smrg 30b8e80941Smrg/* common inlines and macros for vulkan drivers */ 31b8e80941Smrg 32b8e80941Smrg#include <vulkan/vulkan.h> 33b8e80941Smrg 34b8e80941Smrg#define vk_foreach_struct(__iter, __start) \ 35b8e80941Smrg for (struct VkBaseOutStructure *__iter = (struct VkBaseOutStructure *)(__start); \ 36b8e80941Smrg __iter; __iter = __iter->pNext) 37b8e80941Smrg 38b8e80941Smrg#define vk_foreach_struct_const(__iter, __start) \ 39b8e80941Smrg for (const struct VkBaseInStructure *__iter = (const struct VkBaseInStructure *)(__start); \ 40b8e80941Smrg __iter; __iter = __iter->pNext) 41b8e80941Smrg 42b8e80941Smrg/** 43b8e80941Smrg * A wrapper for a Vulkan output array. A Vulkan output array is one that 44b8e80941Smrg * follows the convention of the parameters to 45b8e80941Smrg * vkGetPhysicalDeviceQueueFamilyProperties(). 46b8e80941Smrg * 47b8e80941Smrg * Example Usage: 48b8e80941Smrg * 49b8e80941Smrg * VkResult 50b8e80941Smrg * vkGetPhysicalDeviceQueueFamilyProperties( 51b8e80941Smrg * VkPhysicalDevice physicalDevice, 52b8e80941Smrg * uint32_t* pQueueFamilyPropertyCount, 53b8e80941Smrg * VkQueueFamilyProperties* pQueueFamilyProperties) 54b8e80941Smrg * { 55b8e80941Smrg * VK_OUTARRAY_MAKE(props, pQueueFamilyProperties, 56b8e80941Smrg * pQueueFamilyPropertyCount); 57b8e80941Smrg * 58b8e80941Smrg * vk_outarray_append(&props, p) { 59b8e80941Smrg * p->queueFlags = ...; 60b8e80941Smrg * p->queueCount = ...; 61b8e80941Smrg * } 62b8e80941Smrg * 63b8e80941Smrg * vk_outarray_append(&props, p) { 64b8e80941Smrg * p->queueFlags = ...; 65b8e80941Smrg * p->queueCount = ...; 66b8e80941Smrg * } 67b8e80941Smrg * 68b8e80941Smrg * return vk_outarray_status(&props); 69b8e80941Smrg * } 70b8e80941Smrg */ 71b8e80941Smrgstruct __vk_outarray { 72b8e80941Smrg /** May be null. */ 73b8e80941Smrg void *data; 74b8e80941Smrg 75b8e80941Smrg /** 76b8e80941Smrg * Capacity, in number of elements. Capacity is unlimited (UINT32_MAX) if 77b8e80941Smrg * data is null. 78b8e80941Smrg */ 79b8e80941Smrg uint32_t cap; 80b8e80941Smrg 81b8e80941Smrg /** 82b8e80941Smrg * Count of elements successfully written to the array. Every write is 83b8e80941Smrg * considered successful if data is null. 84b8e80941Smrg */ 85b8e80941Smrg uint32_t *filled_len; 86b8e80941Smrg 87b8e80941Smrg /** 88b8e80941Smrg * Count of elements that would have been written to the array if its 89b8e80941Smrg * capacity were sufficient. Vulkan functions often return VK_INCOMPLETE 90b8e80941Smrg * when `*filled_len < wanted_len`. 91b8e80941Smrg */ 92b8e80941Smrg uint32_t wanted_len; 93b8e80941Smrg}; 94b8e80941Smrg 95b8e80941Smrgstatic inline void 96b8e80941Smrg__vk_outarray_init(struct __vk_outarray *a, 97b8e80941Smrg void *data, uint32_t *restrict len) 98b8e80941Smrg{ 99b8e80941Smrg a->data = data; 100b8e80941Smrg a->cap = *len; 101b8e80941Smrg a->filled_len = len; 102b8e80941Smrg *a->filled_len = 0; 103b8e80941Smrg a->wanted_len = 0; 104b8e80941Smrg 105b8e80941Smrg if (a->data == NULL) 106b8e80941Smrg a->cap = UINT32_MAX; 107b8e80941Smrg} 108b8e80941Smrg 109b8e80941Smrgstatic inline VkResult 110b8e80941Smrg__vk_outarray_status(const struct __vk_outarray *a) 111b8e80941Smrg{ 112b8e80941Smrg if (*a->filled_len < a->wanted_len) 113b8e80941Smrg return VK_INCOMPLETE; 114b8e80941Smrg else 115b8e80941Smrg return VK_SUCCESS; 116b8e80941Smrg} 117b8e80941Smrg 118b8e80941Smrgstatic inline void * 119b8e80941Smrg__vk_outarray_next(struct __vk_outarray *a, size_t elem_size) 120b8e80941Smrg{ 121b8e80941Smrg void *p = NULL; 122b8e80941Smrg 123b8e80941Smrg a->wanted_len += 1; 124b8e80941Smrg 125b8e80941Smrg if (*a->filled_len >= a->cap) 126b8e80941Smrg return NULL; 127b8e80941Smrg 128b8e80941Smrg if (a->data != NULL) 129b8e80941Smrg p = (uint8_t *)a->data + (*a->filled_len) * elem_size; 130b8e80941Smrg 131b8e80941Smrg *a->filled_len += 1; 132b8e80941Smrg 133b8e80941Smrg return p; 134b8e80941Smrg} 135b8e80941Smrg 136b8e80941Smrg#define vk_outarray(elem_t) \ 137b8e80941Smrg struct { \ 138b8e80941Smrg struct __vk_outarray base; \ 139b8e80941Smrg elem_t meta[]; \ 140b8e80941Smrg } 141b8e80941Smrg 142b8e80941Smrg#define vk_outarray_typeof_elem(a) __typeof__((a)->meta[0]) 143b8e80941Smrg#define vk_outarray_sizeof_elem(a) sizeof((a)->meta[0]) 144b8e80941Smrg 145b8e80941Smrg#define vk_outarray_init(a, data, len) \ 146b8e80941Smrg __vk_outarray_init(&(a)->base, (data), (len)) 147b8e80941Smrg 148b8e80941Smrg#define VK_OUTARRAY_MAKE(name, data, len) \ 149b8e80941Smrg vk_outarray(__typeof__((data)[0])) name; \ 150b8e80941Smrg vk_outarray_init(&name, (data), (len)) 151b8e80941Smrg 152b8e80941Smrg#define vk_outarray_status(a) \ 153b8e80941Smrg __vk_outarray_status(&(a)->base) 154b8e80941Smrg 155b8e80941Smrg#define vk_outarray_next(a) \ 156b8e80941Smrg ((vk_outarray_typeof_elem(a) *) \ 157b8e80941Smrg __vk_outarray_next(&(a)->base, vk_outarray_sizeof_elem(a))) 158b8e80941Smrg 159b8e80941Smrg/** 160b8e80941Smrg * Append to a Vulkan output array. 161b8e80941Smrg * 162b8e80941Smrg * This is a block-based macro. For example: 163b8e80941Smrg * 164b8e80941Smrg * vk_outarray_append(&a, elem) { 165b8e80941Smrg * elem->foo = ...; 166b8e80941Smrg * elem->bar = ...; 167b8e80941Smrg * } 168b8e80941Smrg * 169b8e80941Smrg * The array `a` has type `vk_outarray(elem_t) *`. It is usually declared with 170b8e80941Smrg * VK_OUTARRAY_MAKE(). The variable `elem` is block-scoped and has type 171b8e80941Smrg * `elem_t *`. 172b8e80941Smrg * 173b8e80941Smrg * The macro unconditionally increments the array's `wanted_len`. If the array 174b8e80941Smrg * is not full, then the macro also increment its `filled_len` and then 175b8e80941Smrg * executes the block. When the block is executed, `elem` is non-null and 176b8e80941Smrg * points to the newly appended element. 177b8e80941Smrg */ 178b8e80941Smrg#define vk_outarray_append(a, elem) \ 179b8e80941Smrg for (vk_outarray_typeof_elem(a) *elem = vk_outarray_next(a); \ 180b8e80941Smrg elem != NULL; elem = NULL) 181b8e80941Smrg 182b8e80941Smrgstatic inline void * 183b8e80941Smrg__vk_find_struct(void *start, VkStructureType sType) 184b8e80941Smrg{ 185b8e80941Smrg vk_foreach_struct(s, start) { 186b8e80941Smrg if (s->sType == sType) 187b8e80941Smrg return s; 188b8e80941Smrg } 189b8e80941Smrg 190b8e80941Smrg return NULL; 191b8e80941Smrg} 192b8e80941Smrg 193b8e80941Smrg#define vk_find_struct(__start, __sType) \ 194b8e80941Smrg __vk_find_struct((__start), VK_STRUCTURE_TYPE_##__sType) 195b8e80941Smrg 196b8e80941Smrg#define vk_find_struct_const(__start, __sType) \ 197b8e80941Smrg (const void *)__vk_find_struct((void *)(__start), VK_STRUCTURE_TYPE_##__sType) 198b8e80941Smrg 199b8e80941Smrgstatic inline void 200b8e80941Smrg__vk_append_struct(void *start, void *element) 201b8e80941Smrg{ 202b8e80941Smrg vk_foreach_struct(s, start) { 203b8e80941Smrg if (s->pNext) 204b8e80941Smrg continue; 205b8e80941Smrg 206b8e80941Smrg s->pNext = (struct VkBaseOutStructure *) element; 207b8e80941Smrg break; 208b8e80941Smrg } 209b8e80941Smrg} 210b8e80941Smrg 211b8e80941Smrguint32_t vk_get_driver_version(void); 212b8e80941Smrg 213b8e80941Smrguint32_t vk_get_version_override(void); 214b8e80941Smrg 215b8e80941Smrg#define VK_EXT_OFFSET (1000000000UL) 216b8e80941Smrg#define VK_ENUM_EXTENSION(__enum) \ 217b8e80941Smrg ((__enum) >= VK_EXT_OFFSET ? ((((__enum) - VK_EXT_OFFSET) / 1000UL) + 1) : 0) 218b8e80941Smrg#define VK_ENUM_OFFSET(__enum) \ 219b8e80941Smrg ((__enum) >= VK_EXT_OFFSET ? ((__enum) % 1000) : (__enum)) 220b8e80941Smrg 221b8e80941Smrg#ifdef __cplusplus 222b8e80941Smrg} 223b8e80941Smrg#endif 224b8e80941Smrg 225b8e80941Smrg#endif /* VK_UTIL_H */ 226