From eb04db734429971ddc240ba9dc6726a991cc0a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sat, 21 Mar 2020 22:15:20 -0400 Subject: [PATCH] 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: --- 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); - next = node->next; - free(node->data); - free(node); - node = next; + copy_pixelstore(ctx, &ctx->Unpack, &head->Unpack); + _mesa_reference_buffer_object(ctx, &head->Unpack.BufferObj, NULL); + } + + 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 */