Module: Mesa Branch: main Commit: bdb771b27c1a36ad728b02111060001defd55767 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=bdb771b27c1a36ad728b02111060001defd55767
Author: Marek Olšák <[email protected]> Date: Sun Nov 26 22:36:37 2023 -0500 glthread: eliminate push/pop calls in PushMatrix+Draw/MultMatrixf+PopMatrix Viewperf benefits. This implements glPushMatrix marshalling manually and looks ahead in the unmarshal function what the following calls are. Reviewed-by: Timothy Arceri <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26548> --- src/mapi/glapi/gen/gl_API.xml | 2 +- src/mesa/main/glthread_draw.c | 68 ++++++++++++++++++++++++++++++++++++++++ src/mesa/main/glthread_marshal.h | 13 ++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml index de868e45fc2..99c8232d358 100644 --- a/src/mapi/glapi/gen/gl_API.xml +++ b/src/mapi/glapi/gen/gl_API.xml @@ -2959,7 +2959,7 @@ </function> <function name="PushMatrix" es1="1.0" deprecated="3.1" exec="dlist" - marshal_call_after="_mesa_glthread_PushMatrix(ctx);"> + marshal="custom"> <glx rop="184"/> </function> diff --git a/src/mesa/main/glthread_draw.c b/src/mesa/main/glthread_draw.c index b747493aba7..48e9fa59f93 100644 --- a/src/mesa/main/glthread_draw.c +++ b/src/mesa/main/glthread_draw.c @@ -1967,3 +1967,71 @@ _mesa_DrawElementsInstancedBaseVertexBaseInstanceDrawID(void) { unreachable("should never end up here"); } + +struct marshal_cmd_PushMatrix +{ + struct marshal_cmd_base cmd_base; +}; + +uint32_t +_mesa_unmarshal_PushMatrix(struct gl_context *ctx, + const struct marshal_cmd_PushMatrix *restrict cmd) +{ + const unsigned push_matrix_size = 1; + const unsigned mult_matrixf_size = 9; + const unsigned draw_elements_size = + (align(sizeof(struct marshal_cmd_DrawElementsBaseVertex), 8) / 8); + const unsigned pop_matrix_size = 1; + uint64_t *next1 = _mesa_glthread_next_cmd((uint64_t *)cmd, push_matrix_size); + uint64_t *next2; + + /* Viewperf has these call patterns. */ + switch (_mesa_glthread_get_cmd(next1)->cmd_id) { + case DISPATCH_CMD_DrawElementsBaseVertex: + /* Execute this sequence: + * glPushMatrix + * (glMultMatrixf with identity is eliminated by the marshal function) + * glDrawElementsBaseVertex (also used by glDraw{Range}Elements) + * glPopMatrix + * as: + * glDrawElementsBaseVertex (also used by glDraw{Range}Elements) + */ + next2 = _mesa_glthread_next_cmd(next1, draw_elements_size); + + if (_mesa_glthread_get_cmd(next2)->cmd_id == DISPATCH_CMD_PopMatrix) { + assert(_mesa_glthread_get_cmd(next2)->cmd_size == pop_matrix_size); + + /* The beauty of this is that this is inlined. */ + _mesa_unmarshal_DrawElementsBaseVertex(ctx, (void*)next1); + return push_matrix_size + draw_elements_size + pop_matrix_size; + } + break; + + case DISPATCH_CMD_MultMatrixf: + /* Skip this sequence: + * glPushMatrix + * glMultMatrixf + * glPopMatrix + */ + next2 = _mesa_glthread_next_cmd(next1, mult_matrixf_size); + + if (_mesa_glthread_get_cmd(next2)->cmd_id == DISPATCH_CMD_PopMatrix) { + assert(_mesa_glthread_get_cmd(next2)->cmd_size == pop_matrix_size); + return push_matrix_size + mult_matrixf_size + pop_matrix_size; + } + break; + } + + CALL_PushMatrix(ctx->Dispatch.Current, ()); + return push_matrix_size; +} + +void GLAPIENTRY +_mesa_marshal_PushMatrix(void) +{ + GET_CURRENT_CONTEXT(ctx); + + _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_PushMatrix, + sizeof(struct marshal_cmd_PushMatrix)); + _mesa_glthread_PushMatrix(ctx); +} diff --git a/src/mesa/main/glthread_marshal.h b/src/mesa/main/glthread_marshal.h index 84081960ba0..ec3e9c2544b 100644 --- a/src/mesa/main/glthread_marshal.h +++ b/src/mesa/main/glthread_marshal.h @@ -75,6 +75,19 @@ _mesa_glthread_allocate_command(struct gl_context *ctx, return cmd_base; } +static inline struct marshal_cmd_base * +_mesa_glthread_get_cmd(uint64_t *opaque_cmd) +{ + return (struct marshal_cmd_base*)opaque_cmd; +} + +static inline uint64_t * +_mesa_glthread_next_cmd(uint64_t *opaque_cmd, unsigned cmd_size) +{ + assert(_mesa_glthread_get_cmd(opaque_cmd)->cmd_size == cmd_size); + return opaque_cmd + cmd_size; +} + static inline bool _mesa_glthread_call_is_last(struct glthread_state *glthread, struct marshal_cmd_base *last)
