On 11/04/2013 01:09 AM, Chris Forbes wrote: > From: Christoph Bumiller <e0425...@student.tuwien.ac.at> > > v2: > Removed some stray extern qualifiers. > > Documented use of Draw*IndirectCommand sizes. > > Removed separate extension enable flag for ARB_multi_draw_indirect > since this can always be supported by looping. > > Kept generation of GL_INVALID_OPERATION in display list compile. > The spec doesn't say anything about them, but all the direct drawing > commands that support instancing do the same. > > v3: > Initialize DrawIndirectBuffer with NullBufferObj. > > Only hook up the Draw functions in vtxfmt.c if API_OPENGL_CORE > instead of _mesa_is_desktop_gl. > > Fix index bounds. > > v4: [Chris Forbes] Rebase to master -- significant conflicts due to > vtxfmt vtable no longer containing draw functions. > > Conflicts: > src/mesa/main/bufferobj.c > src/mesa/main/dd.h > src/mesa/main/dlist.c > src/mesa/vbo/vbo_exec_array.c > src/mesa/vbo/vbo_save_api.c > --- > src/mapi/glapi/gen/ARB_draw_indirect.xml | 45 ++++++ > src/mapi/glapi/gen/Makefile.am | 1 + > src/mapi/glapi/gen/gl_API.xml | 4 +- > src/mesa/main/api_validate.c | 153 +++++++++++++++++++ > src/mesa/main/api_validate.h | 26 ++++ > src/mesa/main/bufferobj.c | 12 ++ > src/mesa/main/dlist.c | 46 +++++- > src/mesa/main/extensions.c | 2 + > src/mesa/main/get.c | 5 + > src/mesa/main/get_hash_params.py | 2 + > src/mesa/main/mtypes.h | 3 + > src/mesa/main/tests/dispatch_sanity.cpp | 8 +- > src/mesa/vbo/vbo_exec_array.c | 248 > +++++++++++++++++++++++++++++++ > 13 files changed, 549 insertions(+), 6 deletions(-) > create mode 100644 src/mapi/glapi/gen/ARB_draw_indirect.xml > > diff --git a/src/mapi/glapi/gen/ARB_draw_indirect.xml > b/src/mapi/glapi/gen/ARB_draw_indirect.xml > new file mode 100644 > index 0000000..7de03cd > --- /dev/null > +++ b/src/mapi/glapi/gen/ARB_draw_indirect.xml > @@ -0,0 +1,45 @@ > +<?xml version="1.0"?> > +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> > + > +<OpenGLAPI> > + > +<category name="GL_ARB_draw_indirect" number="87"> > + > + <enum name="DRAW_INDIRECT_BUFFER" value="0x8F3F"/> > + <enum name="DRAW_INDIRECT_BUFFER_BINDING" value="0x8F43"/> > + > + <function name="DrawArraysIndirect" offset="assign" exec="dynamic"> > + <param name="mode" type="GLenum"/> > + <param name="indirect" type="const GLvoid *"/> > + </function> > + > + <function name="DrawElementsIndirect" offset="assign" exec="dynamic"> > + <param name="mode" type="GLenum"/> > + <param name="type" type="GLenum"/> > + <param name="indirect" type="const GLvoid *"/> > + </function> > + > +</category> > + > + > +<category name="GL_ARB_multi_draw_indirect" number="133"> > + > + <function name="MultiDrawArraysIndirect" offset="assign" exec="dynamic"> > + <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" offset="assign" > exec="dynamic"> > + <param name="mode" type="GLenum"/> > + <param name="type" type="GLenum"/> > + <param name="indirect" type="const GLvoid *"/> > + <param name="primcount" type="GLsizei"/> > + <param name="stride" type="GLsizei"/> > + </function> > + > +</category> > + > + > +</OpenGLAPI> > diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am > index cbbf659..0c67513 100644 > --- a/src/mapi/glapi/gen/Makefile.am > +++ b/src/mapi/glapi/gen/Makefile.am > @@ -98,6 +98,7 @@ API_XML = \ > ARB_draw_buffers.xml \ > ARB_draw_buffers_blend.xml \ > ARB_draw_elements_base_vertex.xml \ > + ARB_draw_indirect.xml \ > ARB_draw_instanced.xml \ > ARB_ES2_compatibility.xml \ > ARB_ES3_compatibility.xml \ > diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml > index 69014c5..7cab5ba 100644 > --- a/src/mapi/glapi/gen/gl_API.xml > +++ b/src/mapi/glapi/gen/gl_API.xml > @@ -8241,6 +8241,8 @@ > > <!-- ARB extensions #86...#93 --> > > +<xi:include href="ARB_draw_indirect.xml" > xmlns:xi="http://www.w3.org/2001/XInclude"/> > + > <category name="GL_ARB_transform_feedback3" number="94"> > <enum name="MAX_TRANSFORM_FEEDBACK_BUFFERS" value="0x8E70"/> > <enum name="MAX_VERTEX_STREAMS" value="0x8E71"/> > @@ -8466,7 +8468,7 @@ > > <xi:include href="ARB_invalidate_subdata.xml" > xmlns:xi="http://www.w3.org/2001/XInclude"/> > > -<!-- ARB extensions #133...#138 --> > +<!-- ARB extensions #134...#138 --> > > <xi:include href="ARB_texture_buffer_range.xml" > xmlns:xi="http://www.w3.org/2001/XInclude"/> > > diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c > index f285c97..f3128cb 100644 > --- a/src/mesa/main/api_validate.c > +++ b/src/mesa/main/api_validate.c > @@ -837,3 +837,156 @@ _mesa_validate_DrawTransformFeedback(struct gl_context > *ctx, > > return GL_TRUE; > } > + > +static GLboolean
If you do the patch splitting suggested by Brian, perhaps do some s/GLboolean/bool/ too. > +valid_draw_indirect(struct gl_context *ctx, > + GLenum mode, const GLvoid *indirect, > + GLsizei size, const char *name) > +{ > + const GLsizeiptr end = (GLsizeiptr)indirect + size; > + > + if (!_mesa_valid_prim_mode(ctx, mode, name)) > + return GL_FALSE; > + > + if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(indirect is not aligned)", name); > + return GL_FALSE; > + } > + > + if (_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { > + if (_mesa_bufferobj_mapped(ctx->DrawIndirectBuffer)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(DRAW_INDIRECT_BUFFER is mapped)", name); > + return GL_FALSE; > + } > + if (ctx->DrawIndirectBuffer->Size < end) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(DRAW_INDIRECT_BUFFER too small)", name); > + return GL_FALSE; > + } > + } else { > + if (ctx->API != API_OPENGL_COMPAT) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name); > + return GL_FALSE; > + } > + } > + > + if (!check_valid_to_render(ctx, name)) > + return GL_FALSE; > + > + return GL_TRUE; > +} > + > +static inline GLboolean > +valid_draw_indirect_elements(struct gl_context *ctx, > + GLenum mode, GLenum type, const GLvoid > *indirect, > + GLsizeiptr size, const char *name) > +{ > + if (!valid_elements_type(ctx, type, name)) > + return GL_FALSE; > + > + /* > + * 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.ArrayObj->ElementArrayBufferObj)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name); > + return GL_FALSE; > + } > + > + return valid_draw_indirect(ctx, mode, indirect, size, name); > +} > + > +static inline GLboolean > +valid_draw_indirect_multi(struct gl_context *ctx, > + GLsizei primcount, GLsizei stride, > + const char *name) > +{ > + if (primcount < 0) { > + _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name); > + return GL_FALSE; > + } > + > + if (stride % 4) { > + _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name); > + return GL_FALSE; > + } > + > + return GL_TRUE; > +} > + > +GLboolean > +_mesa_validate_DrawArraysIndirect(struct gl_context *ctx, > + GLenum mode, > + const GLvoid *indirect) > +{ > + FLUSH_CURRENT(ctx, 0); > + > + return valid_draw_indirect(ctx, mode, > + indirect, 4 * sizeof(GLuint), > + "glDrawArraysIndirect"); > +} > + > +GLboolean > +_mesa_validate_DrawElementsIndirect(struct gl_context *ctx, > + GLenum mode, GLenum type, > + const GLvoid *indirect) > +{ > + FLUSH_CURRENT(ctx, 0); > + > + return valid_draw_indirect_elements(ctx, mode, type, > + indirect, 5 * sizeof(GLuint), > + "glDrawElementsIndirect"); > +} > + > +GLboolean > +_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx, > + GLenum mode, > + const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + GLsizeiptr size = 0; > + if (primcount) /* &(last command) + sizeof(DrawArraysIndirectCommand) */ > + size = (primcount - 1) * stride + 4 * sizeof(GLuint); > + > + FLUSH_CURRENT(ctx, 0); > + > + if (!valid_draw_indirect_multi(ctx, primcount, stride, > + "glMultiDrawArraysIndirect")) > + return GL_FALSE; > + > + if (!valid_draw_indirect(ctx, mode, indirect, size, > + "glMultiDrawArraysIndirect")) > + return GL_FALSE; > + > + return GL_TRUE; > +} > + > +GLboolean > +_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx, > + GLenum mode, GLenum type, > + const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + GLsizeiptr size = 0; > + if (primcount) /* &(last command) + sizeof(DrawElementsIndirectCommand) */ > + size = (primcount - 1) * stride + 5 * sizeof(GLuint); > + > + FLUSH_CURRENT(ctx, 0); > + > + if (!valid_draw_indirect_multi(ctx, primcount, stride, > + "glMultiDrawElementsIndirect")) > + return GL_FALSE; > + > + if (!valid_draw_indirect_elements(ctx, mode, type, > + indirect, size, > + "glMultiDrawElementsIndirect")) > + return GL_FALSE; > + > + return GL_TRUE; > +} > diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h > index f2b753c..8238df1 100644 > --- a/src/mesa/main/api_validate.h > +++ b/src/mesa/main/api_validate.h > @@ -87,5 +87,31 @@ _mesa_validate_DrawTransformFeedback(struct gl_context > *ctx, > GLuint stream, > GLsizei numInstances); > > +extern GLboolean > +_mesa_validate_DrawArraysIndirect(struct gl_context *ctx, > + GLenum mode, > + const GLvoid *indirect); > + > +extern GLboolean > +_mesa_validate_DrawElementsIndirect(struct gl_context *ctx, > + GLenum mode, > + GLenum type, > + const GLvoid *indirect); > + > +extern GLboolean > +_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx, > + GLenum mode, > + const GLvoid *indirect, > + GLsizei primcount, > + GLsizei stride); > + > +extern GLboolean > +_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx, > + GLenum mode, > + GLenum type, > + const GLvoid *indirect, > + GLsizei primcount, > + GLsizei stride); > + > > #endif > diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c > index 1f55061..69ea1c0 100644 > --- a/src/mesa/main/bufferobj.c > +++ b/src/mesa/main/bufferobj.c > @@ -86,6 +86,10 @@ get_buffer_target(struct gl_context *ctx, GLenum target) > return &ctx->CopyReadBuffer; > case GL_COPY_WRITE_BUFFER: > return &ctx->CopyWriteBuffer; > + case GL_DRAW_INDIRECT_BUFFER: > + if (ctx->Extensions.ARB_draw_indirect) && _mesa_is_desktop_gl(ctx) > + return &ctx->DrawIndirectBuffer; > + break; > case GL_TRANSFORM_FEEDBACK_BUFFER: > if (ctx->Extensions.EXT_transform_feedback) { > return &ctx->TransformFeedback.CurrentBuffer; > @@ -626,6 +630,9 @@ _mesa_init_buffer_objects( struct gl_context *ctx ) > _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, > ctx->Shared->NullBufferObj); > > + _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, > + ctx->Shared->NullBufferObj); > + > for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) { > _mesa_reference_buffer_object(ctx, > &ctx->UniformBufferBindings[i].BufferObject, > @@ -873,6 +880,11 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) > _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); > } > > + /* unbind ARB_draw_indirect binding point */ > + if (ctx->DrawIndirectBuffer == bufObj) { > + _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 ); > + } > + > /* unbind ARB_copy_buffer binding points */ > if (ctx->CopyReadBuffer == bufObj) { > _mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 ); > diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c > index 5956419..c953ffb 100644 > --- a/src/mesa/main/dlist.c > +++ b/src/mesa/main/dlist.c > @@ -1356,6 +1356,42 @@ > save_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, > "glDrawElementsInstancedBaseVertexBaseInstance() during display > list compile"); > } > > +/* GL_ARB_draw_indirect. */ > +static void GLAPIENTRY > +save_DrawArraysIndirect(GLenum mode, const GLvoid *indirect) > +{ > + GET_CURRENT_CONTEXT(ctx); > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glDrawArraysIndirect() during display list compile"); Where is this error documented? I don't see it in the extension spec. Or is this just because we're only doing these extensions in core profiles and there are no display lists in core profile? > +} > + > +static void GLAPIENTRY > +save_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) > +{ > + GET_CURRENT_CONTEXT(ctx); > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glDrawElementsIndirect() during display list compile"); > +} > + > +/* GL_ARB_multi_draw_indirect. */ > +static void GLAPIENTRY > +save_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + GET_CURRENT_CONTEXT(ctx); > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glMultiDrawArraysIndirect() during display list compile"); > +} > + > +static void GLAPIENTRY > +save_MultiDrawElementsIndirect(GLenum mode, GLenum type, > + const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + GET_CURRENT_CONTEXT(ctx); > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glMultiDrawElementsIndirect() during display list compile"); > +} > > /** > * While building a display list we cache some OpenGL state. > @@ -1363,7 +1399,7 @@ save_DrawElementsInstancedBaseVertexBaseInstance(GLenum > mode, > * when we start compiling a list, or after glCallList(s)). > */ > static void > -invalidate_saved_current_state(struct gl_context *ctx) > +invalidate_saved_current_state( struct gl_context *ctx ) > { > GLint i; > > @@ -9283,6 +9319,14 @@ _mesa_initialize_save_table(const struct gl_context > *ctx) > SET_DrawArraysInstancedBaseInstance(table, > save_DrawArraysInstancedBaseInstance); > SET_DrawElementsInstancedBaseInstance(table, > save_DrawElementsInstancedBaseInstance); > SET_DrawElementsInstancedBaseVertexBaseInstance(table, > save_DrawElementsInstancedBaseVertexBaseInstance); > + > + /* GL_ARB_draw_indirect */ > + SET_DrawArraysIndirect(table, save_DrawArraysIndirect); > + SET_DrawElementsIndirect(table, save_DrawElementsIndirect); > + > + /* GL_ARB_multi_draw_indirect */ > + SET_MultiDrawArraysIndirect(table, save_MultiDrawArraysIndirect); > + SET_MultiDrawElementsIndirect(table, save_MultiDrawElementsIndirect); > } > > > diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c > index 48c4e9f..f0aae00 100644 > --- a/src/mesa/main/extensions.c > +++ b/src/mesa/main/extensions.c > @@ -92,6 +92,7 @@ static const struct extension extension_table[] = { > { "GL_ARB_draw_buffers", o(dummy_true), > GL, 2002 }, > { "GL_ARB_draw_buffers_blend", > o(ARB_draw_buffers_blend), GL, 2009 }, > { "GL_ARB_draw_elements_base_vertex", > o(ARB_draw_elements_base_vertex), GL, 2009 }, > + { "GL_ARB_draw_indirect", o(ARB_draw_indirect), > GLC, 2010 }, > { "GL_ARB_draw_instanced", o(ARB_draw_instanced), > GL, 2008 }, > { "GL_ARB_explicit_attrib_location", > o(ARB_explicit_attrib_location), GL, 2009 }, > { "GL_ARB_fragment_coord_conventions", > o(ARB_fragment_coord_conventions), GL, 2009 }, > @@ -109,6 +110,7 @@ static const struct extension extension_table[] = { > { "GL_ARB_invalidate_subdata", o(dummy_true), > GL, 2012 }, > { "GL_ARB_map_buffer_alignment", > o(ARB_map_buffer_alignment), GL, 2011 }, > { "GL_ARB_map_buffer_range", o(ARB_map_buffer_range), > GL, 2008 }, > + { "GL_ARB_multi_draw_indirect", o(ARB_draw_indirect), > GLC, 2012 }, > { "GL_ARB_multisample", o(dummy_true), > GLL, 1994 }, > { "GL_ARB_multitexture", o(dummy_true), > GLL, 1998 }, > { "GL_ARB_occlusion_query2", o(ARB_occlusion_query2), > GL, 2003 }, > diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c > index 6a0de0c..a471383 100644 > --- a/src/mesa/main/get.c > +++ b/src/mesa/main/get.c > @@ -375,6 +375,7 @@ EXTRA_EXT(ARB_texture_buffer_range); > EXTRA_EXT(ARB_texture_multisample); > EXTRA_EXT(ARB_texture_gather); > EXTRA_EXT(ARB_shader_atomic_counters); > +EXTRA_EXT(ARB_draw_indirect); > > static const int > extra_ARB_color_buffer_float_or_glcore[] = { > @@ -913,6 +914,10 @@ find_custom_value(struct gl_context *ctx, const struct > value_desc *d, union valu > case GL_ATOMIC_COUNTER_BUFFER_BINDING: > v->value_int = ctx->AtomicBuffer->Name; > break; > + /* GL_ARB_draw_indirect */ > + case GL_DRAW_INDIRECT_BUFFER_BINDING: > + v->value_int = ctx->DrawIndirectBuffer->Name; > + break; > } > } > > diff --git a/src/mesa/main/get_hash_params.py > b/src/mesa/main/get_hash_params.py > index 0851b7b..226ede0 100644 > --- a/src/mesa/main/get_hash_params.py > +++ b/src/mesa/main/get_hash_params.py > @@ -743,6 +743,8 @@ descriptor=[ > { "apis": ["GL_CORE"], "params": [ > # GL_ARB_texture_buffer_range > [ "TEXTURE_BUFFER_OFFSET_ALIGNMENT", > "CONTEXT_INT(Const.TextureBufferOffsetAlignment), > extra_ARB_texture_buffer_range" ], > +# GL_ARB_draw_indirect > + [ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, > extra_ARB_draw_indirect" ], > ]} > > ] > diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h > index b5c5583..4f4fc52 100644 > --- a/src/mesa/main/mtypes.h > +++ b/src/mesa/main/mtypes.h > @@ -3237,6 +3237,7 @@ struct gl_extensions > GLboolean ARB_depth_texture; > GLboolean ARB_draw_buffers_blend; > GLboolean ARB_draw_elements_base_vertex; > + GLboolean ARB_draw_indirect; > GLboolean ARB_draw_instanced; > GLboolean ARB_fragment_coord_conventions; > GLboolean ARB_fragment_program; > @@ -3812,6 +3813,8 @@ struct gl_context > > struct gl_perf_monitor_state PerfMonitor; > > + struct gl_buffer_object *DrawIndirectBuffer; /** < GL_ARB_draw_indirect */ > + > struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */ > struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */ > > diff --git a/src/mesa/main/tests/dispatch_sanity.cpp > b/src/mesa/main/tests/dispatch_sanity.cpp > index 58cff9b..e7fbcc5 100644 > --- a/src/mesa/main/tests/dispatch_sanity.cpp > +++ b/src/mesa/main/tests/dispatch_sanity.cpp > @@ -667,8 +667,8 @@ const struct function gl_core_functions_possible[] = { > { "glVertexAttribP3uiv", 43, -1 }, > { "glVertexAttribP4ui", 43, -1 }, > { "glVertexAttribP4uiv", 43, -1 }, > -// { "glDrawArraysIndirect", 43, -1 }, // XXX: Add to xml > -// { "glDrawElementsIndirect", 43, -1 }, // XXX: Add to xml > + { "glDrawArraysIndirect", 43, -1 }, > + { "glDrawElementsIndirect", 43, -1 }, > // { "glUniform1d", 43, -1 }, // XXX: Add to xml > // { "glUniform2d", 43, -1 }, // XXX: Add to xml > // { "glUniform3d", 43, -1 }, // XXX: Add to xml > @@ -877,8 +877,8 @@ const struct function gl_core_functions_possible[] = { > { "glInvalidateBufferData", 43, -1 }, > { "glInvalidateFramebuffer", 43, -1 }, > { "glInvalidateSubFramebuffer", 43, -1 }, > -// { "glMultiDrawArraysIndirect", 43, -1 }, // XXX: Add to xml > -// { "glMultiDrawElementsIndirect", 43, -1 }, // XXX: Add to xml > + { "glMultiDrawArraysIndirect", 43, -1 }, > + { "glMultiDrawElementsIndirect", 43, -1 }, > // { "glGetProgramInterfaceiv", 43, -1 }, // XXX: Add to xml > // { "glGetProgramResourceIndex", 43, -1 }, // XXX: Add to xml > // { "glGetProgramResourceName", 43, -1 }, // XXX: Add to xml > diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c > index 5e1f80c..7aa0ad2 100644 > --- a/src/mesa/vbo/vbo_exec_array.c > +++ b/src/mesa/vbo/vbo_exec_array.c > @@ -1564,6 +1564,250 @@ vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum > mode, GLuint name, > vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount); > } > > +static void > +vbo_validated_drawarraysindirect(struct gl_context *ctx, > + GLenum mode, const GLvoid *indirect) > +{ > + struct vbo_context *vbo = vbo_context(ctx); > + struct vbo_exec_context *exec = &vbo->exec; > + struct _mesa_prim prim[1]; > + > + vbo_bind_arrays(ctx); > + > + memset(prim, 0, sizeof(prim)); > + prim[0].begin = 1; > + prim[0].end = 1; > + prim[0].mode = mode; > + prim[0].indirect_offset = (GLsizeiptr)indirect; > + > + /* NOTE: We do NOT want to handle primitive restart here, nor perform any > + * other checks that require knowledge of the values in the command > buffer. > + * That would deafeat the whole purpose of this function. > + */ > + > + check_buffers_are_unmapped(exec->array.inputs); > + vbo->draw_prims(ctx, prim, 1, > + NULL, GL_TRUE, 0, ~0, > + NULL, > + ctx->DrawIndirectBuffer); > + > + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) > + _mesa_flush(ctx); > +} > + > +static void > +vbo_validated_multidrawarraysindirect(struct gl_context *ctx, > + GLenum mode, > + const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + struct vbo_context *vbo = vbo_context(ctx); > + struct vbo_exec_context *exec = &vbo->exec; > + struct _mesa_prim *prim; > + GLsizei i; > + GLsizeiptr offset = (GLsizeiptr)indirect; > + > + if (primcount == 0) > + return; > + prim = calloc(1, primcount * sizeof(*prim)); > + if (prim == NULL) { > + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect"); > + return; > + } > + > + vbo_bind_arrays(ctx); > + > + memset(prim, 0, primcount * sizeof(*prim)); > + prim[0].begin = 1; > + prim[primcount - 1].end = 1; > + for (i = 0; i < primcount; ++i, offset += stride) { > + prim[i].mode = mode; > + prim[i].indirect_offset = offset; > + } > + > + check_buffers_are_unmapped(exec->array.inputs); > + vbo->draw_prims(ctx, prim, primcount, > + NULL, GL_TRUE, 0, ~0, > + NULL, > + ctx->DrawIndirectBuffer); > + > + free(prim); > + > + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) > + _mesa_flush(ctx); > +} > + > +static void > +vbo_validated_drawelementsindirect(struct gl_context *ctx, > + GLenum mode, GLenum type, > + const GLvoid *indirect) > +{ > + struct vbo_context *vbo = vbo_context(ctx); > + struct vbo_exec_context *exec = &vbo->exec; > + struct _mesa_index_buffer ib; > + struct _mesa_prim prim[1]; > + > + vbo_bind_arrays(ctx); > + > + ib.count = 0; /* unknown */ > + ib.type = type; > + ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; > + ib.ptr = NULL; > + > + memset(prim, 0, sizeof(prim)); > + prim[0].begin = 1; > + prim[0].end = 1; > + prim[0].mode = mode; > + prim[0].indexed = 1; > + prim[0].indirect_offset = (GLsizeiptr)indirect; > + > + check_buffers_are_unmapped(exec->array.inputs); > + vbo->draw_prims(ctx, prim, 1, > + &ib, GL_TRUE, 0, ~0, > + NULL, > + ctx->DrawIndirectBuffer); > + > + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) > + _mesa_flush(ctx); > +} > + > +static void > +vbo_validated_multidrawelementsindirect(struct gl_context *ctx, > + GLenum mode, GLenum type, > + const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + struct vbo_context *vbo = vbo_context(ctx); > + struct vbo_exec_context *exec = &vbo->exec; > + struct _mesa_index_buffer ib; > + struct _mesa_prim *prim; > + GLsizei i; > + GLsizeiptr offset = (GLsizeiptr)indirect; > + > + if (primcount == 0) > + return; > + prim = calloc(1, primcount * sizeof(*prim)); > + if (prim == NULL) { > + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect"); > + return; > + } > + > + vbo_bind_arrays(ctx); > + > + /* NOTE: ElementArrayBufferObj is guaranteed to be a VBO. */ > + > + ib.count = 0; /* unknown */ > + ib.type = type; > + ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; > + ib.ptr = NULL; > + > + memset(prim, 0, primcount * sizeof(*prim)); > + prim[0].begin = 1; > + prim[primcount - 1].end = 1; > + for (i = 0; i < primcount; ++i, offset += stride) { > + prim[i].mode = mode; > + prim[i].indexed = 1; > + prim[i].indirect_offset = offset; > + } > + > + check_buffers_are_unmapped(exec->array.inputs); > + vbo->draw_prims(ctx, prim, primcount, > + &ib, GL_TRUE, 0, ~0, > + NULL, > + ctx->DrawIndirectBuffer); > + > + free(prim); > + > + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) > + _mesa_flush(ctx); > +} > + > +/** > + * Like [Multi]DrawArrays/Elements, but they take most arguments from > + * a buffer object. > + */ > +static void GLAPIENTRY > +vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect) > +{ > + GET_CURRENT_CONTEXT(ctx); > + > + if (MESA_VERBOSE & VERBOSE_DRAW) > + _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n", > + _mesa_lookup_enum_by_nr(mode), indirect); > + > + if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect)) > + return; > + > + vbo_validated_drawarraysindirect(ctx, mode, indirect); > +} > + > +static void GLAPIENTRY > +vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type, > + const GLvoid *indirect) > +{ > + GET_CURRENT_CONTEXT(ctx); > + > + if (MESA_VERBOSE & VERBOSE_DRAW) > + _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n", > + _mesa_lookup_enum_by_nr(mode), > + _mesa_lookup_enum_by_nr(type), indirect); > + > + if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect)) > + return; > + > + vbo_validated_drawelementsindirect(ctx, mode, type, indirect); > +} > + > +static void GLAPIENTRY > +vbo_exec_MultiDrawArraysIndirect(GLenum mode, > + const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + GET_CURRENT_CONTEXT(ctx); > + > + if (MESA_VERBOSE & VERBOSE_DRAW) > + _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n", > + _mesa_lookup_enum_by_nr(mode), indirect, primcount, > stride); > + > + /* If <stride> is zero, the array elements are treated as tightly packed. > */ > + if (stride == 0) > + stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ > + > + if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode, > + indirect, > + primcount, stride)) > + return; > + > + vbo_validated_multidrawarraysindirect(ctx, mode, > + indirect, > + primcount, stride); > +} > + > +static void GLAPIENTRY > +vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, > + const GLvoid *indirect, > + GLsizei primcount, GLsizei stride) > +{ > + GET_CURRENT_CONTEXT(ctx); > + > + if (MESA_VERBOSE & VERBOSE_DRAW) > + _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n", > + _mesa_lookup_enum_by_nr(mode), > + _mesa_lookup_enum_by_nr(type), indirect, primcount, > stride); > + > + /* If <stride> is zero, the array elements are treated as tightly packed. > */ > + if (stride == 0) > + stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ > + > + if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, > + indirect, > + primcount, stride)) > + return; > + > + vbo_validated_multidrawelementsindirect(ctx, mode, type, > + indirect, > + primcount, stride); > +} > > /** > * Initialize the dispatch table with the VBO functions for drawing. > @@ -1595,6 +1839,10 @@ vbo_initialize_exec_dispatch(const struct gl_context > *ctx, > SET_DrawElementsInstancedBaseInstance(exec, > vbo_exec_DrawElementsInstancedBaseInstance); > SET_DrawElementsInstancedBaseVertex(exec, > vbo_exec_DrawElementsInstancedBaseVertex); > SET_DrawElementsInstancedBaseVertexBaseInstance(exec, > vbo_exec_DrawElementsInstancedBaseVertexBaseInstance); > + SET_DrawArraysIndirect(exec, vbo_exec_DrawArraysIndirect); > + SET_DrawElementsIndirect(exec, vbo_exec_DrawElementsIndirect); > + SET_MultiDrawArraysIndirect(exec, vbo_exec_MultiDrawArraysIndirect); > + SET_MultiDrawElementsIndirect(exec, > vbo_exec_MultiDrawElementsIndirect); > } > > if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev