aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-31 10:17:49 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 11:09:54 -0500
commit27cf4285e0541afb2d3eb78cf51958665366a4aa (patch)
tree7e81c36319288277eb09bf78e6f1d3fa2652d56b /src
parentb0043b6065abf1949558f9bd6cc0826c76a28f07 (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.h23
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;