Add Address Register Offset shader unit test

This commit is contained in:
Wunkolo 2024-03-20 08:58:46 -07:00
parent d4d74f5b48
commit dbdf7c4ffb

View file

@ -14,6 +14,13 @@ static const nihstro::SourceRegister input0 = nihstro::SourceRegister::MakeInput
static const nihstro::SourceRegister input1 = nihstro::SourceRegister::MakeInput(1);
static const nihstro::DestRegister output0 = nihstro::DestRegister::MakeOutput(0);
static const std::array<Floats::f24, 4> vectorOnes = {
Floats::f24::fromFloat32(1.0f),
Floats::f24::fromFloat32(1.0f),
Floats::f24::fromFloat32(1.0f),
Floats::f24::fromFloat32(1.0f),
};
static std::unique_ptr<PICAShader> assembleVertexShader(std::initializer_list<nihstro::InlineAsm> code) {
const auto shaderBinary = nihstro::InlineAsm::CompileToRawBinary(code);
auto newShader = std::make_unique<PICAShader>(ShaderType::Vertex);
@ -66,7 +73,7 @@ class ShaderInterpreterTest {
[[nodiscard]] std::array<std::array<Floats::f24, 4>, 96>& floatUniforms() const { return shader->floatUniforms; }
[[nodiscard]] std::array<std::array<u8, 4>, 4>& intUniforms() const { return shader->intUniforms; }
[[nodiscard]] u32& boolUniform() const { return shader->boolUniform; }
[[nodiscard]] u32& boolUniforms() const { return shader->boolUniform; }
static std::unique_ptr<ShaderInterpreterTest> assembleTest(std::initializer_list<nihstro::InlineAsm> code) {
return std::make_unique<ShaderInterpreterTest>(code);
@ -307,3 +314,54 @@ SHADER_TEST_CASE("Uniform Read", "[shader][vertex][uniform]") {
REQUIRE(shader->runVector({index + fractional}) == floatUniforms[i]);
}
}
SHADER_TEST_CASE("Address Register Offset", "[video_core][shader][shader_jit]") {
const auto constant40 = nihstro::SourceRegister::MakeFloat(40);
auto shader = TestType::assembleTest({
// mova a0.x, sh_input.x
{nihstro::OpCode::Id::MOVA, nihstro::DestRegister{}, "x", input0, "x", nihstro::SourceRegister{}, "", nihstro::InlineAsm::RelativeAddress::A1
},
// mov sh_output.xyzw, c40[a0.x].xyzw
{nihstro::OpCode::Id::MOV, output0, "xyzw", constant40, "xyzw", nihstro::SourceRegister{}, "", nihstro::InlineAsm::RelativeAddress::A1},
{nihstro::OpCode::Id::END},
});
// Generate uniforms
const bool inverted = true;
std::array<std::array<Floats::f24, 4>, 96> floatUniforms = {};
for (u8 i = 0; i < 0x80; i++) {
// Float uniforms
if (i >= 0x00 && i < 0x60) {
const u32 base = inverted ? (0x60 - i) : i;
const auto color = (base * 2.f) / 255.0f;
const auto color24 = Floats::f24::fromFloat32(color);
const std::array<Floats::f24, 4> testValue = {color24, color24, color24, Floats::f24::fromFloat32(1.0f)};
shader->floatUniforms()[i] = testValue;
floatUniforms[i] = testValue;
}
// Integer uniforms
else if (i >= 0x60 && i < 0x64) {
const u8 color = static_cast<u8>((i - 0x60) * 0x10);
shader->intUniforms()[i - 0x60] = {color, color, color, 255};
}
// Bool uniforms(bools packed into an integer)
else if (i >= 0x70 && i < 0x80) {
shader->boolUniforms() |= (i >= 0x78) << (i - 0x70);
}
}
REQUIRE(shader->runVector({0.f}) == floatUniforms[40]);
REQUIRE(shader->runVector({13.f}) == floatUniforms[53]);
REQUIRE(shader->runVector({50.f}) == floatUniforms[90]);
REQUIRE(shader->runVector({60.f}) == vectorOnes);
REQUIRE(shader->runVector({74.f}) == vectorOnes);
REQUIRE(shader->runVector({87.f}) == vectorOnes);
REQUIRE(shader->runVector({88.f}) == floatUniforms[0]);
REQUIRE(shader->runVector({128.f}) == floatUniforms[40]);
REQUIRE(shader->runVector({-40.f}) == floatUniforms[0]);
REQUIRE(shader->runVector({-42.f}) == vectorOnes);
REQUIRE(shader->runVector({-70.f}) == vectorOnes);
REQUIRE(shader->runVector({-73.f}) == floatUniforms[95]);
REQUIRE(shader->runVector({-127.f}) == floatUniforms[41]);
REQUIRE(shader->runVector({-129.f}) == floatUniforms[40]);
}