diff --git a/tests/shader.cpp b/tests/shader.cpp index 26ba82ea..6b0dece8 100644 --- a/tests/shader.cpp +++ b/tests/shader.cpp @@ -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 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 assembleVertexShader(std::initializer_list code) { const auto shaderBinary = nihstro::InlineAsm::CompileToRawBinary(code); auto newShader = std::make_unique(ShaderType::Vertex); @@ -66,7 +73,7 @@ class ShaderInterpreterTest { [[nodiscard]] std::array, 96>& floatUniforms() const { return shader->floatUniforms; } [[nodiscard]] std::array, 4>& intUniforms() const { return shader->intUniforms; } - [[nodiscard]] u32& boolUniform() const { return shader->boolUniform; } + [[nodiscard]] u32& boolUniforms() const { return shader->boolUniform; } static std::unique_ptr assembleTest(std::initializer_list code) { return std::make_unique(code); @@ -306,4 +313,55 @@ 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, 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 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((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]); } \ No newline at end of file