From d2caa377416de12964b5763ad333f21622d11360 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Mon, 25 Jun 2018 10:32:58 +1000 Subject: mesa: add compat profile support for ARB_multi_draw_indirect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: add missing ARB_base_instance support Reviewed-by: Marek Olšák --- src/mesa/vbo/vbo_exec_array.c | 77 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index dbb2590f0c9..58bba208db1 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -1749,7 +1749,38 @@ vbo_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, /* If is zero, the array elements are treated as tightly packed. */ if (stride == 0) - stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ + stride = sizeof(DrawArraysIndirectCommand); + + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + + if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, + "glMultiDrawArraysIndirect")) + return; + + const ubyte *ptr = (const ubyte *) indirect; + for (unsigned i = 0; i < primcount; i++) { + DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr; + vbo_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, + cmd->count, cmd->primCount, + cmd->baseInstance); + + if (stride == 0) { + ptr += sizeof(DrawArraysIndirectCommand); + } else { + ptr += stride; + } + } + + return; + } FLUSH_FOR_DRAW(ctx); @@ -1788,7 +1819,49 @@ vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, /* If is zero, the array elements are treated as tightly packed. */ if (stride == 0) - stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ + stride = sizeof(DrawElementsIndirectCommand); + + + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + /* + * Unlike regular DrawElementsInstancedBaseVertex commands, the indices + * may not come from a client array and must come from an index buffer. + * If no element array buffer is bound, an INVALID_OPERATION error is + * generated. + */ + if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMultiDrawElementsIndirect(no buffer bound " + "to GL_ELEMENT_ARRAY_BUFFER)"); + + return; + } + + if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, + "glMultiDrawArraysIndirect")) + return; + + const ubyte *ptr = (const ubyte *) indirect; + for (unsigned i = 0; i < primcount; i++) { + vbo_exec_DrawElementsIndirect(mode, type, ptr); + + if (stride == 0) { + ptr += sizeof(DrawElementsIndirectCommand); + } else { + ptr += stride; + } + } + + return; + } FLUSH_FOR_DRAW(ctx); -- cgit v1.2.3