diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 24f97e0f7f6..22362d3081f 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -12944,6 +12944,10 @@
+
+
+
+
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index 9c4ce55f6b4..f4f1f4bf0f5 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1705,6 +1705,7 @@ offsets = {
"DrawElementsInstancedBaseVertexBaseInstanceDrawID": 1669,
"InternalInvalidateFramebufferAncillaryMESA": 1670,
"DrawElementsPacked": 1671,
+ "DrawElementsUserBufPacked": 1672,
}
functions = [
diff --git a/src/mesa/main/draw.c b/src/mesa/main/draw.c
index 764c1284ecd..26a074dd2e7 100644
--- a/src/mesa/main/draw.c
+++ b/src/mesa/main/draw.c
@@ -1973,6 +1973,40 @@ _mesa_DrawElementsUserBuf(const GLvoid *ptr)
ctx->DrawID = 0;
}
+/**
+ * Same as glDrawElementsInstancedBaseVertexBaseInstance, but the index
+ * buffer is set by the indexBuf parameter instead of using the bound
+ * GL_ELEMENT_ARRAY_BUFFER if indexBuf != NULL.
+ */
+void GLAPIENTRY
+_mesa_DrawElementsUserBufPacked(const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_FOR_DRAW(ctx);
+
+ _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
+ ctx->Array._DrawVAO->_EnabledWithMapMode);
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ const struct marshal_cmd_DrawElementsUserBufPacked *cmd =
+ (const struct marshal_cmd_DrawElementsUserBufPacked *)ptr;
+ const GLenum mode = cmd->mode;
+ const GLsizei count = cmd->count;
+ const GLenum type = _mesa_decode_index_type(cmd->type);
+
+ if (!_mesa_is_no_error_enabled(ctx) &&
+ !_mesa_validate_DrawElements(ctx, mode, count, type))
+ return;
+
+ struct gl_buffer_object *index_bo =
+ cmd->index_buffer ? cmd->index_buffer : ctx->Array.VAO->IndexBufferObj;
+
+ const GLvoid *indices = (void*)(uintptr_t)cmd->indices;
+
+ _mesa_validated_drawrangeelements(ctx, index_bo, mode, false, 0, ~0,
+ count, type, indices, 0, 1, 0);
+}
/**
* Inner support for both _mesa_MultiDrawElements() and
diff --git a/src/mesa/main/glthread_draw.c b/src/mesa/main/glthread_draw.c
index 9fc41c81393..1bef35b0d71 100644
--- a/src/mesa/main/glthread_draw.c
+++ b/src/mesa/main/glthread_draw.c
@@ -724,6 +724,28 @@ _mesa_unmarshal_DrawElementsUserBuf(struct gl_context *ctx,
return cmd->num_slots;
}
+uint32_t
+_mesa_unmarshal_DrawElementsUserBufPacked(struct gl_context *ctx,
+ const struct marshal_cmd_DrawElementsUserBufPacked *restrict cmd)
+{
+ const GLuint user_buffer_mask = cmd->user_buffer_mask;
+
+ /* Bind uploaded buffers if needed. */
+ if (user_buffer_mask) {
+ struct gl_buffer_object **buffers = (struct gl_buffer_object **)(cmd + 1);
+ const int *offsets = (const int *)(buffers + util_bitcount(user_buffer_mask));
+
+ _mesa_InternalBindVertexBuffers(ctx, buffers, offsets, user_buffer_mask);
+ }
+
+ /* Draw. */
+ CALL_DrawElementsUserBufPacked(ctx->Dispatch.Current, (cmd));
+
+ struct gl_buffer_object *index_buffer = cmd->index_buffer;
+ _mesa_reference_buffer_object(ctx, &index_buffer, NULL);
+ return cmd->num_slots;
+}
+
static inline bool
should_convert_to_begin_end(struct gl_context *ctx, unsigned count,
unsigned num_upload_vertices,
@@ -923,25 +945,45 @@ draw_elements(GLuint drawid, GLenum mode, GLsizei count, GLenum type,
unsigned num_buffers = util_bitcount(user_buffer_mask);
int buffers_size = num_buffers * sizeof(buffers[0]);
int offsets_size = num_buffers * sizeof(int);
- int cmd_size = sizeof(struct marshal_cmd_DrawElementsUserBuf) +
- buffers_size + offsets_size;
- struct marshal_cmd_DrawElementsUserBuf *cmd;
+ char *variable_data;
- cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsUserBuf, cmd_size);
- cmd->num_slots = align(cmd_size, 8) / 8;
- cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
- cmd->type = encode_index_type(type);
- cmd->count = count;
- cmd->indices = indices;
- cmd->instance_count = instance_count;
- cmd->basevertex = basevertex;
- cmd->baseinstance = baseinstance;
- cmd->user_buffer_mask = user_buffer_mask;
- cmd->index_buffer = index_buffer;
- cmd->drawid = drawid;
+ if (instance_count == 1 && basevertex == 0 && baseinstance == 0 &&
+ drawid == 0 && (count & 0xffff) == count &&
+ (uintptr_t)indices <= UINT32_MAX) {
+ int cmd_size = sizeof(struct marshal_cmd_DrawElementsUserBufPacked) +
+ buffers_size + offsets_size;
+ struct marshal_cmd_DrawElementsUserBufPacked *cmd;
+
+ cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsUserBufPacked, cmd_size);
+ cmd->num_slots = align(cmd_size, 8) / 8;
+ cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
+ cmd->type = encode_index_type(type);
+ cmd->count = count; /* truncated */
+ cmd->indices = (uintptr_t)indices; /* truncated */
+ cmd->user_buffer_mask = user_buffer_mask;
+ cmd->index_buffer = index_buffer;
+ variable_data = (char*)(cmd + 1);
+ } else {
+ int cmd_size = sizeof(struct marshal_cmd_DrawElementsUserBuf) +
+ buffers_size + offsets_size;
+ struct marshal_cmd_DrawElementsUserBuf *cmd;
+
+ cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsUserBuf, cmd_size);
+ cmd->num_slots = align(cmd_size, 8) / 8;
+ cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
+ cmd->type = encode_index_type(type);
+ cmd->count = count;
+ cmd->indices = indices;
+ cmd->instance_count = instance_count;
+ cmd->basevertex = basevertex;
+ cmd->baseinstance = baseinstance;
+ cmd->user_buffer_mask = user_buffer_mask;
+ cmd->index_buffer = index_buffer;
+ cmd->drawid = drawid;
+ variable_data = (char*)(cmd + 1);
+ }
if (user_buffer_mask) {
- char *variable_data = (char*)(cmd + 1);
memcpy(variable_data, buffers, buffers_size);
variable_data += buffers_size;
memcpy(variable_data, offsets, offsets_size);
@@ -1927,6 +1969,12 @@ _mesa_marshal_DrawElementsUserBuf(const GLvoid *cmd)
unreachable("should never end up here");
}
+void GLAPIENTRY
+_mesa_marshal_DrawElementsUserBufPacked(const GLvoid *cmd)
+{
+ unreachable("should never end up here");
+}
+
void GLAPIENTRY
_mesa_marshal_MultiDrawArraysUserBuf(void)
{
diff --git a/src/mesa/main/glthread_marshal.h b/src/mesa/main/glthread_marshal.h
index f8e0bb6d391..5084301ebbf 100644
--- a/src/mesa/main/glthread_marshal.h
+++ b/src/mesa/main/glthread_marshal.h
@@ -76,6 +76,18 @@ struct marshal_cmd_DrawElementsUserBuf
struct gl_buffer_object *index_buffer;
};
+struct marshal_cmd_DrawElementsUserBufPacked
+{
+ struct marshal_cmd_base cmd_base;
+ GLenum8 mode;
+ GLindextype type;
+ uint16_t num_slots;
+ GLushort count;
+ GLuint user_buffer_mask;
+ GLuint indices;
+ struct gl_buffer_object *index_buffer;
+};
+
static inline void *
_mesa_glthread_allocate_command(struct gl_context *ctx,
uint16_t cmd_id,