[Mesa-dev] [PATCH 1/4] vbo: create a new draw function interface for indirect draws

Ilia Mirkin imirkin at alum.mit.edu
Thu Dec 31 11:55:11 PST 2015


This is optional for now in the transition period, but optimally all
backends that support indirect draws would switch over to it and we can
remove the support for indirect in the "regular" draw function.

This should allow a backend to properly support ARB_multi_draw_indirect
and ARB_indirect_parameters.

Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---
 src/mesa/vbo/vbo.h            |  15 ++++
 src/mesa/vbo/vbo_context.c    |   7 ++
 src/mesa/vbo/vbo_context.h    |   6 ++
 src/mesa/vbo/vbo_exec_array.c | 166 +++++++++++++++++++++++++-----------------
 4 files changed, 127 insertions(+), 67 deletions(-)

diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index cef3b8c..0c63bf3 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -110,6 +110,18 @@ typedef void (*vbo_draw_func)( struct gl_context *ctx,
 			       struct gl_buffer_object *indirect);
 
 
+typedef void (*vbo_indirect_draw_func)(
+   struct gl_context *ctx,
+   GLuint mode,
+   struct gl_buffer_object *indirect_data,
+   GLsizeiptr indirect_offset,
+   unsigned draw_count,
+   unsigned stride,
+   struct gl_buffer_object *indirect_params,
+   GLsizeiptr indirect_params_offset,
+   const struct _mesa_index_buffer *ib);
+
+
 
 
 /* Utility function to cope with various constraints on tnl modules or
@@ -179,6 +191,9 @@ void vbo_always_unmap_buffers(struct gl_context *ctx);
 
 void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func);
 
+void vbo_set_indirect_draw_func(struct gl_context *ctx,
+                                vbo_indirect_draw_func func);
+
 void vbo_check_buffers_are_unmapped(struct gl_context *ctx);
 
 void vbo_bind_arrays(struct gl_context *ctx);
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index 5e1a760..8a196e7 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -223,3 +223,10 @@ void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func)
    vbo->draw_prims = func;
 }
 
+
+void vbo_set_indirect_draw_func(struct gl_context *ctx,
+                                vbo_indirect_draw_func func)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   vbo->draw_indirect_prims = func;
+}
diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h
index 6293a8b..11f9b17 100644
--- a/src/mesa/vbo/vbo_context.h
+++ b/src/mesa/vbo/vbo_context.h
@@ -76,6 +76,12 @@ struct vbo_context {
     * is responsible for initiating any fallback actions required:
     */
    vbo_draw_func draw_prims;
+
+   /* Optional callback for indirect draws. This allows multidraws to not be
+    * broken up, as well as for the actual count to be passed in as a separate
+    * indirect parameter.
+    */
+   vbo_indirect_draw_func draw_indirect_prims;
 };
 
 
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 502b288..3da2d19 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -1550,23 +1550,30 @@ vbo_validated_drawarraysindirect(struct gl_context *ctx,
 
    vbo_bind_arrays(ctx);
 
-   memset(prim, 0, sizeof(prim));
-   prim[0].begin = 1;
-   prim[0].end = 1;
-   prim[0].mode = mode;
-   prim[0].is_indirect = 1;
-   prim[0].indirect_offset = (GLsizeiptr)indirect;
-
-   /* NOTE: We do NOT want to handle primitive restart here, nor perform any
-    * other checks that require knowledge of the values in the command buffer.
-    * That would defeat the whole purpose of this function.
-    */
+   if (vbo->draw_indirect_prims) {
+      vbo->draw_indirect_prims(ctx, mode,
+                               ctx->DrawIndirectBuffer, (GLsizeiptr)indirect,
+                               1 /* primcount */, 0 /* stride */,
+                               NULL, 0, NULL);
+   } else {
+      memset(prim, 0, sizeof(prim));
+      prim[0].begin = 1;
+      prim[0].end = 1;
+      prim[0].mode = mode;
+      prim[0].is_indirect = 1;
+      prim[0].indirect_offset = (GLsizeiptr)indirect;
+
+      /* NOTE: We do NOT want to handle primitive restart here, nor perform
+       * any other checks that require knowledge of the values in the command
+       * buffer.  That would defeat the whole purpose of this function.
+       */
 
-   check_buffers_are_unmapped(exec->array.inputs);
-   vbo->draw_prims(ctx, prim, 1,
-                   NULL, GL_TRUE, 0, ~0,
-                   NULL, 0,
-                   ctx->DrawIndirectBuffer);
+      check_buffers_are_unmapped(exec->array.inputs);
+      vbo->draw_prims(ctx, prim, 1,
+                      NULL, GL_TRUE, 0, ~0,
+                      NULL, 0,
+                      ctx->DrawIndirectBuffer);
+   }
 
    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
       _mesa_flush(ctx);
@@ -1586,30 +1593,38 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
 
    if (primcount == 0)
       return;
-   prim = calloc(primcount, sizeof(*prim));
-   if (prim == NULL) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect");
-      return;
-   }
 
    vbo_bind_arrays(ctx);
 
