diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 507606b2af4..8afb148437b 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -3081,15 +3081,8 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex) if (tex->is_shadow && tex->op != nir_texop_lod) src0[nsrc0++] = compare; - if (tex->is_array && tex->op != nir_texop_lod) { - struct ir3_instruction *idx = coord[coords]; - - /* the array coord for cube arrays needs 0.5 added to it */ - if (ctx->compiler->array_index_add_half && !is_isam(opc)) - idx = ir3_ADD_F(b, idx, 0, create_immed(b, fui(0.5)), 0); - - src0[nsrc0++] = idx; - } + if (tex->is_array && tex->op != nir_texop_lod) + src0[nsrc0++] = coord[coords]; if (has_proj) { src0[nsrc0++] = proj; diff --git a/src/freedreno/ir3/ir3_nir.c b/src/freedreno/ir3/ir3_nir.c index 5bc960dc16b..31077a9cc95 100644 --- a/src/freedreno/ir3/ir3_nir.c +++ b/src/freedreno/ir3/ir3_nir.c @@ -264,6 +264,45 @@ ir3_nir_lower_io_to_temporaries(nir_shader *s) NIR_PASS_V(s, nir_lower_indirect_derefs, 0, UINT32_MAX); } +/** + * Inserts an add of 0.5 to floating point array index values in texture coordinates. + */ +static bool +ir3_nir_lower_array_sampler_cb(struct nir_builder *b, nir_instr *instr, void *_data) +{ + if (instr->type != nir_instr_type_tex) + return false; + + nir_tex_instr *tex = nir_instr_as_tex(instr); + if (!tex->is_array || tex->op == nir_texop_lod) + return false; + + int coord_idx = nir_tex_instr_src_index(tex, nir_tex_src_coord); + if (coord_idx == -1 || + nir_tex_instr_src_type(tex, coord_idx) != nir_type_float) + return false; + + b->cursor = nir_before_instr(&tex->instr); + + unsigned ncomp = tex->coord_components; + nir_ssa_def *src = nir_ssa_for_src(b, tex->src[coord_idx].src, ncomp); + + assume(ncomp >= 1); + nir_ssa_def *ai = nir_channel(b, src, ncomp - 1); + ai = nir_fadd(b, ai, nir_imm_floatN_t(b, 0.5, src->bit_size)); + nir_instr_rewrite_src(&tex->instr, &tex->src[coord_idx].src, + nir_src_for_ssa(nir_vector_insert_imm(b, src, ai, ncomp - 1))); + return true; +} + +static bool +ir3_nir_lower_array_sampler(nir_shader *shader) +{ + return nir_shader_instructions_pass( + shader, ir3_nir_lower_array_sampler_cb, + nir_metadata_block_index | nir_metadata_dominance, NULL); +} + void ir3_finalize_nir(struct ir3_compiler *compiler, nir_shader *s) { @@ -298,6 +337,9 @@ ir3_finalize_nir(struct ir3_compiler *compiler, nir_shader *s) OPT_V(s, nir_lower_tex, &tex_options); OPT_V(s, nir_lower_load_const_to_scalar); + if (compiler->array_index_add_half) + OPT_V(s, ir3_nir_lower_array_sampler); + ir3_optimize_loop(compiler, s); /* do idiv lowering after first opt loop to get a chance to propagate