From a41f0e62bbf3d58d5bf64360615903a2f49f2c7f Mon Sep 17 00:00:00 2001 From: squidbus Date: Wed, 22 Apr 2026 14:45:42 -0700 Subject: [PATCH] asahi,nir: Move asahi dynamic clipz pass to common. Acked-by: Alyssa Rosenzweig Part-of: --- src/compiler/nir/nir.h | 1 + src/compiler/nir/nir_intrinsics.py | 2 +- src/compiler/nir/nir_lower_clip_halfz.c | 39 +++++++++++++++++++ .../drivers/asahi/agx_nir_lower_sysvals.c | 2 +- src/gallium/drivers/asahi/agx_state.c | 30 +------------- 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index ddac1ef0646..cf3d2a5e20d 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5444,6 +5444,7 @@ bool nir_lower_vars_to_scratch_global(nir_shader *shader, bool nir_lower_scratch_to_var(nir_shader *nir); bool nir_lower_clip_halfz(nir_shader *shader); +bool nir_lower_clip_halfz_dynamic(nir_shader *shader); void nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint); void nir_gather_clip_cull_distance_sizes_from_vars(nir_shader *nir); diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 8426c0c0140..a896deab094 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -2335,7 +2335,7 @@ intrinsic("quad_ballot_agx", src_comp=[1], dest_comp=1, flags=[CAN_ELIMINATE]) # 1] clipping, we need to transform z' = (z + w) / 2. We express both cases as a # lerp between z and w, where this is the lerp coefficient: 0 for [0, 1] and 0.5 # for [-1, 1]. -system_value("clip_z_coeff_agx", 1) +system_value("clip_z_coeff", 1) # True if drawing triangle fans with first vertex provoking, false otherwise. # This affects flatshading, which is defined weirdly for fans with first. diff --git a/src/compiler/nir/nir_lower_clip_halfz.c b/src/compiler/nir/nir_lower_clip_halfz.c index eb0dc588263..1cd9d07dba3 100644 --- a/src/compiler/nir/nir_lower_clip_halfz.c +++ b/src/compiler/nir/nir_lower_clip_halfz.c @@ -63,3 +63,42 @@ nir_lower_clip_halfz(nir_shader *shader) nir_metadata_control_flow, NULL); } + +/* Dynamic lowered I/O version of nir_lower_clip_halfz. + * nir_intrinsic_load_clip_z_coeff is used to load the dynamic clip coefficient. + */ +static bool +lower_pos_write_dynamic(nir_builder *b, nir_intrinsic_instr *intr, + UNUSED void *data) +{ + if (intr->intrinsic != nir_intrinsic_store_output) + return false; + if (nir_intrinsic_io_semantics(intr).location != VARYING_SLOT_POS) + return false; + + assert(nir_intrinsic_component(intr) == 0 && "not yet scalarized"); + b->cursor = nir_before_instr(&intr->instr); + + nir_def *pos = intr->src[0].ssa; + nir_def *z = nir_channel(b, pos, 2); + nir_def *w = nir_channel(b, pos, 3); + nir_def *c = nir_load_clip_z_coeff(b); + + /* Lerp. If c = 0, reduces to z. If c = 1/2, reduces to (z + w)/2 */ + nir_def *new_z = nir_ffma(b, nir_fneg(b, z), c, nir_ffma(b, w, c, z)); + nir_src_rewrite(&intr->src[0], nir_vector_insert_imm(b, pos, new_z, 2)); + return true; +} + +bool +nir_lower_clip_halfz_dynamic(nir_shader *shader) +{ + if (shader->info.stage != MESA_SHADER_VERTEX && + shader->info.stage != MESA_SHADER_GEOMETRY && + shader->info.stage != MESA_SHADER_TESS_EVAL) + return false; + + return nir_shader_intrinsics_pass(shader, lower_pos_write_dynamic, + nir_metadata_control_flow, + NULL); +} diff --git a/src/gallium/drivers/asahi/agx_nir_lower_sysvals.c b/src/gallium/drivers/asahi/agx_nir_lower_sysvals.c index af34e4ca190..6a75c87ff79 100644 --- a/src/gallium/drivers/asahi/agx_nir_lower_sysvals.c +++ b/src/gallium/drivers/asahi/agx_nir_lower_sysvals.c @@ -194,7 +194,7 @@ lower_intrinsic(nir_builder *b, nir_intrinsic_instr *intr, return load_sysval_root(b, 1, 16, &u->sprite_mask); case nir_intrinsic_load_shader_part_tests_zs_agx: return load_sysval_root(b, 1, 16, &u->no_epilog_discard); - case nir_intrinsic_load_clip_z_coeff_agx: + case nir_intrinsic_load_clip_z_coeff: return nir_f2f32(b, load_sysval_root(b, 1, 16, &u->clip_z_coeff)); case nir_intrinsic_load_rasterization_stream: return nir_imm_int(b, 0); diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 5666735047f..c913e022d94 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -1389,30 +1389,6 @@ asahi_cs_shader_key_equal(const void *a, const void *b) return true; } -/* Dynamic lowered I/O version of nir_lower_clip_halfz */ -static bool -agx_nir_lower_clip_m1_1(nir_builder *b, nir_intrinsic_instr *intr, - UNUSED void *data) -{ - if (intr->intrinsic != nir_intrinsic_store_output) - return false; - if (nir_intrinsic_io_semantics(intr).location != VARYING_SLOT_POS) - return false; - - assert(nir_intrinsic_component(intr) == 0 && "not yet scalarized"); - b->cursor = nir_before_instr(&intr->instr); - - nir_def *pos = intr->src[0].ssa; - nir_def *z = nir_channel(b, pos, 2); - nir_def *w = nir_channel(b, pos, 3); - nir_def *c = nir_load_clip_z_coeff_agx(b); - - /* Lerp. If c = 0, reduces to z. If c = 1/2, reduces to (z + w)/2 */ - nir_def *new_z = nir_ffma(b, nir_fneg(b, z), c, nir_ffma(b, w, c, z)); - nir_src_rewrite(&intr->src[0], nir_vector_insert_imm(b, pos, new_z, 2)); - return true; -} - /* * To implement point sprites, we'll replace TEX0...7 with point coordinate * reads as required. However, the .zw needs to read back 0.0/1.0. This pass @@ -1560,8 +1536,7 @@ agx_compile_variant(struct agx_device *dev, struct pipe_context *pctx, if (key->hw) { NIR_PASS(_, nir, agx_nir_lower_point_size, true); - NIR_PASS(_, nir, nir_shader_intrinsics_pass, agx_nir_lower_clip_m1_1, - nir_metadata_control_flow, NULL); + NIR_PASS(_, nir, nir_lower_clip_halfz_dynamic); NIR_PASS(_, nir, nir_lower_io_to_scalar, nir_var_shader_out, NULL, NULL); @@ -1661,8 +1636,7 @@ agx_compile_variant(struct agx_device *dev, struct pipe_context *pctx, */ NIR_PASS(_, gs_copy, agx_nir_lower_point_size, false); - NIR_PASS(_, gs_copy, nir_shader_intrinsics_pass, agx_nir_lower_clip_m1_1, - nir_metadata_control_flow, NULL); + NIR_PASS(_, gs_copy, nir_lower_clip_halfz_dynamic); NIR_PASS(_, gs_copy, nir_lower_io_to_scalar, nir_var_shader_out, NULL, NULL);