-   prim[0].begin = 1;
-   prim[primcount - 1].end = 1;
-   for (i = 0; i < primcount; ++i, offset += stride) {
-      prim[i].mode = mode;
-      prim[i].indirect_offset = offset;
-      prim[i].is_indirect = 1;
-      prim[i].draw_id = i;
-   }
+   if (vbo->draw_indirect_prims) {
+      vbo->draw_indirect_prims(ctx, mode,
+                               ctx->DrawIndirectBuffer, offset,
+                               primcount, stride,
+                               NULL, 0, NULL);
+   } else {
+      prim = calloc(primcount, sizeof(*prim));
+      if (prim == NULL) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect");
+         return;
+      }
 
-   check_buffers_are_unmapped(exec->array.inputs);
-   vbo->draw_prims(ctx, prim, primcount,
-                   NULL, GL_TRUE, 0, ~0,
-                   NULL, 0,
-                   ctx->DrawIndirectBuffer);
+      prim[0].begin = 1;
+      prim[primcount - 1].end = 1;
+      for (i = 0; i < primcount; ++i, offset += stride) {
+         prim[i].mode = mode;
+         prim[i].indirect_offset = offset;
+         prim[i].is_indirect = 1;
+         prim[i].draw_id = i;
+      }
 
-   free(prim);
+      check_buffers_are_unmapped(exec->array.inputs);
+      vbo->draw_prims(ctx, prim, primcount,
+                      NULL, GL_TRUE, 0, ~0,
+                      NULL, 0,
+                      ctx->DrawIndirectBuffer);
+
+      free(prim);
+   }
 
    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
       _mesa_flush(ctx);
@@ -1632,19 +1647,27 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx,
    ib.obj = ctx->Array.VAO->IndexBufferObj;
    ib.ptr = NULL;
 
-   memset(prim, 0, sizeof(prim));
-   prim[0].begin = 1;
-   prim[0].end = 1;
-   prim[0].mode = mode;
-   prim[0].indexed = 1;
-   prim[0].indirect_offset = (GLsizeiptr)indirect;
-   prim[0].is_indirect = 1;
+   if (vbo->draw_indirect_prims) {
+      vbo->draw_indirect_prims(ctx, mode,
+                               ctx->DrawIndirectBuffer, (GLsizeiptr)indirect,
+                               1 /* primcount */, 0 /* stride */,
+                               NULL, 0,
+                               &ib);
+   } else {
+      memset(prim, 0, sizeof(prim));
+      prim[0].begin = 1;
+      prim[0].end = 1;
+      prim[0].mode = mode;
+      prim[0].indexed = 1;
+      prim[0].indirect_offset = (GLsizeiptr)indirect;
+      prim[0].is_indirect = 1;
 
-   check_buffers_are_unmapped(exec->array.inputs);
-   vbo->draw_prims(ctx, prim, 1,
-                   &ib, GL_TRUE, 0, ~0,
-                   NULL, 0,
-                   ctx->DrawIndirectBuffer);
+      check_buffers_are_unmapped(exec->array.inputs);
+      vbo->draw_prims(ctx, prim, 1,
+                      &ib, GL_TRUE, 0, ~0,
+                      NULL, 0,
+                      ctx->DrawIndirectBuffer);
+   }
 
    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
       _mesa_flush(ctx);
@@ -1665,11 +1688,6 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
 
    if (primcount == 0)
       return;
-   prim = calloc(primcount, sizeof(*prim));
-   if (prim == NULL) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect");
-      return;
-   }
 
    vbo_bind_arrays(ctx);
 
@@ -1680,23 +1698,37 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
    ib.obj = ctx->Array.VAO->IndexBufferObj;
    ib.ptr = NULL;
 
-   prim[0].begin = 1;
-   prim[primcount - 1].end = 1;
-   for (i = 0; i < primcount; ++i, offset += stride) {
-      prim[i].mode = mode;
-      prim[i].indexed = 1;
-      prim[i].indirect_offset = offset;
-      prim[i].is_indirect = 1;
-      prim[i].draw_id = i;
-   }
+   if (vbo->draw_indirect_prims) {
+      vbo->draw_indirect_prims(ctx, mode,
+                               ctx->DrawIndirectBuffer, offset,
+                               primcount, stride,
+                               NULL, 0,
+                               &ib);
+   } else {
+      prim = calloc(primcount, sizeof(*prim));
+      if (prim == NULL) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect");
+         return;
+      }
 
-   check_buffers_are_unmapped(exec->array.inputs);
-   vbo->draw_prims(ctx, prim, primcount,
-                   &ib, GL_TRUE, 0, ~0,
-                   NULL, 0,
-                   ctx->DrawIndirectBuffer);
+      prim[0].begin = 1;
+      prim[primcount - 1].end = 1;
+      for (i = 0; i < primcount; ++i, offset += stride) {
+         prim[i].mode = mode;
+         prim[i].indexed = 1;
+         prim[i].indirect_offset = offset;
+         prim[i].is_indirect = 1;
+         prim[i].draw_id = i;
+      }
 
-   free(prim);
+      check_buffers_are_unmapped(exec->array.inputs);
+      vbo->draw_prims(ctx, prim, primcount,
+                      &ib, GL_TRUE, 0, ~0,
+                      NULL, 0,
+                      ctx->DrawIndirectBuffer);
+
+      free(prim);
+   }
 
    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
       _mesa_flush(ctx);
-- 
2.4.10



More information about the mesa-dev mailing list