[Mesa-dev] [PATCH v2] vbo: create a new draw function interface for indirect draws
Ilia Mirkin
imirkin at alum.mit.edu
Mon Jan 4 20:20:04 PST 2016
All indirect draws are passed to the new draw function. By default
there's a fallback implementation which pipes it right back to
draw_prims, but eventually both the fallback and draw_prim's support for
indirect drawing should be removed.
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>
Acked-by: Marek Olšák <marek.olsak at amd.com>
---
v1 -> v2: Per Ian's suggestion, add a fallback implementation so that the
main paths are nice and clean. The fallback implementation of
draw_indirect_prims just creates a separate _mesa_prim for each indirect
draw as before and calls draw_prims.
src/mesa/vbo/vbo.h | 15 +++++++
src/mesa/vbo/vbo_context.c | 50 +++++++++++++++++++++++
src/mesa/vbo/vbo_context.h | 6 +++
src/mesa/vbo/vbo_exec_array.c | 93 +++++++++----------------------------------
4 files changed, 89 insertions(+), 75 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..c29f72b 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -135,6 +135,48 @@ static void init_mat_currval(struct gl_context *ctx)
}
}
+static void
+vbo_draw_indirect_prims(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)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct _mesa_prim *prim;
+ GLsizei i;
+
+ prim = calloc(draw_count, sizeof(*prim));
+ if (prim == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s",
+ (draw_count > 1) ? "Multi" : "",
+ ib ? "Elements" : "Arrays",
+ indirect_params ? "CountARB" : "");
+ return;
+ }
+
+ prim[0].begin = 1;
+ prim[draw_count - 1].end = 1;
+ for (i = 0; i < draw_count; ++i, indirect_offset += stride) {
+ prim[i].mode = mode;
+ prim[i].indexed = !!ib;
+ prim[i].indirect_offset = indirect_offset;
+ prim[i].is_indirect = 1;
+ prim[i].draw_id = i;
+ }
+
+ vbo->draw_prims(ctx, prim, draw_count,
+ ib, GL_TRUE, 0, ~0,
+ NULL, 0,
+ ctx->DrawIndirectBuffer);
+
+ free(prim);
+}
+
GLboolean _vbo_CreateContext( struct gl_context *ctx )
{
@@ -152,6 +194,7 @@ GLboolean _vbo_CreateContext( struct gl_context *ctx )
init_legacy_currval( ctx );
init_generic_currval( ctx );
init_mat_currval( ctx );
+ vbo_set_indirect_draw_func(ctx, vbo_draw_indirect_prims);
/* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
* of vertex program active.
@@ -223,3 +266,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..2589ff4 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -1546,27 +1546,14 @@ vbo_validated_drawarraysindirect(struct gl_context *ctx,
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
- struct _mesa_prim prim[1];
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.
- */
-
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, prim, 1,
- NULL, GL_TRUE, 0, ~0,
- NULL, 0,
- ctx->DrawIndirectBuffer);
+ vbo->draw_indirect_prims(ctx, mode,
+ ctx->DrawIndirectBuffer, (GLsizeiptr)indirect,
+ 1 /* draw_count */, 16 /* stride */,
+ NULL, 0, NULL);
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
_mesa_flush(ctx);
@@ -1580,36 +1567,18 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
- struct _mesa_prim *prim;
- GLsizei i;
GLsizeiptr offset = (GLsizeiptr)indirect;
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;
- }
-
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, prim, primcount,
- NULL, GL_TRUE, 0, ~0,
- NULL, 0,
- ctx->DrawIndirectBuffer);
-
- free(prim);
+ vbo->draw_indirect_prims(ctx, mode,
+ ctx->DrawIndirectBuffer, offset,
+ primcount, stride,
+ NULL, 0, NULL);
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
_mesa_flush(ctx);
@@ -1623,7 +1592,6 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx,
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_index_buffer ib;
- struct _mesa_prim prim[1];
vbo_bind_arrays(ctx);
@@ -1632,19 +1600,12 @@ 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;
-
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, prim, 1,
- &ib, GL_TRUE, 0, ~0,
- NULL, 0,
- ctx->DrawIndirectBuffer);
+ vbo->draw_indirect_prims(ctx, mode,
+ ctx->DrawIndirectBuffer, (GLsizeiptr)indirect,
+ 1 /* draw_count */, 20 /* stride */,
+ NULL, 0,
+ &ib);
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
_mesa_flush(ctx);
@@ -1659,17 +1620,10 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_index_buffer ib;
- struct _mesa_prim *prim;
- GLsizei i;
GLsizeiptr offset = (GLsizeiptr)indirect;
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 +1634,12 @@ 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;
- }
-
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, prim, primcount,
- &ib, GL_TRUE, 0, ~0,
- NULL, 0,
- ctx->DrawIndirectBuffer);
-
- free(prim);
+ vbo->draw_indirect_prims(ctx, mode,
+ ctx->DrawIndirectBuffer, offset,
+ primcount, stride,
+ NULL, 0,
+ &ib);
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
_mesa_flush(ctx);
--
2.4.10
More information about the mesa-dev
mailing list