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)

Reply via email to