From b7d3c572c18d2cec2e0d22bc2411791b9b81b791 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 4 Oct 2026 22:29:05 +0400 Subject: [PATCH] shader: clear unused sampler bits after constant folding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Çağatay Güçlü <33038942+defektu@users.noreply.github.com> --- .../recompiler/ir/passes/ResourceTracking.cpp | 2 ++ tests/ResourceTrackingTests.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp b/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp index 1284aa6d6..c64ac4cee 100644 --- a/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp +++ b/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp @@ -77,6 +77,8 @@ Value CanonicalizeSampleAdjustDword3(Value value) { value = value.Resolve(); const auto* inst = value.TryInstruction(); if (inst == nullptr || inst->GetOpcode() != ValueOpcode::BitwiseOr32) { + if ((PossibleU32Bits(value) & ~SamplerDword3ReservedMask) == 0) + return Value(0u); return value; } const auto left = inst->Arg(0).Resolve(); diff --git a/tests/ResourceTrackingTests.cpp b/tests/ResourceTrackingTests.cpp index bf8a820dc..9a2e0c3ca 100644 --- a/tests/ResourceTrackingTests.cpp +++ b/tests/ResourceTrackingTests.cpp @@ -1890,6 +1890,13 @@ void TestSampleAdjustSamplerScratch() { fixture.Emit(ValueOpcode::ImageSampleRaw, {image, sampler, fixture.ImageAddress()}, fixture.AddMemory(memory, 0x1ec)); + // PPSA24156's zero border payload leaves the reserved scratch shift as + // the entire DWORD after the frontend folds its OR with zero. + const auto shift_sampler = fixture.Sampler( + {Value(0x36u), Value(0xfff000u), Value(0x02500000u), scratch}, 0x200); + fixture.Emit(ValueOpcode::ImageSampleRaw, + {image, shift_sampler, fixture.ImageAddress()}, + fixture.AddMemory(memory, 0x200)); fixture.PlanAndTrack(); const auto source = fixture.program.info.samplers[0].source; @@ -1905,6 +1912,12 @@ void TestSampleAdjustSamplerScratch() { Check(SrtWalker(fixture.program, runtime).EvaluateDescriptor(source, descriptor) && descriptor.dwords[3] == 0x80000abcu, "SampleAdjust canonicalization lost sampler border fields"); + const auto shift_source = fixture.program.info.samplers[ + shift_sampler.Instruction()->Flags()].source; + Check(SrtWalker(fixture.program, runtime).EvaluateDescriptor(shift_source, descriptor) && + std::ranges::equal(std::span(descriptor.dwords).first(4), + std::array{0x36u, 0xfff000u, 0x02500000u, 0u}), + "SampleAdjust shift-only scratch was not reduced to its zero border payload"); const auto CheckRejected = [](uint32_t flags, uint32_t shift, const char *message) {