diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 381a9f901c8..f7d475d0497 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5711,6 +5711,7 @@ typedef struct nir_lower_idiv_options { bool nir_lower_idiv(nir_shader *shader, const nir_lower_idiv_options *options); typedef struct nir_input_attachment_options { + bool use_ia_coord_intrin; bool use_fragcoord_sysval; bool use_layer_id_sysval; bool use_view_id_for_layer; diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 0b2ecb37d80..1f411a7f26b 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -782,6 +782,7 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) case nir_intrinsic_load_barycentric_coord_at_sample: case nir_intrinsic_load_barycentric_coord_at_offset: case nir_intrinsic_load_persp_center_rhw_ir3: + case nir_intrinsic_load_input_attachment_coord: case nir_intrinsic_interp_deref_at_offset: case nir_intrinsic_interp_deref_at_sample: case nir_intrinsic_interp_deref_at_centroid: diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 813cbf06d1b..ad2f1bc3e6d 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -1125,6 +1125,13 @@ barycentric("coord_at_offset", 3, [2]) intrinsic("load_sample_pos_from_id", src_comp=[1], dest_comp=2, flags=[CAN_ELIMINATE, CAN_REORDER]) +# Load input attachment coordinate: +# +# Takes an input attachment index and returns an ivec with the position in +# input attachment space in .xy and the input attachment array index in .z. +intrinsic("load_input_attachment_coord", src_comp=[1], dest_comp=3, + bit_sizes=[32], flags=[CAN_ELIMINATE, CAN_REORDER]) + # Demote a subset of samples given by a specified sample mask. This acts like a # per-sample demote, or an inverted accumulating gl_SampleMask write. intrinsic("demote_samples", src_comp=[1]) diff --git a/src/compiler/nir/nir_lower_input_attachments.c b/src/compiler/nir/nir_lower_input_attachments.c index b4cd7f7ad23..dd10a6839b8 100644 --- a/src/compiler/nir/nir_lower_input_attachments.c +++ b/src/compiler/nir/nir_lower_input_attachments.c @@ -83,6 +83,29 @@ load_layer_id(nir_builder *b, const nir_input_attachment_options *options) return nir_load_var(b, layer_id); } +static nir_def * +load_coord(nir_builder *b, nir_deref_instr *deref, + const nir_input_attachment_options *options) +{ + if (options->use_ia_coord_intrin) { + nir_def *index; + if (deref->deref_type == nir_deref_type_array) { + ASSERTED nir_deref_instr *parent = nir_deref_instr_parent(deref); + assert(parent->deref_type == nir_deref_type_var); + index = deref->arr.index.ssa; + } else { + assert(deref->deref_type == nir_deref_type_var); + index = nir_imm_int(b, 0); + } + + return nir_load_input_attachment_coord(b, index); + } else { + nir_def *pos = nir_f2i32(b, load_frag_coord(b, deref, options)); + nir_def *layer = load_layer_id(b, options); + return nir_vec3(b, nir_channel(b, pos, 0), nir_channel(b, pos, 1), layer); + } +} + static bool try_lower_input_load(nir_builder *b, nir_intrinsic_instr *load, const nir_input_attachment_options *options) @@ -99,14 +122,10 @@ try_lower_input_load(nir_builder *b, nir_intrinsic_instr *load, b->cursor = nir_instr_remove(&load->instr); - nir_def *frag_coord = load_frag_coord(b, deref, options); - frag_coord = nir_f2i32(b, frag_coord); - nir_def *offset = nir_trim_vector(b, load->src[1].ssa, 2); - nir_def *pos = nir_iadd(b, frag_coord, offset); - - nir_def *layer = load_layer_id(b, options); - nir_def *coord = - nir_vec3(b, nir_channel(b, pos, 0), nir_channel(b, pos, 1), layer); + nir_def *offset = nir_vec3(b, nir_channel(b, load->src[1].ssa, 0), + nir_channel(b, load->src[1].ssa, 1), + nir_imm_int(b, 0)); + nir_def *coord = nir_iadd(b, load_coord(b, deref, options), offset); nir_tex_instr *tex = nir_tex_instr_create(b->shader, 3 + multisampled); @@ -174,15 +193,11 @@ try_lower_input_texop(nir_builder *b, nir_tex_instr *tex, b->cursor = nir_before_instr(&tex->instr); - nir_def *frag_coord = load_frag_coord(b, deref, options); - frag_coord = nir_f2i32(b, frag_coord); - - nir_def *offset = nir_trim_vector(b, tex->src[coord_src_idx].src.ssa, 2); - nir_def *pos = nir_iadd(b, frag_coord, offset); - - nir_def *layer = load_layer_id(b, options); - nir_def *coord = nir_vec3(b, nir_channel(b, pos, 0), - nir_channel(b, pos, 1), layer); + nir_def *offset = tex->src[coord_src_idx].src.ssa; + offset = nir_vec3(b, nir_channel(b, offset, 0), + nir_channel(b, offset, 1), + nir_imm_int(b, 0)); + nir_def *coord = nir_iadd(b, load_coord(b, deref, options), offset); tex->coord_components = 3;