1 /*
2 * Copyright 2024 Valve Corporation
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "nir.h"
7 #include "nir_builder.h"
8
9 /**
10 * If a clip/cull distance is constant >= 0,
11 * we know that it will never cause clipping/culling.
12 * Remove the sysval_output in that case.
13 *
14 * Assumes that nir_lower_io_to_temporaries was run,
15 * and works best with scalar store_outputs.
16 */
17
18 static bool
opt_clip_cull(nir_builder * b,nir_intrinsic_instr * intr,void * unused)19 opt_clip_cull(nir_builder *b, nir_intrinsic_instr *intr, void *unused)
20 {
21 if (intr->intrinsic != nir_intrinsic_store_output)
22 return false;
23
24 const nir_io_semantics io_sem = nir_intrinsic_io_semantics(intr);
25 const unsigned location = io_sem.location;
26
27 if (io_sem.no_sysval_output)
28 return false;
29
30 if (location != VARYING_SLOT_CLIP_DIST0 && location != VARYING_SLOT_CLIP_DIST1)
31 return false;
32
33 nir_def *val = intr->src[0].ssa;
34 for (unsigned i = 0; i < val->num_components; i++) {
35 nir_scalar s = nir_scalar_resolved(val, i);
36 if (!nir_scalar_is_const(s))
37 return false;
38 float distance = nir_scalar_as_float(s);
39
40 /* NaN gets clipped, and INF after interpolation is NaN. */
41 if (isnan(distance) || distance < 0.0 || distance == INFINITY)
42 return false;
43 }
44
45 nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT);
46 return true;
47 }
48
49 bool
nir_opt_clip_cull_const(nir_shader * shader)50 nir_opt_clip_cull_const(nir_shader *shader)
51 {
52 return nir_shader_intrinsics_pass(shader, opt_clip_cull, nir_metadata_control_flow, NULL);
53 }
54