diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index da5c82c6ee1..db75f756b02 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5480,6 +5480,7 @@ typedef struct nir_input_attachment_options { bool use_fragcoord_sysval; bool use_layer_id_sysval; bool use_view_id_for_layer; + uint32_t unscaled_input_attachment_ir3; } nir_input_attachment_options; bool nir_lower_input_attachments(nir_shader *shader, diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 57645cb9840..18763e1c2e3 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -1193,6 +1193,10 @@ system_value("rel_patch_id_ir3", 1) # System values for freedreno compute shaders. system_value("subgroup_id_shift_ir3", 1) +# System values for freedreno fragment shaders. +intrinsic("load_frag_coord_unscaled_ir3", dest_comp=4, + flags=[CAN_ELIMINATE, CAN_REORDER], bit_sizes=[32]) + # IR3-specific intrinsics for tessellation control shaders. cond_end_ir3 end # the shader when src0 is false and is used to narrow down the TCS shader to # just thread 0 before writing out tessellation levels. diff --git a/src/compiler/nir/nir_lower_input_attachments.c b/src/compiler/nir/nir_lower_input_attachments.c index fb168df879e..40a0ecf885c 100644 --- a/src/compiler/nir/nir_lower_input_attachments.c +++ b/src/compiler/nir/nir_lower_input_attachments.c @@ -25,10 +25,30 @@ #include "nir_builder.h" static nir_ssa_def * -load_frag_coord(nir_builder *b, const nir_input_attachment_options *options) +load_frag_coord(nir_builder *b, nir_deref_instr *deref, + const nir_input_attachment_options *options) { - if (options->use_fragcoord_sysval) - return nir_load_frag_coord(b); + if (options->use_fragcoord_sysval) { + nir_ssa_def *frag_coord = nir_load_frag_coord(b); + if (options->unscaled_input_attachment_ir3) { + nir_variable *var = nir_deref_instr_get_variable(deref); + unsigned base = var->data.index; + nir_ssa_def *unscaled_frag_coord = nir_load_frag_coord_unscaled_ir3(b); + if (deref->deref_type == nir_deref_type_array) { + nir_ssa_def *unscaled = + nir_i2b(b, nir_iand(b, nir_ishr(b, + nir_imm_int(b, options->unscaled_input_attachment_ir3 >> base), + deref->arr.index.ssa), + nir_imm_int(b, 1))); + frag_coord = nir_bcsel(b, unscaled, unscaled_frag_coord, frag_coord); + } else { + assert(deref->deref_type == nir_deref_type_var); + bool unscaled = (options->unscaled_input_attachment_ir3 >> base) & 1; + frag_coord = unscaled ? unscaled_frag_coord : frag_coord; + } + } + return frag_coord; + } nir_variable *pos = nir_find_variable_with_location(b->shader, nir_var_shader_in, @@ -92,7 +112,7 @@ try_lower_input_load(nir_builder *b, nir_intrinsic_instr *load, b->cursor = nir_instr_remove(&load->instr); - nir_ssa_def *frag_coord = load_frag_coord(b, options); + nir_ssa_def *frag_coord = load_frag_coord(b, deref, options); frag_coord = nir_f2i32(b, frag_coord); nir_ssa_def *offset = nir_ssa_for_src(b, load->src[1], 2); nir_ssa_def *pos = nir_iadd(b, frag_coord, offset); @@ -162,7 +182,7 @@ try_lower_input_texop(nir_builder *b, nir_tex_instr *tex, b->cursor = nir_before_instr(&tex->instr); - nir_ssa_def *frag_coord = load_frag_coord(b, options); + nir_ssa_def *frag_coord = load_frag_coord(b, deref, options); frag_coord = nir_f2i32(b, frag_coord); nir_ssa_def *layer = load_layer_id(b, options); diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index ea383b05ca5..9d573a47f5e 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -2092,6 +2092,7 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr) emit_intrinsic_copy_ubo_to_uniform(ctx, intr); break; case nir_intrinsic_load_frag_coord: + case nir_intrinsic_load_frag_coord_unscaled_ir3: ir3_split_dest(b, dst, get_frag_coord(ctx, intr), 0, 4); break; case nir_intrinsic_load_sample_pos_from_id: {