diff options
Diffstat (limited to 'src/mesa/vbo')
-rw-r--r-- | src/mesa/vbo/vbo.h | 17 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_context.c | 52 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_context.h | 6 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec.c | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec.h | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec_array.c | 217 |
6 files changed, 217 insertions, 79 deletions
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index cef3b8cd792..0b8b6a9de56 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -78,7 +78,7 @@ struct _mesa_index_buffer { GLboolean _vbo_CreateContext( struct gl_context *ctx ); void _vbo_DestroyContext( struct gl_context *ctx ); -void _vbo_InvalidateState( struct gl_context *ctx, GLuint new_state ); +void _vbo_InvalidateState( struct gl_context *ctx, GLbitfield new_state ); void @@ -110,6 +110,18 @@ typedef void (*vbo_draw_func)( struct gl_context *ctx, struct gl_buffer_object *indirect); +typedef void (*vbo_indirect_draw_func)( + struct gl_context *ctx, + GLuint mode, + struct gl_buffer_object *indirect_data, + GLsizeiptr indirect_offset, + unsigned draw_count, + unsigned stride, + struct gl_buffer_object *indirect_params, + GLsizeiptr indirect_params_offset, + const struct _mesa_index_buffer *ib); + + /* Utility function to cope with various constraints on tnl modules or @@ -179,6 +191,9 @@ void vbo_always_unmap_buffers(struct gl_context *ctx); void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func); +void vbo_set_indirect_draw_func(struct gl_context *ctx, + vbo_indirect_draw_func func); + void vbo_check_buffers_are_unmapped(struct gl_context *ctx); void vbo_bind_arrays(struct gl_context *ctx); diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 5e1a760eb2c..9f807a17512 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -135,6 +135,48 @@ static void init_mat_currval(struct gl_context *ctx) } } +static void +vbo_draw_indirect_prims(struct gl_context *ctx, + GLuint mode, + struct gl_buffer_object *indirect_data, + GLsizeiptr indirect_offset, + unsigned draw_count, + unsigned stride, + struct gl_buffer_object *indirect_params, + GLsizeiptr indirect_params_offset, + const struct _mesa_index_buffer *ib) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct _mesa_prim *prim; + GLsizei i; + + prim = calloc(draw_count, sizeof(*prim)); + if (prim == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s", + (draw_count > 1) ? "Multi" : "", + ib ? "Elements" : "Arrays", + indirect_params ? "CountARB" : ""); + return; + } + + prim[0].begin = 1; + prim[draw_count - 1].end = 1; + for (i = 0; i < draw_count; ++i, indirect_offset += stride) { + prim[i].mode = mode; + prim[i].indexed = !!ib; + prim[i].indirect_offset = indirect_offset; + prim[i].is_indirect = 1; + prim[i].draw_id = i; + } + + vbo->draw_prims(ctx, prim, draw_count, + ib, GL_TRUE, 0, ~0, + NULL, 0, + ctx->DrawIndirectBuffer); + + free(prim); +} + GLboolean _vbo_CreateContext( struct gl_context *ctx ) { @@ -152,6 +194,7 @@ GLboolean _vbo_CreateContext( struct gl_context *ctx ) init_legacy_currval( ctx ); init_generic_currval( ctx ); init_mat_currval( ctx ); + vbo_set_indirect_draw_func(ctx, vbo_draw_indirect_prims); /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type * of vertex program active. @@ -186,7 +229,7 @@ GLboolean _vbo_CreateContext( struct gl_context *ctx ) } -void _vbo_InvalidateState( struct gl_context *ctx, GLuint new_state ) +void _vbo_InvalidateState( struct gl_context *ctx, GLbitfield new_state ) { vbo_exec_invalidate_state(ctx, new_state); } @@ -223,3 +266,10 @@ void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func) vbo->draw_prims = func; } + +void vbo_set_indirect_draw_func(struct gl_context *ctx, + vbo_indirect_draw_func func) +{ + struct vbo_context *vbo = vbo_context(ctx); + vbo->draw_indirect_prims = func; +} diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index 6293a8b9edc..11f9b17c7c4 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -76,6 +76,12 @@ struct vbo_context { * is responsible for initiating any fallback actions required: */ vbo_draw_func draw_prims; + + /* Optional callback for indirect draws. This allows multidraws to not be + * broken up, as well as for the actual count to be passed in as a separate + * indirect parameter. + */ + vbo_indirect_draw_func draw_indirect_prims; }; diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c index a301c6c9a22..4db4f4088b9 100644 --- a/src/mesa/vbo/vbo_exec.c +++ b/src/mesa/vbo/vbo_exec.c @@ -73,7 +73,7 @@ void vbo_exec_destroy( struct gl_context *ctx ) * invoked according to the state flags. That will have to wait for a * mesa rework: */ -void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state ) +void vbo_exec_invalidate_state( struct gl_context *ctx, GLbitfield new_state ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index a80b2c908d1..27bff4a2aa9 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -146,7 +146,7 @@ struct vbo_exec_context */ void vbo_exec_init( struct gl_context *ctx ); void vbo_exec_destroy( struct gl_context *ctx ); -void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state ); +void vbo_exec_invalidate_state( struct gl_context *ctx, GLbitfield new_state ); /* Internal functions: diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 502b2885892..02139ef881f 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -1546,27 +1546,14 @@ vbo_validated_drawarraysindirect(struct gl_context *ctx, { 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].is_indirect = 1; - 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 defeat 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, 0, - ctx->DrawIndirectBuffer); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, (GLsizeiptr)indirect, + 1 /* draw_count */, 16 /* stride */, + NULL, 0, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1580,36 +1567,18 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx, { 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(primcount, sizeof(*prim)); - if (prim == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect"); - return; - } vbo_bind_arrays(ctx); - 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; - prim[i].is_indirect = 1; - prim[i].draw_id = i; - } - check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, primcount, - NULL, GL_TRUE, 0, ~0, - NULL, 0, - ctx->DrawIndirectBuffer); - - free(prim); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, offset, + primcount, stride, + NULL, 0, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1623,7 +1592,6 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx, 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); @@ -1632,19 +1600,12 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx, ib.obj = ctx->Array.VAO->IndexBufferObj; 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; - prim[0].is_indirect = 1; - check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, 1, - &ib, GL_TRUE, 0, ~0, - NULL, 0, - ctx->DrawIndirectBuffer); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, (GLsizeiptr)indirect, + 1 /* draw_count */, 20 /* stride */, + NULL, 0, + &ib); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1659,17 +1620,10 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx, 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(primcount, sizeof(*prim)); - if (prim == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect"); - return; - } vbo_bind_arrays(ctx); @@ -1680,23 +1634,12 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx, ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = NULL; - 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; - prim[i].is_indirect = 1; - prim[i].draw_id = i; - } - check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, primcount, - &ib, GL_TRUE, 0, ~0, - NULL, 0, - ctx->DrawIndirectBuffer); - - free(prim); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, offset, + primcount, stride, + NULL, 0, + &ib); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1789,6 +1732,128 @@ vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, primcount, stride); } +static void +vbo_validated_multidrawarraysindirectcount(struct gl_context *ctx, + GLenum mode, + GLintptr indirect, + GLintptr drawcount, + GLsizei maxdrawcount, + GLsizei stride) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + GLsizeiptr offset = indirect; + + if (maxdrawcount == 0) + return; + + vbo_bind_arrays(ctx); + + check_buffers_are_unmapped(exec->array.inputs); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, offset, + maxdrawcount, stride, + ctx->ParameterBuffer, drawcount, + NULL); + + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) + _mesa_flush(ctx); +} + +static void +vbo_validated_multidrawelementsindirectcount(struct gl_context *ctx, + GLenum mode, GLenum type, + GLintptr indirect, + GLintptr drawcount, + GLsizei maxdrawcount, + GLsizei stride) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct _mesa_index_buffer ib; + GLsizeiptr offset = (GLsizeiptr)indirect; + + if (maxdrawcount == 0) + return; + + vbo_bind_arrays(ctx); + + /* NOTE: IndexBufferObj is guaranteed to be a VBO. */ + + ib.count = 0; /* unknown */ + ib.type = type; + ib.obj = ctx->Array.VAO->IndexBufferObj; + ib.ptr = NULL; + + check_buffers_are_unmapped(exec->array.inputs); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, offset, + maxdrawcount, stride, + ctx->ParameterBuffer, drawcount, + &ib); + + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) + _mesa_flush(ctx); +} + +static void GLAPIENTRY +vbo_exec_MultiDrawArraysIndirectCount(GLenum mode, + GLintptr indirect, + GLintptr drawcount, + GLsizei maxdrawcount, GLsizei stride) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_DRAW) + _mesa_debug(ctx, "glMultiDrawArraysIndirectCountARB" + "(%s, %lx, %lx, %i, %i)\n", + _mesa_enum_to_string(mode), indirect, + drawcount, maxdrawcount, 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_MultiDrawArraysIndirectCount(ctx, mode, + indirect, drawcount, + maxdrawcount, stride)) + return; + + vbo_validated_multidrawarraysindirectcount(ctx, mode, + indirect, drawcount, + maxdrawcount, stride); +} + +static void GLAPIENTRY +vbo_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type, + GLintptr indirect, + GLintptr drawcount, + GLsizei maxdrawcount, GLsizei stride) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_DRAW) + _mesa_debug(ctx, "glMultiDrawElementsIndirectCountARB" + "(%s, %s, %lx, %lx, %i, %i)\n", + _mesa_enum_to_string(mode), + _mesa_enum_to_string(type), indirect, + drawcount, maxdrawcount, 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_MultiDrawElementsIndirectCount(ctx, mode, type, + indirect, drawcount, + maxdrawcount, stride)) + return; + + vbo_validated_multidrawelementsindirectcount(ctx, mode, type, + indirect, drawcount, + maxdrawcount, stride); +} + + /** * Initialize the dispatch table with the VBO functions for drawing. */ @@ -1836,6 +1901,8 @@ vbo_initialize_exec_dispatch(const struct gl_context *ctx, if (ctx->API == API_OPENGL_CORE) { SET_MultiDrawArraysIndirect(exec, vbo_exec_MultiDrawArraysIndirect); SET_MultiDrawElementsIndirect(exec, vbo_exec_MultiDrawElementsIndirect); + SET_MultiDrawArraysIndirectCountARB(exec, vbo_exec_MultiDrawArraysIndirectCount); + SET_MultiDrawElementsIndirectCountARB(exec, vbo_exec_MultiDrawElementsIndirectCount); } if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { |