glthread: convert (Multi)DrawIndirect into direct if user buffers are present

so that user buffers are uploaded without syncing.

Now glthread fully handles non-VBO uploads, so that we can disable user
buffer codepaths in st/mesa.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20624>
This commit is contained in:
Marek Olšák
2022-12-26 09:53:28 -05:00
parent 72b336dbdc
commit cabc08a184
4 changed files with 426 additions and 47 deletions
+4 -10
View File
@@ -8,16 +8,12 @@
<enum name="DRAW_INDIRECT_BUFFER" value="0x8F3F"/>
<enum name="DRAW_INDIRECT_BUFFER_BINDING" value="0x8F43"/>
<function name="DrawArraysIndirect" es2="3.1" exec="dlist"
marshal="async"
marshal_sync="_mesa_glthread_has_non_vbo_vertices_or_indirect(ctx)">
<function name="DrawArraysIndirect" es2="3.1" exec="dlist" marshal="custom">
<param name="mode" type="GLenum"/>
<param name="indirect" type="const GLvoid *"/>
</function>
<function name="DrawElementsIndirect" es2="3.1" exec="dlist"
marshal="async"
marshal_sync="_mesa_glthread_has_non_vbo_vertices_or_indices_or_indirect(ctx)">
<function name="DrawElementsIndirect" es2="3.1" exec="dlist" marshal="custom">
<param name="mode" type="GLenum"/>
<param name="type" type="GLenum"/>
<param name="indirect" type="const GLvoid *"/>
@@ -28,16 +24,14 @@
<category name="GL_ARB_multi_draw_indirect" number="133">
<function name="MultiDrawArraysIndirect" marshal="async" exec="dlist"
marshal_sync="_mesa_glthread_has_non_vbo_vertices_or_indirect(ctx)">
<function name="MultiDrawArraysIndirect" marshal="custom" exec="dlist">
<param name="mode" type="GLenum"/>
<param name="indirect" type="const GLvoid *"/>
<param name="primcount" type="GLsizei"/>
<param name="stride" type="GLsizei"/>
</function>
<function name="MultiDrawElementsIndirect" marshal="async" exec="dlist"
marshal_sync="_mesa_glthread_has_non_vbo_vertices_or_indices_or_indirect(ctx)">
<function name="MultiDrawElementsIndirect" marshal="custom" exec="dlist">
<param name="mode" type="GLenum"/>
<param name="type" type="GLenum"/>
<param name="indirect" type="const GLvoid *"/>
@@ -8,8 +8,7 @@
<enum name="PARAMETER_BUFFER_ARB" value="0x80EE"/>
<enum name="PARAMETER_BUFFER_BINDING_ARB" value="0x80EF"/>
<function name="MultiDrawArraysIndirectCountARB"
marshal_sync="_mesa_glthread_has_non_vbo_vertices(ctx)">
<function name="MultiDrawArraysIndirectCountARB" marshal="custom">
<param name="mode" type="GLenum"/>
<param name="indirect" type="GLintptr"/>
<param name="drawcount" type="GLintptr"/>
@@ -18,8 +17,7 @@
</function>
<!-- Use "...has_non_vbo_vertices", because indices always come from a buffer object. -->
<function name="MultiDrawElementsIndirectCountARB"
marshal_sync="_mesa_glthread_has_non_vbo_vertices(ctx)">
<function name="MultiDrawElementsIndirectCountARB" marshal="custom">
<param name="mode" type="GLenum"/>
<param name="type" type="GLenum"/>
<param name="indirect" type="GLintptr"/>
+420
View File
@@ -1331,6 +1331,426 @@ _mesa_marshal_MultiModeDrawElementsIBM(const GLenum *mode,
}
}
static const void *
map_draw_indirect_params(struct gl_context *ctx, GLintptr offset,
unsigned count, unsigned stride)
{
struct gl_buffer_object *obj = ctx->DrawIndirectBuffer;
if (!obj)
return (void*)offset;
return _mesa_bufferobj_map_range(ctx, offset,
MIN2((size_t)count * stride, obj->Size),
GL_MAP_READ_BIT, obj, MAP_INTERNAL);
}
static void
unmap_draw_indirect_params(struct gl_context *ctx)
{
if (ctx->DrawIndirectBuffer)
_mesa_bufferobj_unmap(ctx, ctx->DrawIndirectBuffer, MAP_INTERNAL);
}
static unsigned
read_draw_indirect_count(struct gl_context *ctx, GLintptr offset)
{
unsigned result = 0;
if (ctx->ParameterBuffer) {
_mesa_bufferobj_get_subdata(ctx, offset, sizeof(result), &result,
ctx->ParameterBuffer);
}
return result;
}
static void
lower_draw_arrays_indirect(struct gl_context *ctx, GLenum mode,
GLintptr indirect, GLsizei stride,
unsigned draw_count)
{
/* If <stride> is zero, the elements are tightly packed. */
if (stride == 0)
stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
const uint32_t *params =
map_draw_indirect_params(ctx, indirect, draw_count, stride);
for (unsigned i = 0; i < draw_count; i++) {
draw_arrays(i, mode,
params[i * stride / 4 + 2],
params[i * stride / 4 + 0],
params[i * stride / 4 + 1],
params[i * stride / 4 + 3], false);
}
unmap_draw_indirect_params(ctx);
}
static void
lower_draw_elements_indirect(struct gl_context *ctx, GLenum mode, GLenum type,
GLintptr indirect, GLsizei stride,
unsigned draw_count)
{
/* If <stride> is zero, the elements are tightly packed. */
if (stride == 0)
stride = 5 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
const uint32_t *params =
map_draw_indirect_params(ctx, indirect, draw_count, stride);
for (unsigned i = 0; i < draw_count; i++) {
draw_elements(i, mode,
params[i * stride / 4 + 0],
type,
(GLvoid*)((uintptr_t)params[i * stride / 4 + 2] *
get_index_size(type)),
params[i * stride / 4 + 1],
params[i * stride / 4 + 3],
params[i * stride / 4 + 4],
false, 0, 0, false);
}
unmap_draw_indirect_params(ctx);
}
struct marshal_cmd_DrawArraysIndirect
{
struct marshal_cmd_base cmd_base;
GLenum16 mode;
const GLvoid * indirect;
};
uint32_t
_mesa_unmarshal_DrawArraysIndirect(struct gl_context *ctx,
const struct marshal_cmd_DrawArraysIndirect *cmd)
{
GLenum mode = cmd->mode;
const GLvoid * indirect = cmd->indirect;
CALL_DrawArraysIndirect(ctx->CurrentServerDispatch, (mode, indirect));
const unsigned cmd_size =
(align(sizeof(struct marshal_cmd_DrawArraysIndirect), 8) / 8);
assert(cmd_size == cmd->cmd_base.cmd_size);
return cmd_size;
}
void GLAPIENTRY
_mesa_marshal_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
unsigned user_buffer_mask =
_mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
if (ctx->GLThread.draw_always_async ||
!ctx->GLThread.CurrentDrawIndirectBufferName ||
!user_buffer_mask) {
int cmd_size = sizeof(struct marshal_cmd_DrawArraysIndirect);
struct marshal_cmd_DrawArraysIndirect *cmd;
cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArraysIndirect, cmd_size);
cmd->mode = MIN2(mode, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->indirect = indirect;
return;
}
_mesa_glthread_finish_before(ctx, "DrawArraysIndirect");
lower_draw_arrays_indirect(ctx, mode, (GLintptr)indirect, 0, 1);
}
struct marshal_cmd_DrawElementsIndirect
{
struct marshal_cmd_base cmd_base;
GLenum16 mode;
GLenum16 type;
const GLvoid * indirect;
};
uint32_t
_mesa_unmarshal_DrawElementsIndirect(struct gl_context *ctx,
const struct marshal_cmd_DrawElementsIndirect *cmd)
{
GLenum mode = cmd->mode;
GLenum type = cmd->type;
const GLvoid * indirect = cmd->indirect;
CALL_DrawElementsIndirect(ctx->CurrentServerDispatch, (mode, type, indirect));
const unsigned cmd_size =
(align(sizeof(struct marshal_cmd_DrawElementsIndirect), 8) / 8);
assert(cmd_size == cmd->cmd_base.cmd_size);
return cmd_size;
}
void GLAPIENTRY
_mesa_marshal_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
unsigned user_buffer_mask =
_mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
if (ctx->GLThread.draw_always_async || !is_index_type_valid(type) ||
!ctx->GLThread.CurrentDrawIndirectBufferName ||
!vao->CurrentElementBufferName || !user_buffer_mask) {
int cmd_size = sizeof(struct marshal_cmd_DrawElementsIndirect);
struct marshal_cmd_DrawElementsIndirect *cmd;
cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsIndirect, cmd_size);
cmd->mode = MIN2(mode, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->indirect = indirect;
return;
}
_mesa_glthread_finish_before(ctx, "DrawElementsIndirect");
lower_draw_elements_indirect(ctx, mode, type, (GLintptr)indirect, 0, 1);
}
struct marshal_cmd_MultiDrawArraysIndirect
{
struct marshal_cmd_base cmd_base;
GLenum16 mode;
GLsizei primcount;
GLsizei stride;
const GLvoid * indirect;
};
uint32_t
_mesa_unmarshal_MultiDrawArraysIndirect(struct gl_context *ctx,
const struct marshal_cmd_MultiDrawArraysIndirect *cmd)
{
GLenum mode = cmd->mode;
const GLvoid * indirect = cmd->indirect;
GLsizei primcount = cmd->primcount;
GLsizei stride = cmd->stride;
CALL_MultiDrawArraysIndirect(ctx->CurrentServerDispatch,
(mode, indirect, primcount, stride));
const unsigned cmd_size =
(align(sizeof(struct marshal_cmd_MultiDrawArraysIndirect), 8) / 8);
assert(cmd_size == cmd->cmd_base.cmd_size);
return cmd_size;
}
void GLAPIENTRY
_mesa_marshal_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
GLsizei primcount, GLsizei stride)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
unsigned user_buffer_mask =
_mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
if (ctx->GLThread.draw_always_async ||
!ctx->GLThread.CurrentDrawIndirectBufferName ||
!user_buffer_mask) {
int cmd_size = sizeof(struct marshal_cmd_MultiDrawArraysIndirect);
struct marshal_cmd_MultiDrawArraysIndirect *cmd;
cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArraysIndirect,
cmd_size);
cmd->mode = MIN2(mode, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->indirect = indirect;
cmd->primcount = primcount;
cmd->stride = stride;
return;
}
/* Lower the draw to direct due to non-VBO vertex arrays. */
_mesa_glthread_finish_before(ctx, "MultiDrawArraysIndirect");
lower_draw_arrays_indirect(ctx, mode, (GLintptr)indirect, stride, primcount);
}
struct marshal_cmd_MultiDrawElementsIndirect
{
struct marshal_cmd_base cmd_base;
GLenum16 mode;
GLenum16 type;
GLsizei primcount;
GLsizei stride;
const GLvoid * indirect;
};
uint32_t
_mesa_unmarshal_MultiDrawElementsIndirect(struct gl_context *ctx,
const struct marshal_cmd_MultiDrawElementsIndirect *cmd)
{
GLenum mode = cmd->mode;
GLenum type = cmd->type;
const GLvoid * indirect = cmd->indirect;
GLsizei primcount = cmd->primcount;
GLsizei stride = cmd->stride;
CALL_MultiDrawElementsIndirect(ctx->CurrentServerDispatch,
(mode, type, indirect, primcount, stride));
const unsigned cmd_size =
(align(sizeof(struct marshal_cmd_MultiDrawElementsIndirect), 8) / 8);
assert(cmd_size == cmd->cmd_base.cmd_size);
return cmd_size;
}
void GLAPIENTRY
_mesa_marshal_MultiDrawElementsIndirect(GLenum mode, GLenum type,
const GLvoid *indirect,
GLsizei primcount, GLsizei stride)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
unsigned user_buffer_mask =
_mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
if (ctx->GLThread.draw_always_async || !is_index_type_valid(type) ||
!ctx->GLThread.CurrentDrawIndirectBufferName ||
!vao->CurrentElementBufferName || !user_buffer_mask) {
int cmd_size = sizeof(struct marshal_cmd_MultiDrawElementsIndirect);
struct marshal_cmd_MultiDrawElementsIndirect *cmd;
cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsIndirect,
cmd_size);
cmd->mode = MIN2(mode, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->indirect = indirect;
cmd->primcount = primcount;
cmd->stride = stride;
return;
}
/* Lower the draw to direct due to non-VBO vertex arrays. */
_mesa_glthread_finish_before(ctx, "MultiDrawElementsIndirect");
lower_draw_elements_indirect(ctx, mode, type, (GLintptr)indirect, stride,
primcount);
}
struct marshal_cmd_MultiDrawArraysIndirectCountARB
{
struct marshal_cmd_base cmd_base;
GLenum16 mode;
GLsizei maxdrawcount;
GLsizei stride;
GLintptr indirect;
GLintptr drawcount;
};
uint32_t
_mesa_unmarshal_MultiDrawArraysIndirectCountARB(struct gl_context *ctx,
const struct marshal_cmd_MultiDrawArraysIndirectCountARB *cmd)
{
GLenum mode = cmd->mode;
GLintptr indirect = cmd->indirect;
GLintptr drawcount = cmd->drawcount;
GLsizei maxdrawcount = cmd->maxdrawcount;
GLsizei stride = cmd->stride;
CALL_MultiDrawArraysIndirectCountARB(ctx->CurrentServerDispatch,
(mode, indirect, drawcount,
maxdrawcount, stride));
const unsigned cmd_size =
(align(sizeof(struct marshal_cmd_MultiDrawArraysIndirectCountARB), 8) / 8);
assert(cmd_size == cmd->cmd_base.cmd_size);
return cmd_size;
}
void GLAPIENTRY
_mesa_marshal_MultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect,
GLintptr drawcount,
GLsizei maxdrawcount,
GLsizei stride)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
unsigned user_buffer_mask =
_mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
if (ctx->GLThread.draw_always_async || !user_buffer_mask ||
!ctx->GLThread.CurrentDrawIndirectBufferName) {
int cmd_size =
sizeof(struct marshal_cmd_MultiDrawArraysIndirectCountARB);
struct marshal_cmd_MultiDrawArraysIndirectCountARB *cmd =
_mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArraysIndirectCountARB,
cmd_size);
cmd->mode = MIN2(mode, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->indirect = indirect;
cmd->drawcount = drawcount;
cmd->maxdrawcount = maxdrawcount;
cmd->stride = stride;
return;
}
/* Lower the draw to direct due to non-VBO vertex arrays. */
_mesa_glthread_finish_before(ctx, "MultiDrawArraysIndirectCountARB");
lower_draw_arrays_indirect(ctx, mode, indirect, stride,
read_draw_indirect_count(ctx, drawcount));
}
struct marshal_cmd_MultiDrawElementsIndirectCountARB
{
struct marshal_cmd_base cmd_base;
GLenum16 mode;
GLenum16 type;
GLsizei maxdrawcount;
GLsizei stride;
GLintptr indirect;
GLintptr drawcount;
};
uint32_t
_mesa_unmarshal_MultiDrawElementsIndirectCountARB(struct gl_context *ctx,
const struct marshal_cmd_MultiDrawElementsIndirectCountARB *cmd)
{
GLenum mode = cmd->mode;
GLenum type = cmd->type;
GLintptr indirect = cmd->indirect;
GLintptr drawcount = cmd->drawcount;
GLsizei maxdrawcount = cmd->maxdrawcount;
GLsizei stride = cmd->stride;
CALL_MultiDrawElementsIndirectCountARB(ctx->CurrentServerDispatch, (mode, type, indirect, drawcount, maxdrawcount, stride));
const unsigned cmd_size = (align(sizeof(struct marshal_cmd_MultiDrawElementsIndirectCountARB), 8) / 8);
assert(cmd_size == cmd->cmd_base.cmd_size);
return cmd_size;
}
void GLAPIENTRY
_mesa_marshal_MultiDrawElementsIndirectCountARB(GLenum mode, GLenum type,
GLintptr indirect,
GLintptr drawcount,
GLsizei maxdrawcount,
GLsizei stride)
{
GET_CURRENT_CONTEXT(ctx);
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
unsigned user_buffer_mask =
_mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
if (ctx->GLThread.draw_always_async || !user_buffer_mask ||
!ctx->GLThread.CurrentDrawIndirectBufferName ||
!is_index_type_valid(type)) {
int cmd_size = sizeof(struct marshal_cmd_MultiDrawElementsIndirectCountARB);
struct marshal_cmd_MultiDrawElementsIndirectCountARB *cmd =
_mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsIndirectCountARB, cmd_size);
cmd->mode = MIN2(mode, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->indirect = indirect;
cmd->drawcount = drawcount;
cmd->maxdrawcount = maxdrawcount;
cmd->stride = stride;
return;
}
/* Lower the draw to direct due to non-VBO vertex arrays. */
_mesa_glthread_finish_before(ctx, "MultiDrawElementsIndirectCountARB");
lower_draw_elements_indirect(ctx, mode, type, indirect, stride,
read_draw_indirect_count(ctx, drawcount));
}
void GLAPIENTRY
_mesa_marshal_DrawArrays(GLenum mode, GLint first, GLsizei count)
{
-33
View File
@@ -94,39 +94,6 @@ _mesa_glthread_has_no_unpack_buffer(const struct gl_context *ctx)
return ctx->GLThread.CurrentPixelUnpackBufferName == 0;
}
static inline bool
_mesa_glthread_has_non_vbo_vertices(const struct gl_context *ctx)
{
const struct glthread_state *glthread = &ctx->GLThread;
const struct glthread_vao *vao = glthread->CurrentVAO;
return ctx->API != API_OPENGL_CORE &&
(vao->UserPointerMask & vao->BufferEnabled);
}
static inline bool
_mesa_glthread_has_non_vbo_vertices_or_indirect(const struct gl_context *ctx)
{
const struct glthread_state *glthread = &ctx->GLThread;
const struct glthread_vao *vao = glthread->CurrentVAO;
return ctx->API != API_OPENGL_CORE &&
(glthread->CurrentDrawIndirectBufferName == 0 ||
(vao->UserPointerMask & vao->BufferEnabled));
}
static inline bool
_mesa_glthread_has_non_vbo_vertices_or_indices_or_indirect(const struct gl_context *ctx)
{
const struct glthread_state *glthread = &ctx->GLThread;
struct glthread_vao *vao = glthread->CurrentVAO;
return ctx->API != API_OPENGL_CORE &&
(glthread->CurrentDrawIndirectBufferName == 0 ||
vao->CurrentElementBufferName == 0 ||
(vao->UserPointerMask & vao->BufferEnabled));
}
static inline void
_mesa_glthread_update_draw_always_async(struct gl_context *ctx)
{