Mesa (master): mesa: optimize glPush/PopClientAttrib by removing malloc overhead

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 30 22:24:57 UTC 2020


Module: Mesa
Branch: master
Commit: eb04db734429971ddc240ba9dc6726a991cc0a14
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=eb04db734429971ddc240ba9dc6726a991cc0a14

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Sat Mar 21 22:15:20 2020 -0400

mesa: optimize glPush/PopClientAttrib by removing malloc overhead

just declare all structures needed by the stack in gl_context.

This improves performance by 5.6% in the game "torcs". FPS: 101.01 -> 106.73

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4314>

---

 src/mesa/main/arrayobj.c |   7 ++-
 src/mesa/main/arrayobj.h |   4 ++
 src/mesa/main/attrib.c   | 158 ++++++++---------------------------------------
 src/mesa/main/mtypes.h   |  14 ++++-
 4 files changed, 46 insertions(+), 137 deletions(-)

diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index dd410c345cc..3ebcedea4e9 100644
--- a/src/mesa/main/arrayobj.c
+++ b/src/mesa/main/arrayobj.c
@@ -304,8 +304,9 @@ _mesa_lookup_vao_err(struct gl_context *ctx, GLuint id,
  * to any buffer objects (VBOs).
  * This is done just prior to array object destruction.
  */
-static void
-unbind_array_object_vbos(struct gl_context *ctx, struct gl_vertex_array_object *obj)
+void
+_mesa_unbind_array_object_vbos(struct gl_context *ctx,
+                               struct gl_vertex_array_object *obj)
 {
    GLuint i;
 
@@ -333,7 +334,7 @@ _mesa_new_vao(struct gl_context *ctx, GLuint name)
 void
 _mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj)
 {
-   unbind_array_object_vbos(ctx, obj);
+   _mesa_unbind_array_object_vbos(ctx, obj);
    _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL);
    free(obj->Label);
    free(obj);
diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h
index 94e22348248..9da996014de 100644
--- a/src/mesa/main/arrayobj.h
+++ b/src/mesa/main/arrayobj.h
@@ -56,6 +56,10 @@ _mesa_lookup_vao_err(struct gl_context *ctx, GLuint id,
 extern struct gl_vertex_array_object *
 _mesa_new_vao(struct gl_context *ctx, GLuint name);
 
+extern void
+_mesa_unbind_array_object_vbos(struct gl_context *ctx,
+                               struct gl_vertex_array_object *obj);
+
 extern void
 _mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj);
 
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index e3df99b0396..74c449bfbcb 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -1690,47 +1690,11 @@ restore_array_attrib(struct gl_context *ctx,
    }
 }
 
-/**
- * init/alloc the fields of 'attrib'.
- * Needs to the init part matching free_array_attrib_data below.
- */
-static bool
-init_array_attrib_data(struct gl_context *ctx,
-                       struct gl_array_attrib *attrib)
-{
-   /* Get a non driver gl_vertex_array_object. */
-   attrib->VAO = MALLOC_STRUCT(gl_vertex_array_object);
-
-   if (attrib->VAO == NULL) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-      return false;
-   }
-
-   _mesa_initialize_vao(ctx, attrib->VAO, 0);
-   return true;
-}
-
-/**
- * Free/unreference the fields of 'attrib' but don't delete it (that's
- * done later in the calling code).
- * Needs to the cleanup part matching init_array_attrib_data above.
- */
-static void
-free_array_attrib_data(struct gl_context *ctx,
-                       struct gl_array_attrib *attrib)
-{
-   /* We use a non driver array object, so don't just unref since we would
-    * end up using the drivers DeleteArrayObject function for deletion. */
-   _mesa_delete_vao(ctx, attrib->VAO);
-   attrib->VAO = 0;
-   _mesa_reference_buffer_object(ctx, &attrib->ArrayBufferObj, NULL);
-}
-
 
 void GLAPIENTRY
 _mesa_PushClientAttrib(GLbitfield mask)
 {
-   struct gl_attrib_node *head;
+   struct gl_client_attrib_node *head;
 
    GET_CURRENT_CONTEXT(ctx);
 
@@ -1739,81 +1703,29 @@ _mesa_PushClientAttrib(GLbitfield mask)
       return;
    }
 
-   /* Build linked list of attribute nodes which save all attribute
-    * groups specified by the mask.
-    */
-   head = NULL;
+   head = &ctx->ClientAttribStack[ctx->ClientAttribStackDepth];
+   head->Mask = mask;
 
    if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
-      struct gl_pixelstore_attrib *attr;
-      /* packing attribs */
-      attr = CALLOC_STRUCT(gl_pixelstore_attrib);
-      if (attr == NULL) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-         goto end;
-      }
-      if (save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr)) {
-         copy_pixelstore(ctx, attr, &ctx->Pack);
-      }
-      else {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-         free(attr);
-         goto end;
-      }
-
-      /* unpacking attribs */
-      attr = CALLOC_STRUCT(gl_pixelstore_attrib);
-      if (attr == NULL) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-         goto end;
-      }
-
-      if (save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr)) {
-         copy_pixelstore(ctx, attr, &ctx->Unpack);
-      }
-      else {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-         free(attr);
-         goto end;
-       }
+      copy_pixelstore(ctx, &head->Pack, &ctx->Pack);
+      copy_pixelstore(ctx, &head->Unpack, &ctx->Unpack);
    }
 
    if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
