Add a shader generation unit test
This commit is contained in:
parent
4df7d0b4e2
commit
8fb7bb78a5
|
|
@ -46,5 +46,6 @@ TOOL.Libraries = {
|
||||||
"NazaraNetwork",
|
"NazaraNetwork",
|
||||||
"NazaraPhysics2D",
|
"NazaraPhysics2D",
|
||||||
"NazaraPhysics3D",
|
"NazaraPhysics3D",
|
||||||
|
"NazaraShader",
|
||||||
"NazaraUtility"
|
"NazaraUtility"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
#include <Nazara/Core/File.hpp>
|
||||||
|
#include <Nazara/Shader/GlslWriter.hpp>
|
||||||
|
#include <Nazara/Shader/ShaderAst.hpp>
|
||||||
|
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvPrinter.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvWriter.hpp>
|
||||||
|
#include <Catch/catch.hpp>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
std::string_view Trim(std::string_view str)
|
||||||
|
{
|
||||||
|
while (!str.empty() && std::isspace(str.front()))
|
||||||
|
str.remove_prefix(1);
|
||||||
|
|
||||||
|
while (!str.empty() && std::isspace(str.back()))
|
||||||
|
str.remove_suffix(1);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpectingGLSL(const Nz::ShaderAst& shader, std::string_view expectedOutput)
|
||||||
|
{
|
||||||
|
Nz::GlslWriter writer;
|
||||||
|
|
||||||
|
std::string output = writer.Generate(shader);
|
||||||
|
std::size_t funcOffset = output.find("void main()");
|
||||||
|
std::string_view subset = Trim(output).substr(funcOffset);
|
||||||
|
expectedOutput = Trim(expectedOutput);
|
||||||
|
|
||||||
|
REQUIRE(subset == expectedOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpectingSpirV(const Nz::ShaderAst& shader, std::string_view expectedOutput)
|
||||||
|
{
|
||||||
|
Nz::SpirvWriter writer;
|
||||||
|
auto spirv = writer.Generate(shader);
|
||||||
|
|
||||||
|
Nz::SpirvPrinter printer;
|
||||||
|
|
||||||
|
Nz::SpirvPrinter::Settings settings;
|
||||||
|
settings.printHeader = false;
|
||||||
|
settings.printParameters = false;
|
||||||
|
|
||||||
|
std::string output = printer.Print(spirv.data(), spirv.size(), settings);
|
||||||
|
std::size_t funcOffset = output.find("OpFunction");
|
||||||
|
std::string_view subset = Trim(output).substr(funcOffset);
|
||||||
|
expectedOutput = Trim(expectedOutput);
|
||||||
|
|
||||||
|
REQUIRE(subset == expectedOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("Shader generation", "[Shader]")
|
||||||
|
{
|
||||||
|
SECTION("Nested member loading")
|
||||||
|
{
|
||||||
|
Nz::ShaderAst baseShader(Nz::ShaderStageType::Vertex);
|
||||||
|
baseShader.AddStruct("innerStruct", {
|
||||||
|
{
|
||||||
|
"field",
|
||||||
|
Nz::ShaderNodes::BasicType::Float3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
baseShader.AddStruct("outerStruct", {
|
||||||
|
{
|
||||||
|
"s",
|
||||||
|
"innerStruct"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
baseShader.AddUniform("ubo", "outerStruct");
|
||||||
|
baseShader.AddOutput("result", Nz::ShaderNodes::BasicType::Float1);
|
||||||
|
|
||||||
|
SECTION("Nested AccessMember")
|
||||||
|
{
|
||||||
|
Nz::ShaderAst shader = baseShader;
|
||||||
|
|
||||||
|
auto uniform = Nz::ShaderBuilder::Uniform("ubo", "outerStruct");
|
||||||
|
auto output = Nz::ShaderBuilder::Output("result", Nz::ShaderNodes::BasicType::Float1);
|
||||||
|
|
||||||
|
auto access = Nz::ShaderBuilder::Swizzle(Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier(uniform), 0, "innerStruct"), 0, Nz::ShaderNodes::BasicType::Float3), Nz::ShaderNodes::SwizzleComponent::Third);
|
||||||
|
auto assign = Nz::ShaderBuilder::Assign(Nz::ShaderBuilder::Identifier(output), access);
|
||||||
|
|
||||||
|
shader.AddFunction("main", Nz::ShaderBuilder::ExprStatement(assign));
|
||||||
|
|
||||||
|
SECTION("Generating GLSL")
|
||||||
|
{
|
||||||
|
ExpectingGLSL(shader, R"(
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
result = ubo.s.field.z;
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
SECTION("Generating Spir-V")
|
||||||
|
{
|
||||||
|
ExpectingSpirV(shader, R"(
|
||||||
|
OpFunction
|
||||||
|
OpLabel
|
||||||
|
OpAccessChain
|
||||||
|
OpAccessChain
|
||||||
|
OpLoad
|
||||||
|
OpCompositeExtract
|
||||||
|
OpStore
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("AccessMember with multiples fields")
|
||||||
|
{
|
||||||
|
Nz::ShaderAst shader = baseShader;
|
||||||
|
|
||||||
|
auto uniform = Nz::ShaderBuilder::Uniform("ubo", "outerStruct");
|
||||||
|
auto output = Nz::ShaderBuilder::Output("result", Nz::ShaderNodes::BasicType::Float1);
|
||||||
|
|
||||||
|
auto access = Nz::ShaderBuilder::Swizzle(Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier(uniform), std::vector<std::size_t>{ 0, 0 }, Nz::ShaderNodes::BasicType::Float3), Nz::ShaderNodes::SwizzleComponent::Third);
|
||||||
|
auto assign = Nz::ShaderBuilder::Assign(Nz::ShaderBuilder::Identifier(output), access);
|
||||||
|
|
||||||
|
shader.AddFunction("main", Nz::ShaderBuilder::ExprStatement(assign));
|
||||||
|
|
||||||
|
SECTION("Generating GLSL")
|
||||||
|
{
|
||||||
|
ExpectingGLSL(shader, R"(
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
result = ubo.s.field.z;
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
SECTION("Generating Spir-V")
|
||||||
|
{
|
||||||
|
ExpectingSpirV(shader, R"(
|
||||||
|
OpFunction
|
||||||
|
OpLabel
|
||||||
|
OpAccessChain
|
||||||
|
OpLoad
|
||||||
|
OpCompositeExtract
|
||||||
|
OpStore
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue