From 33878641305345b9bb76ad5ebf2335ec9c17adfa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Mar 2018 15:07:19 -0700 Subject: [PATCH] broadcom/vc5: Fix transform feedback in the presence of point size. I had this note to myself, and it turns out that a lot of CTS tests use XFB with points to get data out without using a fragment shader. Keep track of two sets of precomputed TF specs (point size in VPM prologue or not), and switch between them when we enable/disable point size. --- src/gallium/drivers/vc5/vc5_context.h | 1 + src/gallium/drivers/vc5/vc5_emit.c | 13 ++++++++++--- src/gallium/drivers/vc5/vc5_program.c | 13 ++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/vc5/vc5_context.h b/src/gallium/drivers/vc5/vc5_context.h index 976fba90f81..7272e045c4f 100644 --- a/src/gallium/drivers/vc5/vc5_context.h +++ b/src/gallium/drivers/vc5/vc5_context.h @@ -131,6 +131,7 @@ struct vc5_uncompiled_shader { uint32_t num_tf_outputs; struct v3d_varying_slot *tf_outputs; uint16_t tf_specs[16]; + uint16_t tf_specs_psiz[16]; uint32_t num_tf_specs; /** diff --git a/src/gallium/drivers/vc5/vc5_emit.c b/src/gallium/drivers/vc5/vc5_emit.c index 1db97081df3..061d6e7c9d9 100644 --- a/src/gallium/drivers/vc5/vc5_emit.c +++ b/src/gallium/drivers/vc5/vc5_emit.c @@ -572,10 +572,18 @@ v3dX(emit_state)(struct pipe_context *pctx) /* Set up the transform feedback data specs (which VPM entries to * output to which buffers). */ - if (vc5->dirty & VC5_DIRTY_STREAMOUT) { + if (vc5->dirty & (VC5_DIRTY_STREAMOUT | + VC5_DIRTY_RASTERIZER | + VC5_DIRTY_PRIM_MODE)) { struct vc5_streamout_stateobj *so = &vc5->streamout; if (so->num_targets) { + bool psiz_per_vertex = (vc5->prim_mode == PIPE_PRIM_POINTS && + vc5->rasterizer->base.point_size_per_vertex); + uint16_t *tf_specs = (psiz_per_vertex ? + vc5->prog.bind_vs->tf_specs_psiz : + vc5->prog.bind_vs->tf_specs); + #if V3D_VERSION >= 40 cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) { tfe.number_of_16_bit_output_data_specs_following = @@ -593,8 +601,7 @@ v3dX(emit_state)(struct pipe_context *pctx) }; #endif /* V3D_VERSION < 40 */ for (int i = 0; i < vc5->prog.bind_vs->num_tf_specs; i++) { - cl_emit_prepacked(&job->bcl, - &vc5->prog.bind_vs->tf_specs[i]); + cl_emit_prepacked(&job->bcl, &tf_specs[i]); } } } diff --git a/src/gallium/drivers/vc5/vc5_program.c b/src/gallium/drivers/vc5/vc5_program.c index a7a089510b2..7bad80a1684 100644 --- a/src/gallium/drivers/vc5/vc5_program.c +++ b/src/gallium/drivers/vc5/vc5_program.c @@ -127,8 +127,19 @@ vc5_set_transform_feedback_outputs(struct vc5_uncompiled_shader *so, assert(so->num_tf_specs != ARRAY_SIZE(so->tf_specs)); V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC_pack(NULL, - (void *)&so->tf_specs[so->num_tf_specs++], + (void *)&so->tf_specs[so->num_tf_specs], &unpacked); + + /* If point size is being written by the shader, then + * all the VPM start offsets are shifted up by one. + * We won't know that until the variant is compiled, + * though. + */ + unpacked.first_shaded_vertex_value_to_output++; + V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC_pack(NULL, + (void *)&so->tf_specs_psiz[so->num_tf_specs], + &unpacked); + so->num_tf_specs++; vpm_start_offset += write_size; vpm_size -= write_size; }