From: Ilia Mirkin Date: Thu, 31 Dec 2015 19:11:07 +0000 (-0500) Subject: st/mesa: add support for new mesa indirect draw interface X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2860f20859454b38ce44e4e3377c036e67c20ae7;p=mesa.git st/mesa: add support for new mesa indirect draw interface 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 --- diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index e12c1663d3f..87193a9d478 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 91b0f975f3f..9db5f11beb5 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 d7a97169bc2..03788f33468 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 */