<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Mar 6, 2017 at 10:25 AM, Chad Versace <span dir="ltr"><<a href="mailto:chadversary@chromium.org" target="_blank">chadversary@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">anv_outarray is a wrapper for a Vulkan output array. A Vulkan output<br>
array is one that follows the convention of the parameters to<br>
vkGetPhysicalDeviceQueueFamily<wbr>Properties().<br>
<br>
In the upcoming dma_buf extensions, anv_outarray will simplify the code<br>
for querying the DRM format modifiers.<br>
---<br>
 src/intel/vulkan/anv_private.h | 140 ++++++++++++++++++++++++++++++<wbr>+++++++++++<br>
 1 file changed, 140 insertions(+)<br>
<br>
diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
index c73196ab5ef..b6dc8be53d2 100644<br>
--- a/src/intel/vulkan/anv_<wbr>private.h<br>
+++ b/src/intel/vulkan/anv_<wbr>private.h<br>
@@ -2100,4 +2100,144 @@ ANV_DEFINE_NONDISP_HANDLE_<wbr>CASTS(anv_shader_module, VkShaderModule)<br>
 #  undef genX<br>
 #endif<br>
<br>
+/**<br>
+ * A wrapper for a Vulkan output array. A Vulkan output array is one that<br>
+ * follows the convention of the parameters to<br>
+ * vkGetPhysicalDeviceQueueFamily<wbr>Properties().<br>
+ *<br>
+ * Example Usage:<br>
+ *<br>
+ *    VkResult<br>
+ *    vkGetPhysicalDeviceQueueFamily<wbr>Properties(<br>
+ *       VkPhysicalDevice           physicalDevice,<br>
+ *       uint32_t*                  pQueueFamilyPropertyCount,<br>
+ *       VkQueueFamilyProperties*   pQueueFamilyProperties)<br>
+ *    {<br>
+ *       ANV_OUTARRAY_MAKE(props, pQueueFamilyProperties,<br>
+ *                         pQueueFamilyPropertyCount);<br>
+ *<br>
+ *       anv_outarray_append(&props, p) {<br>
+ *          p->queueFlags = ...;<br>
+ *          p->queueCount = ...;<br>
+ *       }<br>
+ *<br>
+ *       anv_outarray_append(&props, p) {<br>
+ *          p->queueFlags = ...;<br>
+ *          p->queueCount = ...;<br>
+ *       }<br>
+ *<br>
+ *       if (anv_outarray_is_incomple(&<wbr>props))<br>
+ *          return VK_INCOMPLETE;<br>
+ *<br>
+ *       return VK_SUCCESS;<br>
+ *    }<br>
+ */<br>
+struct __anv_outarray {<br>
+   /** May be null. */<br>
+   void *data;<br>
+<br>
+   /**<br>
+    * Capacity, in number of elements. Capacity is unlimited (UINT32_MAX) if<br>
+    * data is null.<br>
+    */<br>
+   uint32_t cap;<br>
+<br>
+   /**<br>
+    * Count of elements successfully written to the array. Every write is<br>
+    * considered successful if data is null.<br>
+    */<br>
+   uint32_t *filled_len;<br>
+<br>
+   /**<br>
+    * Count of elements that would have been written to the array if its<br>
+    * capacity were sufficient. Vulkan functions often return VK_INCOMPLETE<br>
+    * when `*filled_len < wanted_len`.<br>
+    */<br>
+   uint32_t wanted_len;<br></blockquote><div><br></div><div>I don't think this is needed.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+};<br>
+<br>
+static inline void<br>
+__anv_outarray_init(struct __anv_outarray *restrict a,<br>
+                    void *data, uint32_t *restrict len)<br>
+{<br>
+   a->data = data;<br>
+   a->cap = *len;<br>
+   a->filled_len = len;<br>
+   *a->filled_len = 0;<br>
+   a->wanted_len = 0;<br>
+<br>
+   if (a->data == NULL)<br>
+      a->cap = UINT32_MAX;<br>
+}<br>
+<br>
+static inline bool<br>
+__anv_outarray_is_incomplete(<wbr>const struct __anv_outarray *a)<br>
+{<br>
+   return *a->filled_len < a->wanted_len;<br></blockquote><div><br></div><div>We could implement this as<br><br></div><div>return a->data && *a->filled_len < a->cap<br><br></div><div>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?<br></div><div> <br></div><div>Also, this looks like a really good candidate for common Vulkan code.<br><br></div><div>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.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+}<br>
+<br>
+static inline void *<br>
+__anv_outarray_next(struct __anv_outarray *a, size_t elem_size)<br>
+{<br>
+   void *p = NULL;<br>
+<br>
+   a->wanted_len += 1;<br>
+<br>
+   if (*a->filled_len >= a->cap)<br>
+      return NULL;<br>
+<br>
+   if (a->data != NULL)<br>
+      p = a->data + (*a->filled_len) * elem_size;<br>
+<br>
+   *a->filled_len += 1;<br>
+<br>
+   return p;<br>
+}<br>
+<br>
+#define anv_outarray(elem_t) \<br>
+   struct { \<br>
+      struct __anv_outarray base; \<br>
+      elem_t meta[]; \<br>
+   }<br>
+<br>
+#define anv_outarray_typeof_elem(a) __typeof__((a)->meta[0])<br>
+#define anv_outarray_sizeof_elem(a) sizeof((a)->meta[0])<br>
+<br>
+#define anv_outarray_init(a, data, len) \<br>
+   __anv_outarray_init(&(a)-><wbr>base, (data), (len))<br>
+<br>
+#define ANV_OUTARRAY_MAKE(name, data, len) \<br>
+   anv_outarray(__typeof__((data)<wbr>[0])) name; \<br>
+   anv_outarray_init(&name, (data), (len))<br>
+<br>
+#define anv_outarray_is_incomple(a) \<br>
+   __anv_outarray_is_incomplete(&<wbr>(a)->base)<br>
+<br>
+#define anv_outarray_next(a) \<br>
+   ((anv_outarray_typeof_elem(a) *) \<br>
+      __anv_outarray_next(&(a)-><wbr>base, anv_outarray_sizeof_elem(a)))<br>
+<br>
+/**<br>
+ * Append to a Vulkan output array.<br>
+ *<br>
+ * This is a block-based macro. For example:<br>
+ *<br>
+ *    anv_outarray_append(&a, elem) {<br>
+ *       elem->foo = ...;<br>
+ *       elem->bar = ...;<br>
+ *    }<br>
+ *<br>
+ * The array `a` has type `anv_outarray(elem_t) *`. It is usually declared with<br>
+ * ANV_OUTARRAY_MAKE(). The variable `elem` is block-scoped and has type<br>
+ * `elem_t *`.<br>
+ *<br>
+ * The macro unconditionally increments the array's `wanted_len`. If the array<br>
+ * is not full, then the macro also increment its `filled_len` and then<br>
+ * executes the block. When the block is executed, `elem` is non-null and<br>
+ * points to the newly appended element.<br>
+ */<br>
+#define anv_outarray_append(a, elem) \<br>
+   for (anv_outarray_typeof_elem(a) *elem = anv_outarray_next(a); \<br>
+        elem != NULL; elem = NULL)<br>
+<br>
 #endif /* ANV_PRIVATE_H */<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.12.0<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>