From 2860f20859454b38ce44e4e3377c036e67c20ae7 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Thu, 31 Dec 2015 14:11:07 -0500 Subject: [PATCH] st/mesa: add support for new mesa indirect draw interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This shifts all indirect draws to go through the new function. If the driver doesn't have support for multi draws, we break those up and perform N draws. Otherwise, we pass everything through for just a single draw call. Signed-off-by: Ilia Mirkin Reviewed-by: Marek Olšák --- src/mesa/state_tracker/st_context.c | 2 + src/mesa/state_tracker/st_context.h | 1 + src/mesa/state_tracker/st_draw.c | 90 +++++++++++++++++++++++++++++++++---- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index e12c166..87193a9 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -267,6 +267,8 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED); st->has_half_float_packing = screen->get_param(screen, PIPE_CAP_TGSI_PACK_HALF_FLOAT); + st->has_multi_draw_indirect = + screen->get_param(screen, PIPE_CAP_MULTI_DRAW_INDIRECT); /* GL limits and extensions */ st_init_limits(st->pipe->screen, &ctx->Const, &ctx->Extensions); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 91b0f97..9db5f11 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -102,6 +102,7 @@ struct st_context boolean force_persample_in_shader; boolean has_shareable_shaders; boolean has_half_float_packing; + boolean has_multi_draw_indirect; /** * If a shader can be created when we get its source. diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index d7a9716..03788f3 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -252,13 +252,7 @@ st_draw_vbo(struct gl_context *ctx, } } - if (indirect) { - info.indirect = st_buffer_object(indirect)->buffer; - - /* Primitive restart is not handled by the VBO module in this case. */ - info.primitive_restart = ctx->Array._PrimitiveRestart; - info.restart_index = ctx->Array.RestartIndex; - } + assert(!indirect); /* do actual drawing */ for (i = 0; i < nr_prims; i++) { @@ -274,7 +268,6 @@ st_draw_vbo(struct gl_context *ctx, info.min_index = info.start; info.max_index = info.start + info.count - 1; } - info.indirect_offset = prims[i].indirect_offset; if (ST_DEBUG & DEBUG_DRAW) { debug_printf("st/draw: mode %s start %u count %u indexed %d\n", @@ -284,7 +277,7 @@ st_draw_vbo(struct gl_context *ctx, info.indexed); } - if (info.count_from_stream_output || info.indirect) { + if (info.count_from_stream_output) { cso_draw_vbo(st->cso_context, &info); } else if (info.primitive_restart) { @@ -301,6 +294,84 @@ st_draw_vbo(struct gl_context *ctx, } } +static void +st_indirect_draw_vbo(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 st_context *st = st_context(ctx); + struct pipe_index_buffer ibuffer = {0}; + struct pipe_draw_info info; + + /* Mesa core state should have been validated already */ + assert(ctx->NewState == 0x0); + assert(stride); + + /* Validate state. */ + if (st->dirty.st || ctx->NewDriverState) { + st_validate_state(st); + } + + if (st->vertex_array_out_of_memory) { + return; + } + + util_draw_init_info(&info); + + if (ib) { + if (!setup_index_buffer(st, ib, &ibuffer)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDrawElementsIndirect%s", + (draw_count > 1) ? "Multi" : "", + indirect_params ? "CountARB" : ""); + return; + } + + info.indexed = TRUE; + } + + info.mode = translate_prim(ctx, mode); + info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices; + info.indirect = st_buffer_object(indirect_data)->buffer; + info.indirect_offset = indirect_offset; + + /* Primitive restart is not handled by the VBO module in this case. */ + info.primitive_restart = ctx->Array._PrimitiveRestart; + info.restart_index = ctx->Array.RestartIndex; + + if (ST_DEBUG & DEBUG_DRAW) { + debug_printf("st/draw indirect: mode %s drawcount %d indexed %d\n", + u_prim_name(info.mode), + draw_count, + info.indexed); + } + + if (!st->has_multi_draw_indirect) { + int i; + + assert(!indirect_params); + info.indirect_count = 1; + for (i = 0; i < draw_count; i++) { + info.drawid = i; + cso_draw_vbo(st->cso_context, &info); + info.indirect_offset += stride; + } + } else { + info.indirect_count = draw_count; + info.indirect_stride = stride; + if (indirect_params) { + info.indirect_params = st_buffer_object(indirect_params)->buffer; + info.indirect_params_offset = indirect_params_offset; + } + cso_draw_vbo(st->cso_context, &info); + } +} + void st_init_draw(struct st_context *st) @@ -308,6 +379,7 @@ st_init_draw(struct st_context *st) struct gl_context *ctx = st->ctx; vbo_set_draw_func(ctx, st_draw_vbo); + vbo_set_indirect_draw_func(ctx, st_indirect_draw_vbo); st->draw = draw_create(st->pipe); /* for selection/feedback */ -- 2.7.4