With the issues below fixed, Reviewed-by: Ian Romanick <ian.d.roman...@intel.com>
On 11/09/2013 01:02 AM, Chris Forbes wrote: > Based on part of Patch 2 of Christoph Bumiller's ARB_draw_indirect series. > > Signed-off-by: Chris Forbes <chr...@ijw.co.nz> > --- > src/mesa/vbo/vbo_exec_array.c | 216 > ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 216 insertions(+) > > diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c > index 4ea10ee..1c6b8b3 100644 > --- a/src/mesa/vbo/vbo_exec_array.c > +++ b/src/mesa/vbo/vbo_exec_array.c > @@ -1564,6 +1564,164 @@ 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)); prim = calloc(primcount, sizeof(*prim)); because primcount could be 0x7fffffff, and that would overflow on 32-bit leading to sadness. calloc will do the right thing. > + if (prim == NULL) { > + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect"); > + return; > + } > + > + vbo_bind_arrays(ctx); > + > + memset(prim, 0, primcount * sizeof(*prim)); But you used calloc. :( > + 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)); Same here. > + 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)); Same here. > + 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. > @@ -1571,12 +1729,33 @@ vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum > mode, GLuint name, > 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 > @@ -1584,6 +1763,24 @@ 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 > @@ -1591,6 +1788,25 @@ 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); > } > > /** > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev