[Mesa-dev] [PATCH V3 06/13] vbo: Flesh out implementation of indirect draws
Chris Forbes
chrisf at ijw.co.nz
Tue Nov 19 12:35:06 PST 2013
I've inherited a fair amount of sillyness from the original patches...
sorry, I'll clean that up.
On Wed, Nov 20, 2013 at 9:15 AM, Ian Romanick <idr at freedesktop.org> wrote:
> With the issues below fixed,
>
> Reviewed-by: Ian Romanick <ian.d.romanick at 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 <chrisf at 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);
>> }
>>
>> /**
>>
>
More information about the mesa-dev
mailing list