[Mesa-dev] [PATCH 1/3] anv: Add anv_outarray

Chad Versace chadversary at chromium.org
Thu Mar 9 00:39:50 UTC 2017


On Mon 06 Mar 2017, Jason Ekstrand wrote:
> On Mon, Mar 6, 2017 at 10:25 AM, Chad Versace <chadversary at chromium.org>
> wrote:
> 
> > anv_outarray is a wrapper for a Vulkan output array. A Vulkan output
> > array is one that follows the convention of the parameters to
> > vkGetPhysicalDeviceQueueFamilyProperties().
> >
> > In the upcoming dma_buf extensions, anv_outarray will simplify the code
> > for querying the DRM format modifiers.
> > ---
> >  src/intel/vulkan/anv_private.h | 140 ++++++++++++++++++++++++++++++
> > +++++++++++
> >  1 file changed, 140 insertions(+)
> >
> > diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_
> > private.h
> > index c73196ab5ef..b6dc8be53d2 100644
> > --- a/src/intel/vulkan/anv_private.h
> > +++ b/src/intel/vulkan/anv_private.h
> > @@ -2100,4 +2100,144 @@ ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_shader_module,
> > VkShaderModule)
> >  #  undef genX
> >  #endif
> >
> > +/**
> > + * A wrapper for a Vulkan output array. A Vulkan output array is one that
> > + * follows the convention of the parameters to
> > + * vkGetPhysicalDeviceQueueFamilyProperties().
> > + *
> > + * Example Usage:
> > + *
> > + *    VkResult
> > + *    vkGetPhysicalDeviceQueueFamilyProperties(
> > + *       VkPhysicalDevice           physicalDevice,
> > + *       uint32_t*                  pQueueFamilyPropertyCount,
> > + *       VkQueueFamilyProperties*   pQueueFamilyProperties)
> > + *    {
> > + *       ANV_OUTARRAY_MAKE(props, pQueueFamilyProperties,
> > + *                         pQueueFamilyPropertyCount);
> > + *
> > + *       anv_outarray_append(&props, p) {
> > + *          p->queueFlags = ...;
> > + *          p->queueCount = ...;
> > + *       }
> > + *
> > + *       anv_outarray_append(&props, p) {
> > + *          p->queueFlags = ...;
> > + *          p->queueCount = ...;
> > + *       }
> > + *
> > + *       if (anv_outarray_is_incomple(&props))
> > + *          return VK_INCOMPLETE;
> > + *
> > + *       return VK_SUCCESS;
> > + *    }
> > + */
> > +struct __anv_outarray {
> > +   /** May be null. */
> > +   void *data;
> > +
> > +   /**
> > +    * Capacity, in number of elements. Capacity is unlimited (UINT32_MAX)
> > if
> > +    * data is null.
> > +    */
> > +   uint32_t cap;
> > +
> > +   /**
> > +    * Count of elements successfully written to the array. Every write is
> > +    * considered successful if data is null.
> > +    */
> > +   uint32_t *filled_len;
> > +
> > +   /**
> > +    * Count of elements that would have been written to the array if its
> > +    * capacity were sufficient. Vulkan functions often return
> > VK_INCOMPLETE
> > +    * when `*filled_len < wanted_len`.
> > +    */
> > +   uint32_t wanted_len;
> >
> 
> I don't think this is needed.

You're probably right. I'll try rewriting the patch without wanted_len.

> > +};
> > +
> > +static inline void
> > +__anv_outarray_init(struct __anv_outarray *restrict 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 bool
> > +__anv_outarray_is_incomplete(const struct __anv_outarray *a)
> > +{
> > +   return *a->filled_len < a->wanted_len;
> >
> 
> We could implement this as
> 
> return a->data && *a->filled_len < a->cap
> 
> Or, better yet, we could add a "VkResult status" to the outarray struct and
> set that VK_INCOMPLETE in __anv_outarray_next.  Then the status check is
> just "return out.status".  How does that sound?

When I rewrite the patch to remove 'wanted_len', I'll play around with
that, and see what results in the cleanest code.

> 
> Also, this looks like a really good candidate for common Vulkan code.

Agreed. I'll resend this as a patch to vk_util.h.

> Thanks for doing this by the way!  I've been wanting someone to figure out
> how to make output arrays less painful and this seems like a very good way.

Thanks :)

> 
> +}
> > +
> > +static inline void *
> > +__anv_outarray_next(struct __anv_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 = a->data + (*a->filled_len) * elem_size;
> > +
> > +   *a->filled_len += 1;
> > +
> > +   return p;
> > +}
> > +
> > +#define anv_outarray(elem_t) \
> > +   struct { \
> > +      struct __anv_outarray base; \
> > +      elem_t meta[]; \
> > +   }
> > +
> > +#define anv_outarray_typeof_elem(a) __typeof__((a)->meta[0])
> > +#define anv_outarray_sizeof_elem(a) sizeof((a)->meta[0])
> > +
> > +#define anv_outarray_init(a, data, len) \
> > +   __anv_outarray_init(&(a)->base, (data), (len))
> > +
> > +#define ANV_OUTARRAY_MAKE(name, data, len) \
> > +   anv_outarray(__typeof__((data)[0])) name; \
> > +   anv_outarray_init(&name, (data), (len))
> > +
> > +#define anv_outarray_is_incomple(a) \
> > +   __anv_outarray_is_incomplete(&(a)->base)
> > +
> > +#define anv_outarray_next(a) \
> > +   ((anv_outarray_typeof_elem(a) *) \
> > +      __anv_outarray_next(&(a)->base, anv_outarray_sizeof_elem(a)))
> > +
> > +/**
> > + * Append to a Vulkan output array.
> > + *
> > + * This is a block-based macro. For example:
> > + *
> > + *    anv_outarray_append(&a, elem) {
> > + *       elem->foo = ...;
> > + *       elem->bar = ...;
> > + *    }
> > + *
> > + * The array `a` has type `anv_outarray(elem_t) *`. It is usually
> > declared with
> > + * ANV_OUTARRAY_MAKE(). The variable `elem` is block-scoped and has type
> > + * `elem_t *`.
> > + *
> > + * The macro unconditionally increments the array's `wanted_len`. If the
> > array
> > + * is not full, then the macro also increment its `filled_len` and then
> > + * executes the block. When the block is executed, `elem` is non-null and
> > + * points to the newly appended element.
> > + */
> > +#define anv_outarray_append(a, elem) \
> > +   for (anv_outarray_typeof_elem(a) *elem = anv_outarray_next(a); \
> > +        elem != NULL; elem = NULL)
> > +
> >  #endif /* ANV_PRIVATE_H */
> > --
> > 2.12.0
> >
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
> >

> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev



More information about the mesa-dev mailing list