Path: blob/21.2-virgl/src/vulkan/util/vk_alloc.h
7099 views
/*1* Copyright © 2015 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/22#ifndef VK_ALLOC_H23#define VK_ALLOC_H2425/* common allocation inlines for vulkan drivers */2627#include <string.h>28#include <vulkan/vulkan.h>2930#include "util/u_math.h"31#include "util/macros.h"323334const VkAllocationCallbacks *35vk_default_allocator(void);3637static inline void *38vk_alloc(const VkAllocationCallbacks *alloc,39size_t size, size_t align,40VkSystemAllocationScope scope)41{42return alloc->pfnAllocation(alloc->pUserData, size, align, scope);43}4445static inline void *46vk_zalloc(const VkAllocationCallbacks *alloc,47size_t size, size_t align,48VkSystemAllocationScope scope)49{50void *mem = vk_alloc(alloc, size, align, scope);51if (mem == NULL)52return NULL;5354memset(mem, 0, size);5556return mem;57}5859static inline void *60vk_realloc(const VkAllocationCallbacks *alloc,61void *ptr, size_t size, size_t align,62VkSystemAllocationScope scope)63{64return alloc->pfnReallocation(alloc->pUserData, ptr, size, align, scope);65}6667static inline void68vk_free(const VkAllocationCallbacks *alloc, void *data)69{70if (data == NULL)71return;7273alloc->pfnFree(alloc->pUserData, data);74}7576static inline char *77vk_strdup(const VkAllocationCallbacks *alloc, const char *s,78VkSystemAllocationScope scope)79{80if (s == NULL)81return NULL;8283size_t size = strlen(s) + 1;84char *copy = vk_alloc(alloc, size, 1, scope);85if (copy == NULL)86return NULL;8788memcpy(copy, s, size);8990return copy;91}9293static inline void *94vk_alloc2(const VkAllocationCallbacks *parent_alloc,95const VkAllocationCallbacks *alloc,96size_t size, size_t align,97VkSystemAllocationScope scope)98{99if (alloc)100return vk_alloc(alloc, size, align, scope);101else102return vk_alloc(parent_alloc, size, align, scope);103}104105static inline void *106vk_zalloc2(const VkAllocationCallbacks *parent_alloc,107const VkAllocationCallbacks *alloc,108size_t size, size_t align,109VkSystemAllocationScope scope)110{111void *mem = vk_alloc2(parent_alloc, alloc, size, align, scope);112if (mem == NULL)113return NULL;114115memset(mem, 0, size);116117return mem;118}119120static inline void121vk_free2(const VkAllocationCallbacks *parent_alloc,122const VkAllocationCallbacks *alloc,123void *data)124{125if (alloc)126vk_free(alloc, data);127else128vk_free(parent_alloc, data);129}130131/* A multi-pointer allocator132*133* When copying data structures from the user (such as a render pass), it's134* common to need to allocate data for a bunch of different things. Instead135* of doing several allocations and having to handle all of the error checking136* that entails, it can be easier to do a single allocation. This struct137* helps facilitate that. The intended usage looks like this:138*139* VK_MULTIALLOC(ma)140* vk_multialloc_add(&ma, &main_ptr, 1);141* vk_multialloc_add(&ma, &substruct1, substruct1Count);142* vk_multialloc_add(&ma, &substruct2, substruct2Count);143*144* if (!vk_multialloc_alloc(&ma, pAllocator, VK_ALLOCATION_SCOPE_FOO))145* return vk_error(VK_ERROR_OUT_OF_HOST_MEORY);146*/147struct vk_multialloc {148size_t size;149size_t align;150151uint32_t ptr_count;152void **ptrs[8];153};154155#define VK_MULTIALLOC_INIT \156((struct vk_multialloc) { 0, })157158#define VK_MULTIALLOC(_name) \159struct vk_multialloc _name = VK_MULTIALLOC_INIT160161static ALWAYS_INLINE void162vk_multialloc_add_size_align(struct vk_multialloc *ma,163void **ptr, size_t size, size_t align)164{165assert(util_is_power_of_two_nonzero(align));166if (size == 0) {167*ptr = NULL;168return;169}170171size_t offset = ALIGN_POT(ma->size, align);172ma->size = offset + size;173ma->align = MAX2(ma->align, align);174175/* Store the offset in the pointer. */176*ptr = (void *)(uintptr_t)offset;177178assert(ma->ptr_count < ARRAY_SIZE(ma->ptrs));179ma->ptrs[ma->ptr_count++] = ptr;180}181182#define vk_multialloc_add_size(_ma, _ptr, _type, _size) \183do { \184_type **_tmp = (_ptr); \185(void)_tmp; \186vk_multialloc_add_size_align((_ma), (void **)(_ptr), \187(_size), alignof(_type)); \188} while(0)189190#define vk_multialloc_add(_ma, _ptr, _type, _count) \191vk_multialloc_add_size(_ma, _ptr, _type, (_count) * sizeof(**(_ptr)));192193#define VK_MULTIALLOC_DECL_SIZE(_ma, _type, _name, _size) \194_type *_name; \195vk_multialloc_add_size(_ma, &_name, _type, _size);196197#define VK_MULTIALLOC_DECL(_ma, _type, _name, _count) \198VK_MULTIALLOC_DECL_SIZE(_ma, _type, _name, (_count) * sizeof(_type));199200static ALWAYS_INLINE void *201vk_multialloc_alloc(struct vk_multialloc *ma,202const VkAllocationCallbacks *alloc,203VkSystemAllocationScope scope)204{205char *ptr = vk_alloc(alloc, ma->size, ma->align, scope);206if (!ptr)207return NULL;208209/* Fill out each of the pointers with their final value.210*211* for (uint32_t i = 0; i < ma->ptr_count; i++)212* *ma->ptrs[i] = ptr + (uintptr_t)*ma->ptrs[i];213*214* Unfortunately, even though ma->ptr_count is basically guaranteed to be a215* constant, GCC is incapable of figuring this out and unrolling the loop216* so we have to give it a little help.217*/218STATIC_ASSERT(ARRAY_SIZE(ma->ptrs) == 8);219#define _VK_MULTIALLOC_UPDATE_POINTER(_i) \220if ((_i) < ma->ptr_count) \221*ma->ptrs[_i] = ptr + (uintptr_t)*ma->ptrs[_i]222_VK_MULTIALLOC_UPDATE_POINTER(0);223_VK_MULTIALLOC_UPDATE_POINTER(1);224_VK_MULTIALLOC_UPDATE_POINTER(2);225_VK_MULTIALLOC_UPDATE_POINTER(3);226_VK_MULTIALLOC_UPDATE_POINTER(4);227_VK_MULTIALLOC_UPDATE_POINTER(5);228_VK_MULTIALLOC_UPDATE_POINTER(6);229_VK_MULTIALLOC_UPDATE_POINTER(7);230#undef _VK_MULTIALLOC_UPDATE_POINTER231232return ptr;233}234235static ALWAYS_INLINE void *236vk_multialloc_alloc2(struct vk_multialloc *ma,237const VkAllocationCallbacks *parent_alloc,238const VkAllocationCallbacks *alloc,239VkSystemAllocationScope scope)240{241return vk_multialloc_alloc(ma, alloc ? alloc : parent_alloc, scope);242}243244#endif245246247