diff --git a/src/mapi/glapi/gen/ARB_draw_indirect.xml b/src/mapi/glapi/gen/ARB_draw_indirect.xml index feb6588de35..398720e0b19 100644 --- a/src/mapi/glapi/gen/ARB_draw_indirect.xml +++ b/src/mapi/glapi/gen/ARB_draw_indirect.xml @@ -8,16 +8,12 @@ - + - + @@ -28,16 +24,14 @@ - + - + diff --git a/src/mapi/glapi/gen/ARB_indirect_parameters.xml b/src/mapi/glapi/gen/ARB_indirect_parameters.xml index f08201d4a22..89250abab1d 100644 --- a/src/mapi/glapi/gen/ARB_indirect_parameters.xml +++ b/src/mapi/glapi/gen/ARB_indirect_parameters.xml @@ -8,8 +8,7 @@ - + @@ -18,8 +17,7 @@ - + diff --git a/src/mesa/main/glthread_draw.c b/src/mesa/main/glthread_draw.c index 078264c526f..1c3b13a6c38 100644 --- a/src/mesa/main/glthread_draw.c +++ b/src/mesa/main/glthread_draw.c @@ -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 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 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) { diff --git a/src/mesa/main/glthread_marshal.h b/src/mesa/main/glthread_marshal.h index 25c6641f5c9..157bceab636 100644 --- a/src/mesa/main/glthread_marshal.h +++ b/src/mesa/main/glthread_marshal.h @@ -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) {