mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-03 07:10:15 +01:00
nir/opt_clip_cull_const: support GS
Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35256>
This commit is contained in:
parent
6677d087c0
commit
44fcda9631
1 changed files with 85 additions and 10 deletions
|
|
@ -15,39 +15,114 @@
|
|||
* and works best with scalar store_outputs.
|
||||
*/
|
||||
|
||||
static bool
|
||||
opt_clip_cull(nir_builder *b, nir_intrinsic_instr *intr, void *unused)
|
||||
/* Return -1 if invalid, 0 if it's a normal clip/cull distance value,
|
||||
* and 1 if it's a no-op value.
|
||||
*/
|
||||
static int
|
||||
analyze_clip_cull_value(nir_intrinsic_instr *intr)
|
||||
{
|
||||
if (intr->intrinsic != nir_intrinsic_store_output)
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
const nir_io_semantics io_sem = nir_intrinsic_io_semantics(intr);
|
||||
const unsigned location = io_sem.location;
|
||||
|
||||
if (io_sem.no_sysval_output)
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
if (location != VARYING_SLOT_CLIP_DIST0 && location != VARYING_SLOT_CLIP_DIST1)
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
nir_def *val = intr->src[0].ssa;
|
||||
for (unsigned i = 0; i < val->num_components; i++) {
|
||||
nir_scalar s = nir_scalar_resolved(val, i);
|
||||
if (!nir_scalar_is_const(s))
|
||||
return false;
|
||||
return 0;
|
||||
float distance = nir_scalar_as_float(s);
|
||||
|
||||
/* NaN gets clipped, and INF after interpolation is NaN. */
|
||||
if (isnan(distance) || distance < 0.0 || distance == INFINITY)
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT);
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
opt_clip_cull_vs_tes(nir_builder *b, nir_intrinsic_instr *intr, void *unused)
|
||||
{
|
||||
if (analyze_clip_cull_value(intr) == 1) {
|
||||
nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The types of stores are first gathered for all stores. If a certain slot
|
||||
* component is only written by no-op stores, they are removed.
|
||||
*/
|
||||
typedef struct {
|
||||
bool has_normal_store[8];
|
||||
bool has_noop_store[8];
|
||||
} gs_info;
|
||||
|
||||
static unsigned
|
||||
get_clip_io_index(nir_intrinsic_instr *intr)
|
||||
{
|
||||
nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
|
||||
assert(intr->intrinsic == nir_intrinsic_store_output);
|
||||
assert(sem.location == VARYING_SLOT_CLIP_DIST0 ||
|
||||
sem.location == VARYING_SLOT_CLIP_DIST1);
|
||||
assert(sem.num_slots == 1);
|
||||
assert(nir_src_as_uint(*nir_get_io_offset_src(intr)) == 0); /* no indirect */
|
||||
assert(intr->src[0].ssa->num_components == 1); /* scalar */
|
||||
|
||||
return (sem.location - VARYING_SLOT_CLIP_DIST0) * 4 +
|
||||
nir_intrinsic_component(intr);
|
||||
}
|
||||
|
||||
static bool
|
||||
gather_clip_cull_gs(nir_builder *b, nir_intrinsic_instr *intr, void *unused)
|
||||
{
|
||||
gs_info *info = (gs_info *)unused;
|
||||
int r = analyze_clip_cull_value(intr);
|
||||
|
||||
if (r == 1)
|
||||
info->has_noop_store[get_clip_io_index(intr)] = true;
|
||||
else if (r == 0)
|
||||
info->has_normal_store[get_clip_io_index(intr)] = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
opt_clip_cull_gs(nir_builder *b, nir_intrinsic_instr *intr, void *unused)
|
||||
{
|
||||
gs_info *info = (gs_info *)unused;
|
||||
|
||||
if (intr->intrinsic == nir_intrinsic_store_output &&
|
||||
(nir_intrinsic_io_semantics(intr).location == VARYING_SLOT_CLIP_DIST0 ||
|
||||
nir_intrinsic_io_semantics(intr).location == VARYING_SLOT_CLIP_DIST1)) {
|
||||
unsigned index = get_clip_io_index(intr);
|
||||
|
||||
if (info->has_noop_store[index] && !info->has_normal_store[index]) {
|
||||
nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nir_opt_clip_cull_const(nir_shader *shader)
|
||||
{
|
||||
return nir_shader_intrinsics_pass(shader, opt_clip_cull, nir_metadata_control_flow, NULL);
|
||||
if (shader->info.stage == MESA_SHADER_GEOMETRY) {
|
||||
gs_info info = {0};
|
||||
nir_shader_intrinsics_pass(shader, gather_clip_cull_gs, nir_metadata_all, &info);
|
||||
return nir_shader_intrinsics_pass(shader, opt_clip_cull_gs, nir_metadata_all, &info);
|
||||
} else {
|
||||
return nir_shader_intrinsics_pass(shader, opt_clip_cull_vs_tes, nir_metadata_all, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue