diff options
author | Marek Olšák <marek.olsak@amd.com> | 2022-08-21 20:32:08 -0400 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2022-10-19 04:23:05 +0000 |
commit | 6e6245f1896e7aae20856210f3768f1e520bbda3 (patch) | |
tree | a4655dd89da5cb7ae4bfff5375428078cec98b72 | |
parent | 9b6e2783ebc0709b6d908c48c50e6e5375110789 (diff) |
glthread: merge and collapse glBindBuffer calls that unbind and then bind
This is a small optimization for viewperf. See the comment in the code.
Acked-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18199>
-rw-r--r-- | src/mapi/glapi/gen/gl_API.xml | 3 | ||||
-rw-r--r-- | src/mesa/main/glthread.c | 3 | ||||
-rw-r--r-- | src/mesa/main/glthread.h | 3 | ||||
-rw-r--r-- | src/mesa/main/glthread_bufferobj.c | 80 | ||||
-rw-r--r-- | src/mesa/main/glthread_list.c | 4 | ||||
-rw-r--r-- | src/mesa/main/glthread_marshal.h | 9 |
6 files changed, 94 insertions, 8 deletions
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml index a72bd9f5a05..c69539c88ab 100644 --- a/src/mapi/glapi/gen/gl_API.xml +++ b/src/mapi/glapi/gen/gl_API.xml @@ -5094,8 +5094,7 @@ <type name="intptr" size="4" glx_name="CARD32"/> <type name="sizeiptr" size="4" unsigned="true" glx_name="CARD32"/> - <function name="BindBuffer" es1="1.1" es2="2.0" no_error="true" - marshal_call_after="_mesa_glthread_BindBuffer(ctx, target, buffer);"> + <function name="BindBuffer" es1="1.1" es2="2.0" no_error="true" marshal="custom"> <param name="target" type="GLenum"/> <param name="buffer" type="GLuint"/> <glx ignore="true"/> diff --git a/src/mesa/main/glthread.c b/src/mesa/main/glthread.c index c4bdbaa7cd2..279d1db063d 100644 --- a/src/mesa/main/glthread.c +++ b/src/mesa/main/glthread.c @@ -246,6 +246,7 @@ _mesa_glthread_flush_batch(struct gl_context *ctx) _glapi_set_dispatch(ctx->CurrentClientDispatch); glthread->LastCallList = NULL; + glthread->LastBindBuffer = NULL; return; } @@ -260,6 +261,7 @@ _mesa_glthread_flush_batch(struct gl_context *ctx) glthread->used = 0; glthread->LastCallList = NULL; + glthread->LastBindBuffer = NULL; } /** @@ -298,6 +300,7 @@ _mesa_glthread_finish(struct gl_context *ctx) glthread->used = 0; glthread->LastCallList = NULL; + glthread->LastBindBuffer = NULL; /* Since glthread_unmarshal_batch changes the dispatch to direct, * restore it after it's done. diff --git a/src/mesa/main/glthread.h b/src/mesa/main/glthread.h index c94f63bf89c..d8b7f4b35a1 100644 --- a/src/mesa/main/glthread.h +++ b/src/mesa/main/glthread.h @@ -243,6 +243,7 @@ struct glthread_state /** The last added call of the given function. */ struct marshal_cmd_CallList *LastCallList; + struct marshal_cmd_BindBuffer *LastBindBuffer; }; void _mesa_glthread_init(struct gl_context *ctx); @@ -278,8 +279,6 @@ void _mesa_error_glthread_safe(struct gl_context *ctx, GLenum error, bool glthread, const char *format, ...); void _mesa_glthread_execute_list(struct gl_context *ctx, GLuint list); -void _mesa_glthread_BindBuffer(struct gl_context *ctx, GLenum target, - GLuint buffer); void _mesa_glthread_DeleteBuffers(struct gl_context *ctx, GLsizei n, const GLuint *buffers); diff --git a/src/mesa/main/glthread_bufferobj.c b/src/mesa/main/glthread_bufferobj.c index 13908b90bc1..80af250fab3 100644 --- a/src/mesa/main/glthread_bufferobj.c +++ b/src/mesa/main/glthread_bufferobj.c @@ -173,7 +173,7 @@ _mesa_glthread_upload(struct gl_context *ctx, const void *data, * feature that if you pass a bad name, it just gens a buffer object for you, * so we escape without having to know if things are valid or not. */ -void +static void _mesa_glthread_BindBuffer(struct gl_context *ctx, GLenum target, GLuint buffer) { struct glthread_state *glthread = &ctx->GLThread; @@ -204,6 +204,84 @@ _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]; +}; + +uint32_t +_mesa_unmarshal_BindBuffer(struct gl_context *ctx, + const struct marshal_cmd_BindBuffer *cmd, + const uint64_t *last) +{ + CALL_BindBuffer(ctx->CurrentServerDispatch, (cmd->target[0], cmd->buffer[0])); + + if (cmd->target[1]) + CALL_BindBuffer(ctx->CurrentServerDispatch, (cmd->target[1], cmd->buffer[1])); + + const unsigned cmd_size = (align(sizeof(struct marshal_cmd_BindBuffer), 8) / 8); + assert (cmd_size == cmd->cmd_base.cmd_size); + return cmd_size; +} + +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; + + _mesa_glthread_BindBuffer(ctx, target, buffer); + + /* If the last call is BindBuffer... */ + if (_mesa_glthread_call_is_last(glthread, &last->cmd_base)) { + /* 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; + return; + } + } + + int cmd_size = sizeof(struct marshal_cmd_BindBuffer); + struct marshal_cmd_BindBuffer *cmd = + _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BindBuffer, cmd_size); + + cmd->target[0] = MIN2(target, 0xffff); /* clamped to 0xffff (invalid enum) */ + cmd->target[1] = 0; + cmd->buffer[0] = buffer; + + glthread->LastBindBuffer = cmd; +} + void _mesa_glthread_DeleteBuffers(struct gl_context *ctx, GLsizei n, const GLuint *buffers) diff --git a/src/mesa/main/glthread_list.c b/src/mesa/main/glthread_list.c index 32c74ffee71..7e214879dde 100644 --- a/src/mesa/main/glthread_list.c +++ b/src/mesa/main/glthread_list.c @@ -57,9 +57,7 @@ _mesa_marshal_CallList(GLuint list) _mesa_glthread_CallList(ctx, list); /* If the last call is CallList and there is enough space to append another list... */ - if (last && - (uint64_t*)last + last->cmd_base.cmd_size == - &glthread->next_batch->buffer[glthread->used] && + if (_mesa_glthread_call_is_last(glthread, &last->cmd_base) && glthread->used + 1 <= MARSHAL_MAX_CMD_SIZE / 8) { STATIC_ASSERT(sizeof(*last) == 8); diff --git a/src/mesa/main/glthread_marshal.h b/src/mesa/main/glthread_marshal.h index 2b3571f199b..605e332bb10 100644 --- a/src/mesa/main/glthread_marshal.h +++ b/src/mesa/main/glthread_marshal.h @@ -74,6 +74,15 @@ _mesa_glthread_allocate_command(struct gl_context *ctx, } static inline bool +_mesa_glthread_call_is_last(struct glthread_state *glthread, + struct marshal_cmd_base *last) +{ + return last && + (uint64_t*)last + last->cmd_size == + &glthread->next_batch->buffer[glthread->used]; +} + +static inline bool _mesa_glthread_has_no_pack_buffer(const struct gl_context *ctx) { return ctx->GLThread.CurrentPixelPackBufferName == 0; |