ac/nir/ngg: add an option to skip viewport-based culling

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 <timur.kristof@gmail.com>
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33482>
This commit is contained in:
Marek Olšák
2025-02-09 16:15:41 -05:00
committed by Marge Bot
parent d429e35169
commit d2141e6751
5 changed files with 30 additions and 8 deletions
+4
View File
@@ -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;
+21 -5
View File
@@ -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;
}
+1
View File
@@ -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,
+1 -1
View File
@@ -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);
}
+3 -2
View File
@@ -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));
{