ac/nir/ngg: fix gs culling vertex liveness check for odd vertices
authorQiang Yu <yuq825@gmail.com>
Wed, 5 Apr 2023 01:27:50 +0000 (09:27 +0800)
committerMarge Bot <emma+marge@anholt.net>
Fri, 7 Apr 2023 03:42:25 +0000 (03:42 +0000)
If vertex does not complete a primitive, it should not set the odd
flag which miss lead liveness check when culling is enabled.

For example, if odd flag is set regardless of complete flag, when
culling is enabled, 3 vertices of a triangle's init prim flag:
  [0x00 0x04 0x01]

then after culling, this triangle has been culled, their prim flag:
  [0x00 0x04 0x00]

the second vertex is miss treat as live because its odd flag (code
check prim_flag!=0 for liveness).

Fixes: 1bdeb961bd8 ("ac/nir/ngg: add gs culling")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8725
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22304>

src/amd/common/ac_nir_lower_ngg.c

index c2ed883..af80322 100644 (file)
@@ -2758,6 +2758,7 @@ lower_ngg_gs_emit_vertex_with_counter(nir_builder *b, nir_intrinsic_instr *intri
    /* Calculate and store per-vertex primitive flags based on vertex counts:
     * - bit 0: whether this vertex finishes a primitive (a real primitive, not the strip)
     * - bit 1: whether the primitive index is odd (if we are emitting triangle strips, otherwise always 0)
+    *          only set when the vertex also finishes the primitive
     * - bit 2: whether vertex is live (if culling is enabled: set after culling, otherwise always 1)
     */
 
@@ -2771,8 +2772,9 @@ lower_ngg_gs_emit_vertex_with_counter(nir_builder *b, nir_intrinsic_instr *intri
 
    nir_ssa_def *prim_flag = nir_ior(b, vertex_live_flag, complete_flag);
    if (s->num_vertices_per_primitive == 3) {
-      nir_ssa_def *odd = nir_iand_imm(b, current_vtx_per_prim, 1);
-      prim_flag = nir_iadd_nuw(b, prim_flag, nir_ishl(b, odd, nir_imm_int(b, 1)));
+      nir_ssa_def *odd = nir_iand(b, current_vtx_per_prim, complete_flag);
+      nir_ssa_def *odd_flag = nir_ishl(b, odd, nir_imm_int(b, 1));
+      prim_flag = nir_ior(b, prim_flag, odd_flag);
    }
 
    nir_store_shared(b, nir_u2u8(b, prim_flag), gs_emit_vtx_addr, .base = s->lds_offs_primflags + stream, .align_mul = 4u);