diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 68cf0544521..18a0ad1a1fc 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -970,6 +970,7 @@ agx_lod_mode_for_nir(nir_texop op) case nir_texop_tex: return AGX_LOD_MODE_AUTO_LOD; case nir_texop_txb: return AGX_LOD_MODE_AUTO_LOD_BIAS; case nir_texop_txl: return AGX_LOD_MODE_LOD_MIN; + case nir_texop_txf: return AGX_LOD_MODE_LOD_MIN; default: unreachable("Unhandled texture op"); } } @@ -979,6 +980,7 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) { switch (instr->op) { case nir_texop_tex: + case nir_texop_txf: case nir_texop_txl: case nir_texop_txb: break; @@ -992,6 +994,8 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) lod = agx_immediate(0), offset = agx_null(); + bool txf = instr->op == nir_texop_txf; + for (unsigned i = 0; i < instr->num_srcs; ++i) { agx_index index = agx_src_index(&instr->src[i].src); @@ -1008,6 +1012,9 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) * max(0, min(d - 1, floor(layer + 0.5))) = * max(0, min(d - 1, f32_to_u32(layer + 0.5))) = * min(d - 1, f32_to_u32(layer + 0.5)) + * + * For txf, the coordinates are already integers, so we only need to + * clamp (not convert). */ if (instr->is_array) { unsigned nr = nir_src_num_components(instr->src[i].src); @@ -1016,15 +1023,18 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) for (unsigned i = 0; i < nr; ++i) channels[i] = agx_emit_extract(b, index, i); - agx_index layer = agx_fadd(b, channels[nr - 1], - agx_immediate_f(0.5f)); - agx_index d1 = agx_indexed_sysval(b->shader, AGX_PUSH_ARRAY_SIZE_MINUS_1, AGX_SIZE_16, instr->texture_index, 1); - layer = agx_convert(b, agx_immediate(AGX_CONVERT_F_TO_U32), layer, - AGX_ROUND_RTZ); + agx_index layer = channels[nr - 1]; + + if (!txf) { + layer = agx_fadd(b, channels[nr - 1], agx_immediate_f(0.5f)); + + layer = agx_convert(b, agx_immediate(AGX_CONVERT_F_TO_U32), layer, + AGX_ROUND_RTZ); + } agx_index layer16 = agx_temp(b->shader, AGX_SIZE_16); agx_mov_to(b, layer16, layer); @@ -1058,12 +1068,16 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) } agx_index dst = agx_dest_index(&instr->dest); - agx_texture_sample_to(b, dst, coords, lod, texture, sampler, offset, + + agx_instr *I = agx_texture_sample_to(b, dst, coords, lod, texture, sampler, offset, agx_tex_dim(instr->sampler_dim, instr->is_array), agx_lod_mode_for_nir(instr->op), 0xF, /* TODO: wrmask */ 0); + if (txf) + I->op = AGX_OPCODE_TEXTURE_LOAD; + agx_wait(b, 0); agx_emit_cached_split(b, dst, 4); } diff --git a/src/asahi/compiler/agx_opcodes.py b/src/asahi/compiler/agx_opcodes.py index 6592afb52d5..7774866d687 100644 --- a/src/asahi/compiler/agx_opcodes.py +++ b/src/asahi/compiler/agx_opcodes.py @@ -194,7 +194,10 @@ op("fcmpsel", # sources are coordinates, LOD, texture, sampler, offset # TODO: anything else? op("texture_sample", - encoding_32 = (0x32, 0x7F, 8, 10), # XXX WRONG SIZE + encoding_32 = (0x31, 0x7F, 8, 10), # XXX WRONG SIZE + srcs = 5, imms = [DIM, LOD_MODE, MASK, SCOREBOARD]) +op("texture_load", + encoding_32 = (0x71, 0x7F, 8, 10), # XXX WRONG SIZE srcs = 5, imms = [DIM, LOD_MODE, MASK, SCOREBOARD]) # sources are base, index diff --git a/src/asahi/compiler/agx_pack.c b/src/asahi/compiler/agx_pack.c index 65b93143ffd..69637ba0ac0 100644 --- a/src/asahi/compiler/agx_pack.c +++ b/src/asahi/compiler/agx_pack.c @@ -570,6 +570,7 @@ agx_pack_instr(struct util_dynarray *emission, struct util_dynarray *fixups, agx break; } + case AGX_OPCODE_TEXTURE_LOAD: case AGX_OPCODE_TEXTURE_SAMPLE: { assert(I->mask != 0); @@ -611,6 +612,7 @@ agx_pack_instr(struct util_dynarray *emission, struct util_dynarray *fixups, agx uint64_t raw = 0x31 | + ((I->op == AGX_OPCODE_TEXTURE_LOAD) ? (1 << 6) : 0) | (Rt ? (1 << 8) : 0) | ((R & BITFIELD_MASK(6)) << 9) | (L ? (1 << 15) : 0) | diff --git a/src/asahi/compiler/agx_register_allocate.c b/src/asahi/compiler/agx_register_allocate.c index b31363f368c..0d4950f806e 100644 --- a/src/asahi/compiler/agx_register_allocate.c +++ b/src/asahi/compiler/agx_register_allocate.c @@ -38,6 +38,7 @@ agx_write_registers(agx_instr *I, unsigned d) return I->channels * size; case AGX_OPCODE_DEVICE_LOAD: + case AGX_OPCODE_TEXTURE_LOAD: case AGX_OPCODE_TEXTURE_SAMPLE: case AGX_OPCODE_LD_TILE: /* TODO: mask */