diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c index 4f8209e5d76..0d40b02f5e1 100644 --- a/src/panfrost/bifrost/bifrost_compile.c +++ b/src/panfrost/bifrost/bifrost_compile.c @@ -3160,6 +3160,171 @@ enum bifrost_tex_dreg { BIFROST_TEX_DREG_COUNT, }; +static void +bi_emit_texc(bi_builder *b, nir_tex_instr *instr) +{ + /* TODO: support more with other encodings */ + assert(instr->sampler_index < 16); + + /* TODO: support more ops */ + switch (instr->op) { + case nir_texop_tex: + case nir_texop_txl: + case nir_texop_txb: + case nir_texop_txf: + case nir_texop_txf_ms: + break; + default: + unreachable("Unsupported texture op"); + } + + struct bifrost_texture_operation desc = { + .sampler_index_or_mode = instr->sampler_index, + .index = instr->texture_index, + .immediate_indices = 1, /* TODO */ + .op = bi_tex_op(instr->op), + .offset_or_bias_disable = false, /* TODO */ + .shadow_or_clamp_disable = instr->is_shadow, + .array = instr->is_array, + .dimension = bifrost_tex_format(instr->sampler_dim), + .format = bi_texture_format(instr->dest_type | nir_dest_bit_size(instr->dest), BI_CLAMP_NONE), /* TODO */ + .mask = 0xF, + }; + + switch (desc.op) { + case BIFROST_TEX_OP_TEX: + desc.lod_or_fetch = BIFROST_LOD_MODE_COMPUTE; + break; + case BIFROST_TEX_OP_FETCH: + /* TODO: gathers */ + desc.lod_or_fetch = BIFROST_TEXTURE_FETCH_TEXEL; + break; + default: + unreachable("texture op unsupported"); + } + + /* 32-bit indices to be allocated as consecutive staging registers */ + bi_index dregs[BIFROST_TEX_DREG_COUNT] = { }; + bi_index cx = bi_null(), cy = bi_null(); + + for (unsigned i = 0; i < instr->num_srcs; ++i) { + bi_index index = bi_src_index(&instr->src[i].src); + unsigned sz = nir_src_bit_size(instr->src[i].src); + ASSERTED nir_alu_type base = nir_tex_instr_src_type(instr, i); + nir_alu_type T = base | sz; + + switch (instr->src[i].src_type) { + case nir_tex_src_coord: + if (instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE) { + cx = bi_emit_texc_cube_coord(b, index, &cy); + } else { + unsigned components = nir_src_num_components(instr->src[i].src); + + /* Copy XY (for 2D+) or XX (for 1D) */ + cx = index; + cy = bi_word(index, MIN2(1, components - 1)); + + assert(components >= 1 && components <= 3); + + if (components < 3) { + /* nothing to do */ + } else if (desc.array) { + /* 2D array */ + dregs[BIFROST_TEX_DREG_ARRAY] = + bi_emit_texc_array_index(b, + bi_word(index, 2), T); + } else { + /* 3D */ + dregs[BIFROST_TEX_DREG_Z_COORD] = + bi_word(index, 2); + } + } + break; + + case nir_tex_src_lod: + if (desc.op == BIFROST_TEX_OP_TEX && + nir_src_is_const(instr->src[i].src) && + nir_src_as_uint(instr->src[i].src) == 0) { + desc.lod_or_fetch = BIFROST_LOD_MODE_ZERO; + } else if (desc.op == BIFROST_TEX_OP_TEX) { + assert(base == nir_type_float); + + assert(sz == 16 || sz == 32); + dregs[BIFROST_TEX_DREG_LOD] = + bi_emit_texc_lod_88(b, index, sz == 16); + desc.lod_or_fetch = BIFROST_LOD_MODE_EXPLICIT; + } else { + assert(desc.op == BIFROST_TEX_OP_FETCH); + assert(base == nir_type_uint || base == nir_type_int); + assert(sz == 16 || sz == 32); + + dregs[BIFROST_TEX_DREG_LOD] = + bi_emit_texc_lod_cube(b, index); + } + + break; + + case nir_tex_src_bias: + /* Upper 16-bits interpreted as a clamp, leave zero */ + assert(desc.op == BIFROST_TEX_OP_TEX); + assert(base == nir_type_float); + assert(sz == 16 || sz == 32); + dregs[BIFROST_TEX_DREG_LOD] = + bi_emit_texc_lod_88(b, index, sz == 16); + desc.lod_or_fetch = BIFROST_LOD_MODE_BIAS; + break; + + case nir_tex_src_ms_index: + case nir_tex_src_offset: + if (desc.offset_or_bias_disable) + break; + + dregs[BIFROST_TEX_DREG_OFFSETMS] = + bi_emit_texc_offset_ms_index(b, instr); + if (!bi_is_equiv(dregs[BIFROST_TEX_DREG_OFFSETMS], bi_zero())) + desc.offset_or_bias_disable = true; + break; + + case nir_tex_src_comparator: + dregs[BIFROST_TEX_DREG_SHADOW] = index; + break; + + default: + unreachable("Unhandled src type in texc emit"); + } + } + + if (desc.op == BIFROST_TEX_OP_FETCH && bi_is_null(dregs[BIFROST_TEX_DREG_LOD])) { + dregs[BIFROST_TEX_DREG_LOD] = + bi_emit_texc_lod_cube(b, bi_zero()); + } + + /* Allocate staging registers contiguously by compacting the array. + * Index is not SSA (tied operands) */ + + bi_index idx = bi_temp_reg(b->shader); + unsigned sr_count = 0; + + for (unsigned i = 0; i < ARRAY_SIZE(dregs); ++i) { + if (!bi_is_null(dregs[i])) + dregs[sr_count++] = dregs[i]; + } + + if (sr_count) + bi_make_vec_to(b, idx, dregs, NULL, sr_count, 32); + else + bi_mov_i32_to(b, idx, bi_zero()); /* XXX: shouldn't be necessary */ + + uint32_t desc_u = 0; + memcpy(&desc_u, &desc, sizeof(desc_u)); + bi_texc_to(b, idx, idx, cx, cy, bi_imm_u32(desc_u), sr_count); + + /* Explicit copy to facilitate tied operands */ + bi_index srcs[4] = { idx, idx, idx, idx }; + unsigned channels[4] = { 0, 1, 2, 3 }; + bi_make_vec_to(b, bi_dest_index(&instr->dest), srcs, channels, 4, 32); +} + static void emit_texc(bi_context *ctx, nir_tex_instr *instr) {