ir3: Split out bindless tex/samp encoding

It will be used with prefetching, which is an intrinsic.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29873>
This commit is contained in:
Connor Abbott 2024-06-24 07:25:44 -04:00 committed by Marge Bot
parent ccf88d940b
commit fa8758fc81

View file

@ -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);