vbo: create a new draw function interface for indirect draws
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@alum.mit.edu> Acked-by: Marek Olšák <marek.olsak@amd.com> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
parent
2923c7a0ed
commit
60d0cfd429
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue