agx: Plumb through nir_op_txf

nir_op_txf maps to AGX's texture_load, which is encoded like
texture_sample. The one outstanding question with this commit is the
rules for the sample required ... in NIR and APIs (including Metal), txf
is samplerless, but the AGX instruction consumes a sampler. Hopefully
any sampler will do, though?

Passes dEQP-GLES3.functional.shaders.texture_functions.texelfetch.*

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18380>
This commit is contained in:
Alyssa Rosenzweig
2022-09-03 15:31:15 -04:00
committed by Marge Bot
parent 44d79d39b6
commit 10c9aceadf
4 changed files with 27 additions and 7 deletions

View File

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

View File

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

View File

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

View File

@@ -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 */