239 lines
9.3 KiB
C++
239 lines
9.3 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include <XCEngine/Rendering/Passes/BuiltinObjectIdPass.h>
|
|
#include <XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h>
|
|
#include <XCEngine/Resources/BuiltinResources.h>
|
|
#include <XCEngine/Resources/Mesh/Mesh.h>
|
|
#include <XCEngine/Resources/Shader/Shader.h>
|
|
#include <XCEngine/Resources/Shader/ShaderLoader.h>
|
|
#include <XCEngine/RHI/RHIEnums.h>
|
|
|
|
using namespace XCEngine::Rendering::Pipelines;
|
|
using namespace XCEngine::Rendering::Passes;
|
|
using namespace XCEngine::Rendering;
|
|
using namespace XCEngine::Containers;
|
|
using namespace XCEngine::Resources;
|
|
using namespace XCEngine::RHI;
|
|
|
|
TEST(BuiltinForwardPipeline_Test, UsesFloat3PositionInputLayoutForStaticMeshVertices) {
|
|
const InputLayoutDesc inputLayout = BuiltinForwardPipeline::BuildInputLayout();
|
|
|
|
ASSERT_EQ(inputLayout.elements.size(), 3u);
|
|
|
|
const InputElementDesc& position = inputLayout.elements[0];
|
|
EXPECT_EQ(position.semanticName, "POSITION");
|
|
EXPECT_EQ(position.semanticIndex, 0u);
|
|
EXPECT_EQ(position.format, static_cast<uint32_t>(Format::R32G32B32_Float));
|
|
EXPECT_EQ(position.inputSlot, 0u);
|
|
EXPECT_EQ(position.alignedByteOffset, 0u);
|
|
|
|
const InputElementDesc& normal = inputLayout.elements[1];
|
|
EXPECT_EQ(normal.semanticName, "NORMAL");
|
|
EXPECT_EQ(normal.semanticIndex, 0u);
|
|
EXPECT_EQ(normal.format, static_cast<uint32_t>(Format::R32G32B32_Float));
|
|
EXPECT_EQ(normal.inputSlot, 0u);
|
|
EXPECT_EQ(normal.alignedByteOffset, static_cast<uint32_t>(offsetof(StaticMeshVertex, normal)));
|
|
|
|
const InputElementDesc& texcoord = inputLayout.elements[2];
|
|
EXPECT_EQ(texcoord.semanticName, "TEXCOORD");
|
|
EXPECT_EQ(texcoord.semanticIndex, 0u);
|
|
EXPECT_EQ(texcoord.format, static_cast<uint32_t>(Format::R32G32_Float));
|
|
EXPECT_EQ(texcoord.inputSlot, 0u);
|
|
EXPECT_EQ(texcoord.alignedByteOffset, static_cast<uint32_t>(offsetof(StaticMeshVertex, uv0)));
|
|
}
|
|
|
|
TEST(BuiltinForwardPipeline_Test, BuiltinForwardShaderDeclaresExplicitForwardResourceContract) {
|
|
ShaderLoader loader;
|
|
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
|
|
ASSERT_TRUE(result);
|
|
ASSERT_NE(result.resource, nullptr);
|
|
|
|
Shader* shader = static_cast<Shader*>(result.resource);
|
|
ASSERT_NE(shader, nullptr);
|
|
|
|
const ShaderPass* pass = shader->FindPass("ForwardLit");
|
|
ASSERT_NE(pass, nullptr);
|
|
ASSERT_EQ(pass->resources.Size(), 4u);
|
|
|
|
EXPECT_EQ(pass->resources[0].semantic, "PerObject");
|
|
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
|
|
EXPECT_EQ(pass->resources[0].set, 1u);
|
|
EXPECT_EQ(pass->resources[0].binding, 0u);
|
|
|
|
EXPECT_EQ(pass->resources[1].semantic, "Material");
|
|
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer);
|
|
EXPECT_EQ(pass->resources[1].set, 2u);
|
|
EXPECT_EQ(pass->resources[1].binding, 0u);
|
|
|
|
EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture");
|
|
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D);
|
|
EXPECT_EQ(pass->resources[2].set, 3u);
|
|
EXPECT_EQ(pass->resources[2].binding, 0u);
|
|
|
|
EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler");
|
|
EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler);
|
|
EXPECT_EQ(pass->resources[3].set, 4u);
|
|
EXPECT_EQ(pass->resources[3].binding, 0u);
|
|
|
|
delete shader;
|
|
}
|
|
|
|
TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderDeclaresExplicitSurfaceResourceContract) {
|
|
ShaderLoader loader;
|
|
LoadResult result = loader.Load(GetBuiltinUnlitShaderPath());
|
|
ASSERT_TRUE(result);
|
|
ASSERT_NE(result.resource, nullptr);
|
|
|
|
Shader* shader = static_cast<Shader*>(result.resource);
|
|
ASSERT_NE(shader, nullptr);
|
|
|
|
const ShaderPass* pass = shader->FindPass("Unlit");
|
|
ASSERT_NE(pass, nullptr);
|
|
ASSERT_EQ(pass->resources.Size(), 4u);
|
|
|
|
EXPECT_EQ(pass->resources[0].semantic, "PerObject");
|
|
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
|
|
EXPECT_EQ(pass->resources[0].set, 1u);
|
|
EXPECT_EQ(pass->resources[0].binding, 0u);
|
|
|
|
EXPECT_EQ(pass->resources[1].semantic, "Material");
|
|
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer);
|
|
EXPECT_EQ(pass->resources[1].set, 2u);
|
|
EXPECT_EQ(pass->resources[1].binding, 0u);
|
|
|
|
EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture");
|
|
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D);
|
|
EXPECT_EQ(pass->resources[2].set, 3u);
|
|
EXPECT_EQ(pass->resources[2].binding, 0u);
|
|
|
|
EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler");
|
|
EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler);
|
|
EXPECT_EQ(pass->resources[3].set, 4u);
|
|
EXPECT_EQ(pass->resources[3].binding, 0u);
|
|
|
|
delete shader;
|
|
}
|
|
|
|
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplicitForwardResources) {
|
|
ShaderLoader loader;
|
|
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
|
|
ASSERT_TRUE(result);
|
|
ASSERT_NE(result.resource, nullptr);
|
|
|
|
Shader* shader = static_cast<Shader*>(result.resource);
|
|
ASSERT_NE(shader, nullptr);
|
|
|
|
const ShaderPass* pass = shader->FindPass("ForwardLit");
|
|
ASSERT_NE(pass, nullptr);
|
|
|
|
BuiltinPassResourceBindingPlan plan = {};
|
|
String error;
|
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
|
|
EXPECT_TRUE(plan.perObject.IsValid());
|
|
EXPECT_TRUE(plan.material.IsValid());
|
|
EXPECT_TRUE(plan.baseColorTexture.IsValid());
|
|
EXPECT_TRUE(plan.linearClampSampler.IsValid());
|
|
EXPECT_EQ(plan.firstDescriptorSet, 1u);
|
|
EXPECT_EQ(plan.descriptorSetCount, 4u);
|
|
EXPECT_TRUE(plan.usesConstantBuffers);
|
|
EXPECT_TRUE(plan.usesTextures);
|
|
EXPECT_TRUE(plan.usesSamplers);
|
|
|
|
delete shader;
|
|
}
|
|
|
|
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplicitUnlitResources) {
|
|
ShaderLoader loader;
|
|
LoadResult result = loader.Load(GetBuiltinUnlitShaderPath());
|
|
ASSERT_TRUE(result);
|
|
ASSERT_NE(result.resource, nullptr);
|
|
|
|
Shader* shader = static_cast<Shader*>(result.resource);
|
|
ASSERT_NE(shader, nullptr);
|
|
|
|
const ShaderPass* pass = shader->FindPass("Unlit");
|
|
ASSERT_NE(pass, nullptr);
|
|
|
|
BuiltinPassResourceBindingPlan plan = {};
|
|
String error;
|
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
|
|
EXPECT_TRUE(plan.perObject.IsValid());
|
|
EXPECT_TRUE(plan.material.IsValid());
|
|
EXPECT_TRUE(plan.baseColorTexture.IsValid());
|
|
EXPECT_TRUE(plan.linearClampSampler.IsValid());
|
|
EXPECT_EQ(plan.firstDescriptorSet, 1u);
|
|
EXPECT_EQ(plan.descriptorSetCount, 4u);
|
|
EXPECT_TRUE(plan.usesConstantBuffers);
|
|
EXPECT_TRUE(plan.usesTextures);
|
|
EXPECT_TRUE(plan.usesSamplers);
|
|
|
|
delete shader;
|
|
}
|
|
|
|
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLegacyFallbackResources) {
|
|
const Array<ShaderResourceBindingDesc> bindings = BuildLegacyBuiltinForwardPassResourceBindings();
|
|
ASSERT_EQ(bindings.Size(), 4u);
|
|
|
|
BuiltinPassResourceBindingPlan plan = {};
|
|
String error;
|
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(bindings, plan, &error)) << error.CStr();
|
|
ASSERT_EQ(plan.bindings.Size(), 4u);
|
|
EXPECT_EQ(plan.perObject.set, 1u);
|
|
EXPECT_EQ(plan.material.set, 2u);
|
|
EXPECT_EQ(plan.baseColorTexture.set, 3u);
|
|
EXPECT_EQ(plan.linearClampSampler.set, 4u);
|
|
}
|
|
|
|
TEST(BuiltinObjectIdPass_Test, BuiltinObjectIdShaderDeclaresExplicitPerObjectResourceContract) {
|
|
ShaderLoader loader;
|
|
LoadResult result = loader.Load(GetBuiltinObjectIdShaderPath());
|
|
ASSERT_TRUE(result);
|
|
ASSERT_NE(result.resource, nullptr);
|
|
|
|
Shader* shader = static_cast<Shader*>(result.resource);
|
|
ASSERT_NE(shader, nullptr);
|
|
|
|
const ShaderPass* pass = shader->FindPass("ObjectId");
|
|
ASSERT_NE(pass, nullptr);
|
|
ASSERT_EQ(pass->resources.Size(), 1u);
|
|
|
|
EXPECT_EQ(pass->resources[0].semantic, "PerObject");
|
|
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
|
|
EXPECT_EQ(pass->resources[0].set, 0u);
|
|
EXPECT_EQ(pass->resources[0].binding, 0u);
|
|
|
|
delete shader;
|
|
}
|
|
|
|
TEST(BuiltinObjectIdPass_Test, BuildsBuiltinPassResourceBindingPlanFromLegacyFallbackResources) {
|
|
const Array<ShaderResourceBindingDesc> bindings = BuildLegacyBuiltinObjectIdPassResourceBindings();
|
|
ASSERT_EQ(bindings.Size(), 1u);
|
|
|
|
BuiltinPassResourceBindingPlan plan = {};
|
|
String error;
|
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(bindings, plan, &error)) << error.CStr();
|
|
ASSERT_EQ(plan.bindings.Size(), 1u);
|
|
EXPECT_TRUE(plan.perObject.IsValid());
|
|
EXPECT_FALSE(plan.material.IsValid());
|
|
EXPECT_FALSE(plan.baseColorTexture.IsValid());
|
|
EXPECT_FALSE(plan.linearClampSampler.IsValid());
|
|
EXPECT_EQ(plan.firstDescriptorSet, 0u);
|
|
EXPECT_EQ(plan.descriptorSetCount, 1u);
|
|
EXPECT_TRUE(plan.usesConstantBuffers);
|
|
EXPECT_FALSE(plan.usesTextures);
|
|
EXPECT_FALSE(plan.usesSamplers);
|
|
}
|
|
|
|
TEST(BuiltinObjectIdPass_Test, UsesFloat3PositionInputLayoutForStaticMeshVertices) {
|
|
const InputLayoutDesc inputLayout = BuiltinObjectIdPass::BuildInputLayout();
|
|
|
|
ASSERT_EQ(inputLayout.elements.size(), 1u);
|
|
|
|
const InputElementDesc& position = inputLayout.elements[0];
|
|
EXPECT_EQ(position.semanticName, "POSITION");
|
|
EXPECT_EQ(position.semanticIndex, 0u);
|
|
EXPECT_EQ(position.format, static_cast<uint32_t>(Format::R32G32B32_Float));
|
|
EXPECT_EQ(position.inputSlot, 0u);
|
|
EXPECT_EQ(position.alignedByteOffset, static_cast<uint32_t>(offsetof(StaticMeshVertex, position)));
|
|
}
|