mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 11:26:56 +02:00
shader: bound material selectors by proven one-wave LDS append lists
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <span>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
@@ -49,6 +50,48 @@ void CompileSrtWalker(ResourcePlan& program);
|
||||
// Uses the strict reader for values that affect shader specialization.
|
||||
SrtRuntime CleanRuntime(SrtRuntime runtime);
|
||||
|
||||
// Nonnegative affine coefficients: element zero is constant, remaining elements are
|
||||
// caller-selected leaves. Runtime range proofs must additionally exclude U32 wrap.
|
||||
template <size_t Size>
|
||||
std::optional<std::array<uint64_t, Size>> AffineIndex(
|
||||
Value value, const auto& resolve, const auto& leaf, uint32_t depth = 0) {
|
||||
value = resolve(value);
|
||||
if (depth > 32u || value.GetType() != Type::U32) return {};
|
||||
std::array<uint64_t, Size> result {};
|
||||
if (value.IsImmediate()) {
|
||||
result[0] = value.U32();
|
||||
return result;
|
||||
}
|
||||
if (const auto index = leaf(value)) {
|
||||
result[*index] = 1u;
|
||||
return result;
|
||||
}
|
||||
const auto* inst = value.TryInstruction();
|
||||
if (inst == nullptr) return {};
|
||||
const auto op = inst->GetOpcode();
|
||||
if (op != ValueOpcode::IAdd32 && op != ValueOpcode::IMul32 &&
|
||||
op != ValueOpcode::ShiftLeftLogical32) return {};
|
||||
auto left = AffineIndex<Size>(inst->Arg(0), resolve, leaf, depth + 1u);
|
||||
auto right = AffineIndex<Size>(inst->Arg(1), resolve, leaf, depth + 1u);
|
||||
if (!left || !right) return {};
|
||||
const auto constant = [](const auto& coefficients) {
|
||||
return std::ranges::all_of(std::span(coefficients).subspan(1u),
|
||||
[](uint64_t coefficient) { return coefficient == 0u; });
|
||||
};
|
||||
if (op == ValueOpcode::IMul32 && !constant(*right)) std::swap(left, right);
|
||||
if (op != ValueOpcode::IAdd32 && !constant(*right)) return {};
|
||||
if (op == ValueOpcode::ShiftLeftLogical32) {
|
||||
if ((*right)[0] >= 32u) return {};
|
||||
(*right)[0] = uint64_t {1} << (*right)[0];
|
||||
}
|
||||
for (size_t index = 0; index < Size; ++index) {
|
||||
(*left)[index] = op == ValueOpcode::IAdd32
|
||||
? (*left)[index] + (*right)[index] : (*left)[index] * (*right)[0];
|
||||
if ((*left)[index] > UINT32_MAX) return {};
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
// One memoized evaluation session shared by the entire shader resource refresh.
|
||||
class SrtWalker {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user