diff --git a/src/compiler/nir/nir_builder.c b/src/compiler/nir/nir_builder.c index 3c6be2d513e..7098b360faa 100644 --- a/src/compiler/nir/nir_builder.c +++ b/src/compiler/nir/nir_builder.c @@ -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); + } +} diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index d825bf78473..02e2dc683d6 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -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); diff --git a/src/compiler/nir/nir_lower_system_values.c b/src/compiler/nir/nir_lower_system_values.c index 489f504c1b9..34061abe689 100644 --- a/src/compiler/nir/nir_lower_system_values.c +++ b/src/compiler/nir/nir_lower_system_values.c @@ -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; } diff --git a/src/compiler/nir/nir_shader_compiler_options.h b/src/compiler/nir/nir_shader_compiler_options.h index 9efb3f8a985..9d76a6f524d 100644 --- a/src/compiler/nir/nir_shader_compiler_options.h +++ b/src/compiler/nir/nir_shader_compiler_options.h @@ -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; diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c index f4e777d6fa9..a38543707b5 100644 --- a/src/gallium/auxiliary/nir/tgsi_to_nir.c +++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c @@ -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);