nir: allow using sysvals in nir_lower_clip

By passing a `NULL` pointer for the `ucp_enable` argument the
value will be loaded from a sysval
This commit is contained in:
antonino 2023-08-02 17:44:39 +02:00 committed by Anna Maniscalco
parent 0068da6f45
commit cd269ebfa2
9 changed files with 88 additions and 60 deletions

View file

@ -1255,8 +1255,9 @@ v3d_nir_lower_fs_late(struct v3d_compile *c)
* array variable, so we have GL's clip lowering follow suit
* (compact_arrays option at nir_shader_compiler_options)
*/
if (c->fs_key->ucp_enables)
NIR_PASS(_, c->s, nir_lower_clip_fs, c->fs_key->ucp_enables, true, false);
unsigned ucp_enables = c->fs_key->ucp_enables;
if (ucp_enables)
NIR_PASS(_, c->s, nir_lower_clip_fs, &ucp_enables, true, false);
NIR_PASS(_, c->s, nir_lower_io_to_scalar, nir_var_shader_in, NULL, NULL);
}

View file

@ -6051,14 +6051,14 @@ typedef struct nir_input_attachment_options {
bool nir_lower_input_attachments(nir_shader *shader,
const nir_input_attachment_options *options);
bool nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables,
bool nir_lower_clip_vs(nir_shader *shader, unsigned *ucp_enables,
bool use_vars,
bool use_clipdist_array,
const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH]);
bool nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables,
bool nir_lower_clip_gs(nir_shader *shader, unsigned *ucp_enables,
bool use_clipdist_array,
const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH]);
bool nir_lower_clip_fs(nir_shader *shader, unsigned ucp_enables,
bool nir_lower_clip_fs(nir_shader *shader, unsigned *ucp_enables,
bool use_clipdist_array, bool use_load_interp);
bool nir_lower_clip_cull_distance_to_vec4s(nir_shader *shader);

View file

@ -275,6 +275,7 @@ struct lower_clip_state {
nir_variable *out[2];
unsigned ucp_enables;
bool use_clipdist_array;
bool use_enables_sysval;
const gl_state_index16 (*clipplane_state_tokens)[STATE_LENGTH];
/* This holds the current CLIP_VERTEX value for GS. */
@ -294,17 +295,16 @@ lower_clip_vertex_var(nir_builder *b, const struct lower_clip_state *state)
}
for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) {
if (state->ucp_enables & (1 << plane)) {
nir_def *ucp = get_ucp(b, plane, state->clipplane_state_tokens);
/* calculate clipdist[plane] - dot(ucp, cv): */
clipdist[plane] = nir_fdot(b, ucp, cv);
} else {
/* 0.0 == don't-clip == disabled: */
clipdist[plane] = nir_imm_float(b, 0.0);
}
nir_def *ucp = get_ucp(b, plane, state->clipplane_state_tokens);
nir_def *ucp_enable_def;
if (state->use_enables_sysval)
ucp_enable_def = nir_load_clip_plane_enable(b);
else
ucp_enable_def = nir_imm_int(b, state->ucp_enables);
clipdist[plane] = nir_bcsel(b, nir_b2b1(b, nir_iand_imm(b, ucp_enable_def, 1 << plane)),
nir_fdot(b, ucp, cv), nir_imm_float(b, 0.0));
if (state->use_clipdist_array &&
plane < util_last_bit(state->ucp_enables)) {
(state->use_enables_sysval || plane < util_last_bit(state->ucp_enables))) {
nir_deref_instr *deref;
deref = nir_build_deref_array_imm(b,
nir_build_deref_var(b, state->out[0]),
@ -338,15 +338,14 @@ lower_clip_vertex_intrin(nir_builder *b, const struct lower_clip_state *state)
}
for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) {
if (state->ucp_enables & (1 << plane)) {
nir_def *ucp = get_ucp(b, plane, state->clipplane_state_tokens);
/* calculate clipdist[plane] - dot(ucp, cv): */
clipdist[plane] = nir_fdot(b, ucp, cv);
} else {
/* 0.0 == don't-clip == disabled: */
clipdist[plane] = nir_imm_float(b, 0.0);
}
nir_def *ucp = get_ucp(b, plane, state->clipplane_state_tokens);
nir_def *ucp_enable_def;
if (state->use_enables_sysval)
ucp_enable_def = nir_load_clip_plane_enable(b);
else
ucp_enable_def = nir_imm_int(b, state->ucp_enables);
clipdist[plane] = nir_bcsel(b, nir_b2b1(b, nir_iand_imm(b, ucp_enable_def, 1 << plane)),
nir_fdot(b, ucp, cv), nir_imm_float(b, 0.0));
}
if (state->use_clipdist_array) {
@ -383,11 +382,13 @@ lower_clip_vertex_intrin(nir_builder *b, const struct lower_clip_state *state)
* clipdist output instead of two vec4s.
*/
bool
nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars,
nir_lower_clip_vs(nir_shader *shader, unsigned *ucp_enables, bool use_vars,
bool use_clipdist_array,
const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH])
{
if (!ucp_enables)
unsigned ucp_enables_val = ucp_enables ? *ucp_enables : 0xff;
if (!ucp_enables_val)
return false;
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
@ -406,8 +407,9 @@ nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars,
b.cursor = nir_after_impl(impl);
struct lower_clip_state state = { NULL };
state.ucp_enables = ucp_enables;
state.ucp_enables = ucp_enables_val;
state.use_clipdist_array = use_clipdist_array;
state.use_enables_sysval = !ucp_enables;
state.clipplane_state_tokens = clipplane_state_tokens;
/* find clipvertex/position outputs */
@ -415,20 +417,20 @@ nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars,
&state.position))
return false;
shader->info.clip_distance_array_size = util_last_bit(ucp_enables);
shader->info.clip_distance_array_size = util_last_bit(ucp_enables_val);
if (!use_vars || shader->info.io_lowered) {
/* If the driver has lowered IO instead of st/mesa, the driver expects
* that variables are present even with lowered IO, so create them.
*/
if (!shader->info.io_lowered) {
create_clipdist_vars(shader, state.out, ucp_enables, true,
create_clipdist_vars(shader, state.out, ucp_enables_val, true,
use_clipdist_array);
}
lower_clip_vertex_intrin(&b, &state);
} else {
create_clipdist_vars(shader, state.out, ucp_enables, true,
create_clipdist_vars(shader, state.out, ucp_enables_val, true,
use_clipdist_array);
lower_clip_vertex_var(&b, &state);
}
@ -504,16 +506,19 @@ save_clipvertex_to_temp_gs(nir_builder *b, nir_intrinsic_instr *intr,
}
bool
nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables,
nir_lower_clip_gs(nir_shader *shader, unsigned *ucp_enables,
bool use_clipdist_array,
const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH])
{
if (!ucp_enables)
unsigned ucp_enables_val = ucp_enables ? *ucp_enables : 0xff;
if (!ucp_enables_val)
return false;
struct lower_clip_state state = { NULL };
state.ucp_enables = ucp_enables;
state.ucp_enables = ucp_enables ? *ucp_enables : 0xff;
state.use_clipdist_array = use_clipdist_array;
state.use_enables_sysval = !ucp_enables;
state.clipplane_state_tokens = clipplane_state_tokens;
/* find clipvertex/position outputs */
@ -521,7 +526,7 @@ nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables,
&state.position))
return false;
shader->info.clip_distance_array_size = util_last_bit(ucp_enables);
shader->info.clip_distance_array_size = util_last_bit(ucp_enables_val);
if (shader->info.io_lowered) {
/* Track the current value of CLIP_VERTEX or POS in a local variable. */
@ -533,7 +538,7 @@ nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables,
return false;
} else {
/* insert CLIPDIST outputs */
create_clipdist_vars(shader, state.out, ucp_enables, true,
create_clipdist_vars(shader, state.out, ucp_enables_val, true,
use_clipdist_array);
}
@ -548,7 +553,8 @@ nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables,
static void
lower_clip_fs(nir_function_impl *impl, unsigned ucp_enables,
nir_variable **in, bool use_clipdist_array, bool use_load_interp)
nir_variable **in, bool use_clipdist_array, bool use_load_interp,
bool use_enables_sysval)
{
nir_def *clipdist[MAX_CLIP_PLANES];
nir_builder b = nir_builder_at(nir_before_impl(impl));
@ -568,12 +574,23 @@ lower_clip_fs(nir_function_impl *impl, unsigned ucp_enables,
nir_def *cond = NULL;
for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) {
if (ucp_enables & (1 << plane)) {
nir_def *this_cond =
nir_flt_imm(&b, clipdist[plane], 0.0);
if (use_enables_sysval)
cond = nir_imm_int(&b, 0);
cond = cond ? nir_ior(&b, cond, this_cond) : this_cond;
for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) {
if (use_enables_sysval) {
nir_def *this_cond =
nir_iand(&b, nir_flt(&b, clipdist[plane], nir_imm_float(&b, 0.0)),
nir_iand_imm(&b, nir_load_user_clip_plane(&b), (1 << plane)));
cond = nir_ior(&b, cond, this_cond);
} else {
if (ucp_enables & (1 << plane)) {
nir_def *this_cond =
nir_flt_imm(&b, clipdist[plane], 0.0);
cond = cond ? nir_ior(&b, cond, this_cond) : this_cond;
}
}
}
@ -607,31 +624,32 @@ fs_has_clip_dist_input_var(nir_shader *shader, nir_variable **io_vars,
/* insert conditional kill based on interpolated CLIPDIST
*/
bool
nir_lower_clip_fs(nir_shader *shader, unsigned ucp_enables,
nir_lower_clip_fs(nir_shader *shader, unsigned *ucp_enables,
bool use_clipdist_array, bool use_load_interp)
{
nir_variable *in[2] = { 0 };
unsigned ucp_enables_val = ucp_enables ? *ucp_enables : 0xff;
if (!ucp_enables)
if (!ucp_enables_val)
return false;
/* this is probably broken until https://gitlab.freedesktop.org/mesa/mesa/-/issues/10826 is fixed */
assert(!shader->info.io_lowered);
shader->info.clip_distance_array_size = util_last_bit(ucp_enables);
shader->info.clip_distance_array_size = util_last_bit(ucp_enables_val);
/* No hard reason to require use_clipdist_arr to work with
* frag-shader-based gl_ClipDistance, except that the only user that does
* not enable this does not support GL 3.0 (or EXT_clip_cull_distance).
*/
if (!fs_has_clip_dist_input_var(shader, in, &ucp_enables))
create_clipdist_vars(shader, in, ucp_enables, false, use_clipdist_array);
if (!fs_has_clip_dist_input_var(shader, in, &ucp_enables_val))
create_clipdist_vars(shader, in, ucp_enables_val, false, use_clipdist_array);
else
assert(use_clipdist_array);
nir_foreach_function_with_impl(function, impl, shader) {
if (!strcmp(function->name, "main")) {
lower_clip_fs(impl, ucp_enables, in, use_clipdist_array,
use_load_interp);
lower_clip_fs(impl, ucp_enables_val, in, use_clipdist_array,
use_load_interp, !ucp_enables);
}
}

View file

@ -1164,11 +1164,12 @@ ir3_nir_lower_variant(struct ir3_shader_variant *so,
/* Note that it is intentional to use the VS lowering pass for GS, since we
* lower GS into something that looks more like a VS in ir3_nir_lower_gs():
*/
unsigned ucp_enables = so->key.ucp_enables;
if (lower_ucp_vs(so)) {
progress |= OPT(s, nir_lower_clip_vs, so->key.ucp_enables, false, true, NULL);
progress |= OPT(s, nir_lower_clip_vs, &ucp_enables, false, true, NULL);
} else if (s->info.stage == MESA_SHADER_FRAGMENT) {
if (so->key.ucp_enables && !so->compiler->has_clip_cull)
progress |= OPT(s, nir_lower_clip_fs, so->key.ucp_enables, true, true);
progress |= OPT(s, nir_lower_clip_fs, &ucp_enables, true, true);
}
if (so->binning_pass) {

View file

@ -1179,7 +1179,8 @@ crocus_compile_vs(struct crocus_context *ice,
if (key->nr_userclip_plane_consts) {
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
/* Check if variables were found. */
if (nir_lower_clip_vs(nir, (1 << key->nr_userclip_plane_consts) - 1,
unsigned ucp_enables = (1 << key->nr_userclip_plane_consts) - 1;
if (nir_lower_clip_vs(nir, &ucp_enables,
true, false, NULL)) {
nir_lower_io_vars_to_temporaries(nir, impl, nir_var_shader_out);
nir_lower_global_vars_to_local(nir);
@ -1539,7 +1540,8 @@ crocus_compile_tes(struct crocus_context *ice,
if (key->nr_userclip_plane_consts) {
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
nir_lower_clip_vs(nir, (1 << key->nr_userclip_plane_consts) - 1, true,
unsigned ucp_enables = (1 << key->nr_userclip_plane_consts) - 1;
nir_lower_clip_vs(nir, &ucp_enables, true,
false, NULL);
nir_lower_io_vars_to_temporaries(nir, impl, nir_var_shader_out);
nir_lower_global_vars_to_local(nir);
@ -1682,7 +1684,8 @@ crocus_compile_gs(struct crocus_context *ice,
if (key->nr_userclip_plane_consts) {
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
nir_lower_clip_gs(nir, (1 << key->nr_userclip_plane_consts) - 1, false,
unsigned ucp_enables = (1 << key->nr_userclip_plane_consts) - 1;
nir_lower_clip_gs(nir, &ucp_enables, false,
NULL);
nir_lower_io_vars_to_temporaries(nir, impl, nir_var_shader_out);
nir_lower_global_vars_to_local(nir);

View file

@ -1908,7 +1908,8 @@ iris_compile_vs(struct iris_screen *screen,
if (key->vue.nr_userclip_plane_consts) {
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
/* Check if variables were found. */
if (nir_lower_clip_vs(nir, (1 << key->vue.nr_userclip_plane_consts) - 1,
unsigned ucp_enables = (1 << key->vue.nr_userclip_plane_consts) - 1;
if (nir_lower_clip_vs(nir, &ucp_enables,
true, false, NULL)) {
nir_lower_io_vars_to_temporaries(nir, impl, nir_var_shader_out);
nir_lower_global_vars_to_local(nir);
@ -2355,7 +2356,8 @@ iris_compile_tes(struct iris_screen *screen,
if (key->vue.nr_userclip_plane_consts) {
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
nir_lower_clip_vs(nir, (1 << key->vue.nr_userclip_plane_consts) - 1,
unsigned ucp_enables = (1 << key->vue.nr_userclip_plane_consts) - 1;
nir_lower_clip_vs(nir, &ucp_enables,
true, false, NULL);
nir_lower_io_vars_to_temporaries(nir, impl, nir_var_shader_out);
nir_lower_global_vars_to_local(nir);
@ -2550,7 +2552,8 @@ iris_compile_gs(struct iris_screen *screen,
if (key->vue.nr_userclip_plane_consts) {
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
nir_lower_clip_gs(nir, (1 << key->vue.nr_userclip_plane_consts) - 1,
unsigned ucp_enables = (1 << key->vue.nr_userclip_plane_consts) - 1;
nir_lower_clip_gs(nir, &ucp_enables,
false, NULL);
nir_lower_io_vars_to_temporaries(nir, impl, nir_var_shader_out);
nir_lower_global_vars_to_local(nir);

View file

@ -182,7 +182,8 @@ panfrost_shader_compile(struct panfrost_screen *screen, const nir_shader *ir,
}
if (key->fs.clip_plane_enable) {
NIR_PASS(_, s, nir_lower_clip_fs, key->fs.clip_plane_enable,
unsigned ucp_enables = key->fs.clip_plane_enable;
NIR_PASS(_, s, nir_lower_clip_fs, &ucp_enables,
false, true);
inputs.fixed_varying_mask =
pan_get_fixed_varying_mask(s->info.inputs_read);

View file

@ -2263,7 +2263,8 @@ vc4_shader_ntq(struct vc4_context *vc4, enum qstage stage,
NIR_PASS(_, c->s, nir_lower_tex, &tex_options);
if (c->fs_key && c->fs_key->ucp_enables) {
NIR_PASS(_, c->s, nir_lower_clip_fs, c->fs_key->ucp_enables, false, false);
unsigned ucp_enables = c->fs_key->ucp_enables;
NIR_PASS(_, c->s, nir_lower_clip_fs, &ucp_enables, false, false);
}
if (c->stage == QSTAGE_FRAG)

View file

@ -719,10 +719,10 @@ lower_ucp(struct st_context *st,
if (nir->info.stage == MESA_SHADER_VERTEX ||
nir->info.stage == MESA_SHADER_TESS_EVAL) {
NIR_PASS(_, nir, nir_lower_clip_vs, ucp_enables,
NIR_PASS(_, nir, nir_lower_clip_vs, &ucp_enables,
true, can_compact, clipplane_state);
} else if (nir->info.stage == MESA_SHADER_GEOMETRY) {
NIR_PASS(_, nir, nir_lower_clip_gs, ucp_enables,
NIR_PASS(_, nir, nir_lower_clip_gs, &ucp_enables,
can_compact, clipplane_state);
}