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:
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user