diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index d36753ce5d8..bc80313439e 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -3991,6 +3991,9 @@ setup_input(struct ir3_context *ctx, nir_intrinsic_instr *intr) unsigned idx = (n * 4) + i + frac; ctx->last_dst[i] = create_frag_input(ctx, coord, idx); } + + if (slot == VARYING_SLOT_PRIMITIVE_ID) + so->reads_primid = true; } else { struct ir3_instruction *input = NULL; diff --git a/src/freedreno/ir3/ir3_shader.h b/src/freedreno/ir3/ir3_shader.h index f356bc6a444..5c62daeb544 100644 --- a/src/freedreno/ir3/ir3_shader.h +++ b/src/freedreno/ir3/ir3_shader.h @@ -650,6 +650,7 @@ struct ir3_shader_variant { bool half : 1; bool flat : 1; } inputs[32 + 2]; /* +POSITION +FACE */ + bool reads_primid; /* sum of input components (scalar). For frag shaders, it only counts * the varying inputs: @@ -1120,7 +1121,7 @@ ir3_link_shaders(struct ir3_shader_linkage *l, k = ir3_find_output(vs, (gl_varying_slot)fs->inputs[j].slot); - if (k < 0 && fs->inputs[j].slot == VARYING_SLOT_PRIMITIVE_ID) { + if (fs->inputs[j].slot == VARYING_SLOT_PRIMITIVE_ID) { l->primid_loc = fs->inputs[j].inloc; } diff --git a/src/freedreno/vulkan/tu_pipeline.cc b/src/freedreno/vulkan/tu_pipeline.cc index 4de9034a72c..e536333d526 100644 --- a/src/freedreno/vulkan/tu_pipeline.cc +++ b/src/freedreno/vulkan/tu_pipeline.cc @@ -841,7 +841,7 @@ tu6_emit_vs_system_values(struct tu_cs *cs, const struct ir3_shader_variant *hs, const struct ir3_shader_variant *ds, const struct ir3_shader_variant *gs, - bool primid_passthru) + const struct ir3_shader_variant *fs) { const uint32_t vertexid_regid = ir3_find_sysval_regid(vs, SYSTEM_VALUE_VERTEX_ID); @@ -896,7 +896,7 @@ tu6_emit_vs_system_values(struct tu_cs *cs, tu_cs_emit(cs, 0x000000fc); /* VFD_CONTROL_4 */ tu_cs_emit(cs, A6XX_VFD_CONTROL_5_REGID_GSHEADER(gsheader_regid) | 0xfc00); /* VFD_CONTROL_5 */ - tu_cs_emit(cs, COND(primid_passthru, A6XX_VFD_CONTROL_6_PRIMID4PSEN)); /* VFD_CONTROL_6 */ + tu_cs_emit(cs, COND(fs && fs->reads_primid, A6XX_VFD_CONTROL_6_PRIMID4PSEN)); /* VFD_CONTROL_6 */ } static void @@ -1280,11 +1280,7 @@ tu6_emit_vpc(struct tu_cs *cs, if (last_shader->stream_output.num_outputs) ir3_link_stream_out(&linkage, last_shader); - /* We do this after linking shaders in order to know whether PrimID - * passthrough needs to be enabled. - */ - bool primid_passthru = linkage.primid_loc != 0xff; - tu6_emit_vs_system_values(cs, vs, hs, ds, gs, primid_passthru); + tu6_emit_vs_system_values(cs, vs, hs, ds, gs, fs); tu_cs_emit_pkt4(cs, REG_A6XX_VPC_VAR_DISABLE(0), 4); tu_cs_emit(cs, ~linkage.varmask[0]); @@ -1437,7 +1433,7 @@ tu6_emit_vpc(struct tu_cs *cs, tu_cs_emit(cs, CONDREG(layer_regid, A6XX_GRAS_GS_LAYER_CNTL_WRITES_LAYER) | CONDREG(view_regid, A6XX_GRAS_GS_LAYER_CNTL_WRITES_VIEW)); - tu_cs_emit_regs(cs, A6XX_PC_PS_CNTL(.primitiveiden = primid_passthru)); + tu_cs_emit_regs(cs, A6XX_PC_PS_CNTL(.primitiveiden = fs && fs->reads_primid)); tu_cs_emit_pkt4(cs, REG_A6XX_VPC_CNTL_0, 1); tu_cs_emit(cs, A6XX_VPC_CNTL_0_NUMNONPOSVAR(fs ? fs->total_in : 0) | diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.cc b/src/gallium/drivers/freedreno/a6xx/fd6_program.cc index 3c40eb2eff1..efb9a1b96df 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_program.cc +++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.cc @@ -622,7 +622,6 @@ setup_stateobj(struct fd_screen *screen, struct fd_ringbuffer *ring, */ ir3_link_shaders(&l, last_shader, do_streamout ? state->fs : fs, true); - bool primid_passthru = l.primid_loc != 0xff; clip0_loc = l.clip0_loc; clip1_loc = l.clip1_loc; @@ -1141,7 +1140,7 @@ setup_stateobj(struct fd_screen *screen, struct fd_ringbuffer *ring, if (fs->instrlen) fd6_emit_shader(ctx, ring, fs); - OUT_REG(ring, A6XX_PC_PS_CNTL(.primitiveiden = primid_passthru)); + OUT_REG(ring, A6XX_PC_PS_CNTL(.primitiveiden = fs->reads_primid)); uint32_t non_sysval_input_count = 0; for (uint32_t i = 0; i < vs->inputs_count; i++) @@ -1175,7 +1174,7 @@ setup_stateobj(struct fd_screen *screen, struct fd_ringbuffer *ring, OUT_RING(ring, 0x000000fc); /* VFD_CONTROL_4 */ OUT_RING(ring, A6XX_VFD_CONTROL_5_REGID_GSHEADER(gs_header_regid) | 0xfc00); /* VFD_CONTROL_5 */ - OUT_RING(ring, COND(primid_passthru, + OUT_RING(ring, COND(fs->reads_primid, A6XX_VFD_CONTROL_6_PRIMID4PSEN)); /* VFD_CONTROL_6 */ if (!binning_pass)