}
}
-/* Set the primitive type seen by the rasterizer. GS and tessellation affect this. */
+/* Update these two GS_STATE fields. They depend on whatever the last shader before PS is
+ * and the rasterizer state.
+ *
+ * It's expected that hw_vs and ngg are inline constants in draw_vbo after optimizations.
+ */
+static inline void
+si_update_ngg_prim_state_sgpr(struct si_context *sctx, struct si_shader *hw_vs, bool ngg)
+{
+ if (!ngg || !hw_vs)
+ return;
+
+ if (hw_vs->uses_vs_state_provoking_vertex) {
+ unsigned vtx_index = sctx->queued.named.rasterizer->flatshade_first ? 0 : sctx->gs_out_prim;
+
+ SET_FIELD(sctx->current_gs_state, GS_STATE_PROVOKING_VTX_INDEX, vtx_index);
+ }
+
+ if (hw_vs->uses_gs_state_outprim) {
+ SET_FIELD(sctx->current_gs_state, GS_STATE_OUTPRIM, sctx->gs_out_prim);
+ }
+}
+
+/* Set the primitive type seen by the rasterizer. GS and tessellation affect this.
+ * It's expected that hw_vs and ngg are inline constants in draw_vbo after optimizations.
+ */
static inline void
-si_set_rasterized_prim(struct si_context *sctx, enum pipe_prim_type rast_prim)
+si_set_rasterized_prim(struct si_context *sctx, enum pipe_prim_type rast_prim,
+ struct si_shader *hw_vs, bool ngg)
{
if (rast_prim != sctx->current_rast_prim) {
bool is_rect = rast_prim == SI_PRIM_RECTANGLE_LIST;
is_lines ? V_028A6C_LINESTRIP :
is_rect ? V_028A6C_RECTLIST : V_028A6C_POINTLIST;
sctx->do_update_shaders = true;
+ si_update_ngg_prim_state_sgpr(sctx, hw_vs, ngg);
}
}
old_rs->poly_stipple_enable != rs->poly_stipple_enable ||
old_rs->flatshade != rs->flatshade)
si_update_vrs_flat_shading(sctx);
+
+ if (old_rs->flatshade_first != rs->flatshade_first)
+ si_update_ngg_prim_state_sgpr(sctx, si_get_vs(sctx)->current, sctx->ngg);
}
static void si_delete_rs_state(struct pipe_context *ctx, void *state)
struct pipe_context *ctx = (struct pipe_context *)sctx;
struct si_shader *old_vs = si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current;
unsigned old_pa_cl_vs_out_cntl = old_vs ? old_vs->pa_cl_vs_out_cntl : 0;
+ bool old_uses_vs_state_provoking_vertex = old_vs ? old_vs->uses_vs_state_provoking_vertex : false;
+ bool old_uses_gs_state_outprim = old_vs ? old_vs->uses_gs_state_outprim : false;
struct si_shader *old_ps = sctx->shader.ps.current;
unsigned old_spi_shader_col_format =
old_ps ? old_ps->key.ps.part.epilog.spi_shader_col_format : 0;
*pm4 = si_build_vgt_shader_config(sctx->screen, key);
si_pm4_bind_state(sctx, vgt_shader_config, *pm4);
- if (old_pa_cl_vs_out_cntl !=
- si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current->pa_cl_vs_out_cntl)
+ struct si_shader *hw_vs = si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current;
+
+ if (old_pa_cl_vs_out_cntl != hw_vs->pa_cl_vs_out_cntl)
si_mark_atom_dirty(sctx, &sctx->atoms.s.clip_regs);
+ /* If we start to use any of these, we need to update the SGPR. */
+ if ((hw_vs->uses_vs_state_provoking_vertex && !old_uses_vs_state_provoking_vertex) ||
+ (hw_vs->uses_gs_state_outprim && !old_uses_gs_state_outprim))
+ si_update_ngg_prim_state_sgpr(sctx, hw_vs, NGG);
+
r = si_shader_select(ctx, &sctx->shader.ps);
if (r)
return false;
radeon_end_update_context_roll(sctx);
else
radeon_end();
-
- if (NGG) {
- struct si_shader *hw_vs = si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current;
-
- if (hw_vs->uses_vs_state_provoking_vertex) {
- unsigned vtx_index = rs->flatshade_first ? 0 : gs_out_prim;
-
- SET_FIELD(sctx->current_gs_state, GS_STATE_PROVOKING_VTX_INDEX, vtx_index);
- }
-
- if (hw_vs->uses_gs_state_outprim) {
- SET_FIELD(sctx->current_gs_state, GS_STATE_OUTPRIM, gs_out_prim);
- }
- }
}
template <amd_gfx_level GFX_VERSION, si_has_tess HAS_TESS, si_has_gs HAS_GS, si_has_ngg NGG,
rast_prim = prim;
}
- si_set_rasterized_prim(sctx, rast_prim);
+ si_set_rasterized_prim(sctx, rast_prim, si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current,
+ NGG);
}
if (IS_DRAW_VERTEX_STATE) {
static void si_update_rasterized_prim(struct si_context *sctx)
{
+ struct si_shader *hw_vs = si_get_vs(sctx)->current;
+
if (sctx->shader.gs.cso) {
/* Only possibilities: POINTS, LINE_STRIP, TRIANGLES */
- si_set_rasterized_prim(sctx, sctx->shader.gs.cso->rast_prim);
+ si_set_rasterized_prim(sctx, sctx->shader.gs.cso->rast_prim, hw_vs, sctx->ngg);
} else if (sctx->shader.tes.cso) {
/* Only possibilities: POINTS, LINE_STRIP, TRIANGLES */
- si_set_rasterized_prim(sctx, sctx->shader.tes.cso->rast_prim);
+ si_set_rasterized_prim(sctx, sctx->shader.tes.cso->rast_prim, hw_vs, sctx->ngg);
} else {
/* The rasterized prim is determined by draw calls. */
}
+
+ /* This must be done unconditionally because it also depends on si_shader fields. */
+ si_update_ngg_prim_state_sgpr(sctx, hw_vs, sctx->ngg);
}
static void si_update_common_shader_state(struct si_context *sctx, struct si_shader_selector *sel,