mirror of
https://github.com/PabloMK7/citra
synced 2024-11-14 20:58:23 +00:00
shader_jit/tests: Test both the shader interpreter and jit (#72)
* shader_jit/tests: Test both the shader interpreter and jit Uses Catch2's `TEMPLATE_TEST_CASE`-feature to test both the JIT and the interpreter. * shader_jit/tests: Use generator-expressions for nested-loop test cases Tests more permutations of inputs than just the two it had before * shader/tests: Refactor `shader_jit` tests to just `shader` tests Since these tests will test both the interpreter and the jit, they are no longer jit-specific tests and are more general shader-tests. * shaders/tests: Disable Nested-Loop `ShaderInterpreterTest` test Restoring loop-state on nested loops is bugged on the ShaderInterpreter. * shader/tests: Fix Nested Loop generator expressions
This commit is contained in:
parent
f782903587
commit
d2bd58287c
2 changed files with 106 additions and 96 deletions
|
@ -13,7 +13,7 @@ add_executable(tests
|
||||||
audio_core/lle/lle.cpp
|
audio_core/lle/lle.cpp
|
||||||
audio_core/audio_fixures.h
|
audio_core/audio_fixures.h
|
||||||
audio_core/decoder_tests.cpp
|
audio_core/decoder_tests.cpp
|
||||||
video_core/shader/shader_jit_compiler.cpp
|
video_core/shader.cpp
|
||||||
audio_core/merryhime_3ds_audio/merry_audio/merry_audio.cpp
|
audio_core/merryhime_3ds_audio/merry_audio/merry_audio.cpp
|
||||||
audio_core/merryhime_3ds_audio/merry_audio/merry_audio.h
|
audio_core/merryhime_3ds_audio/merry_audio/merry_audio.h
|
||||||
audio_core/merryhime_3ds_audio/merry_audio/service_fixture.cpp
|
audio_core/merryhime_3ds_audio/merry_audio/service_fixture.cpp
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <catch2/catch_approx.hpp>
|
#include <catch2/catch_approx.hpp>
|
||||||
|
#include <catch2/catch_template_test_macros.hpp>
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <catch2/generators/catch_generators.hpp>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <nihstro/inline_assembly.h>
|
#include <nihstro/inline_assembly.h>
|
||||||
#include "video_core/pica/shader_setup.h"
|
#include "video_core/pica/shader_setup.h"
|
||||||
|
@ -73,18 +75,19 @@ static std::unique_ptr<Pica::ShaderSetup> CompileShaderSetup(
|
||||||
class ShaderTest {
|
class ShaderTest {
|
||||||
public:
|
public:
|
||||||
explicit ShaderTest(std::initializer_list<nihstro::InlineAsm> code)
|
explicit ShaderTest(std::initializer_list<nihstro::InlineAsm> code)
|
||||||
: shader_setup(CompileShaderSetup(code)) {
|
: shader_setup(CompileShaderSetup(code)) {}
|
||||||
shader_jit.Compile(&shader_setup->program_code, &shader_setup->swizzle_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit ShaderTest(std::unique_ptr<Pica::ShaderSetup> input_shader_setup)
|
explicit ShaderTest(std::unique_ptr<Pica::ShaderSetup> input_shader_setup)
|
||||||
: shader_setup(std::move(input_shader_setup)) {
|
: shader_setup(std::move(input_shader_setup)) {}
|
||||||
shader_jit.Compile(&shader_setup->program_code, &shader_setup->swizzle_data);
|
|
||||||
}
|
virtual ~ShaderTest() = default;
|
||||||
|
|
||||||
|
virtual void RunShader(Pica::ShaderUnit& shader_unit,
|
||||||
|
std::span<const Common::Vec4f> inputs) = 0;
|
||||||
|
|
||||||
Common::Vec4f Run(std::span<const Common::Vec4f> inputs) {
|
Common::Vec4f Run(std::span<const Common::Vec4f> inputs) {
|
||||||
Pica::ShaderUnit shader_unit;
|
Pica::ShaderUnit shader_unit;
|
||||||
RunJit(shader_unit, inputs);
|
RunShader(shader_unit, inputs);
|
||||||
return {shader_unit.output[0].x.ToFloat32(), shader_unit.output[0].y.ToFloat32(),
|
return {shader_unit.output[0].x.ToFloat32(), shader_unit.output[0].y.ToFloat32(),
|
||||||
shader_unit.output[0].z.ToFloat32(), shader_unit.output[0].w.ToFloat32()};
|
shader_unit.output[0].z.ToFloat32(), shader_unit.output[0].w.ToFloat32()};
|
||||||
}
|
}
|
||||||
|
@ -105,24 +108,23 @@ public:
|
||||||
return Run(std::vector<Common::Vec4f>{inputs});
|
return Run(std::vector<Common::Vec4f>{inputs});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunJit(Pica::ShaderUnit& shader_unit, std::span<const Common::Vec4f> inputs) {
|
void Run(Pica::ShaderUnit& shader_unit, float input) {
|
||||||
for (std::size_t i = 0; i < inputs.size(); ++i) {
|
|
||||||
const Common::Vec4f& input = inputs[i];
|
|
||||||
shader_unit.input[i].x = Pica::f24::FromFloat32(input.x);
|
|
||||||
shader_unit.input[i].y = Pica::f24::FromFloat32(input.y);
|
|
||||||
shader_unit.input[i].z = Pica::f24::FromFloat32(input.z);
|
|
||||||
shader_unit.input[i].w = Pica::f24::FromFloat32(input.w);
|
|
||||||
}
|
|
||||||
shader_unit.temporary.fill(Common::Vec4<Pica::f24>::AssignToAll(Pica::f24::Zero()));
|
|
||||||
shader_jit.Run(*shader_setup, shader_unit, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunJit(Pica::ShaderUnit& shader_unit, float input) {
|
|
||||||
const Common::Vec4f input_vec(input, 0, 0, 0);
|
const Common::Vec4f input_vec(input, 0, 0, 0);
|
||||||
RunJit(shader_unit, {&input_vec, 1});
|
RunShader(shader_unit, {&input_vec, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunInterpreter(Pica::ShaderUnit& shader_unit, std::span<const Common::Vec4f> inputs) {
|
std::unique_ptr<Pica::ShaderSetup> shader_setup;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderInterpreterTest : public ShaderTest {
|
||||||
|
public:
|
||||||
|
explicit ShaderInterpreterTest(std::initializer_list<nihstro::InlineAsm> code)
|
||||||
|
: ShaderTest(code) {}
|
||||||
|
|
||||||
|
explicit ShaderInterpreterTest(std::unique_ptr<Pica::ShaderSetup> input_shader_setup)
|
||||||
|
: ShaderTest(std::move(input_shader_setup)) {}
|
||||||
|
|
||||||
|
void RunShader(Pica::ShaderUnit& shader_unit, std::span<const Common::Vec4f> inputs) override {
|
||||||
for (std::size_t i = 0; i < inputs.size(); ++i) {
|
for (std::size_t i = 0; i < inputs.size(); ++i) {
|
||||||
const Common::Vec4f& input = inputs[i];
|
const Common::Vec4f& input = inputs[i];
|
||||||
shader_unit.input[i].x = Pica::f24::FromFloat32(input.x);
|
shader_unit.input[i].x = Pica::f24::FromFloat32(input.x);
|
||||||
|
@ -134,23 +136,46 @@ public:
|
||||||
shader_interpreter.Run(*shader_setup, shader_unit);
|
shader_interpreter.Run(*shader_setup, shader_unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunInterpreter(Pica::ShaderUnit& shader_unit, float input) {
|
private:
|
||||||
const Common::Vec4f input_vec(input, 0, 0, 0);
|
|
||||||
RunInterpreter(shader_unit, {&input_vec, 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
JitShader shader_jit;
|
|
||||||
ShaderInterpreter shader_interpreter;
|
ShaderInterpreter shader_interpreter;
|
||||||
std::unique_ptr<Pica::ShaderSetup> shader_setup;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE("ADD", "[video_core][shader][shader_jit]") {
|
class ShaderJitTest : public ShaderTest {
|
||||||
|
public:
|
||||||
|
explicit ShaderJitTest(std::initializer_list<nihstro::InlineAsm> code) : ShaderTest(code) {
|
||||||
|
shader_jit.Compile(&shader_setup->program_code, &shader_setup->swizzle_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ShaderJitTest(std::unique_ptr<Pica::ShaderSetup> input_shader_setup)
|
||||||
|
: ShaderTest(std::move(input_shader_setup)) {
|
||||||
|
shader_jit.Compile(&shader_setup->program_code, &shader_setup->swizzle_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunShader(Pica::ShaderUnit& shader_unit, std::span<const Common::Vec4f> inputs) override {
|
||||||
|
for (std::size_t i = 0; i < inputs.size(); ++i) {
|
||||||
|
const Common::Vec4f& input = inputs[i];
|
||||||
|
shader_unit.input[i].x = Pica::f24::FromFloat32(input.x);
|
||||||
|
shader_unit.input[i].y = Pica::f24::FromFloat32(input.y);
|
||||||
|
shader_unit.input[i].z = Pica::f24::FromFloat32(input.z);
|
||||||
|
shader_unit.input[i].w = Pica::f24::FromFloat32(input.w);
|
||||||
|
}
|
||||||
|
shader_unit.temporary.fill(Common::Vec4<Pica::f24>::AssignToAll(Pica::f24::Zero()));
|
||||||
|
shader_jit.Run(*shader_setup, shader_unit, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JitShader shader_jit;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SHADER_TEST_CASE(NAME, TAG) \
|
||||||
|
TEMPLATE_TEST_CASE(NAME, TAG, ShaderInterpreterTest, ShaderJitTest)
|
||||||
|
|
||||||
|
SHADER_TEST_CASE("ADD", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::ADD, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::ADD, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -162,7 +187,7 @@ TEST_CASE("ADD", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(std::isinf(shader.Run({INFINITY, -1.0f}).x));
|
REQUIRE(std::isinf(shader.Run({INFINITY, -1.0f}).x));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("CALL", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("CALL", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
|
@ -192,17 +217,17 @@ TEST_CASE("CALL", "[video_core][shader][shader_jit]") {
|
||||||
CALL.flow_control.num_instructions = 1;
|
CALL.flow_control.num_instructions = 1;
|
||||||
shader_setup->program_code[2] = CALL.hex;
|
shader_setup->program_code[2] = CALL.hex;
|
||||||
|
|
||||||
auto shader = ShaderTest(std::move(shader_setup));
|
auto shader = TestType(std::move(shader_setup));
|
||||||
|
|
||||||
REQUIRE(shader.Run(0.f).x == Catch::Approx(1.f));
|
REQUIRE(shader.Run(0.f).x == Catch::Approx(1.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("DP3", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("DP3", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::DP3, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::DP3, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -213,12 +238,12 @@ TEST_CASE("DP3", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({vec4_one, vec4_one}).x == 3.0f);
|
REQUIRE(shader.Run({vec4_one, vec4_one}).x == 3.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("DP4", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("DP4", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::DP4, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::DP4, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -229,12 +254,12 @@ TEST_CASE("DP4", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({vec4_one, vec4_one}).x == 4.0f);
|
REQUIRE(shader.Run({vec4_one, vec4_one}).x == 4.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("DPH", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("DPH", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::DPH, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::DPH, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -246,11 +271,11 @@ TEST_CASE("DPH", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({vec4_zero, vec4_one}).x == 1.0f);
|
REQUIRE(shader.Run({vec4_zero, vec4_one}).x == 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("LG2", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("LG2", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::LG2, sh_output, sh_input},
|
{OpCode::Id::LG2, sh_output, sh_input},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -263,11 +288,11 @@ TEST_CASE("LG2", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run(1.e24f).x == Catch::Approx(79.7262742773f));
|
REQUIRE(shader.Run(1.e24f).x == Catch::Approx(79.7262742773f));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("EX2", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("EX2", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::EX2, sh_output, sh_input},
|
{OpCode::Id::EX2, sh_output, sh_input},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -281,12 +306,12 @@ TEST_CASE("EX2", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(std::isinf(shader.Run(800.f).x));
|
REQUIRE(std::isinf(shader.Run(800.f).x));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("MUL", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("MUL", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::MUL, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::MUL, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -300,12 +325,12 @@ TEST_CASE("MUL", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({+INFINITY, -INFINITY}).x == -INFINITY);
|
REQUIRE(shader.Run({+INFINITY, -INFINITY}).x == -INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("SGE", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("SGE", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::SGE, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::SGE, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -321,12 +346,12 @@ TEST_CASE("SGE", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({-1.0f, +1.0f}).x == 0.0f);
|
REQUIRE(shader.Run({-1.0f, +1.0f}).x == 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("SLT", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("SLT", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::SLT, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::SLT, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -342,11 +367,11 @@ TEST_CASE("SLT", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({-1.0f, +1.0f}).x == 1.0f);
|
REQUIRE(shader.Run({-1.0f, +1.0f}).x == 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("FLR", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("FLR", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::FLR, sh_output, sh_input1},
|
{OpCode::Id::FLR, sh_output, sh_input1},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -359,12 +384,12 @@ TEST_CASE("FLR", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(std::isinf(shader.Run({INFINITY}).x));
|
REQUIRE(std::isinf(shader.Run({INFINITY}).x));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("MAX", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("MAX", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::MAX, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::MAX, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -378,12 +403,12 @@ TEST_CASE("MAX", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({-INFINITY, +INFINITY}).x == +INFINITY);
|
REQUIRE(shader.Run({-INFINITY, +INFINITY}).x == +INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("MIN", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("MIN", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::MIN, sh_output, sh_input1, sh_input2},
|
{OpCode::Id::MIN, sh_output, sh_input1, sh_input2},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -397,11 +422,11 @@ TEST_CASE("MIN", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({-INFINITY, +INFINITY}).x == -INFINITY);
|
REQUIRE(shader.Run({-INFINITY, +INFINITY}).x == -INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("RCP", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("RCP", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::RCP, sh_output, sh_input},
|
{OpCode::Id::RCP, sh_output, sh_input},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -422,11 +447,11 @@ TEST_CASE("RCP", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({0.0625f}).x == Catch::Approx(16.0f).margin(0.004f));
|
REQUIRE(shader.Run({0.0625f}).x == Catch::Approx(16.0f).margin(0.004f));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("RSQ", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("RSQ", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
{OpCode::Id::RSQ, sh_output, sh_input},
|
{OpCode::Id::RSQ, sh_output, sh_input},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -448,12 +473,12 @@ TEST_CASE("RSQ", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({0.0625f}).x == Catch::Approx(4.0f).margin(0.004f));
|
REQUIRE(shader.Run({0.0625f}).x == Catch::Approx(4.0f).margin(0.004f));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Uniform Read", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("Uniform Read", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_c0 = SourceRegister::MakeFloat(0);
|
const auto sh_c0 = SourceRegister::MakeFloat(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
// mova a0.x, sh_input.x
|
// mova a0.x, sh_input.x
|
||||||
{OpCode::Id::MOVA, DestRegister{}, "x", sh_input, "x", SourceRegister{}, "",
|
{OpCode::Id::MOVA, DestRegister{}, "x", sh_input, "x", SourceRegister{}, "",
|
||||||
nihstro::InlineAsm::RelativeAddress::A1},
|
nihstro::InlineAsm::RelativeAddress::A1},
|
||||||
|
@ -481,12 +506,12 @@ TEST_CASE("Uniform Read", "[video_core][shader][shader_jit]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Address Register Offset", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("Address Register Offset", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_c40 = SourceRegister::MakeFloat(40);
|
const auto sh_c40 = SourceRegister::MakeFloat(40);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader = ShaderTest({
|
auto shader = TestType({
|
||||||
// mova a0.x, sh_input.x
|
// mova a0.x, sh_input.x
|
||||||
{OpCode::Id::MOVA, DestRegister{}, "x", sh_input, "x", SourceRegister{}, "",
|
{OpCode::Id::MOVA, DestRegister{}, "x", sh_input, "x", SourceRegister{}, "",
|
||||||
nihstro::InlineAsm::RelativeAddress::A1},
|
nihstro::InlineAsm::RelativeAddress::A1},
|
||||||
|
@ -531,12 +556,12 @@ TEST_CASE("Address Register Offset", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run(-129.f) == f_uniforms[40]);
|
REQUIRE(shader.Run(-129.f) == f_uniforms[40]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Dest Mask", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("Dest Mask", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
const auto shader = [&sh_input, &sh_output](const char* dest_mask) {
|
const auto shader = [&sh_input, &sh_output](const char* dest_mask) {
|
||||||
return std::unique_ptr<ShaderTest>(new ShaderTest{
|
return std::unique_ptr<TestType>(new TestType{
|
||||||
{OpCode::Id::MOV, sh_output, dest_mask, sh_input, "xyzw", SourceRegister{}, ""},
|
{OpCode::Id::MOV, sh_output, dest_mask, sh_input, "xyzw", SourceRegister{}, ""},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
||||||
|
@ -561,7 +586,7 @@ TEST_CASE("Dest Mask", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader("xyzw")->Run({iota_vec}) == iota_vec);
|
REQUIRE(shader("xyzw")->Run({iota_vec}) == iota_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("MAD", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("MAD", "[video_core][shader]") {
|
||||||
const auto sh_input1 = SourceRegister::MakeInput(0);
|
const auto sh_input1 = SourceRegister::MakeInput(0);
|
||||||
const auto sh_input2 = SourceRegister::MakeInput(1);
|
const auto sh_input2 = SourceRegister::MakeInput(1);
|
||||||
const auto sh_input3 = SourceRegister::MakeInput(2);
|
const auto sh_input3 = SourceRegister::MakeInput(2);
|
||||||
|
@ -601,7 +626,7 @@ TEST_CASE("MAD", "[video_core][shader][shader_jit]") {
|
||||||
swizzle.SetSelectorSrc3(3, SwizzlePattern::Selector::w);
|
swizzle.SetSelectorSrc3(3, SwizzlePattern::Selector::w);
|
||||||
shader_setup->swizzle_data[0] = swizzle.hex;
|
shader_setup->swizzle_data[0] = swizzle.hex;
|
||||||
|
|
||||||
auto shader = ShaderTest(std::move(shader_setup));
|
auto shader = TestType(std::move(shader_setup));
|
||||||
|
|
||||||
REQUIRE(shader.Run({vec4_zero, vec4_zero, vec4_zero}) == vec4_zero);
|
REQUIRE(shader.Run({vec4_zero, vec4_zero, vec4_zero}) == vec4_zero);
|
||||||
REQUIRE(shader.Run({vec4_one, vec4_one, vec4_one}) == (vec4_one * 2.0f));
|
REQUIRE(shader.Run({vec4_one, vec4_one, vec4_one}) == (vec4_one * 2.0f));
|
||||||
|
@ -609,12 +634,14 @@ TEST_CASE("MAD", "[video_core][shader][shader_jit]") {
|
||||||
REQUIRE(shader.Run({vec4_nan, vec4_zero, vec4_zero}) == vec4_nan);
|
REQUIRE(shader.Run({vec4_nan, vec4_zero, vec4_zero}) == vec4_nan);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Nested Loop", "[video_core][shader][shader_jit]") {
|
// Nested Loops are bugged on on the Shader-Interpreter at the moment
|
||||||
|
// SHADER_TEST_CASE("Nested Loop", "[video_core][shader]") {
|
||||||
|
TEMPLATE_TEST_CASE("Nested Loop", "[video_core][shader]", ShaderJitTest) {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_temp = SourceRegister::MakeTemporary(0);
|
const auto sh_temp = SourceRegister::MakeTemporary(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
auto shader_test = ShaderTest({
|
auto shader_test = TestType({
|
||||||
// clang-format off
|
// clang-format off
|
||||||
{OpCode::Id::MOV, sh_temp, sh_input},
|
{OpCode::Id::MOV, sh_temp, sh_input},
|
||||||
{OpCode::Id::LOOP, 0},
|
{OpCode::Id::LOOP, 0},
|
||||||
|
@ -628,8 +655,8 @@ TEST_CASE("Nested Loop", "[video_core][shader][shader_jit]") {
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
shader_test.shader_setup->uniforms.i[0] = {4, 0, 1, 0};
|
shader_test.shader_setup->uniforms.i[0] = {(u8)GENERATE(4, 9), 0, (u8)GENERATE(1, 2), 0};
|
||||||
shader_test.shader_setup->uniforms.i[1] = {4, 0, 1, 0};
|
shader_test.shader_setup->uniforms.i[1] = {(u8)GENERATE(4, 7), 0, (u8)GENERATE(1, 1), 0};
|
||||||
Common::Vec4<u8> loop_parms{shader_test.shader_setup->uniforms.i[0]};
|
Common::Vec4<u8> loop_parms{shader_test.shader_setup->uniforms.i[0]};
|
||||||
|
|
||||||
const int expected_aL = loop_parms[1] + ((loop_parms[0] + 1) * loop_parms[2]);
|
const int expected_aL = loop_parms[1] + ((loop_parms[0] + 1) * loop_parms[2]);
|
||||||
|
@ -639,37 +666,20 @@ TEST_CASE("Nested Loop", "[video_core][shader][shader_jit]") {
|
||||||
input) +
|
input) +
|
||||||
input;
|
input;
|
||||||
|
|
||||||
Pica::ShaderUnit shader_unit_jit;
|
Pica::ShaderUnit shader_unit;
|
||||||
shader_test.RunJit(shader_unit_jit, input);
|
shader_test.Run(shader_unit, input);
|
||||||
|
|
||||||
REQUIRE(shader_unit_jit.address_registers[2] == expected_aL);
|
REQUIRE(shader_unit.address_registers[2] == expected_aL);
|
||||||
REQUIRE(shader_unit_jit.output[0].x.ToFloat32() == Catch::Approx(expected_out));
|
REQUIRE(shader_unit.output[0].x.ToFloat32() == Catch::Approx(expected_out));
|
||||||
}
|
|
||||||
{
|
|
||||||
shader_test.shader_setup->uniforms.i[0] = {9, 0, 2, 0};
|
|
||||||
shader_test.shader_setup->uniforms.i[1] = {7, 0, 1, 0};
|
|
||||||
|
|
||||||
const Common::Vec4<u8> loop_parms{shader_test.shader_setup->uniforms.i[0]};
|
|
||||||
const int expected_aL = loop_parms[1] + ((loop_parms[0] + 1) * loop_parms[2]);
|
|
||||||
const float input = 1.0f;
|
|
||||||
const float expected_out = (((shader_test.shader_setup->uniforms.i[0][0] + 1) *
|
|
||||||
(shader_test.shader_setup->uniforms.i[1][0] + 1)) *
|
|
||||||
input) +
|
|
||||||
input;
|
|
||||||
Pica::ShaderUnit shader_unit_jit;
|
|
||||||
shader_test.RunJit(shader_unit_jit, input);
|
|
||||||
|
|
||||||
REQUIRE(shader_unit_jit.address_registers[2] == expected_aL);
|
|
||||||
REQUIRE(shader_unit_jit.output[0].x.ToFloat32() == Catch::Approx(expected_out));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Source Swizzle", "[video_core][shader][shader_jit]") {
|
SHADER_TEST_CASE("Source Swizzle", "[video_core][shader]") {
|
||||||
const auto sh_input = SourceRegister::MakeInput(0);
|
const auto sh_input = SourceRegister::MakeInput(0);
|
||||||
const auto sh_output = DestRegister::MakeOutput(0);
|
const auto sh_output = DestRegister::MakeOutput(0);
|
||||||
|
|
||||||
const auto shader = [&sh_input, &sh_output](const char* swizzle) {
|
const auto shader = [&sh_input, &sh_output](const char* swizzle) {
|
||||||
return std::unique_ptr<ShaderTest>(new ShaderTest{
|
return std::unique_ptr<TestType>(new TestType{
|
||||||
{OpCode::Id::MOV, sh_output, "xyzw", sh_input, swizzle, SourceRegister{}, ""},
|
{OpCode::Id::MOV, sh_output, "xyzw", sh_input, swizzle, SourceRegister{}, ""},
|
||||||
{OpCode::Id::END},
|
{OpCode::Id::END},
|
||||||
});
|
});
|
Loading…
Reference in a new issue