-      struct gl_array_attrib *attr;
-      attr = CALLOC_STRUCT(gl_array_attrib);
-      if (attr == NULL) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-         goto end;
-      }
-
-      if (!init_array_attrib_data(ctx, attr)) {
-         free(attr);
-         goto end;
-      }
-
-      if (save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr)) {
-         save_array_attrib(ctx, attr, &ctx->Array);
-      }
-      else {
-         free_array_attrib_data(ctx, attr);
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-         free(attr);
-         /* goto to keep safe from possible later changes */
-         goto end;
-      }
-   }
-end:
-   if (head != NULL) {
-       ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
-       ctx->ClientAttribStackDepth++;
+      _mesa_initialize_vao(ctx, &head->VAO, 0);
+      /* Use the VAO declared within the node instead of allocating it. */
+      head->Array.VAO = &head->VAO;
+      save_array_attrib(ctx, &head->Array, &ctx->Array);
    }
+
+   ctx->ClientAttribStackDepth++;
 }
 
 
 void GLAPIENTRY
 _mesa_PopClientAttrib(void)
 {
-   struct gl_attrib_node *node, *next;
+   struct gl_client_attrib_node *head;
 
    GET_CURRENT_CONTEXT(ctx);
    FLUSH_VERTICES(ctx, 0);
@@ -1824,41 +1736,21 @@ _mesa_PopClientAttrib(void)
    }
 
    ctx->ClientAttribStackDepth--;
-   node = ctx->ClientAttribStack[ctx->ClientAttribStackDepth];
+   head = &ctx->ClientAttribStack[ctx->ClientAttribStackDepth];
 
-   while (node) {
-      switch (node->kind) {
-         case GL_CLIENT_PACK_BIT:
-            {
-               struct gl_pixelstore_attrib *store =
-                  (struct gl_pixelstore_attrib *) node->data;
-               copy_pixelstore(ctx, &ctx->Pack, store);
-               _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
-            }
-            break;
-         case GL_CLIENT_UNPACK_BIT:
-            {
-               struct gl_pixelstore_attrib *store =
-                  (struct gl_pixelstore_attrib *) node->data;
-               copy_pixelstore(ctx, &ctx->Unpack, store);
-               _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
-            }
-            break;
-         case GL_CLIENT_VERTEX_ARRAY_BIT: {
-            struct gl_array_attrib * attr =
-               (struct gl_array_attrib *) node->data;
-            restore_array_attrib(ctx, &ctx->Array, attr);
-            free_array_attrib_data(ctx, attr);
-            break;
-         }
-         default:
-            unreachable("Bad attrib flag in PopClientAttrib");
-      }
+   if (head->Mask & GL_CLIENT_PIXEL_STORE_BIT) {
+      copy_pixelstore(ctx, &ctx->Pack, &head->Pack);
+      _mesa_reference_buffer_object(ctx, &head->Pack.BufferObj, NULL);
+
+      copy_pixelstore(ctx, &ctx->Unpack, &head->Unpack);
+      _mesa_reference_buffer_object(ctx, &head->Unpack.BufferObj, NULL);
+   }
 
-      next = node->next;
-      free(node->data);
-      free(node);
-      node = next;
+   if (head->Mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+      restore_array_attrib(ctx, &ctx->Array, &head->Array);
+      _mesa_unbind_array_object_vbos(ctx, &head->VAO);
+      _mesa_reference_buffer_object(ctx, &head->VAO.IndexBufferObj, NULL);
+      _mesa_reference_buffer_object(ctx, &head->Array.ArrayBufferObj, NULL);
    }
 }
 
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 0a50e929986..5bb6ac58be4 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -4830,6 +4830,18 @@ struct gl_semaphore_object
    GLuint Name;            /**< hash table ID/name */
 };
 
+/**
+ * One element of the client attrib stack.
+ */
+struct gl_client_attrib_node
+{
+   GLbitfield Mask;
+   struct gl_array_attrib Array;
+   struct gl_vertex_array_object VAO;
+   struct gl_pixelstore_attrib Pack;
+   struct gl_pixelstore_attrib Unpack;
+};
+
 /**
  * Mesa rendering context.
  *
@@ -4968,7 +4980,7 @@ struct gl_context
    /** \name Client attribute stack */
    /*@{*/
    GLuint ClientAttribStackDepth;
-   struct gl_attrib_node *ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH];
+   struct gl_client_attrib_node ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH];
    /*@}*/
 
    /** \name Client attribute groups */



More information about the mesa-commit mailing list