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>
This commit is contained in:
Marek Olšák 2020-03-21 22:15:20 -04:00 committed by Marge Bot
parent beb02a781c
commit eb04db7344
4 changed files with 46 additions and 137 deletions

View 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);

View File

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

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

View File

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