[Mesa-dev] [PATCH 2/2] i965: Implement ARB_indirect_parameters
Bas Nieuwenhuizen
bas at basnieuwenhuizen.nl
Wed Aug 30 07:17:47 UTC 2017
So as a random drive-by review, I think the risk in this implementation
is that apps just set maxdrawcount to some high value . If I'm reading
the spec correctly there is no real bound on the value except for the
max-representable value for the integer. Also AFAIK the AMD and NVidia
implementation don't really get slower if you specify maxdrawcount very
large, so I wouldn't be surprised if a good number of apps would set the
maxdrawcount really high, like MAX_INT or something. I suspect you
wouldn't want to emit that .
On Tue, Aug 29, 2017, at 18:24, Plamena Manolova wrote:
> We can implement ARB_indirect_parameters for i965 by
> taking advantage of the conditional rendering mechanism.
> This works by issuing maxdrawcount draw calls and using
> conditional rendering to predicate each of them with
> "drawcount > gl_DrawID"
>
> Signed-off-by: Plamena Manolova <plamena.manolova at intel.com>
> ---
> src/mesa/drivers/dri/i965/brw_context.h | 3 +
> src/mesa/drivers/dri/i965/brw_draw.c | 97
> ++++++++++++++++++++++++++++
> src/mesa/drivers/dri/i965/brw_draw.h | 11 ++++
> src/mesa/drivers/dri/i965/intel_extensions.c | 2 +
> 4 files changed, 113 insertions(+)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_context.h
> b/src/mesa/drivers/dri/i965/brw_context.h
> index 2274fe5..4639d5b 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.h
> +++ b/src/mesa/drivers/dri/i965/brw_context.h
> @@ -831,6 +831,9 @@ struct brw_context
> int gl_drawid;
> struct brw_bo *draw_id_bo;
> uint32_t draw_id_offset;
> +
> + struct brw_bo *draw_params_count_bo;
> + uint32_t draw_params_count_offset;
> } draw;
>
> struct {
> diff --git a/src/mesa/drivers/dri/i965/brw_draw.c
> b/src/mesa/drivers/dri/i965/brw_draw.c
> index 7597bae..473958c 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw.c
> +++ b/src/mesa/drivers/dri/i965/brw_draw.c
> @@ -820,6 +820,11 @@ brw_end_draw_prims(struct gl_context *ctx,
> brw_program_cache_check_size(brw);
> brw_postdraw_reconcile_align_wa_slices(brw);
> brw_postdraw_set_buffers_need_resolve(brw);
> +
> + if (brw->draw.draw_params_count_bo) {
> + brw_bo_unreference(brw->draw.draw_params_count_bo);
> + brw->draw.draw_params_count_bo = NULL;
> + }
> }
>
> void
> @@ -837,6 +842,8 @@ brw_draw_prims(struct gl_context *ctx,
> struct brw_context *brw = brw_context(ctx);
> const struct gl_vertex_array **arrays = ctx->Array._DrawArrays;
> int i;
> + int predicate_state = brw->predicate.state;
> + int combine_op = MI_PREDICATE_COMBINEOP_SET;
> struct brw_transform_feedback_object *xfb_obj =
> (struct brw_transform_feedback_object *) gl_xfb_obj;
>
> @@ -890,12 +897,101 @@ brw_draw_prims(struct gl_context *ctx,
> * to it.
> */
>
> + if (brw->draw.draw_params_count_bo &&
> + predicate_state == BRW_PREDICATE_STATE_USE_BIT) {
> + /* We do this to empty the MI_PREDICATE_DATA register */
> + BEGIN_BATCH(4);
> + OUT_BATCH(MI_PREDICATE_DATA);
> + OUT_BATCH(0u);
> + OUT_BATCH(MI_PREDICATE_DATA + 4);
> + OUT_BATCH(0u);
> + ADVANCE_BATCH();
> +
> + combine_op = MI_PREDICATE_COMBINEOP_AND;
> + }
> +
> for (i = 0; i < nr_prims; i++) {
> + if (brw->draw.draw_params_count_bo) {
> + struct brw_bo *draw_id_bo = brw_bo_alloc(brw->bufmgr,
> "draw_id", 4, 4);
> +
> + brw_bo_reference(draw_id_bo);
> + brw_bo_subdata(draw_id_bo, 0, 4, &prims[i].draw_id);
> +
> + brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE);
> +
> + brw_load_register_mem(brw, MI_PREDICATE_SRC0,
> + brw->draw.draw_params_count_bo,
> + brw->draw.draw_params_count_offset);
> + brw_load_register_mem(brw, MI_PREDICATE_SRC1, draw_id_bo, 0);
> +
> + BEGIN_BATCH(1);
> + OUT_BATCH(GEN7_MI_PREDICATE |
> + MI_PREDICATE_LOADOP_LOADINV | combine_op |
> + MI_PREDICATE_COMPAREOP_DELTAS_EQUAL);
> + ADVANCE_BATCH();
> +
> + brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT;
> +
> + brw_bo_unreference(draw_id_bo);
> + }
> +
> brw_try_draw_prim(ctx, arrays, &prims[i], ib, index_bounds_valid,
> min_index, max_index, xfb_obj, stream,
> indirect);
> }
> +
> brw_end_draw_prims(ctx, arrays, prims, nr_prims, ib,
> index_bounds_valid,
> min_index, max_index, xfb_obj, stream, indirect);
> +
> + brw->predicate.state = predicate_state;
> +}
> +
> +void
> +brw_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 brw_context *brw = brw_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;
> + }
> +
> + if (indirect_params) {
> + brw->draw.draw_params_count_bo =
> + intel_buffer_object(indirect_params)->buffer;
> + brw_bo_reference(brw->draw.draw_params_count_bo);
> + brw->draw.draw_params_count_offset = indirect_params_offset;
> + }
> +
> + brw_draw_prims(ctx, prim, draw_count,
> + ib, false, 0, ~0,
> + NULL, 0,
> + indirect_data);
> +
> + free(prim);
> }
>
> void
> @@ -907,6 +1003,7 @@ brw_draw_init(struct brw_context *brw)
> /* Register our drawing function:
> */
> vbo->draw_prims = brw_draw_prims;
> + vbo->draw_indirect_prims = brw_draw_indirect_prims;
>
> for (int i = 0; i < VERT_ATTRIB_MAX; i++)
> brw->vb.inputs[i].buffer = -1;
> diff --git a/src/mesa/drivers/dri/i965/brw_draw.h
> b/src/mesa/drivers/dri/i965/brw_draw.h
> index 3b99915..07aab1c 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw.h
> +++ b/src/mesa/drivers/dri/i965/brw_draw.h
> @@ -58,6 +58,17 @@ void brw_draw_prims(struct gl_context *ctx,
> void brw_draw_init( struct brw_context *brw );
> void brw_draw_destroy( struct brw_context *brw );
>
> +void
> +brw_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);
> +
> void brw_prepare_shader_draw_parameters(struct brw_context *);
>
> /* brw_primitive_restart.c */
> diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c
> b/src/mesa/drivers/dri/i965/intel_extensions.c
> index deacd0d..c116d43 100644
> --- a/src/mesa/drivers/dri/i965/intel_extensions.c
> +++ b/src/mesa/drivers/dri/i965/intel_extensions.c
> @@ -230,6 +230,8 @@ intelInitExtensions(struct gl_context *ctx)
>
> if (can_do_pipelined_register_writes(brw->screen)) {
> ctx->Extensions.ARB_draw_indirect = true;
> + if (ctx->Extensions.ARB_conditional_render_inverted)
> + ctx->Extensions.ARB_indirect_parameters = true;
> ctx->Extensions.ARB_transform_feedback2 = true;
> ctx->Extensions.ARB_transform_feedback3 = true;
> ctx->Extensions.ARB_transform_feedback_instanced = true;
> --
> 2.9.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list