nir: add direct lowered frag_coord building to replace lowering passes

Instead of lowering frag_coord 4 times during compilation,
just use this.

Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Reviewed-by: Emma Anholt <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41227>
This commit is contained in:
Marek Olšák 2026-04-29 05:46:21 -04:00 committed by Marge Bot
parent 9c5ad16819
commit b63a9a8b39
5 changed files with 56 additions and 1 deletions

View file

@ -790,3 +790,40 @@ nir_call_serialized(nir_builder *b, const uint32_t *serialized,
ralloc_free(memctx);
return ret;
}
/* Build frag_coord according to NIR options. This should generate the final
* lowered form expected by drivers.
*
* The purpose of "num_components" is to generate less dead code for the split
* form if some components are not needed.
*/
nir_def *
nir_build_frag_coord(nir_builder *b, unsigned num_components)
{
assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
assert(num_components && num_components <= 4);
if (b->shader->options->frag_coord_form >= nir_frag_coord_xy_z_w_separate) {
nir_def *xy = nir_load_frag_coord_xy(b);
if (num_components <= 2)
return nir_trim_vector(b, xy, num_components);
nir_def *z = nir_load_frag_coord_z(b);
if (num_components == 3)
return nir_vec3(b, nir_channel(b, xy, 0), nir_channel(b, xy, 1), z);
nir_def *w;
if (b->shader->options->frag_coord_form ==
nir_frag_coord_xy_z_w_rcp_separate)
w = nir_frcp(b, nir_load_frag_coord_w_rcp(b));
else
w = nir_load_frag_coord_w(b);
return nir_vec4(b, nir_channel(b, xy, 0), nir_channel(b, xy, 1), z, w);
} else {
return nir_trim_vector(b, nir_load_frag_coord(b), num_components);
}
}

View file

@ -2347,6 +2347,9 @@ nir_inverse_ballot_imm(nir_builder *build, uint64_t imm, unsigned bit_size)
return nir_inverse_ballot(build, nir_imm_intN_t(build, imm, bit_size));
}
nir_def *
nir_build_frag_coord(nir_builder *b, unsigned num_components);
nir_def *
nir_build_string(nir_builder *build, const char *value);

View file

@ -299,6 +299,9 @@ lower_system_value_instr(nir_builder *b, nir_instr *instr, void *_state)
bit_size, column, .base = 0,
.range = intrin->def.num_components * bit_size / 8);
case SYSTEM_VALUE_FRAG_COORD:
return nir_build_frag_coord(b, 4);
default:
break;
}

View file

@ -243,6 +243,15 @@ typedef enum {
nir_lower_packing_num_ops,
} nir_lower_packing_op;
typedef enum {
/* Build: frag_coord */
nir_frag_coord_regular,
/* Build: frag_coord_xy, frag_coord_z, frag_coord_w */
nir_frag_coord_xy_z_w_separate,
/* Build: frag_coord_xy, frag_coord_z, frcp(frag_coord_w_rcp) */
nir_frag_coord_xy_z_w_rcp_separate,
} nir_frag_coord_form;
typedef struct nir_shader_compiler_options {
bool lower_fdiv;
bool lower_ffma16;
@ -803,6 +812,9 @@ typedef struct nir_shader_compiler_options {
/** Lower VARYING_SLOT_LAYER in FS to SYSTEM_VALUE_LAYER_ID. */
bool lower_layer_fs_input_to_sysval;
/** How nir_build_frag_coord generates frag_coord. */
nir_frag_coord_form frag_coord_form;
/** clip/cull distance and tess level arrays use compact semantics */
bool compact_arrays;

View file

@ -604,7 +604,7 @@ ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,
break;
case TGSI_SEMANTIC_POSITION:
assert(c->cap_position_is_sysval);
load = nir_load_frag_coord(b);
load = nir_build_frag_coord(b, 4);
break;
case TGSI_SEMANTIC_PCOORD:
assert(c->cap_point_is_sysval);