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 <tarceri@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26548>
This commit is contained in:
Marek Olšák 2023-11-26 22:36:37 -05:00 committed by Marge Bot
parent c3b95d1507
commit bdb771b27c
3 changed files with 82 additions and 1 deletions

View file

@ -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>

View file

@ -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);
}

View file

@ -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)