diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-31 10:17:49 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-11-01 11:09:54 -0500 |
| commit | 27cf4285e0541afb2d3eb78cf51958665366a4aa (patch) | |
| tree | 7e81c36319288277eb09bf78e6f1d3fa2652d56b /src | |
| parent | b0043b6065abf1949558f9bd6cc0826c76a28f07 (diff) | |
nx2: lower TLD4 with a texel offset
Bit 76 puts a texel offset after the coordinates, as for TEX: x and y in Ra, Ra+1
and the offsets in Rb. Maxwell TLD4 takes it as AOFFI (bits 54-55) from Rb.
Diffstat (limited to 'src')
| -rw-r--r-- | src/shader_recompiler/frontend/ampere/lower_to_maxwell.h | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h index d9c52522f3..5436b50d39 100644 --- a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h +++ b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h @@ -1649,26 +1649,35 @@ inline LoweredProgram LowerToMaxwellWith(std::span<const Instruction> code, u32 const u32 mask = insn.Bits(72, 4), second_dest = insn.Bits(64, 8); const u32 source_a = insn.Bits(24, 8), source_b = insn.Bits(32, 8); const u32 binding = insn.Bits(54, 5); - if (insn.Bits(61, 3) != 1 || insn.Bits(76, 4) || insn.Bits(81, 3) != 7 || insn.Bits(59, 1) || + // Bit 76: a texel offset after the coordinates (x, y in Ra, Ra+1, offsets in Rb, as + // for TEX); Maxwell TLD4 takes it as AOFFI (bits 54-55) from Rb. + const bool offsets = insn.Bits(76, 1) != 0; + if (insn.Bits(61, 3) != 1 || insn.Bits(77, 3) || insn.Bits(81, 3) != 7 || insn.Bits(59, 1) || + (offsets && (bindless || source_b == 255 || (source_a != 255 && source_a >= 245))) || insn.Bits(89, 1) || mask == 0 || (bindless ? (handle >= 246 || insn.Bits(46, 13) || !insn.Bits(91, 1)) : (insn.Bits(40, 14) > 0x1fff || binding >= 18 || (result.required_texture_buffer != ~0U && result.required_texture_buffer != binding)))) return fail(index, "native texture gather mode"); if (!bindless) result.required_texture_buffer = binding; - // Two coordinates: x in Ra, y in Rb (the coordinate list splits evenly across them). + // Two coordinates: x in Ra, y in Rb (the coordinate list splits evenly across them); + // with an offset, x and y in Ra, Ra+1 and the offset in Rb. + const u32 y = !offsets ? source_b : source_a == 255 ? 255U : source_a + 1; emit(0x5c98000000000000ULL | predicate | 250 | (u64{15} << 39) | (u64{source_a} << 20)); - emit(0x5c98000000000000ULL | predicate | 251 | (u64{15} << 39) | - (u64{source_b == 255 ? 255U : source_b} << 20)); + emit(0x5c98000000000000ULL | predicate | 251 | (u64{15} << 39) | (u64{y} << 20)); + if (offsets) { + emit(0x5c98000000000000ULL | predicate | 246 | (u64{15} << 39) | (u64{source_b} << 20)); + } if (bindless) { emit(0x5c98000000000000ULL | predicate | 246 | (u64{15} << 39) | (u64{handle} << 20)); emit(0xdec0000000000000ULL | predicate | 250 | (u64{250} << 8) | (u64{246} << 20) | (u64{2} << 28) | (u64{mask} << 31) | (u64{insn.Bits(87, 2)} << 38) | (u64{insn.Bits(90, 1)} << 49) | (u64{7} << 51)); } else { - emit(0xc800000000000000ULL | predicate | 250 | (u64{250} << 8) | (u64{255} << 20) | - (u64{2} << 28) | (u64{mask} << 31) | (u64{insn.Bits(40, 14)} << 36) | - (u64{insn.Bits(90, 1)} << 49) | (u64{7} << 51) | (u64{insn.Bits(87, 2)} << 56)); + emit(0xc800000000000000ULL | predicate | 250 | (u64{250} << 8) | + (u64{offsets ? 246U : 255U} << 20) | (u64{2} << 28) | (u64{mask} << 31) | + (u64{insn.Bits(40, 14)} << 36) | (u64{insn.Bits(90, 1)} << 49) | (u64{7} << 51) | + (u64{offsets ? 1U : 0U} << 54) | (u64{insn.Bits(87, 2)} << 56)); } const u32 components = static_cast<u32>(std::popcount(mask)); const bool split = second_dest != 255; |
