mesa: optimize glPush/PopClientAttrib by removing malloc overhead
authorMarek Olšák <marek.olsak@amd.com>
Sun, 22 Mar 2020 02:15:20 +0000 (22:15 -0400)
committerMarge Bot <eric+marge@anholt.net>
Thu, 30 Apr 2020 22:01:55 +0000 (22:01 +0000)
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
src/mesa/main/arrayobj.h
src/mesa/main/attrib.c
src/mesa/main/mtypes.h

index dd410c3..3ebcede 100644 (file)
@@ -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);
index 94e2234..9da9960 100644 (file)
@@ -57,6 +57,10 @@ 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);
 
 extern void
index e3df99b..74c449b 100644 (file)
@@ -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);
    }
 }
 
index 0a50e92..5bb6ac5 100644 (file)
@@ -4831,6 +4831,18 @@ struct gl_semaphore_object
 };
 
 /**
+ * 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.
  *
  * This is the central context data structure for Mesa.  Almost all
@@ -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 */