radeonsi: pass cull face state via user SGPRs for shader culling

The culling code always computes the determinant for culling zero-area
triangles, so passing the state via user SGPRs doesn't really add much
shader code to justify having shader variants for front/back face
culling that uses the same determinant.

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32288>
This commit is contained in:
Marek Olšák
2024-11-21 12:49:11 -05:00
committed by Marge Bot
parent ca9bf43d0b
commit 511a637a5c
7 changed files with 35 additions and 37 deletions
@@ -420,10 +420,10 @@ static bool lower_intrinsic(nir_builder *b, nir_instr *instr, struct lower_abi_s
replacement = nir_imm_bool(b, si_shader_culling_enabled(shader));
break;
case nir_intrinsic_load_cull_back_face_enabled_amd:
replacement = nir_imm_bool(b, key->ge.opt.ngg_culling & SI_NGG_CULL_BACK_FACE);
replacement = nir_i2b(b, GET_FIELD_NIR(GS_STATE_CULL_FACE_BACK));
break;
case nir_intrinsic_load_cull_front_face_enabled_amd:
replacement = nir_imm_bool(b, key->ge.opt.ngg_culling & SI_NGG_CULL_FRONT_FACE);
replacement = nir_i2b(b, GET_FIELD_NIR(GS_STATE_CULL_FACE_FRONT));
break;
case nir_intrinsic_load_cull_small_triangle_precision_amd:
replacement = get_small_prim_precision(b, s, false);
+14
View File
@@ -2171,6 +2171,20 @@ si_update_ngg_sgpr_state_out_prim(struct si_context *sctx, struct si_shader *hw_
SET_FIELD(sctx->current_gs_state, GS_STATE_OUTPRIM, sctx->gs_out_prim);
}
static inline void
si_update_ngg_cull_face_state(struct si_context *sctx)
{
struct si_state_rasterizer *rs = sctx->queued.named.rasterizer;
if (sctx->viewport0_y_inverted) {
SET_FIELD(sctx->current_gs_state, GS_STATE_CULL_FACE_FRONT, rs->ngg_cull_back);
SET_FIELD(sctx->current_gs_state, GS_STATE_CULL_FACE_BACK, rs->ngg_cull_front);
} else {
SET_FIELD(sctx->current_gs_state, GS_STATE_CULL_FACE_FRONT, rs->ngg_cull_front);
SET_FIELD(sctx->current_gs_state, GS_STATE_CULL_FACE_BACK, rs->ngg_cull_back);
}
}
/* 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.
*/
+9 -7
View File
@@ -242,8 +242,12 @@ enum
* can be 55 at most. The ESGS vertex stride in dwords is: NUM_ES_OUTPUTS * 4 + 1
* Only used by GFX9+ to compute LDS addresses of GS inputs.
*/
#define GS_STATE_NUM_ES_OUTPUTS__SHIFT 13
#define GS_STATE_NUM_ES_OUTPUTS__SHIFT 14
#define GS_STATE_NUM_ES_OUTPUTS__MASK 0x3f
#define GS_STATE_CULL_FACE_FRONT__SHIFT 20
#define GS_STATE_CULL_FACE_FRONT__MASK 0x1
#define GS_STATE_CULL_FACE_BACK__SHIFT 21
#define GS_STATE_CULL_FACE_BACK__MASK 0x1
/* Small prim filter precision = num_samples / quant_mode where num_samples is in {1, 2, 4, 8} and
* quant_mode is in {256, 1024, 4096}, which is equal to 1/2^n where n is between 5 and 12.
*
@@ -333,11 +337,9 @@ enum
*/
#define SI_NGG_CULL_VS_TRIANGLES (1 << 0) /* this implies W, view.xy, and small prim culling */
#define SI_NGG_CULL_VS_LINES (1 << 1) /* this implies W and view.xy culling */
#define SI_NGG_CULL_BACK_FACE (1 << 2) /* back faces */
#define SI_NGG_CULL_FRONT_FACE (1 << 3) /* front faces */
#define SI_NGG_CULL_SMALL_LINES_DIAMOND_EXIT (1 << 4) /* cull small lines according to the diamond exit rule */
#define SI_NGG_CULL_CLIP_PLANE_ENABLE(enable) (((enable) & 0xff) << 5)
#define SI_NGG_CULL_GET_CLIP_PLANE_ENABLE(x) (((x) >> 5) & 0xff)
#define SI_NGG_CULL_SMALL_LINES_DIAMOND_EXIT (1 << 2) /* cull small lines according to the diamond exit rule */
#define SI_NGG_CULL_CLIP_PLANE_ENABLE(enable) (((enable) & 0xff) << 3)
#define SI_NGG_CULL_GET_CLIP_PLANE_ENABLE(x) (((x) >> 3) & 0xff)
struct si_shader_profile {
uint32_t blake3[BLAKE3_OUT_LEN32];
@@ -768,7 +770,7 @@ struct si_shader_key_ge {
unsigned remove_streamout : 1;
/* For NGG VS and TES. */
unsigned ngg_culling : 13; /* SI_NGG_CULL_* */
unsigned ngg_culling : 11; /* SI_NGG_CULL_* */
/* For shaders where monolithic variants have better code.
+6 -25
View File
@@ -1016,35 +1016,15 @@ static void *si_create_rs_state(struct pipe_context *ctx, const struct pipe_rast
S_028810_DX_LINEAR_ATTR_CLIP_ENA(1);
rs->ngg_cull_flags_tris = SI_NGG_CULL_CLIP_PLANE_ENABLE(state->clip_plane_enable);
rs->ngg_cull_flags_tris_y_inverted = rs->ngg_cull_flags_tris;
rs->ngg_cull_flags_lines = (!rs->perpendicular_end_caps ? SI_NGG_CULL_SMALL_LINES_DIAMOND_EXIT : 0) |
SI_NGG_CULL_CLIP_PLANE_ENABLE(state->clip_plane_enable);
if (rs->rasterizer_discard) {
rs->ngg_cull_flags_tris |= SI_NGG_CULL_FRONT_FACE |
SI_NGG_CULL_BACK_FACE;
rs->ngg_cull_flags_tris_y_inverted = rs->ngg_cull_flags_tris;
if (!state->front_ccw) {
rs->ngg_cull_front = state->cull_face & PIPE_FACE_FRONT || rs->rasterizer_discard;
rs->ngg_cull_back = state->cull_face & PIPE_FACE_BACK || rs->rasterizer_discard;
} else {
bool cull_front, cull_back;
if (!state->front_ccw) {
cull_front = !!(state->cull_face & PIPE_FACE_FRONT);
cull_back = !!(state->cull_face & PIPE_FACE_BACK);
} else {
cull_back = !!(state->cull_face & PIPE_FACE_FRONT);
cull_front = !!(state->cull_face & PIPE_FACE_BACK);
}
if (cull_front) {
rs->ngg_cull_flags_tris |= SI_NGG_CULL_FRONT_FACE;
rs->ngg_cull_flags_tris_y_inverted |= SI_NGG_CULL_BACK_FACE;
}
if (cull_back) {
rs->ngg_cull_flags_tris |= SI_NGG_CULL_BACK_FACE;
rs->ngg_cull_flags_tris_y_inverted |= SI_NGG_CULL_FRONT_FACE;
}
rs->ngg_cull_front = state->cull_face & PIPE_FACE_BACK || rs->rasterizer_discard;
rs->ngg_cull_back = state->cull_face & PIPE_FACE_FRONT || rs->rasterizer_discard;
}
/* Force gl_FrontFacing to true or false if the other face is culled. */
@@ -1335,6 +1315,7 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state)
SET_FIELD(sctx->current_vs_state, VS_STATE_CLAMP_VERTEX_COLOR, rs->clamp_vertex_color);
si_pm4_bind_state(sctx, rasterizer, rs);
si_update_ngg_cull_face_state(sctx);
if (old_rs->scissor_enable != rs->scissor_enable)
si_mark_atom_dirty(sctx, &sctx->atoms.s.scissors);
+2 -1
View File
@@ -74,10 +74,11 @@ struct si_state_rasterizer {
float line_width;
float max_point_size;
unsigned ngg_cull_flags_tris : 16;
unsigned ngg_cull_flags_tris_y_inverted : 16;
unsigned ngg_cull_flags_lines : 16;
unsigned sprite_coord_enable : 8;
unsigned clip_plane_enable : 8;
bool ngg_cull_front : 1;
bool ngg_cull_back : 1;
unsigned half_pixel_center : 1;
unsigned flatshade : 1;
unsigned flatshade_first : 1;
@@ -2258,8 +2258,7 @@ static void si_draw(struct pipe_context *ctx,
ngg_culling = rs->ngg_cull_flags_lines |
(!HAS_TESS && !HAS_GS ? SI_NGG_CULL_VS_LINES : 0);
} else {
ngg_culling = (sctx->viewport0_y_inverted ? rs->ngg_cull_flags_tris_y_inverted :
rs->ngg_cull_flags_tris) |
ngg_culling = rs->ngg_cull_flags_tris |
(!HAS_TESS && !HAS_GS ? SI_NGG_CULL_VS_TRIANGLES : 0);
}
@@ -486,6 +486,7 @@ static void si_set_viewport_states(struct pipe_context *pctx, unsigned start_slo
if (start_slot == 0) {
ctx->viewport0_y_inverted = state->scale[1] < 0;
si_update_ngg_cull_face_state(ctx);
/* NGG cull state uses the viewport and quant mode. */
if (ctx->screen->use_ngg_culling)