We tend to try to reduce the number of allocation calls the Vulkan driver uses by doing a single allocation whenever possible for a data structure. While this has certain downsides (usually code complexity), it does mean error handling and cleanup is much easier. This commit adds a nice little helper struct for getting rid of some of that complexity. --- src/intel/vulkan/anv_private.h | 65 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 53057a5..1c5c044 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -269,6 +269,71 @@ void anv_loge_v(const char *format, va_list va); #define anv_assert(x) #endif +struct anv_multialloc { + const VkAllocationCallbacks *alloc; + VkSystemAllocationScope scope; + + size_t size; + size_t align; + + uint32_t ptr_count; + void **ptrs[10]; +}; + +static inline void +anv_multialloc_init(struct anv_multialloc *ma, + const VkAllocationCallbacks *alloc, + VkSystemAllocationScope scope) +{ + ma->alloc = alloc; + ma->scope = scope; + ma->size = 0; + ma->align = 0; + ma->ptr_count = 0; +} + +static inline void +anv_multialloc_init2(struct anv_multialloc *ma, + const VkAllocationCallbacks *parent_alloc, + const VkAllocationCallbacks *alloc, + VkSystemAllocationScope scope) +{ + anv_multialloc_init(ma, alloc ? alloc : parent_alloc, scope); +} + +static inline void +_anv_multialloc_add(struct anv_multialloc *ma, + void **ptr, size_t size, size_t align) +{ + size_t offset = align_u64(ma->size, align); + ma->size = offset + size; + ma->align = MAX2(ma->align, align); + + /* Store the offset in the pointer. */ + *ptr = (void *)(uintptr_t)offset; + + assert(ma->ptr_count < ARRAY_SIZE(ma->ptrs)); + ma->ptrs[ma->ptr_count++] = ptr; +} + +#define anv_multialloc_add(_ma, _ptr, _count) \ + _anv_multialloc_add((_ma), (void **)(_ptr), \ + (_count) * sizeof(**(_ptr)), __alignof__(**(_ptr))) + +static inline void * +anv_multialloc_finish(struct anv_multialloc *ma) +{ + void *ptr = vk_alloc(ma->alloc, ma->size, ma->align, ma->scope); + if (!ptr) + return NULL; + + /* Fill out each of the pointers with their final value */ + for (uint32_t i = 0; i < ma->ptr_count; i++) + *ma->ptrs[i] = ptr + (uintptr_t)*ma->ptrs[i]; + + return ptr; +} + /** * A dynamically growable, circular buffer. Elements are added at head and * removed from tail. head and tail are free-running uint32_t indices and we -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev