diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index b052a2bd638..d9c94982010 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -1647,6 +1647,105 @@ emit_intrinsic_image_size_tex(struct ir3_context *ctx, } } +static struct tex_src_info +get_bindless_samp_src(struct ir3_context *ctx, nir_src *tex, + nir_src *samp) +{ + struct ir3_block *b = ctx->block; + struct tex_src_info info = {0}; + + info.flags |= IR3_INSTR_B; + + /* Gather information required to determine which encoding to + * choose as well as for prefetch. + */ + nir_intrinsic_instr *bindless_tex = NULL; + bool tex_const; + if (tex) { + ctx->so->bindless_tex = true; + bindless_tex = ir3_bindless_resource(*tex); + assert(bindless_tex); + info.tex_base = nir_intrinsic_desc_set(bindless_tex); + tex_const = nir_src_is_const(bindless_tex->src[0]); + if (tex_const) + info.tex_idx = nir_src_as_uint(bindless_tex->src[0]); + } else { + /* To simplify some of the logic below, assume the index is + * constant 0 when it's not enabled. + */ + tex_const = true; + info.tex_idx = 0; + } + nir_intrinsic_instr *bindless_samp = NULL; + bool samp_const; + if (samp) { + ctx->so->bindless_samp = true; + bindless_samp = ir3_bindless_resource(*samp); + assert(bindless_samp); + info.samp_base = nir_intrinsic_desc_set(bindless_samp); + samp_const = nir_src_is_const(bindless_samp->src[0]); + if (samp_const) + info.samp_idx = nir_src_as_uint(bindless_samp->src[0]); + } else { + samp_const = true; + info.samp_idx = 0; + } + + /* Choose encoding. */ + if (tex_const && samp_const && info.tex_idx < 256 && + info.samp_idx < 256) { + if (info.tex_idx < 16 && info.samp_idx < 16 && + (!bindless_tex || !bindless_samp || + info.tex_base == info.samp_base)) { + /* Everything fits within the instruction */ + info.base = info.tex_base; + } else { + info.base = info.tex_base; + if (ctx->compiler->gen <= 6) { + info.a1_val = info.tex_idx << 3 | info.samp_base; + } else { + info.a1_val = info.samp_idx << 3 | info.samp_base; + } + + info.flags |= IR3_INSTR_A1EN; + } + info.samp_tex = NULL; + } else { + info.flags |= IR3_INSTR_S2EN; + /* In the indirect case, we only use a1.x to store the sampler + * base if it differs from the texture base. + */ + if (!bindless_tex || !bindless_samp || + info.tex_base == info.samp_base) { + info.base = info.tex_base; + } else { + info.base = info.tex_base; + info.a1_val = info.samp_base; + info.flags |= IR3_INSTR_A1EN; + } + + /* Note: the indirect source is now a vec2 instead of hvec2, and + * for some reason the texture and sampler are swapped. + */ + struct ir3_instruction *texture, *sampler; + + if (bindless_tex) { + texture = ir3_get_src(ctx, tex)[0]; + } else { + texture = create_immed(b, 0); + } + + if (bindless_samp) { + sampler = ir3_get_src(ctx, samp)[0]; + } else { + sampler = create_immed(b, 0); + } + info.samp_tex = ir3_collect(b, texture, sampler); + } + + return info; +} + /* src[] = { buffer_index, offset }. No const_index */ static void emit_intrinsic_load_ssbo(struct ir3_context *ctx, @@ -3057,97 +3156,12 @@ get_tex_samp_tex_src(struct ir3_context *ctx, nir_tex_instr *tex) if (texture_idx >= 0 || sampler_idx >= 0) { /* Bindless case */ - info.flags |= IR3_INSTR_B; + info = get_bindless_samp_src(ctx, + texture_idx >= 0 ? &tex->src[texture_idx].src : NULL, + sampler_idx >= 0 ? &tex->src[sampler_idx].src : NULL); if (tex->texture_non_uniform || tex->sampler_non_uniform) info.flags |= IR3_INSTR_NONUNIF; - - /* Gather information required to determine which encoding to - * choose as well as for prefetch. - */ - nir_intrinsic_instr *bindless_tex = NULL; - bool tex_const; - if (texture_idx >= 0) { - ctx->so->bindless_tex = true; - bindless_tex = ir3_bindless_resource(tex->src[texture_idx].src); - assert(bindless_tex); - info.tex_base = nir_intrinsic_desc_set(bindless_tex); - tex_const = nir_src_is_const(bindless_tex->src[0]); - if (tex_const) - info.tex_idx = nir_src_as_uint(bindless_tex->src[0]); - } else { - /* To simplify some of the logic below, assume the index is - * constant 0 when it's not enabled. - */ - tex_const = true; - info.tex_idx = 0; - } - nir_intrinsic_instr *bindless_samp = NULL; - bool samp_const; - if (sampler_idx >= 0) { - ctx->so->bindless_samp = true; - bindless_samp = ir3_bindless_resource(tex->src[sampler_idx].src); - assert(bindless_samp); - info.samp_base = nir_intrinsic_desc_set(bindless_samp); - samp_const = nir_src_is_const(bindless_samp->src[0]); - if (samp_const) - info.samp_idx = nir_src_as_uint(bindless_samp->src[0]); - } else { - samp_const = true; - info.samp_idx = 0; - } - - /* Choose encoding. */ - if (tex_const && samp_const && info.tex_idx < 256 && - info.samp_idx < 256) { - if (info.tex_idx < 16 && info.samp_idx < 16 && - (!bindless_tex || !bindless_samp || - info.tex_base == info.samp_base)) { - /* Everything fits within the instruction */ - info.base = info.tex_base; - } else { - info.base = info.tex_base; - if (ctx->compiler->gen <= 6) { - info.a1_val = info.tex_idx << 3 | info.samp_base; - } else { - info.a1_val = info.samp_idx << 3 | info.samp_base; - } - - info.flags |= IR3_INSTR_A1EN; - } - info.samp_tex = NULL; - } else { - info.flags |= IR3_INSTR_S2EN; - /* In the indirect case, we only use a1.x to store the sampler - * base if it differs from the texture base. - */ - if (!bindless_tex || !bindless_samp || - info.tex_base == info.samp_base) { - info.base = info.tex_base; - } else { - info.base = info.tex_base; - info.a1_val = info.samp_base; - info.flags |= IR3_INSTR_A1EN; - } - - /* Note: the indirect source is now a vec2 instead of hvec2, and - * for some reason the texture and sampler are swapped. - */ - struct ir3_instruction *texture, *sampler; - - if (bindless_tex) { - texture = ir3_get_src(ctx, &tex->src[texture_idx].src)[0]; - } else { - texture = create_immed(b, 0); - } - - if (bindless_samp) { - sampler = ir3_get_src(ctx, &tex->src[sampler_idx].src)[0]; - } else { - sampler = create_immed(b, 0); - } - info.samp_tex = ir3_collect(b, texture, sampler); - } } else { info.flags |= IR3_INSTR_S2EN; texture_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_offset);