From 27e3e88f184642796f2e4482670725bbb9cd89c7 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 2 Jan 2024 18:15:25 -0400 Subject: [PATCH] asahi: rotate xfb'd tri strips spec req. GTF-GL46.gtf30.GL3Tests.transform_feedback.transform_feedback_geometry Signed-off-by: Alyssa Rosenzweig Part-of: --- src/asahi/lib/agx_nir_lower_gs.c | 37 +++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/asahi/lib/agx_nir_lower_gs.c b/src/asahi/lib/agx_nir_lower_gs.c index 6be6b354900..90fba752cd2 100644 --- a/src/asahi/lib/agx_nir_lower_gs.c +++ b/src/asahi/lib/agx_nir_lower_gs.c @@ -46,6 +46,9 @@ struct lower_gs_state { */ int count_index[MAX_VERTEX_STREAMS][GS_NUM_COUNTERS]; + /* Provoking vertex mode, required for transform feedback calculations */ + nir_def *flatshade_first; + bool rasterizer_discard; }; @@ -597,7 +600,7 @@ verts_in_output_prim(nir_shader *gs) static void write_xfb(nir_builder *b, struct lower_gs_state *state, unsigned stream, - nir_def *prim_id_in_invocation) + nir_def *index_in_strip, nir_def *prim_id_in_invocation) { /* If there is no XFB info, there is no XFB */ struct nir_xfb_info *xfb = b->shader->xfb_info; @@ -649,10 +652,23 @@ write_xfb(nir_builder *b, struct lower_gs_state *state, unsigned stream, */ value = nir_pad_vector_imm_int(b, value, 0, 4); + nir_def *rotated_vert = nir_imm_int(b, vert); + if (verts == 3) { + /* Map vertices for output so we get consistent winding order. For + * the primitive index, we use the index_in_strip. This is actually + * the vertex index in the strip, hence + * offset by 2 relative to the true primitive index (#2 for the + * first triangle in the strip, #3 for the second). That's ok + * because only the parity matters. + */ + rotated_vert = libagx_map_vertex_in_tri_strip( + b, index_in_strip, rotated_vert, state->flatshade_first); + } + nir_def *addr = libagx_xfb_vertex_address( - b, nir_load_geometry_param_buffer_agx(b), base_index, - nir_imm_int(b, vert), nir_imm_int(b, buffer), - nir_imm_int(b, stride), nir_imm_int(b, output.offset)); + b, nir_load_geometry_param_buffer_agx(b), base_index, rotated_vert, + nir_imm_int(b, buffer), nir_imm_int(b, stride), + nir_imm_int(b, output.offset)); nir_store_global(b, addr, 4, nir_channels(b, value, output.component_mask), @@ -726,7 +742,8 @@ lower_emit_vertex(nir_builder *b, nir_intrinsic_instr *intr, nir_push_if(b, nir_uge_imm(b, index_in_strip, first_prim)); { - write_xfb(b, state, nir_intrinsic_stream_id(intr), intr->src[3].ssa); + write_xfb(b, state, nir_intrinsic_stream_id(intr), index_in_strip, + intr->src[3].ssa); } nir_pop_if(b, NULL); @@ -1151,6 +1168,16 @@ agx_nir_lower_gs(nir_shader *gs, nir_shader *vs, const nir_shader *libagx, NIR_PASS_V(gs, nir_shader_instructions_pass, lower_output_to_var, nir_metadata_block_index | nir_metadata_dominance, &state); + /* Set flatshade_first. For now this is always a constant, but in the future + * we will want this to be dynamic. + */ + { + nir_builder b = + nir_builder_at(nir_before_impl(nir_shader_get_entrypoint(gs))); + + gs_state.flatshade_first = nir_imm_bool(&b, ia->flatshade_first); + } + NIR_PASS_V(gs, nir_shader_intrinsics_pass, lower_gs_instr, nir_metadata_none, &gs_state);