Formalize gaussian splat prepare-order pass
This commit is contained in:
@@ -885,7 +885,7 @@ TEST(BuiltinForwardPipeline_Test, BuiltinGaussianSplatShaderUsesAuthoringContrac
|
||||
|
||||
const ShaderPass* pass = shader->FindPass("GaussianSplat");
|
||||
ASSERT_NE(pass, nullptr);
|
||||
EXPECT_EQ(pass->resources.Size(), 5u);
|
||||
EXPECT_EQ(pass->resources.Size(), 6u);
|
||||
EXPECT_TRUE(pass->hasFixedFunctionState);
|
||||
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::None);
|
||||
EXPECT_FALSE(pass->fixedFunctionState.depthWriteEnable);
|
||||
@@ -900,12 +900,22 @@ TEST(BuiltinForwardPipeline_Test, BuiltinGaussianSplatShaderUsesAuthoringContrac
|
||||
ASSERT_NE(opacityScale, nullptr);
|
||||
EXPECT_EQ(opacityScale->type, ShaderPropertyType::Float);
|
||||
|
||||
const ShaderResourceBindingDesc* order =
|
||||
shader->FindPassResourceBinding("GaussianSplat", "GaussianSplatOrderBuffer");
|
||||
ASSERT_NE(order, nullptr);
|
||||
EXPECT_EQ(order->type, ShaderResourceType::StructuredBuffer);
|
||||
EXPECT_EQ(order->set, 2u);
|
||||
EXPECT_EQ(order->binding, 0u);
|
||||
EXPECT_EQ(
|
||||
ResolveBuiltinPassResourceSemantic(*order),
|
||||
BuiltinPassResourceSemantic::GaussianSplatOrderBuffer);
|
||||
|
||||
const ShaderResourceBindingDesc* positions =
|
||||
shader->FindPassResourceBinding("GaussianSplat", "GaussianSplatPositions");
|
||||
ASSERT_NE(positions, nullptr);
|
||||
EXPECT_EQ(positions->type, ShaderResourceType::StructuredBuffer);
|
||||
EXPECT_EQ(positions->set, 2u);
|
||||
EXPECT_EQ(positions->binding, 0u);
|
||||
EXPECT_EQ(positions->binding, 1u);
|
||||
EXPECT_EQ(
|
||||
ResolveBuiltinPassResourceSemantic(*positions),
|
||||
BuiltinPassResourceSemantic::GaussianSplatPositionBuffer);
|
||||
@@ -915,7 +925,7 @@ TEST(BuiltinForwardPipeline_Test, BuiltinGaussianSplatShaderUsesAuthoringContrac
|
||||
ASSERT_NE(other, nullptr);
|
||||
EXPECT_EQ(other->type, ShaderResourceType::StructuredBuffer);
|
||||
EXPECT_EQ(other->set, 2u);
|
||||
EXPECT_EQ(other->binding, 1u);
|
||||
EXPECT_EQ(other->binding, 2u);
|
||||
EXPECT_EQ(
|
||||
ResolveBuiltinPassResourceSemantic(*other),
|
||||
BuiltinPassResourceSemantic::GaussianSplatOtherBuffer);
|
||||
@@ -925,7 +935,7 @@ TEST(BuiltinForwardPipeline_Test, BuiltinGaussianSplatShaderUsesAuthoringContrac
|
||||
ASSERT_NE(color, nullptr);
|
||||
EXPECT_EQ(color->type, ShaderResourceType::StructuredBuffer);
|
||||
EXPECT_EQ(color->set, 2u);
|
||||
EXPECT_EQ(color->binding, 2u);
|
||||
EXPECT_EQ(color->binding, 3u);
|
||||
EXPECT_EQ(
|
||||
ResolveBuiltinPassResourceSemantic(*color),
|
||||
BuiltinPassResourceSemantic::GaussianSplatColorBuffer);
|
||||
@@ -948,21 +958,24 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
||||
BuiltinPassResourceBindingPlan plan = {};
|
||||
String error;
|
||||
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
|
||||
ASSERT_EQ(plan.bindings.Size(), 5u);
|
||||
ASSERT_EQ(plan.bindings.Size(), 6u);
|
||||
EXPECT_TRUE(plan.perObject.IsValid());
|
||||
EXPECT_TRUE(plan.material.IsValid());
|
||||
EXPECT_TRUE(plan.gaussianSplatOrderBuffer.IsValid());
|
||||
EXPECT_TRUE(plan.gaussianSplatPositionBuffer.IsValid());
|
||||
EXPECT_TRUE(plan.gaussianSplatOtherBuffer.IsValid());
|
||||
EXPECT_TRUE(plan.gaussianSplatColorBuffer.IsValid());
|
||||
EXPECT_FALSE(plan.gaussianSplatSHBuffer.IsValid());
|
||||
EXPECT_EQ(plan.perObject.set, 0u);
|
||||
EXPECT_EQ(plan.material.set, 1u);
|
||||
EXPECT_EQ(plan.gaussianSplatOrderBuffer.set, 2u);
|
||||
EXPECT_EQ(plan.gaussianSplatOrderBuffer.binding, 0u);
|
||||
EXPECT_EQ(plan.gaussianSplatPositionBuffer.set, 2u);
|
||||
EXPECT_EQ(plan.gaussianSplatPositionBuffer.binding, 0u);
|
||||
EXPECT_EQ(plan.gaussianSplatPositionBuffer.binding, 1u);
|
||||
EXPECT_EQ(plan.gaussianSplatOtherBuffer.set, 2u);
|
||||
EXPECT_EQ(plan.gaussianSplatOtherBuffer.binding, 1u);
|
||||
EXPECT_EQ(plan.gaussianSplatOtherBuffer.binding, 2u);
|
||||
EXPECT_EQ(plan.gaussianSplatColorBuffer.set, 2u);
|
||||
EXPECT_EQ(plan.gaussianSplatColorBuffer.binding, 2u);
|
||||
EXPECT_EQ(plan.gaussianSplatColorBuffer.binding, 3u);
|
||||
EXPECT_EQ(plan.firstDescriptorSet, 0u);
|
||||
EXPECT_EQ(plan.descriptorSetCount, 3u);
|
||||
|
||||
@@ -971,10 +984,11 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
||||
ASSERT_EQ(setLayouts.size(), 3u);
|
||||
EXPECT_TRUE(setLayouts[0].usesPerObject);
|
||||
EXPECT_TRUE(setLayouts[1].usesMaterial);
|
||||
EXPECT_TRUE(setLayouts[2].usesGaussianSplatOrderBuffer);
|
||||
EXPECT_TRUE(setLayouts[2].usesGaussianSplatPositionBuffer);
|
||||
EXPECT_TRUE(setLayouts[2].usesGaussianSplatOtherBuffer);
|
||||
EXPECT_TRUE(setLayouts[2].usesGaussianSplatColorBuffer);
|
||||
ASSERT_EQ(setLayouts[2].bindings.size(), 3u);
|
||||
ASSERT_EQ(setLayouts[2].bindings.size(), 4u);
|
||||
EXPECT_EQ(
|
||||
static_cast<DescriptorType>(setLayouts[2].bindings[0].type),
|
||||
DescriptorType::SRV);
|
||||
@@ -984,6 +998,9 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
||||
EXPECT_EQ(
|
||||
static_cast<DescriptorType>(setLayouts[2].bindings[2].type),
|
||||
DescriptorType::SRV);
|
||||
EXPECT_EQ(
|
||||
static_cast<DescriptorType>(setLayouts[2].bindings[3].type),
|
||||
DescriptorType::SRV);
|
||||
EXPECT_EQ(
|
||||
setLayouts[2].bindings[0].resourceDimension,
|
||||
ResourceViewDimension::StructuredBuffer);
|
||||
@@ -993,6 +1010,9 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
||||
EXPECT_EQ(
|
||||
setLayouts[2].bindings[2].resourceDimension,
|
||||
ResourceViewDimension::StructuredBuffer);
|
||||
EXPECT_EQ(
|
||||
setLayouts[2].bindings[3].resourceDimension,
|
||||
ResourceViewDimension::StructuredBuffer);
|
||||
|
||||
delete shader;
|
||||
}
|
||||
@@ -1034,16 +1054,20 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesAuthoringGauss
|
||||
"register(b1)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
d3d12Source,
|
||||
"StructuredBuffer<float3> GaussianSplatPositions",
|
||||
"StructuredBuffer<uint> GaussianSplatOrderBuffer",
|
||||
"register(t0)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
d3d12Source,
|
||||
"StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther",
|
||||
"StructuredBuffer<float3> GaussianSplatPositions",
|
||||
"register(t1)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
d3d12Source,
|
||||
"StructuredBuffer<float4> GaussianSplatColor",
|
||||
"StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther",
|
||||
"register(t2)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
d3d12Source,
|
||||
"StructuredBuffer<float4> GaussianSplatColor",
|
||||
"register(t3)"));
|
||||
EXPECT_EQ(d3d12Source.find("space0"), std::string::npos);
|
||||
EXPECT_EQ(d3d12Source.find("space1"), std::string::npos);
|
||||
EXPECT_EQ(d3d12Source.find("space2"), std::string::npos);
|
||||
@@ -1073,16 +1097,20 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesAuthoringGauss
|
||||
"register(b0, space1)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
vulkanSource,
|
||||
"StructuredBuffer<float3> GaussianSplatPositions",
|
||||
"StructuredBuffer<uint> GaussianSplatOrderBuffer",
|
||||
"register(t0, space2)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
vulkanSource,
|
||||
"StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther",
|
||||
"StructuredBuffer<float3> GaussianSplatPositions",
|
||||
"register(t1, space2)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
vulkanSource,
|
||||
"StructuredBuffer<float4> GaussianSplatColor",
|
||||
"StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther",
|
||||
"register(t2, space2)"));
|
||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||
vulkanSource,
|
||||
"StructuredBuffer<float4> GaussianSplatColor",
|
||||
"register(t3, space2)"));
|
||||
|
||||
delete shader;
|
||||
}
|
||||
@@ -2410,6 +2438,57 @@ TEST(BuiltinPassLayout_Test, AcceptsRuntimeMaterialRawUavBufferBindings) {
|
||||
EXPECT_TRUE(setLayouts[4].usesMaterialBuffers);
|
||||
}
|
||||
|
||||
TEST(BuiltinPassLayout_Test, AcceptsRuntimeMaterialTextureBindingsWithoutBuiltinSemanticMetadata) {
|
||||
Array<ShaderResourceBindingDesc> bindings;
|
||||
|
||||
ShaderResourceBindingDesc perObjectBinding = {};
|
||||
perObjectBinding.name = "PerObjectConstants";
|
||||
perObjectBinding.type = ShaderResourceType::ConstantBuffer;
|
||||
perObjectBinding.set = 0u;
|
||||
perObjectBinding.binding = 0u;
|
||||
perObjectBinding.semantic = "PerObject";
|
||||
bindings.PushBack(perObjectBinding);
|
||||
|
||||
ShaderResourceBindingDesc materialBinding = {};
|
||||
materialBinding.name = "MaterialConstants";
|
||||
materialBinding.type = ShaderResourceType::ConstantBuffer;
|
||||
materialBinding.set = 1u;
|
||||
materialBinding.binding = 0u;
|
||||
materialBinding.semantic = "Material";
|
||||
bindings.PushBack(materialBinding);
|
||||
|
||||
ShaderResourceBindingDesc textureBinding = {};
|
||||
textureBinding.name = "_LightMap";
|
||||
textureBinding.type = ShaderResourceType::Texture2D;
|
||||
textureBinding.set = 4u;
|
||||
textureBinding.binding = 1u;
|
||||
bindings.PushBack(textureBinding);
|
||||
|
||||
BuiltinPassResourceBindingPlan plan = {};
|
||||
String error;
|
||||
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(bindings, plan, &error)) << error.CStr();
|
||||
EXPECT_TRUE(plan.usesMaterialTextures);
|
||||
ASSERT_EQ(plan.materialTextureBindings.Size(), 1u);
|
||||
EXPECT_EQ(plan.materialTextureBindings[0].name, "_LightMap");
|
||||
EXPECT_EQ(plan.materialTextureBindings[0].semantic, BuiltinPassResourceSemantic::MaterialTexture);
|
||||
EXPECT_EQ(plan.materialTextureBindings[0].resourceType, ShaderResourceType::Texture2D);
|
||||
EXPECT_EQ(plan.materialTextureBindings[0].location.set, 4u);
|
||||
EXPECT_EQ(plan.materialTextureBindings[0].location.binding, 1u);
|
||||
|
||||
std::vector<BuiltinPassSetLayoutMetadata> setLayouts;
|
||||
ASSERT_TRUE(TryBuildBuiltinPassSetLayouts(plan, setLayouts, &error)) << error.CStr();
|
||||
ASSERT_EQ(setLayouts.size(), 5u);
|
||||
EXPECT_TRUE(setLayouts[4].usesTexture);
|
||||
EXPECT_TRUE(setLayouts[4].usesMaterialTextures);
|
||||
ASSERT_EQ(setLayouts[4].materialTextureBindings.size(), 1u);
|
||||
EXPECT_EQ(setLayouts[4].materialTextureBindings[0].name, "_LightMap");
|
||||
ASSERT_EQ(setLayouts[4].bindings.size(), 1u);
|
||||
EXPECT_EQ(
|
||||
static_cast<DescriptorType>(setLayouts[4].bindings[0].type),
|
||||
DescriptorType::SRV);
|
||||
EXPECT_EQ(setLayouts[4].bindings[0].resourceDimension, ResourceViewDimension::Texture2D);
|
||||
}
|
||||
|
||||
TEST(BuiltinDepthOnlyPass_Test, UsesFloat3PositionInputLayoutForStaticMeshVertices) {
|
||||
const InputLayoutDesc inputLayout = BuiltinDepthOnlyPass::BuildInputLayout();
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <XCEngine/Resources/Shader/Shader.h>
|
||||
#include <XCEngine/Core/Asset/ResourceTypes.h>
|
||||
#include <XCEngine/Core/Containers/Array.h>
|
||||
#include <XCEngine/RHI/RHITypes.h>
|
||||
#include "Rendering/Internal/ShaderVariantUtils.h"
|
||||
|
||||
using namespace XCEngine::Resources;
|
||||
using namespace XCEngine::Containers;
|
||||
@@ -77,6 +79,69 @@ TEST(Shader, AddGetAttributes) {
|
||||
EXPECT_EQ(attributes[0].name, "aPosition");
|
||||
}
|
||||
|
||||
TEST(Shader, StoresBackendCompiledBinariesPerBackend) {
|
||||
ShaderStageVariant variant = {};
|
||||
variant.stage = ShaderType::Fragment;
|
||||
variant.language = ShaderLanguage::HLSL;
|
||||
variant.backend = ShaderBackend::Generic;
|
||||
|
||||
Array<XCEngine::Core::uint8> d3d12Payload;
|
||||
d3d12Payload.PushBack(0x01);
|
||||
d3d12Payload.PushBack(0x02);
|
||||
variant.SetCompiledBinaryForBackend(ShaderBackend::D3D12, d3d12Payload);
|
||||
|
||||
Array<XCEngine::Core::uint8> vulkanPayload;
|
||||
vulkanPayload.PushBack(0x03);
|
||||
vulkanPayload.PushBack(0x04);
|
||||
vulkanPayload.PushBack(0x05);
|
||||
variant.SetCompiledBinaryForBackend(ShaderBackend::Vulkan, vulkanPayload);
|
||||
|
||||
const Array<XCEngine::Core::uint8>* d3d12Binary =
|
||||
variant.GetCompiledBinaryForBackend(ShaderBackend::D3D12);
|
||||
ASSERT_NE(d3d12Binary, nullptr);
|
||||
ASSERT_EQ(d3d12Binary->Size(), 2u);
|
||||
EXPECT_EQ((*d3d12Binary)[1], 0x02);
|
||||
|
||||
const Array<XCEngine::Core::uint8>* vulkanBinary =
|
||||
variant.GetCompiledBinaryForBackend(ShaderBackend::Vulkan);
|
||||
ASSERT_NE(vulkanBinary, nullptr);
|
||||
ASSERT_EQ(vulkanBinary->Size(), 3u);
|
||||
EXPECT_EQ((*vulkanBinary)[2], 0x05);
|
||||
|
||||
EXPECT_EQ(variant.GetCompiledBinaryForBackend(ShaderBackend::OpenGL), nullptr);
|
||||
}
|
||||
|
||||
TEST(Shader, ApplyShaderStageVariantCarriesMatchedBackendCompiledBinary) {
|
||||
ShaderPass pass = {};
|
||||
pass.name = "ForwardLit";
|
||||
|
||||
ShaderStageVariant variant = {};
|
||||
variant.stage = ShaderType::Fragment;
|
||||
variant.language = ShaderLanguage::HLSL;
|
||||
variant.backend = ShaderBackend::Generic;
|
||||
variant.entryPoint = "MainPS";
|
||||
variant.profile = "ps_5_1";
|
||||
variant.sourceCode = "float4 MainPS() : SV_TARGET { return 1; }";
|
||||
|
||||
Array<XCEngine::Core::uint8> vulkanPayload;
|
||||
vulkanPayload.PushBack(0x07);
|
||||
vulkanPayload.PushBack(0x08);
|
||||
vulkanPayload.PushBack(0x09);
|
||||
variant.SetCompiledBinaryForBackend(ShaderBackend::Vulkan, vulkanPayload);
|
||||
|
||||
XCEngine::RHI::ShaderCompileDesc compileDesc = {};
|
||||
::XCEngine::Rendering::Internal::ApplyShaderStageVariant(
|
||||
pass,
|
||||
ShaderBackend::Vulkan,
|
||||
variant,
|
||||
compileDesc);
|
||||
|
||||
EXPECT_EQ(compileDesc.compiledBinaryBackend, XCEngine::RHI::ShaderBinaryBackend::Vulkan);
|
||||
ASSERT_EQ(compileDesc.compiledBinary.size(), 3u);
|
||||
EXPECT_EQ(compileDesc.compiledBinary[0], 0x07);
|
||||
EXPECT_EQ(compileDesc.compiledBinary[2], 0x09);
|
||||
}
|
||||
|
||||
TEST(Shader, FindsBackendSpecificVariantAndFallsBackToGeneric) {
|
||||
Shader shader;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user