From f3cdf217eab4d769776d892b5a5628664ff486fe Mon Sep 17 00:00:00 2001 From: nmzik Date: Sat, 15 Aug 2026 17:10:09 +0200 Subject: [PATCH] shader: evaluate unsigned min in runtime descriptors --- .../shader/recompiler/ir/passes/SrtWalker.cpp | 7 ++++ tests/ResourceTrackingTests.cpp | 34 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/graphics/shader/recompiler/ir/passes/SrtWalker.cpp b/src/graphics/shader/recompiler/ir/passes/SrtWalker.cpp index 8ffd61bba..05c08301c 100644 --- a/src/graphics/shader/recompiler/ir/passes/SrtWalker.cpp +++ b/src/graphics/shader/recompiler/ir/passes/SrtWalker.cpp @@ -85,6 +85,7 @@ bool IsRuntimeIntegerOp(ValueOpcode op) { case ValueOpcode::ISub64: case ValueOpcode::IMul32: case ValueOpcode::IMul64: + case ValueOpcode::UMin32: case ValueOpcode::ShiftLeftLogical32: case ValueOpcode::ShiftLeftLogical64: case ValueOpcode::ShiftRightLogical32: @@ -639,6 +640,12 @@ private: return true; } return false; + case ValueOpcode::UMin32: + if (binary()) { + result = std::min(static_cast(a), static_cast(b)); + return true; + } + return false; case ValueOpcode::BitwiseAnd32: if (binary()) { result = static_cast(a & b); diff --git a/tests/ResourceTrackingTests.cpp b/tests/ResourceTrackingTests.cpp index e0da7f013..2cef71bc8 100644 --- a/tests/ResourceTrackingTests.cpp +++ b/tests/ResourceTrackingTests.cpp @@ -234,6 +234,35 @@ void TestScalarAndVectorBufferAlias() { "scalar/vector alias did not share a dense index"); } +void TestRuntimeUnsignedMinDescriptor() { + Fixture fixture; + const auto word3 = fixture.Emit( + ValueOpcode::UMin32, {fixture.UserData(0), Value(0x100u)}); + const auto descriptor = + fixture.Buffer({Value(0u), Value(0u), Value(64u), word3}, 0x330); + MemoryInfo memory; + memory.kind = ResourceKind::Buffer; + fixture.Emit(ValueOpcode::LoadBufferU32, + {descriptor, Value(0u), Value(0u), Value(0u), Value(true)}, + fixture.AddMemory(memory, 0x330)); + fixture.PlanAndTrack(); + + std::array user_data{0xffffffffu}; + SrtRuntime runtime{.user_data = user_data}; + DescriptorValue value; + std::string error; + const auto source = fixture.program.info.buffers[0].source; + Check(EvaluateDescriptorSource(fixture.program, source, 0x330, runtime, value, + &error) && + value.dwords[3] == 0x100u, + "runtime descriptor unsigned minimum did not clamp its first operand"); + user_data[0] = 0x80u; + Check(EvaluateDescriptorSource(fixture.program, source, 0x330, runtime, value, + &error) && + value.dwords[3] == 0x80u, + "runtime descriptor unsigned minimum did not preserve its first operand"); +} + void TestImagesSamplersAndAliases() { Fixture fixture; std::array image_words; @@ -426,9 +455,11 @@ void TestPhiValidation() { static_cast(Type::U32)); phi.AddPhiOperand(left, Value(1u)); phi.AddPhiOperand(right, Value(2u)); + const auto word3 = fixture.Emit( + ValueOpcode::UMin32, {Value(&phi), Value(0x100u)}, 0, merge); const auto handle = fixture.Emit(ValueOpcode::GetBufferResource, - {Value(&phi), Value(0u), Value(0u), Value(0u)}, + {Value(0u), Value(0u), Value(0u), word3}, MemoryFlags{0, 20}, merge); MemoryInfo memory; memory.kind = ResourceKind::Buffer; @@ -628,6 +659,7 @@ int main() { }; Run("dense buffers", TestDenseBufferTracking); Run("scalar/vector alias", TestScalarAndVectorBufferAlias); + Run("runtime unsigned min", TestRuntimeUnsignedMinDescriptor); Run("images and samplers", TestImagesSamplersAndAliases); Run("SRT runtime", TestSrtFlatteningAndRuntimeMemoization); Run("dynamic SRT", TestDynamicSrtReadRemainsExplicit);