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:
parent
beb02a781c
commit
eb04db7344
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
_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);
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue