From 3b7ac45162412a79c3cd4d4dbc16bd54db597608 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sun, 4 Apr 2010 18:21:16 -0600 Subject: [PATCH] mesa: implement core Mesa support for GL_ARB_draw_instanced --- src/mesa/main/dd.h | 5 ++ src/mesa/main/vtxfmt.c | 2 + src/mesa/main/vtxfmt_tmp.h | 21 ++++++++ src/mesa/vbo/vbo.h | 1 + src/mesa/vbo/vbo_exec_api.c | 1 + src/mesa/vbo/vbo_exec_array.c | 90 +++++++++++++++++++++++++++++++++-- src/mesa/vbo/vbo_save_api.c | 2 + 7 files changed, 118 insertions(+), 4 deletions(-) diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 7c02faaa535..4679be72f76 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -1186,6 +1186,11 @@ typedef struct { const GLvoid **indices, GLsizei primcount, const GLint *basevertex); + void (GLAPIENTRYP DrawArraysInstanced)(GLenum mode, GLint first, + GLsizei count, GLsizei primcount); + void (GLAPIENTRYP DrawElementsInstanced)(GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices, + GLsizei primcount); /*@}*/ /** diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c index 0dd3e5e52ee..ca352e88e6b 100644 --- a/src/mesa/main/vtxfmt.c +++ b/src/mesa/main/vtxfmt.c @@ -140,6 +140,8 @@ install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt ) SET_DrawElementsBaseVertex(tab, vfmt->DrawElementsBaseVertex); SET_DrawRangeElementsBaseVertex(tab, vfmt->DrawRangeElementsBaseVertex); SET_MultiDrawElementsBaseVertex(tab, vfmt->MultiDrawElementsBaseVertex); + SET_DrawArraysInstanced(tab, vfmt->DrawArraysInstanced); + SET_DrawElementsInstanced(tab, vfmt->DrawElementsInstanced); /* GL_NV_vertex_program */ SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV); diff --git a/src/mesa/main/vtxfmt_tmp.h b/src/mesa/main/vtxfmt_tmp.h index 037c4b1888b..9ec6ea49aa2 100644 --- a/src/mesa/main/vtxfmt_tmp.h +++ b/src/mesa/main/vtxfmt_tmp.h @@ -391,6 +391,25 @@ static void GLAPIENTRY TAG(MultiDrawElementsBaseVertex)( GLenum mode, primcount, basevertex )); } +static void GLAPIENTRY +TAG(DrawArraysInstanced)(GLenum mode, GLint first, + GLsizei count, GLsizei primcount) +{ + PRE_LOOPBACK( DrawArraysInstanced ); + CALL_DrawArraysInstanced(GET_DISPATCH(), (mode, first, count, primcount)); +} + +static void GLAPIENTRY +TAG(DrawElementsInstanced)(GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices, + GLsizei primcount) +{ + PRE_LOOPBACK( DrawElementsInstanced ); + CALL_DrawElementsInstanced(GET_DISPATCH(), + (mode, count, type, indices, primcount)); +} + + static void GLAPIENTRY TAG(EvalMesh1)( GLenum mode, GLint i1, GLint i2 ) { PRE_LOOPBACK( EvalMesh1 ); @@ -574,6 +593,8 @@ static GLvertexformat TAG(vtxfmt) = { TAG(DrawElementsBaseVertex), TAG(DrawRangeElementsBaseVertex), TAG(MultiDrawElementsBaseVertex), + TAG(DrawArraysInstanced), + TAG(DrawElementsInstanced), TAG(EvalMesh1), TAG(EvalMesh2) }; diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index b24ecfd7cde..7a085f63c73 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -45,6 +45,7 @@ struct _mesa_prim { GLuint start; GLuint count; GLint basevertex; + GLsizei num_instances; }; /* Would like to call this a "vbo_index_buffer", but this would be diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index e40f5f9dc44..e83bd9e4045 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -531,6 +531,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) exec->vtx.prim[i].pad = 0; exec->vtx.prim[i].start = exec->vtx.vert_count; exec->vtx.prim[i].count = 0; + exec->vtx.prim[i].num_instances = 1; ctx->Driver.CurrentExecPrimitive = mode; } diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 90474da7c02..d4dbc8d2562 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -520,6 +520,7 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) prim[0].count = count; prim[0].indexed = 0; prim[0].basevertex = 0; + prim[0].num_instances = 1; vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, GL_TRUE, start, start + count - 1 ); @@ -532,6 +533,62 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) } +static void GLAPIENTRY +vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count, + GLsizei primcount) +{ + GET_CURRENT_CONTEXT(ctx); + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct _mesa_prim prim[1]; + + if (MESA_VERBOSE & VERBOSE_DRAW) + _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n", + _mesa_lookup_enum_by_nr(mode), start, count, primcount); + + if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, primcount)) + return; + + FLUSH_CURRENT( ctx, 0 ); + + if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) { + return; + } + +#if 0 /* debug */ + check_draw_arrays_data(ctx, start, count); +#endif + + bind_arrays( ctx ); + + /* Again... because we may have changed the bitmask of per-vertex varying + * attributes. If we regenerate the fixed-function vertex program now + * we may be able to prune down the number of vertex attributes which we + * need in the shader. + */ + if (ctx->NewState) + _mesa_update_state( ctx ); + + prim[0].begin = 1; + prim[0].end = 1; + prim[0].weak = 0; + prim[0].pad = 0; + prim[0].mode = mode; + prim[0].start = start; + prim[0].count = count; + prim[0].indexed = 0; + prim[0].basevertex = 0; + prim[0].num_instances = primcount; + + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, + GL_TRUE, start, start + count - 1 ); + +#if 0 /* debug */ + print_draw_arrays(ctx, exec, mode, start, count); +#endif +} + + /** * Map GL_ELEMENT_ARRAY_BUFFER and print contents. */ @@ -595,7 +652,7 @@ vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, - GLint basevertex) + GLint basevertex, GLint primcount) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; @@ -628,6 +685,7 @@ vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode, prim[0].count = count; prim[0].indexed = 1; prim[0].basevertex = basevertex; + prim[0].num_instances = primcount; /* Need to give special consideration to rendering a range of * indices starting somewhere above zero. Typically the @@ -769,7 +827,7 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode, #endif vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end, - count, type, indices, basevertex); + count, type, indices, basevertex, 1); } @@ -805,7 +863,7 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, return; vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, - count, type, indices, 0); + count, type, indices, 0, 1); } @@ -825,7 +883,27 @@ vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, return; vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, - count, type, indices, basevertex); + count, type, indices, basevertex, 1); +} + + +static void GLAPIENTRY +vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_DRAW) + _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n", + _mesa_lookup_enum_by_nr(mode), count, + _mesa_lookup_enum_by_nr(type), indices, primcount); + + if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, + primcount)) + return; + + vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, + count, type, indices, 0, primcount); } @@ -926,6 +1004,7 @@ vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode, prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size; prim[i].count = count[i]; prim[i].indexed = 1; + prim[i].num_instances = 1; if (basevertex != NULL) prim[i].basevertex = basevertex[i]; else @@ -950,6 +1029,7 @@ vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode, prim[0].start = 0; prim[0].count = count[i]; prim[0].indexed = 1; + prim[0].num_instances = 1; if (basevertex != NULL) prim[0].basevertex = basevertex[i]; else @@ -1024,6 +1104,8 @@ vbo_exec_array_init( struct vbo_exec_context *exec ) exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex; exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex; exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex; + exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced; + exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced; #else exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays; exec->vtxfmt.DrawElements = _mesa_noop_DrawElements; diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index a5d027982f4..c867cb03f63 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -418,6 +418,7 @@ static void _save_wrap_buffers( GLcontext *ctx ) save->prim[0].pad = 0; save->prim[0].start = 0; save->prim[0].count = 0; + save->prim[0].num_instances = 1; save->prim_count = 1; } @@ -773,6 +774,7 @@ GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode ) save->prim[i].pad = 0; save->prim[i].start = save->vert_count; save->prim[i].count = 0; + save->prim[i].num_instances = 1; _mesa_install_save_vtxfmt( ctx, &save->vtxfmt ); ctx->Driver.SaveNeedFlush = 1; -- 2.30.2