glthread: rewrite glBindBuffer packing

We always reserved space for a doubled glBindBuffer call, occupying
2 slots. Thanks to the removal of cmd_size, we can finally represent
glBindBuffer in only 1 slot, so do that. This saves space if there is
only 1 glBindBuffer call.

The combining of back-to-back BindBuffer calls is preserved by keeping
track of 2 last BindBuffer calls.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27350>
This commit is contained in:
Marek Olšák 2024-01-08 01:23:50 -05:00 committed by Marge Bot
parent 1f9b554839
commit 5925a864b5
3 changed files with 41 additions and 47 deletions

View file

@ -347,7 +347,8 @@ glthread_finalize_batch(struct glthread_state *glthread,
glthread->used = 0;
glthread->LastCallList = NULL;
glthread->LastBindBuffer = NULL;
glthread->LastBindBuffer1 = NULL;
glthread->LastBindBuffer2 = NULL;
}
void

View file

@ -274,7 +274,8 @@ struct glthread_state
/** The last added call of the given function. */
struct marshal_cmd_CallList *LastCallList;
struct marshal_cmd_BindBuffer *LastBindBuffer;
struct marshal_cmd_BindBuffer *LastBindBuffer1;
struct marshal_cmd_BindBuffer *LastBindBuffer2;
/** Global mutex update info. */
unsigned GlobalLockUpdateBatchCounter;

View file

@ -213,33 +213,18 @@ _mesa_glthread_BindBuffer(struct gl_context *ctx, GLenum target, GLuint buffer)
}
}
/* This can hold up to 2 BindBuffer calls. This is used to eliminate
* duplicated BindBuffer calls, which are plentiful in viewperf2020/catia.
* In this example, the first 2 calls are eliminated by glthread by keeping
* track of the last 2 BindBuffer calls and overwriting them if the target
* matches.
*
* glBindBuffer(GL_ARRAY_BUFFER, 0);
* glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
* glBindBuffer(GL_ARRAY_BUFFER, 6);
* glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 7);
*/
struct marshal_cmd_BindBuffer
{
struct marshal_cmd_base cmd_base;
GLenum16 target[2];
GLuint buffer[2];
GLenum16 target;
GLuint buffer;
};
uint32_t
_mesa_unmarshal_BindBuffer(struct gl_context *ctx,
const struct marshal_cmd_BindBuffer *restrict cmd)
{
CALL_BindBuffer(ctx->Dispatch.Current, (cmd->target[0], cmd->buffer[0]));
if (cmd->target[1])
CALL_BindBuffer(ctx->Dispatch.Current, (cmd->target[1], cmd->buffer[1]));
CALL_BindBuffer(ctx->Dispatch.Current, (cmd->target, cmd->buffer));
return align(sizeof(struct marshal_cmd_BindBuffer), 8) / 8;
}
@ -247,46 +232,53 @@ void GLAPIENTRY
_mesa_marshal_BindBuffer(GLenum target, GLuint buffer)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_state *glthread = &ctx->GLThread;
struct marshal_cmd_BindBuffer *last = glthread->LastBindBuffer;
int cmd_size = sizeof(struct marshal_cmd_BindBuffer);
_mesa_glthread_BindBuffer(ctx, target, buffer);
/* If the last call is BindBuffer... */
if (_mesa_glthread_call_is_last(glthread, &last->cmd_base,
struct glthread_state *glthread = &ctx->GLThread;
struct marshal_cmd_BindBuffer *last1 = glthread->LastBindBuffer1;
struct marshal_cmd_BindBuffer *last2 = glthread->LastBindBuffer2;
int cmd_size = sizeof(struct marshal_cmd_BindBuffer);
/* Eliminate duplicated BindBuffer calls, which are plentiful
* in viewperf2020/catia. In this example, the first 2 calls are eliminated
* by glthread by keeping track of the last 2 BindBuffer calls and
* overwriting them if the target matches.
*
* glBindBuffer(GL_ARRAY_BUFFER, 0);
* glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
* glBindBuffer(GL_ARRAY_BUFFER, 6);
* glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 7);
*
* If the last call is BindBuffer...
* last2 is more recent. last1 is before last2.
*/
if (_mesa_glthread_call_is_last(glthread, &last2->cmd_base,
align(cmd_size, 8) / 8)) {
/* If the target is in the last call and unbinding the buffer, overwrite
* the buffer ID there.
*
* We can't optimize out binding non-zero buffers because binding also
* creates the GL objects (like glCreateBuffers), which can't be skipped.
*/
if (target == last->target[0] && !last->buffer[0]) {
last->buffer[0] = buffer;
return;
}
if (target == last->target[1] && !last->buffer[1]) {
last->buffer[1] = buffer;
return;
}
/* If the last call has an unused buffer field, add this call to it. */
if (last->target[1] == 0) {
last->target[1] = MIN2(target, 0xffff); /* clamped to 0xffff (invalid enum) */
last->buffer[1] = buffer;
if (target == last2->target) {
/* We can't overwrite binding non-zero buffers because binding also
* creates the GL objects (like glCreateBuffers), which can't be skipped.
*/
if (!last2->buffer) {
last2->buffer = buffer;
return;
}
} else if (last1 + 1 == last2 && target == last1->target &&
!last1->buffer) {
last1->buffer = buffer;
return;
}
}
struct marshal_cmd_BindBuffer *cmd =
_mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BindBuffer, cmd_size);
cmd->target = MIN2(target, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->buffer = buffer;
cmd->target[0] = MIN2(target, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->target[1] = 0;
cmd->buffer[0] = buffer;
glthread->LastBindBuffer = cmd;
glthread->LastBindBuffer1 = last2;
glthread->LastBindBuffer2 = cmd;
}
void