Edit

IABSD.fr/xenocara/lib/mesa/src/vulkan/util/vk_alloc.h

Branch :

  • Show log

    Commit

  • Author : jsg
    Date : 2025-06-05 14:17:56
    Hash : 452696b8
    Message : Merge Mesa 25.0.7

  • lib/mesa/src/vulkan/util/vk_alloc.h
  • /*
     * Copyright © 2015 Intel Corporation
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice (including the next
     * paragraph) shall be included in all copies or substantial portions of the
     * Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     * IN THE SOFTWARE.
     */
    #ifndef VK_ALLOC_H
    #define VK_ALLOC_H
    
    /* common allocation inlines for vulkan drivers */
    
    #include <stdio.h>
    #include <string.h>
    #include <vulkan/vulkan_core.h>
    
    #include "util/u_math.h"
    #include "util/macros.h"
    #include "util/u_printf.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    const VkAllocationCallbacks *
    vk_default_allocator(void);
    
    static inline void *
    vk_alloc(const VkAllocationCallbacks *alloc,
             size_t size, size_t align,
             VkSystemAllocationScope scope)
    {
       return alloc->pfnAllocation(alloc->pUserData, size, align, scope);
    }
    
    static inline void *
    vk_zalloc(const VkAllocationCallbacks *alloc,
              size_t size, size_t align,
              VkSystemAllocationScope scope)
    {
       void *mem = vk_alloc(alloc, size, align, scope);
       if (mem == NULL)
          return NULL;
    
       memset(mem, 0, size);
    
       return mem;
    }
    
    static inline void *
    vk_realloc(const VkAllocationCallbacks *alloc,
               void *ptr, size_t size, size_t align,
               VkSystemAllocationScope scope)
    {
       return alloc->pfnReallocation(alloc->pUserData, ptr, size, align, scope);
    }
    
    static inline void
    vk_free(const VkAllocationCallbacks *alloc, void *data)
    {
       if (data == NULL)
          return;
    
       alloc->pfnFree(alloc->pUserData, data);
    }
    
    static inline char *
    vk_strdup(const VkAllocationCallbacks *alloc, const char *s,
              VkSystemAllocationScope scope)
    {
       if (s == NULL)
          return NULL;
    
       size_t size = strlen(s) + 1;
       char *copy = (char *)vk_alloc(alloc, size, 1, scope);
       if (copy == NULL)
          return NULL;
    
       memcpy(copy, s, size);
    
       return copy;
    }
    
    static inline char *
    vk_vasprintf(const VkAllocationCallbacks *alloc,
                 VkSystemAllocationScope scope,
                 const char *fmt, va_list args)
    {
       size_t size = u_printf_length(fmt, args) + 1;
       char *ptr = (char *)vk_alloc(alloc, size, 1, scope);
       if (ptr != NULL)
          vsnprintf(ptr, size, fmt, args);
    
       return ptr;
    }
    
    PRINTFLIKE(3, 4) static inline char *
    vk_asprintf(const VkAllocationCallbacks *alloc,
                VkSystemAllocationScope scope,
                const char *fmt, ...)
    {
       va_list args;
       va_start(args, fmt);
       char *ptr = vk_vasprintf(alloc, scope, fmt, args);
       va_end(args);
    
       return ptr;
    }
    
    static inline void *
    vk_alloc2(const VkAllocationCallbacks *parent_alloc,
              const VkAllocationCallbacks *alloc,
              size_t size, size_t align,
              VkSystemAllocationScope scope)
    {
       if (alloc)
          return vk_alloc(alloc, size, align, scope);
       else
          return vk_alloc(parent_alloc, size, align, scope);
    }
    
    static inline void *
    vk_zalloc2(const VkAllocationCallbacks *parent_alloc,
               const VkAllocationCallbacks *alloc,
               size_t size, size_t align,
               VkSystemAllocationScope scope)
    {
       void *mem = vk_alloc2(parent_alloc, alloc, size, align, scope);
       if (mem == NULL)
          return NULL;
    
       memset(mem, 0, size);
    
       return mem;
    }
    
    static inline void
    vk_free2(const VkAllocationCallbacks *parent_alloc,
             const VkAllocationCallbacks *alloc,
             void *data)
    {
       if (alloc)
          vk_free(alloc, data);
       else
          vk_free(parent_alloc, data);
    }
    
    /* A multi-pointer allocator
     *
     * When copying data structures from the user (such as a render pass), it's
     * common to need to allocate data for a bunch of different things.  Instead
     * of doing several allocations and having to handle all of the error checking
     * that entails, it can be easier to do a single allocation.  This struct
     * helps facilitate that.  The intended usage looks like this:
     *
     *    VK_MULTIALLOC(ma)
     *    vk_multialloc_add(&ma, &main_ptr, 1);
     *    vk_multialloc_add(&ma, &substruct1, substruct1Count);
     *    vk_multialloc_add(&ma, &substruct2, substruct2Count);
     *
     *    if (!vk_multialloc_alloc(&ma, pAllocator, VK_ALLOCATION_SCOPE_FOO))
     *       return vk_error(VK_ERROR_OUT_OF_HOST_MEORY);
     */
    struct vk_multialloc {
        size_t size;
        size_t align;
    
        uint32_t ptr_count;
        void **ptrs[16];
    };
    
    #define VK_MULTIALLOC(_name) \
       struct vk_multialloc _name = { .align = 1 }
    
    static ALWAYS_INLINE void
    vk_multialloc_add_size_align(struct vk_multialloc *ma,
                                 void **ptr, size_t size, size_t align)
    {
       assert(util_is_power_of_two_nonzero_uintptr(align));
       if (size == 0) {
          *ptr = NULL;
          return;
       }
    
       size_t offset = ALIGN_POT(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 vk_multialloc_add_size(_ma, _ptr, _type, _size) \
       do { \
          _type **_tmp = (_ptr); \
          (void)_tmp; \
          vk_multialloc_add_size_align((_ma), (void **)(_ptr), \
                                       (_size), alignof(_type)); \
       } while(0)
    
    #define vk_multialloc_add(_ma, _ptr, _type, _count) \
       vk_multialloc_add_size(_ma, _ptr, _type, (_count) * sizeof(**(_ptr)));
    
    #define VK_MULTIALLOC_DECL_SIZE(_ma, _type, _name, _size) \
       _type *_name; \
       vk_multialloc_add_size(_ma, &_name, _type, _size);
    
    #define VK_MULTIALLOC_DECL(_ma, _type, _name, _count) \
       VK_MULTIALLOC_DECL_SIZE(_ma, _type, _name, (_count) * sizeof(_type));
    
    static ALWAYS_INLINE void *
    vk_multialloc_alloc(struct vk_multialloc *ma,
                        const VkAllocationCallbacks *alloc,
                        VkSystemAllocationScope scope)
    {
       void *ptr = vk_alloc(alloc, ma->size, ma->align, 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];
        *
        * Unfortunately, even though ma->ptr_count is basically guaranteed to be a
        * constant, GCC is incapable of figuring this out and unrolling the loop
        * so we have to give it a little help.
        */
       STATIC_ASSERT(ARRAY_SIZE(ma->ptrs) == 16);
    #define _VK_MULTIALLOC_UPDATE_POINTER(_i) \
       if ((_i) < ma->ptr_count) \
          *ma->ptrs[_i] = (char *)ptr + (uintptr_t)*ma->ptrs[_i]
       _VK_MULTIALLOC_UPDATE_POINTER(0);
       _VK_MULTIALLOC_UPDATE_POINTER(1);
       _VK_MULTIALLOC_UPDATE_POINTER(2);
       _VK_MULTIALLOC_UPDATE_POINTER(3);
       _VK_MULTIALLOC_UPDATE_POINTER(4);
       _VK_MULTIALLOC_UPDATE_POINTER(5);
       _VK_MULTIALLOC_UPDATE_POINTER(6);
       _VK_MULTIALLOC_UPDATE_POINTER(7);
       _VK_MULTIALLOC_UPDATE_POINTER(8);
       _VK_MULTIALLOC_UPDATE_POINTER(9);
       _VK_MULTIALLOC_UPDATE_POINTER(10);
       _VK_MULTIALLOC_UPDATE_POINTER(11);
       _VK_MULTIALLOC_UPDATE_POINTER(12);
       _VK_MULTIALLOC_UPDATE_POINTER(13);
       _VK_MULTIALLOC_UPDATE_POINTER(14);
       _VK_MULTIALLOC_UPDATE_POINTER(15);
    #undef _VK_MULTIALLOC_UPDATE_POINTER
    
       return ptr;
    }
    
    static ALWAYS_INLINE void *
    vk_multialloc_alloc2(struct vk_multialloc *ma,
                         const VkAllocationCallbacks *parent_alloc,
                         const VkAllocationCallbacks *alloc,
                         VkSystemAllocationScope scope)
    {
       return vk_multialloc_alloc(ma, alloc ? alloc : parent_alloc, scope);
    }
    
    static ALWAYS_INLINE void *
    vk_multialloc_zalloc(struct vk_multialloc *ma,
                         const VkAllocationCallbacks *alloc,
                         VkSystemAllocationScope scope)
    {
       void *ptr = vk_multialloc_alloc(ma, alloc, scope);
    
       if (ptr == NULL)
          return NULL;
    
       memset(ptr, 0, ma->size);
    
       return ptr;
    }
    
    static ALWAYS_INLINE void *
    vk_multialloc_zalloc2(struct vk_multialloc *ma,
                          const VkAllocationCallbacks *parent_alloc,
                          const VkAllocationCallbacks *alloc,
                          VkSystemAllocationScope scope)
    {
       return vk_multialloc_zalloc(ma, alloc ? alloc : parent_alloc, scope);
    }
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif