From d2141e675144b42ff98b14dd6bc0964f8037d173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 9 Feb 2025 16:15:41 -0500 Subject: [PATCH] ac/nir/ngg: add an option to skip viewport-based culling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can do W and face culling when we have multiple viewports, but not frustum and small prim culling because those are dependent on the viewport. When a shader writes the viewport index, the new option allows skipping viewport-based culling while keeping W and face culling. Reviewed-by: Timur Kristóf Reviewed-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/amd/common/nir/ac_nir.h | 4 ++++ src/amd/common/nir/ac_nir_cull.c | 26 +++++++++++++++++++----- src/amd/common/nir/ac_nir_helpers.h | 1 + src/amd/common/nir/ac_nir_lower_ngg.c | 2 +- src/amd/common/nir/ac_nir_lower_ngg_gs.c | 5 +++-- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/amd/common/nir/ac_nir.h b/src/amd/common/nir/ac_nir.h index 6ec148971bc..56e6d43d6ca 100644 --- a/src/amd/common/nir/ac_nir.h +++ b/src/amd/common/nir/ac_nir.h @@ -160,6 +160,10 @@ typedef struct { bool kill_layer; bool force_vrs; bool compact_primitives; + /* Skip culling dependent on the viewport state, which is frustum culling and small prim + * culling. Set this when the shader writes the viewport index. + */ + bool skip_viewport_culling; /* VS */ unsigned num_vertices_per_primitive; diff --git a/src/amd/common/nir/ac_nir_cull.c b/src/amd/common/nir/ac_nir_cull.c index bb1fa921575..b08ec5292c5 100644 --- a/src/amd/common/nir/ac_nir_cull.c +++ b/src/amd/common/nir/ac_nir_cull.c @@ -134,6 +134,7 @@ call_accept_func(nir_builder *b, nir_def *accepted, ac_nir_cull_accepted accept_ static nir_def * ac_nir_cull_triangle(nir_builder *b, + bool skip_viewport_culling, nir_def *initially_accepted, nir_def *pos[3][4], position_w_info *w_info, @@ -144,6 +145,11 @@ ac_nir_cull_triangle(nir_builder *b, accepted = nir_iand(b, accepted, nir_inot(b, w_info->all_w_negative_or_zero_or_nan)); accepted = nir_iand(b, accepted, nir_inot(b, cull_face_triangle(b, pos, w_info))); + if (skip_viewport_culling) { + call_accept_func(b, accepted, accept_func, state); + return accepted; + } + nir_def *bbox_accepted = NULL; nir_if *if_accepted = nir_push_if(b, accepted); @@ -305,6 +311,7 @@ cull_small_primitive_line(nir_builder *b, nir_def *pos[3][4], static nir_def * ac_nir_cull_line(nir_builder *b, + bool skip_viewport_culling, nir_def *initially_accepted, nir_def *pos[3][4], position_w_info *w_info, @@ -314,6 +321,11 @@ ac_nir_cull_line(nir_builder *b, nir_def *accepted = initially_accepted; accepted = nir_iand(b, accepted, nir_inot(b, w_info->all_w_negative_or_zero_or_nan)); + if (skip_viewport_culling) { + call_accept_func(b, accepted, accept_func, state); + return accepted; + } + nir_def *bbox_accepted = NULL; nir_if *if_accepted = nir_push_if(b, accepted); @@ -336,6 +348,7 @@ ac_nir_cull_line(nir_builder *b, nir_def * ac_nir_cull_primitive(nir_builder *b, + bool skip_viewport_culling, nir_def *initially_accepted, nir_def *pos[3][4], unsigned num_vertices, @@ -345,12 +358,15 @@ ac_nir_cull_primitive(nir_builder *b, position_w_info w_info = {0}; analyze_position_w(b, pos, num_vertices, &w_info); - if (num_vertices == 3) - return ac_nir_cull_triangle(b, initially_accepted, pos, &w_info, accept_func, state); - else if (num_vertices == 2) - return ac_nir_cull_line(b, initially_accepted, pos, &w_info, accept_func, state); - else + if (num_vertices == 3) { + return ac_nir_cull_triangle(b, skip_viewport_culling, initially_accepted, pos, &w_info, + accept_func, state); + } else if (num_vertices == 2) { + return ac_nir_cull_line(b, skip_viewport_culling, initially_accepted, pos, &w_info, + accept_func, state); + } else { unreachable("point culling not implemented"); + } return NULL; } diff --git a/src/amd/common/nir/ac_nir_helpers.h b/src/amd/common/nir/ac_nir_helpers.h index a3b7226dcae..8c145b7fb3b 100644 --- a/src/amd/common/nir/ac_nir_helpers.h +++ b/src/amd/common/nir/ac_nir_helpers.h @@ -146,6 +146,7 @@ ac_nir_map_io_location(unsigned location, nir_def * ac_nir_cull_primitive(nir_builder *b, + bool skip_viewport_culling, nir_def *initially_accepted, nir_def *pos[3][4], unsigned num_vertices, diff --git a/src/amd/common/nir/ac_nir_lower_ngg.c b/src/amd/common/nir/ac_nir_lower_ngg.c index b2005ac1a20..9c9a9706a96 100644 --- a/src/amd/common/nir/ac_nir_lower_ngg.c +++ b/src/amd/common/nir/ac_nir_lower_ngg.c @@ -1288,7 +1288,7 @@ add_deferred_attribute_culling(nir_builder *b, nir_cf_list *original_extracted_c } /* See if the current primitive is accepted */ - ac_nir_cull_primitive(b, accepted_by_clipdist, pos, + ac_nir_cull_primitive(b, s->options->skip_viewport_culling, accepted_by_clipdist, pos, s->options->num_vertices_per_primitive, cull_primitive_accepted, s); } diff --git a/src/amd/common/nir/ac_nir_lower_ngg_gs.c b/src/amd/common/nir/ac_nir_lower_ngg_gs.c index 72946fd2b2a..9d4eb5e45ff 100644 --- a/src/amd/common/nir/ac_nir_lower_ngg_gs.c +++ b/src/amd/common/nir/ac_nir_lower_ngg_gs.c @@ -631,8 +631,9 @@ ngg_gs_cull_primitive(nir_builder *b, nir_def *tid_in_tg, nir_def *max_vtxcnt, /* TODO: support clipdist culling in GS */ nir_def *accepted_by_clipdist = nir_imm_true(b); - nir_def *accepted = ac_nir_cull_primitive( - b, accepted_by_clipdist, pos, s->num_vertices_per_primitive, NULL, NULL); + nir_def *accepted = ac_nir_cull_primitive(b, s->options->skip_viewport_culling, + accepted_by_clipdist, pos, + s->num_vertices_per_primitive, NULL, NULL); nir_if *if_rejected = nir_push_if(b, nir_inot(b, accepted)); {