Add SH shading to gaussian splat renderer
This commit is contained in:
@@ -15,6 +15,72 @@ Shader "Builtin Gaussian Splat Utilities"
|
|||||||
float4 colorOpacity;
|
float4 colorOpacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GaussianSplatSHData
|
||||||
|
{
|
||||||
|
float coefficients[45];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const float SH_C1 = 0.4886025;
|
||||||
|
static const float SH_C2[] = { 1.0925484, -1.0925484, 0.3153916, -1.0925484, 0.5462742 };
|
||||||
|
static const float SH_C3[] = { -0.5900436, 2.8906114, -0.4570458, 0.3731763, -0.4570458, 1.4453057, -0.5900436 };
|
||||||
|
|
||||||
|
float3 LoadSHCoefficientTriplet(GaussianSplatSHData data, uint coefficientIndex)
|
||||||
|
{
|
||||||
|
return float3(
|
||||||
|
data.coefficients[coefficientIndex + 0u],
|
||||||
|
data.coefficients[coefficientIndex + 15u],
|
||||||
|
data.coefficients[coefficientIndex + 30u]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 ShadeGaussianSplatSH(float3 baseColor, GaussianSplatSHData data, float3 direction, uint shOrder)
|
||||||
|
{
|
||||||
|
direction *= -1.0;
|
||||||
|
|
||||||
|
const float x = direction.x;
|
||||||
|
const float y = direction.y;
|
||||||
|
const float z = direction.z;
|
||||||
|
float3 result = baseColor;
|
||||||
|
|
||||||
|
if (shOrder >= 1u)
|
||||||
|
{
|
||||||
|
result += SH_C1 * (
|
||||||
|
-LoadSHCoefficientTriplet(data, 0u) * y +
|
||||||
|
LoadSHCoefficientTriplet(data, 1u) * z -
|
||||||
|
LoadSHCoefficientTriplet(data, 2u) * x);
|
||||||
|
|
||||||
|
if (shOrder >= 2u)
|
||||||
|
{
|
||||||
|
const float xx = x * x;
|
||||||
|
const float yy = y * y;
|
||||||
|
const float zz = z * z;
|
||||||
|
const float xy = x * y;
|
||||||
|
const float yz = y * z;
|
||||||
|
const float xz = x * z;
|
||||||
|
|
||||||
|
result +=
|
||||||
|
(SH_C2[0] * xy) * LoadSHCoefficientTriplet(data, 3u) +
|
||||||
|
(SH_C2[1] * yz) * LoadSHCoefficientTriplet(data, 4u) +
|
||||||
|
(SH_C2[2] * (2.0 * zz - xx - yy)) * LoadSHCoefficientTriplet(data, 5u) +
|
||||||
|
(SH_C2[3] * xz) * LoadSHCoefficientTriplet(data, 6u) +
|
||||||
|
(SH_C2[4] * (xx - yy)) * LoadSHCoefficientTriplet(data, 7u);
|
||||||
|
|
||||||
|
if (shOrder >= 3u)
|
||||||
|
{
|
||||||
|
result +=
|
||||||
|
(SH_C3[0] * y * (3.0 * xx - yy)) * LoadSHCoefficientTriplet(data, 8u) +
|
||||||
|
(SH_C3[1] * xy * z) * LoadSHCoefficientTriplet(data, 9u) +
|
||||||
|
(SH_C3[2] * y * (4.0 * zz - xx - yy)) * LoadSHCoefficientTriplet(data, 10u) +
|
||||||
|
(SH_C3[3] * z * (2.0 * zz - 3.0 * xx - 3.0 * yy)) * LoadSHCoefficientTriplet(data, 11u) +
|
||||||
|
(SH_C3[4] * x * (4.0 * zz - xx - yy)) * LoadSHCoefficientTriplet(data, 12u) +
|
||||||
|
(SH_C3[5] * z * (xx - yy)) * LoadSHCoefficientTriplet(data, 13u) +
|
||||||
|
(SH_C3[6] * x * (xx - 3.0 * yy)) * LoadSHCoefficientTriplet(data, 14u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return max(result, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
uint FloatToSortableUint(float value)
|
uint FloatToSortableUint(float value)
|
||||||
{
|
{
|
||||||
const uint rawValue = asuint(value);
|
const uint rawValue = asuint(value);
|
||||||
@@ -133,8 +199,10 @@ Shader "Builtin Gaussian Splat Utilities"
|
|||||||
float4x4 gProjectionMatrix;
|
float4x4 gProjectionMatrix;
|
||||||
float4x4 gViewMatrix;
|
float4x4 gViewMatrix;
|
||||||
float4x4 gModelMatrix;
|
float4x4 gModelMatrix;
|
||||||
|
float4x4 gWorldToObjectMatrix;
|
||||||
float4 gCameraRight;
|
float4 gCameraRight;
|
||||||
float4 gCameraUp;
|
float4 gCameraUp;
|
||||||
|
float4 gCameraWorldPos;
|
||||||
float4 gScreenParams;
|
float4 gScreenParams;
|
||||||
float4 gSplatParams;
|
float4 gSplatParams;
|
||||||
};
|
};
|
||||||
@@ -142,6 +210,7 @@ Shader "Builtin Gaussian Splat Utilities"
|
|||||||
StructuredBuffer<float4> GaussianSplatPositions;
|
StructuredBuffer<float4> GaussianSplatPositions;
|
||||||
StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther;
|
StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther;
|
||||||
StructuredBuffer<float4> GaussianSplatColor;
|
StructuredBuffer<float4> GaussianSplatColor;
|
||||||
|
StructuredBuffer<GaussianSplatSHData> GaussianSplatSH;
|
||||||
RWStructuredBuffer<uint> GaussianSplatSortDistances;
|
RWStructuredBuffer<uint> GaussianSplatSortDistances;
|
||||||
RWStructuredBuffer<uint> GaussianSplatOrderBuffer;
|
RWStructuredBuffer<uint> GaussianSplatOrderBuffer;
|
||||||
RWStructuredBuffer<GaussianSplatViewData> GaussianSplatViewDataBuffer;
|
RWStructuredBuffer<GaussianSplatViewData> GaussianSplatViewDataBuffer;
|
||||||
@@ -170,6 +239,8 @@ Shader "Builtin Gaussian Splat Utilities"
|
|||||||
const float3 localCenter = GaussianSplatPositions[index].xyz;
|
const float3 localCenter = GaussianSplatPositions[index].xyz;
|
||||||
const GaussianSplatOtherData otherData = GaussianSplatOther[index];
|
const GaussianSplatOtherData otherData = GaussianSplatOther[index];
|
||||||
const float4 colorOpacity = GaussianSplatColor[index];
|
const float4 colorOpacity = GaussianSplatColor[index];
|
||||||
|
const GaussianSplatSHData shData = GaussianSplatSH[index];
|
||||||
|
const uint shOrder = min((uint)gSplatParams.z, 3u);
|
||||||
|
|
||||||
const float3 worldCenter = mul(gModelMatrix, float4(localCenter, 1.0)).xyz;
|
const float3 worldCenter = mul(gModelMatrix, float4(localCenter, 1.0)).xyz;
|
||||||
const float3 viewCenter = mul(gViewMatrix, float4(worldCenter, 1.0)).xyz;
|
const float3 viewCenter = mul(gViewMatrix, float4(worldCenter, 1.0)).xyz;
|
||||||
@@ -202,7 +273,16 @@ Shader "Builtin Gaussian Splat Utilities"
|
|||||||
viewData.clipCenter = clipCenter;
|
viewData.clipCenter = clipCenter;
|
||||||
viewData.ellipseAxisU = float4(axisU, 0.0, 0.0);
|
viewData.ellipseAxisU = float4(axisU, 0.0, 0.0);
|
||||||
viewData.ellipseAxisV = float4(axisV, 0.0, 0.0);
|
viewData.ellipseAxisV = float4(axisV, 0.0, 0.0);
|
||||||
viewData.colorOpacity = colorOpacity;
|
float3 shadedColor = colorOpacity.rgb;
|
||||||
|
if (shOrder > 0u)
|
||||||
|
{
|
||||||
|
const float3 worldViewDirection = gCameraWorldPos.xyz - worldCenter;
|
||||||
|
const float3 objectViewDirection = normalize(
|
||||||
|
mul((float3x3)gWorldToObjectMatrix, worldViewDirection));
|
||||||
|
shadedColor = ShadeGaussianSplatSH(colorOpacity.rgb, shData, objectViewDirection, shOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewData.colorOpacity = float4(shadedColor, colorOpacity.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
GaussianSplatViewDataBuffer[index] = viewData;
|
GaussianSplatViewDataBuffer[index] = viewData;
|
||||||
@@ -222,8 +302,10 @@ Shader "Builtin Gaussian Splat Utilities"
|
|||||||
float4x4 gProjectionMatrix;
|
float4x4 gProjectionMatrix;
|
||||||
float4x4 gViewMatrix;
|
float4x4 gViewMatrix;
|
||||||
float4x4 gModelMatrix;
|
float4x4 gModelMatrix;
|
||||||
|
float4x4 gWorldToObjectMatrix;
|
||||||
float4 gCameraRight;
|
float4 gCameraRight;
|
||||||
float4 gCameraUp;
|
float4 gCameraUp;
|
||||||
|
float4 gCameraWorldPos;
|
||||||
float4 gScreenParams;
|
float4 gScreenParams;
|
||||||
float4 gSplatParams;
|
float4 gSplatParams;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ Shader "Builtin Gaussian Splat"
|
|||||||
float4x4 gProjectionMatrix;
|
float4x4 gProjectionMatrix;
|
||||||
float4x4 gViewMatrix;
|
float4x4 gViewMatrix;
|
||||||
float4x4 gModelMatrix;
|
float4x4 gModelMatrix;
|
||||||
|
float4x4 gWorldToObjectMatrix;
|
||||||
float4 gCameraRight;
|
float4 gCameraRight;
|
||||||
float4 gCameraUp;
|
float4 gCameraUp;
|
||||||
|
float4 gCameraWorldPos;
|
||||||
float4 gScreenParams;
|
float4 gScreenParams;
|
||||||
float4 gSplatParams;
|
float4 gSplatParams;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,8 +57,10 @@ private:
|
|||||||
Math::Matrix4x4 projection = Math::Matrix4x4::Identity();
|
Math::Matrix4x4 projection = Math::Matrix4x4::Identity();
|
||||||
Math::Matrix4x4 view = Math::Matrix4x4::Identity();
|
Math::Matrix4x4 view = Math::Matrix4x4::Identity();
|
||||||
Math::Matrix4x4 model = Math::Matrix4x4::Identity();
|
Math::Matrix4x4 model = Math::Matrix4x4::Identity();
|
||||||
|
Math::Matrix4x4 worldToObject = Math::Matrix4x4::Identity();
|
||||||
Math::Vector4 cameraRight = Math::Vector4::Zero();
|
Math::Vector4 cameraRight = Math::Vector4::Zero();
|
||||||
Math::Vector4 cameraUp = Math::Vector4::Zero();
|
Math::Vector4 cameraUp = Math::Vector4::Zero();
|
||||||
|
Math::Vector4 cameraWorldPos = Math::Vector4::Zero();
|
||||||
Math::Vector4 screenParams = Math::Vector4::Zero();
|
Math::Vector4 screenParams = Math::Vector4::Zero();
|
||||||
Math::Vector4 splatParams = Math::Vector4::Zero();
|
Math::Vector4 splatParams = Math::Vector4::Zero();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -243,7 +243,8 @@ bool BuiltinGaussianSplatPass::PrepareGaussianSplatResources(
|
|||||||
if (cachedGaussianSplat == nullptr ||
|
if (cachedGaussianSplat == nullptr ||
|
||||||
cachedGaussianSplat->positions.shaderResourceView == nullptr ||
|
cachedGaussianSplat->positions.shaderResourceView == nullptr ||
|
||||||
cachedGaussianSplat->other.shaderResourceView == nullptr ||
|
cachedGaussianSplat->other.shaderResourceView == nullptr ||
|
||||||
cachedGaussianSplat->color.shaderResourceView == nullptr) {
|
cachedGaussianSplat->color.shaderResourceView == nullptr ||
|
||||||
|
cachedGaussianSplat->sh.shaderResourceView == nullptr) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"BuiltinGaussianSplatPass::PrepareGaussianSplatResources failed: gaussian splat GPU cache incomplete");
|
"BuiltinGaussianSplatPass::PrepareGaussianSplatResources failed: gaussian splat GPU cache incomplete");
|
||||||
@@ -599,9 +600,10 @@ BuiltinGaussianSplatPass::PassResourceLayout* BuiltinGaussianSplatPass::GetOrCre
|
|||||||
!passLayout.gaussianSplatPositionBuffer.IsValid() ||
|
!passLayout.gaussianSplatPositionBuffer.IsValid() ||
|
||||||
!passLayout.gaussianSplatOtherBuffer.IsValid() ||
|
!passLayout.gaussianSplatOtherBuffer.IsValid() ||
|
||||||
!passLayout.gaussianSplatColorBuffer.IsValid() ||
|
!passLayout.gaussianSplatColorBuffer.IsValid() ||
|
||||||
|
!passLayout.gaussianSplatSHBuffer.IsValid() ||
|
||||||
!passLayout.gaussianSplatViewDataBuffer.IsValid()) {
|
!passLayout.gaussianSplatViewDataBuffer.IsValid()) {
|
||||||
return failLayout(
|
return failLayout(
|
||||||
"BuiltinGaussianSplatPass prepare-order pass requires sort distance, order, position, other, color, and view-data gaussian splat buffer bindings");
|
"BuiltinGaussianSplatPass prepare-order pass requires sort distance, order, position, other, color, SH, and view-data gaussian splat buffer bindings");
|
||||||
}
|
}
|
||||||
} else if (usage == PassLayoutUsage::BitonicSort) {
|
} else if (usage == PassLayoutUsage::BitonicSort) {
|
||||||
if (!passLayout.gaussianSplatSortDistanceBuffer.IsValid() ||
|
if (!passLayout.gaussianSplatSortDistanceBuffer.IsValid() ||
|
||||||
@@ -1012,7 +1014,11 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
|||||||
|
|
||||||
const RenderResourceCache::CachedGaussianSplat* cachedGaussianSplat =
|
const RenderResourceCache::CachedGaussianSplat* cachedGaussianSplat =
|
||||||
m_resourceCache.GetOrCreateGaussianSplat(m_device, visibleGaussianSplat.gaussianSplat);
|
m_resourceCache.GetOrCreateGaussianSplat(m_device, visibleGaussianSplat.gaussianSplat);
|
||||||
if (cachedGaussianSplat == nullptr || cachedGaussianSplat->positions.shaderResourceView == nullptr) {
|
if (cachedGaussianSplat == nullptr ||
|
||||||
|
cachedGaussianSplat->positions.shaderResourceView == nullptr ||
|
||||||
|
cachedGaussianSplat->other.shaderResourceView == nullptr ||
|
||||||
|
cachedGaussianSplat->color.shaderResourceView == nullptr ||
|
||||||
|
cachedGaussianSplat->sh.shaderResourceView == nullptr) {
|
||||||
return fail("BuiltinGaussianSplatPass prepare-order failed: gaussian splat GPU cache is incomplete");
|
return fail("BuiltinGaussianSplatPass prepare-order failed: gaussian splat GPU cache is incomplete");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,8 +1068,10 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
|||||||
sceneData.cameraData.projection,
|
sceneData.cameraData.projection,
|
||||||
sceneData.cameraData.view,
|
sceneData.cameraData.view,
|
||||||
visibleGaussianSplat.localToWorld.Transpose(),
|
visibleGaussianSplat.localToWorld.Transpose(),
|
||||||
|
visibleGaussianSplat.localToWorld.Inverse(),
|
||||||
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
||||||
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
||||||
|
Math::Vector4(sceneData.cameraData.worldPosition, 0.0f),
|
||||||
Math::Vector4(
|
Math::Vector4(
|
||||||
static_cast<float>(sceneData.cameraData.viewportWidth),
|
static_cast<float>(sceneData.cameraData.viewportWidth),
|
||||||
static_cast<float>(sceneData.cameraData.viewportHeight),
|
static_cast<float>(sceneData.cameraData.viewportHeight),
|
||||||
@@ -1072,7 +1080,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
|||||||
Math::Vector4(
|
Math::Vector4(
|
||||||
static_cast<float>(cachedGaussianSplat->splatCount),
|
static_cast<float>(cachedGaussianSplat->splatCount),
|
||||||
static_cast<float>(workingSet->sortCapacity),
|
static_cast<float>(workingSet->sortCapacity),
|
||||||
0.0f,
|
3.0f,
|
||||||
0.0f)
|
0.0f)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1095,6 +1103,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
|||||||
setLayout.usesGaussianSplatPositionBuffer ||
|
setLayout.usesGaussianSplatPositionBuffer ||
|
||||||
setLayout.usesGaussianSplatOtherBuffer ||
|
setLayout.usesGaussianSplatOtherBuffer ||
|
||||||
setLayout.usesGaussianSplatColorBuffer ||
|
setLayout.usesGaussianSplatColorBuffer ||
|
||||||
|
setLayout.usesGaussianSplatSHBuffer ||
|
||||||
setLayout.usesGaussianSplatViewDataBuffer)) {
|
setLayout.usesGaussianSplatViewDataBuffer)) {
|
||||||
return fail("BuiltinGaussianSplatPass prepare-order failed: unexpected descriptor set layout");
|
return fail("BuiltinGaussianSplatPass prepare-order failed: unexpected descriptor set layout");
|
||||||
}
|
}
|
||||||
@@ -1107,6 +1116,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
|||||||
setLayout.usesGaussianSplatPositionBuffer ||
|
setLayout.usesGaussianSplatPositionBuffer ||
|
||||||
setLayout.usesGaussianSplatOtherBuffer ||
|
setLayout.usesGaussianSplatOtherBuffer ||
|
||||||
setLayout.usesGaussianSplatColorBuffer ||
|
setLayout.usesGaussianSplatColorBuffer ||
|
||||||
|
setLayout.usesGaussianSplatSHBuffer ||
|
||||||
setLayout.usesGaussianSplatViewDataBuffer)
|
setLayout.usesGaussianSplatViewDataBuffer)
|
||||||
? visibleGaussianSplat.gaussianSplat
|
? visibleGaussianSplat.gaussianSplat
|
||||||
: nullptr;
|
: nullptr;
|
||||||
@@ -1239,8 +1249,10 @@ bool BuiltinGaussianSplatPass::SortVisibleGaussianSplat(
|
|||||||
sceneData.cameraData.projection,
|
sceneData.cameraData.projection,
|
||||||
sceneData.cameraData.view,
|
sceneData.cameraData.view,
|
||||||
visibleGaussianSplat.localToWorld.Transpose(),
|
visibleGaussianSplat.localToWorld.Transpose(),
|
||||||
|
visibleGaussianSplat.localToWorld.Inverse(),
|
||||||
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
||||||
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
||||||
|
Math::Vector4(sceneData.cameraData.worldPosition, 0.0f),
|
||||||
Math::Vector4(
|
Math::Vector4(
|
||||||
static_cast<float>(sceneData.cameraData.viewportWidth),
|
static_cast<float>(sceneData.cameraData.viewportWidth),
|
||||||
static_cast<float>(sceneData.cameraData.viewportHeight),
|
static_cast<float>(sceneData.cameraData.viewportHeight),
|
||||||
@@ -1409,8 +1421,10 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
|||||||
sceneData.cameraData.projection,
|
sceneData.cameraData.projection,
|
||||||
sceneData.cameraData.view,
|
sceneData.cameraData.view,
|
||||||
visibleGaussianSplat.localToWorld.Transpose(),
|
visibleGaussianSplat.localToWorld.Transpose(),
|
||||||
|
visibleGaussianSplat.localToWorld.Inverse(),
|
||||||
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
||||||
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
||||||
|
Math::Vector4(sceneData.cameraData.worldPosition, 0.0f),
|
||||||
Math::Vector4(
|
Math::Vector4(
|
||||||
static_cast<float>(sceneData.cameraData.viewportWidth),
|
static_cast<float>(sceneData.cameraData.viewportWidth),
|
||||||
static_cast<float>(sceneData.cameraData.viewportHeight),
|
static_cast<float>(sceneData.cameraData.viewportHeight),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -135,7 +135,7 @@ private:
|
|||||||
TEST(BuiltinForwardPipeline_Test, UsesFloat3PositionInputLayoutForStaticMeshVertices) {
|
TEST(BuiltinForwardPipeline_Test, UsesFloat3PositionInputLayoutForStaticMeshVertices) {
|
||||||
const InputLayoutDesc inputLayout = BuiltinForwardPipeline::BuildInputLayout();
|
const InputLayoutDesc inputLayout = BuiltinForwardPipeline::BuildInputLayout();
|
||||||
|
|
||||||
ASSERT_EQ(inputLayout.elements.size(), 3u);
|
ASSERT_EQ(inputLayout.elements.size(), 5u);
|
||||||
|
|
||||||
const InputElementDesc& position = inputLayout.elements[0];
|
const InputElementDesc& position = inputLayout.elements[0];
|
||||||
EXPECT_EQ(position.semanticName, "POSITION");
|
EXPECT_EQ(position.semanticName, "POSITION");
|
||||||
@@ -157,6 +157,20 @@ TEST(BuiltinForwardPipeline_Test, UsesFloat3PositionInputLayoutForStaticMeshVert
|
|||||||
EXPECT_EQ(texcoord.format, static_cast<uint32_t>(Format::R32G32_Float));
|
EXPECT_EQ(texcoord.format, static_cast<uint32_t>(Format::R32G32_Float));
|
||||||
EXPECT_EQ(texcoord.inputSlot, 0u);
|
EXPECT_EQ(texcoord.inputSlot, 0u);
|
||||||
EXPECT_EQ(texcoord.alignedByteOffset, static_cast<uint32_t>(offsetof(StaticMeshVertex, uv0)));
|
EXPECT_EQ(texcoord.alignedByteOffset, static_cast<uint32_t>(offsetof(StaticMeshVertex, uv0)));
|
||||||
|
|
||||||
|
const InputElementDesc& tangent = inputLayout.elements[3];
|
||||||
|
EXPECT_EQ(tangent.semanticName, "TEXCOORD");
|
||||||
|
EXPECT_EQ(tangent.semanticIndex, 1u);
|
||||||
|
EXPECT_EQ(tangent.format, static_cast<uint32_t>(Format::R32G32B32_Float));
|
||||||
|
EXPECT_EQ(tangent.inputSlot, 0u);
|
||||||
|
EXPECT_EQ(tangent.alignedByteOffset, static_cast<uint32_t>(offsetof(StaticMeshVertex, tangent)));
|
||||||
|
|
||||||
|
const InputElementDesc& bitangent = inputLayout.elements[4];
|
||||||
|
EXPECT_EQ(bitangent.semanticName, "TEXCOORD");
|
||||||
|
EXPECT_EQ(bitangent.semanticIndex, 2u);
|
||||||
|
EXPECT_EQ(bitangent.format, static_cast<uint32_t>(Format::R32G32B32_Float));
|
||||||
|
EXPECT_EQ(bitangent.inputSlot, 0u);
|
||||||
|
EXPECT_EQ(bitangent.alignedByteOffset, static_cast<uint32_t>(offsetof(StaticMeshVertex, bitangent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RenderSurfacePipelineUtils_Test, ResolvesContiguousSurfaceAttachmentFormatsIntoPipelineDesc) {
|
TEST(RenderSurfacePipelineUtils_Test, ResolvesContiguousSurfaceAttachmentFormatsIntoPipelineDesc) {
|
||||||
@@ -1081,7 +1095,7 @@ TEST(BuiltinForwardPipeline_Test, BuiltinGaussianSplatUtilitiesShaderUsesCompute
|
|||||||
|
|
||||||
const ShaderPass* pass = shader->FindPass("GaussianSplatPrepareOrder");
|
const ShaderPass* pass = shader->FindPass("GaussianSplatPrepareOrder");
|
||||||
ASSERT_NE(pass, nullptr);
|
ASSERT_NE(pass, nullptr);
|
||||||
EXPECT_EQ(pass->resources.Size(), 7u);
|
EXPECT_EQ(pass->resources.Size(), 8u);
|
||||||
|
|
||||||
const ShaderResourceBindingDesc* perObject =
|
const ShaderResourceBindingDesc* perObject =
|
||||||
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "PerObjectConstants");
|
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "PerObjectConstants");
|
||||||
@@ -1123,6 +1137,16 @@ TEST(BuiltinForwardPipeline_Test, BuiltinGaussianSplatUtilitiesShaderUsesCompute
|
|||||||
ResolveBuiltinPassResourceSemantic(*color),
|
ResolveBuiltinPassResourceSemantic(*color),
|
||||||
BuiltinPassResourceSemantic::GaussianSplatColorBuffer);
|
BuiltinPassResourceSemantic::GaussianSplatColorBuffer);
|
||||||
|
|
||||||
|
const ShaderResourceBindingDesc* sh =
|
||||||
|
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "GaussianSplatSH");
|
||||||
|
ASSERT_NE(sh, nullptr);
|
||||||
|
EXPECT_EQ(sh->type, ShaderResourceType::StructuredBuffer);
|
||||||
|
EXPECT_EQ(sh->set, 2u);
|
||||||
|
EXPECT_EQ(sh->binding, 3u);
|
||||||
|
EXPECT_EQ(
|
||||||
|
ResolveBuiltinPassResourceSemantic(*sh),
|
||||||
|
BuiltinPassResourceSemantic::GaussianSplatSHBuffer);
|
||||||
|
|
||||||
const ShaderResourceBindingDesc* sortDistances =
|
const ShaderResourceBindingDesc* sortDistances =
|
||||||
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "GaussianSplatSortDistances");
|
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "GaussianSplatSortDistances");
|
||||||
ASSERT_NE(sortDistances, nullptr);
|
ASSERT_NE(sortDistances, nullptr);
|
||||||
@@ -1231,11 +1255,12 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
|||||||
BuiltinPassResourceBindingPlan plan = {};
|
BuiltinPassResourceBindingPlan plan = {};
|
||||||
String error;
|
String error;
|
||||||
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
|
||||||
ASSERT_EQ(plan.bindings.Size(), 7u);
|
ASSERT_EQ(plan.bindings.Size(), 8u);
|
||||||
EXPECT_TRUE(plan.perObject.IsValid());
|
EXPECT_TRUE(plan.perObject.IsValid());
|
||||||
EXPECT_TRUE(plan.gaussianSplatPositionBuffer.IsValid());
|
EXPECT_TRUE(plan.gaussianSplatPositionBuffer.IsValid());
|
||||||
EXPECT_TRUE(plan.gaussianSplatOtherBuffer.IsValid());
|
EXPECT_TRUE(plan.gaussianSplatOtherBuffer.IsValid());
|
||||||
EXPECT_TRUE(plan.gaussianSplatColorBuffer.IsValid());
|
EXPECT_TRUE(plan.gaussianSplatColorBuffer.IsValid());
|
||||||
|
EXPECT_TRUE(plan.gaussianSplatSHBuffer.IsValid());
|
||||||
EXPECT_TRUE(plan.gaussianSplatSortDistanceBuffer.IsValid());
|
EXPECT_TRUE(plan.gaussianSplatSortDistanceBuffer.IsValid());
|
||||||
EXPECT_TRUE(plan.gaussianSplatOrderBuffer.IsValid());
|
EXPECT_TRUE(plan.gaussianSplatOrderBuffer.IsValid());
|
||||||
EXPECT_TRUE(plan.gaussianSplatViewDataBuffer.IsValid());
|
EXPECT_TRUE(plan.gaussianSplatViewDataBuffer.IsValid());
|
||||||
@@ -1245,6 +1270,8 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
|||||||
EXPECT_EQ(plan.gaussianSplatOtherBuffer.binding, 1u);
|
EXPECT_EQ(plan.gaussianSplatOtherBuffer.binding, 1u);
|
||||||
EXPECT_EQ(plan.gaussianSplatColorBuffer.set, 2u);
|
EXPECT_EQ(plan.gaussianSplatColorBuffer.set, 2u);
|
||||||
EXPECT_EQ(plan.gaussianSplatColorBuffer.binding, 2u);
|
EXPECT_EQ(plan.gaussianSplatColorBuffer.binding, 2u);
|
||||||
|
EXPECT_EQ(plan.gaussianSplatSHBuffer.set, 2u);
|
||||||
|
EXPECT_EQ(plan.gaussianSplatSHBuffer.binding, 3u);
|
||||||
EXPECT_EQ(plan.gaussianSplatSortDistanceBuffer.set, 4u);
|
EXPECT_EQ(plan.gaussianSplatSortDistanceBuffer.set, 4u);
|
||||||
EXPECT_EQ(plan.gaussianSplatSortDistanceBuffer.binding, 0u);
|
EXPECT_EQ(plan.gaussianSplatSortDistanceBuffer.binding, 0u);
|
||||||
EXPECT_EQ(plan.gaussianSplatOrderBuffer.set, 4u);
|
EXPECT_EQ(plan.gaussianSplatOrderBuffer.set, 4u);
|
||||||
@@ -1261,10 +1288,11 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
|||||||
EXPECT_TRUE(setLayouts[2].usesGaussianSplatPositionBuffer);
|
EXPECT_TRUE(setLayouts[2].usesGaussianSplatPositionBuffer);
|
||||||
EXPECT_TRUE(setLayouts[2].usesGaussianSplatOtherBuffer);
|
EXPECT_TRUE(setLayouts[2].usesGaussianSplatOtherBuffer);
|
||||||
EXPECT_TRUE(setLayouts[2].usesGaussianSplatColorBuffer);
|
EXPECT_TRUE(setLayouts[2].usesGaussianSplatColorBuffer);
|
||||||
|
EXPECT_TRUE(setLayouts[2].usesGaussianSplatSHBuffer);
|
||||||
EXPECT_TRUE(setLayouts[4].usesGaussianSplatSortDistanceBuffer);
|
EXPECT_TRUE(setLayouts[4].usesGaussianSplatSortDistanceBuffer);
|
||||||
EXPECT_TRUE(setLayouts[4].usesGaussianSplatOrderBuffer);
|
EXPECT_TRUE(setLayouts[4].usesGaussianSplatOrderBuffer);
|
||||||
EXPECT_TRUE(setLayouts[4].usesGaussianSplatViewDataBuffer);
|
EXPECT_TRUE(setLayouts[4].usesGaussianSplatViewDataBuffer);
|
||||||
ASSERT_EQ(setLayouts[2].bindings.size(), 3u);
|
ASSERT_EQ(setLayouts[2].bindings.size(), 4u);
|
||||||
ASSERT_EQ(setLayouts[4].bindings.size(), 3u);
|
ASSERT_EQ(setLayouts[4].bindings.size(), 3u);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
static_cast<DescriptorType>(setLayouts[2].bindings[0].type),
|
static_cast<DescriptorType>(setLayouts[2].bindings[0].type),
|
||||||
@@ -1275,6 +1303,9 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
|||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
static_cast<DescriptorType>(setLayouts[2].bindings[2].type),
|
static_cast<DescriptorType>(setLayouts[2].bindings[2].type),
|
||||||
DescriptorType::SRV);
|
DescriptorType::SRV);
|
||||||
|
EXPECT_EQ(
|
||||||
|
static_cast<DescriptorType>(setLayouts[2].bindings[3].type),
|
||||||
|
DescriptorType::SRV);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
static_cast<DescriptorType>(setLayouts[4].bindings[0].type),
|
static_cast<DescriptorType>(setLayouts[4].bindings[0].type),
|
||||||
DescriptorType::UAV);
|
DescriptorType::UAV);
|
||||||
@@ -1293,6 +1324,9 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
|
|||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
setLayouts[2].bindings[2].resourceDimension,
|
setLayouts[2].bindings[2].resourceDimension,
|
||||||
ResourceViewDimension::StructuredBuffer);
|
ResourceViewDimension::StructuredBuffer);
|
||||||
|
EXPECT_EQ(
|
||||||
|
setLayouts[2].bindings[3].resourceDimension,
|
||||||
|
ResourceViewDimension::StructuredBuffer);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
setLayouts[4].bindings[0].resourceDimension,
|
setLayouts[4].bindings[0].resourceDimension,
|
||||||
ResourceViewDimension::StructuredBuffer);
|
ResourceViewDimension::StructuredBuffer);
|
||||||
@@ -1389,9 +1423,10 @@ TEST(BuiltinForwardPipeline_Test, OpenGLPipelineLayoutUsesUnifiedStorageBufferBi
|
|||||||
EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 0u), 0u);
|
EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 0u), 0u);
|
||||||
EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 1u), 1u);
|
EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 1u), 1u);
|
||||||
EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 2u), 2u);
|
EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 2u), 2u);
|
||||||
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 0u), 3u);
|
EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 3u), 3u);
|
||||||
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 1u), 4u);
|
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 0u), 4u);
|
||||||
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 2u), 5u);
|
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 1u), 5u);
|
||||||
|
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 2u), 6u);
|
||||||
|
|
||||||
pipelineLayout.Shutdown();
|
pipelineLayout.Shutdown();
|
||||||
delete shader;
|
delete shader;
|
||||||
@@ -1440,6 +1475,10 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesGaussianSplatU
|
|||||||
d3d12Source,
|
d3d12Source,
|
||||||
"StructuredBuffer<float4> GaussianSplatColor",
|
"StructuredBuffer<float4> GaussianSplatColor",
|
||||||
"register(t2)"));
|
"register(t2)"));
|
||||||
|
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||||
|
d3d12Source,
|
||||||
|
"StructuredBuffer<GaussianSplatSHData> GaussianSplatSH",
|
||||||
|
"register(t3)"));
|
||||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||||
d3d12Source,
|
d3d12Source,
|
||||||
"RWStructuredBuffer<uint> GaussianSplatSortDistances",
|
"RWStructuredBuffer<uint> GaussianSplatSortDistances",
|
||||||
@@ -1484,6 +1523,10 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesGaussianSplatU
|
|||||||
vulkanSource,
|
vulkanSource,
|
||||||
"StructuredBuffer<float4> GaussianSplatColor",
|
"StructuredBuffer<float4> GaussianSplatColor",
|
||||||
"register(t2, space2)"));
|
"register(t2, space2)"));
|
||||||
|
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||||
|
vulkanSource,
|
||||||
|
"StructuredBuffer<GaussianSplatSHData> GaussianSplatSH",
|
||||||
|
"register(t3, space2)"));
|
||||||
EXPECT_TRUE(SourceContainsRegisterBinding(
|
EXPECT_TRUE(SourceContainsRegisterBinding(
|
||||||
vulkanSource,
|
vulkanSource,
|
||||||
"RWStructuredBuffer<uint> GaussianSplatSortDistances",
|
"RWStructuredBuffer<uint> GaussianSplatSortDistances",
|
||||||
@@ -1550,13 +1593,16 @@ TEST(BuiltinForwardPipeline_Test, OpenGLRuntimeTranspilesGaussianSplatUtilitiesC
|
|||||||
glslSource.find("layout(binding = 2, std430) readonly buffer GaussianSplatColor"),
|
glslSource.find("layout(binding = 2, std430) readonly buffer GaussianSplatColor"),
|
||||||
std::string::npos);
|
std::string::npos);
|
||||||
EXPECT_NE(
|
EXPECT_NE(
|
||||||
glslSource.find("layout(binding = 3, std430) buffer type_RWStructuredBuffer_uint"),
|
glslSource.find("layout(binding = 3, std430) readonly buffer type_StructuredBuffer_GaussianSplatSHData"),
|
||||||
std::string::npos);
|
std::string::npos);
|
||||||
EXPECT_NE(
|
EXPECT_NE(
|
||||||
glslSource.find("layout(binding = 4, std430) buffer GaussianSplatOrderBuffer"),
|
glslSource.find("layout(binding = 4, std430) buffer type_RWStructuredBuffer_uint"),
|
||||||
std::string::npos);
|
std::string::npos);
|
||||||
EXPECT_NE(
|
EXPECT_NE(
|
||||||
glslSource.find("layout(binding = 5, std430) buffer type_RWStructuredBuffer_GaussianSplatViewData"),
|
glslSource.find("layout(binding = 5, std430) buffer GaussianSplatOrderBuffer"),
|
||||||
|
std::string::npos);
|
||||||
|
EXPECT_NE(
|
||||||
|
glslSource.find("layout(binding = 6, std430) buffer type_RWStructuredBuffer_GaussianSplatViewData"),
|
||||||
std::string::npos);
|
std::string::npos);
|
||||||
|
|
||||||
delete shader;
|
delete shader;
|
||||||
|
|||||||
Reference in New Issue
Block a user