Merge pull request #2790 from tototomate123/fix/hfw-shader-split

fix(shader): evaluate signed minimum in runtime SRT expressions
This commit is contained in:
Adrià 2026-10-11 09:23:58 +02:00 committed by GitHub
commit 6968564656
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 31 additions and 0 deletions

View File

@ -7,6 +7,7 @@
#include "Optimization/ShaderStageInputInfo.hpp"
#include "Optimization/SrtWalker/SrtDescriptorEvaluation.hpp"
#include "Optimization/SrtWalker/SrtEvaluator.hpp"
#include "Optimization/SrtWalker/SrtInstructionPredicates.hpp"
#include "Optimization/SrtWalker/SrtFlatSlotClasses.hpp"
#include "SpirvBackend/SpirvAnalysis.hpp"
#if ANYPS5_ENABLE_SPIRV_TOOLS
@ -360,6 +361,28 @@ void verifyRegisterSources() {
require(!EquivalentValue(plan, &samplerRegister, &firstVector), "different register types were merged");
}
void verifySignedMinimum() {
using namespace ShaderRecompiler;
IrResourcePlan plan;
IrValue reg(IrOpcode::Void, IrType::ScalarReg, 0);
reg.SetRegister({RegisterBank::Scalar, 0});
IrValue input(IrOpcode::GetUserData, IrType::U32, 1);
input.AddArgument(&reg);
IrValue limit(IrOpcode::Void, IrType::U32, 2);
limit.SetImmediateU32(8);
IrValue minimum(IrOpcode::SMin32, IrType::U32, 3);
minimum.AddArgument(&input);
minimum.AddArgument(&limit);
require(Detail::IsRuntimeUniformOp(IrOpcode::SMin32), "signed minimum must be a runtime uniform operation");
for (const auto& [value, expected] : std::array<std::pair<std::uint32_t, std::uint32_t>, 6>{{{0, 0}, {4, 4}, {20, 8}, {0x7fffffffu, 8}, {0xffffffffu, 0xffffffffu}, {0x80000000u, 0x80000000u}}}) {
std::array<std::uint32_t, 1> data{value};
SrtRuntime runtime{data};
Detail::Evaluator evaluator(plan, runtime);
std::uint32_t result = 0;
require(evaluator.Evaluate(&minimum, result) && result == expected, "SRT signed minimum used unsigned ordering or failed evaluation");
}
}
void verifyEvaluatedValues() {
using namespace ShaderRecompiler;
std::vector<std::unique_ptr<IrValue>> values;
@ -2588,6 +2611,7 @@ int main(int argc, char** argv) {
verifyEvaluatedValues();
verifyFrontendPair();
verifySignedSrtComparison();
verifySignedMinimum();
verifyPureFlatSlots();
verifyBindlessTable();
verifyDescriptorPhis();

View File

@ -262,6 +262,12 @@ bool Evaluator::EvaluateInst(IrValue& inst, std::uint64_t& result) {
return true;
}
return false;
case IrOpcode::SMin32:
if (binary()) {
result = static_cast<std::uint32_t>(std::min(std::bit_cast<std::int32_t>(static_cast<std::uint32_t>(a)), std::bit_cast<std::int32_t>(static_cast<std::uint32_t>(b))));
return true;
}
return false;
case IrOpcode::UMin32:
if (binary()) {
result = std::min(static_cast<std::uint32_t>(a), static_cast<std::uint32_t>(b));

View File

@ -70,6 +70,7 @@ bool IsRuntimeUniformOp(IrOpcode opcode) {
case IrOpcode::ISub64:
case IrOpcode::IMul32:
case IrOpcode::IMul64:
case IrOpcode::SMin32:
case IrOpcode::UMin32:
case IrOpcode::ShiftLeftLogical32:
case IrOpcode::ShiftLeftLogical64: