Files
AnyPS5/core/libs/tests/InterpolationReferenceRange.cpp
T
2309fbaadf fix(recompiler): name the attribute of an out-of-range interpolation reference
The shader info collector refused an out-of-range interpolation parameter
reference without saying which one. The message now gives the attribute,
component and mode it read and the pixel input count it was checked
against, so a title's stop at this check names the attribute its pixel shader
reads past the inputs the draw declares.

Test: interpolation_reference_range builds pixel programs with an
attribute past the inputs, a component past w and a reserved mode, and
checks the message names each.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: overlordxrz-source <overlordxrz-source@users.noreply.github.com>
2026-10-13 15:57:17 -04:00

54 lines
2.3 KiB
C++

#include "IntermediateRepresentation/IrBuilder.hpp"
#include "Optimization/ShaderInfoCollector.hpp"
#include <cstdint>
#include <cstdio>
#include <stdexcept>
#include <string>
using namespace ShaderRecompiler;
namespace {
std::string Collect(std::uint32_t attribute, std::uint32_t component, std::uint32_t mode, std::uint32_t inputNum) {
IrProgram program;
program.Resources().stage = IrShaderStage::Pixel;
program.Resources().resourceTrackingComplete = true;
auto& block = program.CreateBlock();
program.SetEntryBlock(block);
program.BlockOrder().push_back(&block);
IrBuilder builder(program);
builder.SetInsertionPoint(block);
auto& parameter = builder.Emit(IrOpcode::GetInterpolationParameter, IrType::U32, {&builder.Constant(attribute), &builder.Constant(component), &builder.Constant(mode)});
static_cast<void>(builder.Emit(IrOpcode::ReferenceU32, IrType::Void, {&parameter}));
static_cast<void>(builder.Emit(IrOpcode::Return, IrType::Void, {}));
ShaderPixelInputInfo pixel {};
pixel.inputNum = inputNum;
try {
ShaderInfoCollector().Collect(program, ShaderStageInputInfo {nullptr, &pixel, nullptr});
} catch (const std::runtime_error& error) {
return error.what();
}
return {};
}
}
int main() {
int failures = 0;
const auto expect = [&](bool value, const char* name, const std::string& message) {
if (!value) {
std::fprintf(stderr, "%s: %s\n", name, message.c_str());
++failures;
}
};
const auto attribute = Collect(5u, 1u, 0u, 2u);
expect(attribute.find("interpolation parameter reference is out of range (attribute 5 component 1 mode 0, 2 inputs)") != std::string::npos, "an attribute past the pixel inputs", attribute);
const auto component = Collect(0u, 4u, 2u, 1u);
expect(component.find("(attribute 0 component 4 mode 2, 1 inputs)") != std::string::npos, "a component past w", component);
const auto mode = Collect(1u, 3u, 3u, 3u);
expect(mode.find("(attribute 1 component 3 mode 3, 3 inputs)") != std::string::npos, "a reserved interpolation mode", mode);
const auto inRange = Collect(1u, 3u, 2u, 2u);
expect(inRange.find("interpolation parameter reference") == std::string::npos, "an in-range reference", inRange);
return failures == 0 ? 0 : 1;
}