#ifndef VK_UTIL_H
#define VK_UTIL_H
#include "util/bitscan.h"
#include "util/macros.h"
#include "compiler/shader_enums.h"
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <vulkan/vulkan.h>
#define vk_foreach_struct(__iter, __start) \
for (struct VkBaseOutStructure *__iter = (struct VkBaseOutStructure *)(__start); \
__iter; __iter = __iter->pNext)
#define vk_foreach_struct_const(__iter, __start) \
for (const struct VkBaseInStructure *__iter = (const struct VkBaseInStructure *)(__start); \
__iter; __iter = __iter->pNext)
struct __vk_outarray {
void *data;
uint32_t cap;
uint32_t *filled_len;
uint32_t wanted_len;
};
static inline void
__vk_outarray_init(struct __vk_outarray *a,
void *data, uint32_t *restrict len)
{
a->data = data;
a->cap = *len;
a->filled_len = len;
*a->filled_len = 0;
a->wanted_len = 0;
if (a->data == NULL)
a->cap = UINT32_MAX;
}
static inline VkResult
__vk_outarray_status(const struct __vk_outarray *a)
{
if (*a->filled_len < a->wanted_len)
return VK_INCOMPLETE;
else
return VK_SUCCESS;
}
static inline void *
__vk_outarray_next(struct __vk_outarray *a, size_t elem_size)
{
void *p = NULL;
a->wanted_len += 1;
if (*a->filled_len >= a->cap)
return NULL;
if (a->data != NULL)
p = (uint8_t *)a->data + (*a->filled_len) * elem_size;
*a->filled_len += 1;
return p;
}
#define vk_outarray(elem_t) \
struct { \
struct __vk_outarray base; \
elem_t meta[]; \
}
#define vk_outarray_typeof_elem(a) __typeof__((a)->meta[0])
#define vk_outarray_sizeof_elem(a) sizeof((a)->meta[0])
#define vk_outarray_init(a, data, len) \
__vk_outarray_init(&(a)->base, (data), (len))
#define VK_OUTARRAY_MAKE(name, data, len) \
VK_OUTARRAY_MAKE_TYPED(__typeof__((data)[0]), name, data, len)
#define VK_OUTARRAY_MAKE_TYPED(type, name, data, len) \
vk_outarray(type) name; \
vk_outarray_init(&name, (data), (len))
#define vk_outarray_status(a) \
__vk_outarray_status(&(a)->base)
#define vk_outarray_next(a) \
vk_outarray_next_typed(vk_outarray_typeof_elem(a), a)
#define vk_outarray_next_typed(type, a) \
((type *) \
__vk_outarray_next(&(a)->base, vk_outarray_sizeof_elem(a)))
#define vk_outarray_append(a, elem) \
vk_outarray_append_typed(vk_outarray_typeof_elem(a), a, elem)
#define vk_outarray_append_typed(type, a, elem) \
for (type *elem = vk_outarray_next_typed(type, a); \
elem != NULL; elem = NULL)
static inline void *
__vk_find_struct(void *start, VkStructureType sType)
{
vk_foreach_struct(s, start) {
if (s->sType == sType)
return s;
}
return NULL;
}
#define vk_find_struct(__start, __sType) \
__vk_find_struct((__start), VK_STRUCTURE_TYPE_##__sType)
#define vk_find_struct_const(__start, __sType) \
(const void *)__vk_find_struct((void *)(__start), VK_STRUCTURE_TYPE_##__sType)
static inline void
__vk_append_struct(void *start, void *element)
{
vk_foreach_struct(s, start) {
if (s->pNext)
continue;
s->pNext = (struct VkBaseOutStructure *) element;
break;
}
}
uint32_t vk_get_driver_version(void);
uint32_t vk_get_version_override(void);
void vk_warn_non_conformant_implementation(const char *driver_name);
struct vk_pipeline_cache_header {
uint32_t header_size;
uint32_t header_version;
uint32_t vendor_id;
uint32_t device_id;
uint8_t uuid[VK_UUID_SIZE];
};
#define VK_EXT_OFFSET (1000000000UL)
#define VK_ENUM_EXTENSION(__enum) \
((__enum) >= VK_EXT_OFFSET ? ((((__enum) - VK_EXT_OFFSET) / 1000UL) + 1) : 0)
#define VK_ENUM_OFFSET(__enum) \
((__enum) >= VK_EXT_OFFSET ? ((__enum) % 1000) : (__enum))
#define typed_memcpy(dest, src, count) do { \
STATIC_ASSERT(sizeof(*(src)) == sizeof(*(dest))); \
memcpy((dest), (src), (count) * sizeof(*(src))); \
} while (0)
static inline gl_shader_stage
vk_to_mesa_shader_stage(VkShaderStageFlagBits vk_stage)
{
assert(util_bitcount((uint32_t) vk_stage) == 1);
return (gl_shader_stage) (ffs((uint32_t) vk_stage) - 1);
}
static inline VkShaderStageFlagBits
mesa_to_vk_shader_stage(gl_shader_stage mesa_stage)
{
return (VkShaderStageFlagBits) (1 << ((uint32_t) mesa_stage));
}
#define vk_foreach_multi_draw_indexed(_draw, _i, _pDrawInfo, _num_draws, _stride) \
for (const VkMultiDrawIndexedInfoEXT *_draw = (const void*)(_pDrawInfo); \
(_i) < (_num_draws); \
(_i)++, (_draw) = (const VkMultiDrawIndexedInfoEXT*)((const uint8_t*)(_draw) + (_stride)))
#define vk_foreach_multi_draw(_draw, _i, _pDrawInfo, _num_draws, _stride) \
for (const VkMultiDrawInfoEXT *_draw = (const void*)(_pDrawInfo); \
(_i) < (_num_draws); \
(_i)++, (_draw) = (const VkMultiDrawInfoEXT*)((const uint8_t*)(_draw) + (_stride)))
#ifdef __cplusplus
}
#endif
#endif