[Mesa-dev] [PATCH v3 2/6] anv: Add a helper for doing mass allocations

Chris Wilson chris at chris-wilson.co.uk
Fri Apr 7 20:26:23 UTC 2017


On Fri, Apr 07, 2017 at 12:55:53PM -0700, Jason Ekstrand wrote:
> 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 | 77 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 77 insertions(+)
> 
> diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
> index 90974d9..f941cc7 100644
> --- a/src/intel/vulkan/anv_private.h
> +++ b/src/intel/vulkan/anv_private.h
> @@ -269,6 +269,83 @@ void anv_loge_v(const char *format, va_list va);
>  #define anv_assert(x)
>  #endif
>  
> +struct anv_multialloc {
> +    size_t size;
> +    size_t align;
> +
> +    uint32_t ptr_count;
> +    void **ptrs[8];
> +};
> +
> +#define ANV_MULTIALLOC_INIT \
> +   ((struct anv_multialloc) { 0, })
> +
> +#define ANV_MULTIALLOC(_name) \
> +   struct anv_multialloc _name = ANV_MULTIALLOC_INIT
> +
> +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_alloc(struct anv_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) == 8);
> +#define _ANV_MULTIALLOC_UPDATE_POINTER(_i) \
> +   if ((_i) < ma->ptr_count) \
> +      *ma->ptrs[_i] = ptr + (uintptr_t)*ma->ptrs[_i]
> +   _ANV_MULTIALLOC_UPDATE_POINTER(0);
> +   _ANV_MULTIALLOC_UPDATE_POINTER(1);
> +   _ANV_MULTIALLOC_UPDATE_POINTER(2);
> +   _ANV_MULTIALLOC_UPDATE_POINTER(3);
> +   _ANV_MULTIALLOC_UPDATE_POINTER(4);
> +   _ANV_MULTIALLOC_UPDATE_POINTER(5);
> +   _ANV_MULTIALLOC_UPDATE_POINTER(6);
> +   _ANV_MULTIALLOC_UPDATE_POINTER(7);
> +#undef _ANV_MULTIALLOC_UPDATE_POINTER

#define _ANV_MULTIALLOC_UPDATE_POINTER(_i) case _i + 1: *ma->ptrs[_i] = ptr +(uintptr)*ma->ptrs[_i]

switch (ma->ptr_count) {
_ANV_MULTIALLOC_UPDATE_POINTER(7);
_ANV_MULTIALLOC_UPDATE_POINTER(6);
_ANV_MULTIALLOC_UPDATE_POINTER(5);
_ANV_MULTIALLOC_UPDATE_POINTER(4);
_ANV_MULTIALLOC_UPDATE_POINTER(3);
_ANV_MULTIALLOC_UPDATE_POINTER(2);
_ANV_MULTIALLOC_UPDATE_POINTER(1);
_ANV_MULTIALLOC_UPDATE_POINTER(0);
}

#undef _ANV_MULITALLOC_UPDATE_POINTER

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the mesa-dev mailing list