glthread: rewrite CallList merging and do it in the app thread

This looks simpler and hopefully faster, but it may just move the overhead
to the app thread.

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>
This commit is contained in:
Marek Olšák 2022-08-21 23:49:14 -04:00 committed by Marge Bot
parent 6f8cbbfce2
commit 3cb96b18f6
4 changed files with 57 additions and 52 deletions

View file

@ -244,6 +244,8 @@ _mesa_glthread_flush_batch(struct gl_context *ctx)
if (false) {
glthread_unmarshal_batch(next, NULL, 0);
_glapi_set_dispatch(ctx->CurrentClientDispatch);
glthread->LastCallList = NULL;
return;
}
@ -256,6 +258,8 @@ _mesa_glthread_flush_batch(struct gl_context *ctx)
glthread->next = (glthread->next + 1) % MARSHAL_MAX_BATCHES;
glthread->next_batch = &glthread->batches[glthread->next];
glthread->used = 0;
glthread->LastCallList = NULL;
}
/**
@ -293,6 +297,8 @@ _mesa_glthread_finish(struct gl_context *ctx)
next->used = glthread->used;
glthread->used = 0;
glthread->LastCallList = NULL;
/* Since glthread_unmarshal_batch changes the dispatch to direct,
* restore it after it's done.
*/

View file

@ -240,6 +240,9 @@ struct glthread_state
GLuint CurrentDrawFramebuffer;
GLuint CurrentReadFramebuffer;
GLuint CurrentProgram;
/** The last added call of the given function. */
struct marshal_cmd_CallList *LastCallList;
};
void _mesa_glthread_init(struct gl_context *ctx);

View file

@ -26,66 +26,68 @@
#include "main/glthread_marshal.h"
#include "main/dispatch.h"
struct marshal_cmd_CallList
{
struct marshal_cmd_base cmd_base;
GLuint num;
GLuint list[];
};
uint32_t
_mesa_unmarshal_CallList(struct gl_context *ctx, const struct marshal_cmd_CallList *cmd, const uint64_t *last)
{
const GLuint list = cmd->list;
uint64_t *ptr = (uint64_t *) cmd;
const unsigned cmd_size = align(sizeof(*cmd), 8) / 8;
const GLuint num = cmd->num;
assert(cmd_size == cmd->cmd_base.cmd_size);
ptr += cmd_size;
if (ptr < last) {
const struct marshal_cmd_base *next =
(const struct marshal_cmd_base *)ptr;
/* If the 'next' is also a DISPATCH_CMD_CallList, we transform 'cmd' and 'next' in a CALL_CallLists.
* If the following commands are also CallList they're including in the CallLists we're building.
*/
if (next->cmd_id == DISPATCH_CMD_CallList) {
const int max_list_count = 2048;
struct marshal_cmd_CallList *next_callist = (struct marshal_cmd_CallList *) next;
uint32_t *lists = alloca(max_list_count * sizeof(uint32_t));
lists[0] = cmd->list;
lists[1] = next_callist->list;
int count = 2;
assert(cmd_size == next_callist->cmd_base.cmd_size);
ptr += cmd_size;
while (ptr < last && count < max_list_count) {
next = (const struct marshal_cmd_base *)ptr;
if (next->cmd_id == DISPATCH_CMD_CallList) {
next_callist = (struct marshal_cmd_CallList *) next;
lists[count++] = next_callist->list;
assert(cmd_size == next_callist->cmd_base.cmd_size);
ptr += cmd_size;
} else {
break;
}
}
CALL_CallLists(ctx->CurrentServerDispatch, (count, GL_UNSIGNED_INT, lists));
return (uint32_t) (ptr - (uint64_t*)cmd);
}
if (cmd->cmd_base.cmd_size == sizeof(*cmd) / 8) {
CALL_CallList(ctx->CurrentServerDispatch, (num));
} else {
CALL_CallLists(ctx->CurrentServerDispatch, (num, GL_UNSIGNED_INT, cmd->list));
}
CALL_CallList(ctx->CurrentServerDispatch, (list));
return cmd_size;
return cmd->cmd_base.cmd_size;
}
void GLAPIENTRY
_mesa_marshal_CallList(GLuint list)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_state *glthread = &ctx->GLThread;
struct marshal_cmd_CallList *last = glthread->LastCallList;
_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] &&
glthread->used + 1 <= MARSHAL_MAX_CMD_SIZE / 8) {
STATIC_ASSERT(sizeof(*last) == 8);
/* Add the list to the last call. */
if (last->cmd_base.cmd_size > sizeof(*last) / 8) {
last->list[last->num++] = list;
if (last->num % 2 == 1) {
last->cmd_base.cmd_size++;
glthread->used++;
}
} else {
/* Initially, num contains the first list. After we increase cmd_size,
* num contains the number of lists and list[] contains the lists.
*/
last->list[0] = last->num;
last->list[1] = list;
last->num = 2;
last->cmd_base.cmd_size++;
glthread->used++;
}
assert(align(sizeof(*last) + last->num * 4, 8) / 8 == last->cmd_base.cmd_size);
return;
}
int cmd_size = sizeof(struct marshal_cmd_CallList);
struct marshal_cmd_CallList *cmd;
cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_CallList, cmd_size);
cmd->list = list;
cmd->num = list;
_mesa_glthread_CallList(ctx, list);
glthread->LastCallList = cmd;
}

View file

@ -865,10 +865,4 @@ _mesa_glthread_DeleteFramebuffers(struct gl_context *ctx, GLsizei n,
}
}
struct marshal_cmd_CallList
{
struct marshal_cmd_base cmd_base;
GLuint list;
};
#endif /* MARSHAL_H */