Bind gaussian splat chunk metadata in prepare pass

This commit is contained in:
2026-04-11 13:55:39 +08:00
parent ff4e3f639a
commit 88a71a5426
7 changed files with 148 additions and 15 deletions

View File

@@ -20,6 +20,25 @@ Shader "Builtin Gaussian Splat Utilities"
float coefficients[45]; float coefficients[45];
}; };
struct GaussianSplatChunkData
{
uint colR;
uint colG;
uint colB;
uint colA;
float2 posX;
float2 posY;
float2 posZ;
uint sclX;
uint sclY;
uint sclZ;
uint shR;
uint shG;
uint shB;
};
static const uint GAUSSIAN_SPLAT_CHUNK_SIZE = 256u;
static const float SH_C1 = 0.4886025; 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_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 }; static const float SH_C3[] = { -0.5900436, 2.8906114, -0.4570458, 0.3731763, -0.4570458, 1.4453057, -0.5900436 };
@@ -211,6 +230,7 @@ Shader "Builtin Gaussian Splat Utilities"
StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther; StructuredBuffer<GaussianSplatOtherData> GaussianSplatOther;
StructuredBuffer<float4> GaussianSplatColor; StructuredBuffer<float4> GaussianSplatColor;
StructuredBuffer<GaussianSplatSHData> GaussianSplatSH; StructuredBuffer<GaussianSplatSHData> GaussianSplatSH;
StructuredBuffer<GaussianSplatChunkData> GaussianSplatChunks;
RWStructuredBuffer<uint> GaussianSplatSortDistances; RWStructuredBuffer<uint> GaussianSplatSortDistances;
RWStructuredBuffer<uint> GaussianSplatOrderBuffer; RWStructuredBuffer<uint> GaussianSplatOrderBuffer;
RWStructuredBuffer<GaussianSplatViewData> GaussianSplatViewDataBuffer; RWStructuredBuffer<GaussianSplatViewData> GaussianSplatViewDataBuffer;
@@ -240,7 +260,16 @@ Shader "Builtin Gaussian Splat Utilities"
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 GaussianSplatSHData shData = GaussianSplatSH[index];
const GaussianSplatChunkData chunkData = GaussianSplatChunks[index / GAUSSIAN_SPLAT_CHUNK_SIZE];
const uint shOrder = min((uint)gSplatParams.z, 3u); const uint shOrder = min((uint)gSplatParams.z, 3u);
if (chunkData.posX.x > chunkData.posX.y ||
chunkData.posY.x > chunkData.posY.y ||
chunkData.posZ.x > chunkData.posZ.y)
{
GaussianSplatSortDistances[index] = 0xffffffffu;
GaussianSplatViewDataBuffer[index] = viewData;
return;
}
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;

View File

@@ -46,6 +46,7 @@ inline bool TryBuildBuiltinPassResourceBindingPlan(
location = &outPlan.material; location = &outPlan.material;
break; break;
case BuiltinPassResourceSemantic::MaterialBuffer: case BuiltinPassResourceSemantic::MaterialBuffer:
case BuiltinPassResourceSemantic::MaterialTexture:
break; break;
case BuiltinPassResourceSemantic::Lighting: case BuiltinPassResourceSemantic::Lighting:
location = &outPlan.lighting; location = &outPlan.lighting;
@@ -80,6 +81,9 @@ inline bool TryBuildBuiltinPassResourceBindingPlan(
case BuiltinPassResourceSemantic::GaussianSplatSHBuffer: case BuiltinPassResourceSemantic::GaussianSplatSHBuffer:
location = &outPlan.gaussianSplatSHBuffer; location = &outPlan.gaussianSplatSHBuffer;
break; break;
case BuiltinPassResourceSemantic::GaussianSplatChunkBuffer:
location = &outPlan.gaussianSplatChunkBuffer;
break;
case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer: case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer:
location = &outPlan.gaussianSplatViewDataBuffer; location = &outPlan.gaussianSplatViewDataBuffer;
break; break;
@@ -109,7 +113,9 @@ inline bool TryBuildBuiltinPassResourceBindingPlan(
break; break;
} }
if (semantic != BuiltinPassResourceSemantic::MaterialBuffer && location == nullptr) { if (semantic != BuiltinPassResourceSemantic::MaterialBuffer &&
semantic != BuiltinPassResourceSemantic::MaterialTexture &&
location == nullptr) {
return fail("Builtin pass resource semantic could not be mapped"); return fail("Builtin pass resource semantic could not be mapped");
} }
if (location != nullptr && location->IsValid()) { if (location != nullptr && location->IsValid()) {
@@ -137,6 +143,9 @@ inline bool TryBuildBuiltinPassResourceBindingPlan(
if (semantic == BuiltinPassResourceSemantic::MaterialBuffer) { if (semantic == BuiltinPassResourceSemantic::MaterialBuffer) {
outPlan.materialBufferBindings.PushBack(resolvedBinding); outPlan.materialBufferBindings.PushBack(resolvedBinding);
outPlan.usesMaterialBuffers = true; outPlan.usesMaterialBuffers = true;
} else if (semantic == BuiltinPassResourceSemantic::MaterialTexture) {
outPlan.materialTextureBindings.PushBack(resolvedBinding);
outPlan.usesMaterialTextures = true;
} }
outPlan.maxSetIndex = std::max(outPlan.maxSetIndex, binding.set); outPlan.maxSetIndex = std::max(outPlan.maxSetIndex, binding.set);
@@ -593,6 +602,11 @@ inline bool TryBuildBuiltinPassSetLayouts(
setLayout.usesMaterialBuffers = true; setLayout.usesMaterialBuffers = true;
setLayout.materialBufferBindings.push_back(binding); setLayout.materialBufferBindings.push_back(binding);
break; break;
case BuiltinPassResourceSemantic::MaterialTexture:
setLayout.usesTexture = true;
setLayout.usesMaterialTextures = true;
setLayout.materialTextureBindings.push_back(binding);
break;
case BuiltinPassResourceSemantic::Lighting: case BuiltinPassResourceSemantic::Lighting:
setLayout.usesLighting = true; setLayout.usesLighting = true;
break; break;
@@ -626,6 +640,9 @@ inline bool TryBuildBuiltinPassSetLayouts(
case BuiltinPassResourceSemantic::GaussianSplatSHBuffer: case BuiltinPassResourceSemantic::GaussianSplatSHBuffer:
setLayout.usesGaussianSplatSHBuffer = true; setLayout.usesGaussianSplatSHBuffer = true;
break; break;
case BuiltinPassResourceSemantic::GaussianSplatChunkBuffer:
setLayout.usesGaussianSplatChunkBuffer = true;
break;
case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer: case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer:
setLayout.usesGaussianSplatViewDataBuffer = true; setLayout.usesGaussianSplatViewDataBuffer = true;
break; break;

View File

@@ -183,6 +183,12 @@ inline BuiltinPassResourceSemantic ResolveBuiltinPassResourceSemantic(
return BuiltinPassResourceSemantic::GaussianSplatSHBuffer; return BuiltinPassResourceSemantic::GaussianSplatSHBuffer;
} }
if (semantic == Containers::String("gaussiansplatchunkbuffer") ||
semantic == Containers::String("gaussiansplatchunks") ||
semantic == Containers::String("splatchunks")) {
return BuiltinPassResourceSemantic::GaussianSplatChunkBuffer;
}
if (semantic == Containers::String("gaussiansplatviewdatabuffer") || if (semantic == Containers::String("gaussiansplatviewdatabuffer") ||
semantic == Containers::String("gaussiansplatviewdata") || semantic == Containers::String("gaussiansplatviewdata") ||
semantic == Containers::String("splatviewdata")) { semantic == Containers::String("splatviewdata")) {
@@ -221,6 +227,9 @@ inline BuiltinPassResourceSemantic ResolveBuiltinPassResourceSemantic(
} }
switch (binding.type) { switch (binding.type) {
case Resources::ShaderResourceType::Texture2D:
case Resources::ShaderResourceType::TextureCube:
return BuiltinPassResourceSemantic::MaterialTexture;
case Resources::ShaderResourceType::StructuredBuffer: case Resources::ShaderResourceType::StructuredBuffer:
case Resources::ShaderResourceType::RawBuffer: case Resources::ShaderResourceType::RawBuffer:
case Resources::ShaderResourceType::RWStructuredBuffer: case Resources::ShaderResourceType::RWStructuredBuffer:
@@ -241,6 +250,8 @@ inline const char* BuiltinPassResourceSemanticToString(BuiltinPassResourceSemant
return "Material"; return "Material";
case BuiltinPassResourceSemantic::MaterialBuffer: case BuiltinPassResourceSemantic::MaterialBuffer:
return "MaterialBuffer"; return "MaterialBuffer";
case BuiltinPassResourceSemantic::MaterialTexture:
return "MaterialTexture";
case BuiltinPassResourceSemantic::Lighting: case BuiltinPassResourceSemantic::Lighting:
return "Lighting"; return "Lighting";
case BuiltinPassResourceSemantic::ShadowReceiver: case BuiltinPassResourceSemantic::ShadowReceiver:
@@ -263,6 +274,8 @@ inline const char* BuiltinPassResourceSemanticToString(BuiltinPassResourceSemant
return "GaussianSplatColorBuffer"; return "GaussianSplatColorBuffer";
case BuiltinPassResourceSemantic::GaussianSplatSHBuffer: case BuiltinPassResourceSemantic::GaussianSplatSHBuffer:
return "GaussianSplatSHBuffer"; return "GaussianSplatSHBuffer";
case BuiltinPassResourceSemantic::GaussianSplatChunkBuffer:
return "GaussianSplatChunkBuffer";
case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer: case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer:
return "GaussianSplatViewDataBuffer"; return "GaussianSplatViewDataBuffer";
case BuiltinPassResourceSemantic::BaseColorTexture: case BuiltinPassResourceSemantic::BaseColorTexture:
@@ -350,6 +363,9 @@ inline bool IsBuiltinPassResourceTypeCompatible(
type == Resources::ShaderResourceType::RawBuffer || type == Resources::ShaderResourceType::RawBuffer ||
type == Resources::ShaderResourceType::RWStructuredBuffer || type == Resources::ShaderResourceType::RWStructuredBuffer ||
type == Resources::ShaderResourceType::RWRawBuffer; type == Resources::ShaderResourceType::RWRawBuffer;
case BuiltinPassResourceSemantic::MaterialTexture:
return type == Resources::ShaderResourceType::Texture2D ||
type == Resources::ShaderResourceType::TextureCube;
case BuiltinPassResourceSemantic::VolumeField: case BuiltinPassResourceSemantic::VolumeField:
return type == Resources::ShaderResourceType::StructuredBuffer || return type == Resources::ShaderResourceType::StructuredBuffer ||
type == Resources::ShaderResourceType::RawBuffer; type == Resources::ShaderResourceType::RawBuffer;
@@ -359,6 +375,7 @@ inline bool IsBuiltinPassResourceTypeCompatible(
case BuiltinPassResourceSemantic::GaussianSplatOtherBuffer: case BuiltinPassResourceSemantic::GaussianSplatOtherBuffer:
case BuiltinPassResourceSemantic::GaussianSplatColorBuffer: case BuiltinPassResourceSemantic::GaussianSplatColorBuffer:
case BuiltinPassResourceSemantic::GaussianSplatSHBuffer: case BuiltinPassResourceSemantic::GaussianSplatSHBuffer:
case BuiltinPassResourceSemantic::GaussianSplatChunkBuffer:
case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer: case BuiltinPassResourceSemantic::GaussianSplatViewDataBuffer:
return type == Resources::ShaderResourceType::StructuredBuffer || return type == Resources::ShaderResourceType::StructuredBuffer ||
type == Resources::ShaderResourceType::RawBuffer || type == Resources::ShaderResourceType::RawBuffer ||

View File

@@ -42,6 +42,7 @@ enum class BuiltinPassResourceSemantic : Core::uint8 {
PerObject, PerObject,
Material, Material,
MaterialBuffer, MaterialBuffer,
MaterialTexture,
Lighting, Lighting,
ShadowReceiver, ShadowReceiver,
Environment, Environment,
@@ -53,6 +54,7 @@ enum class BuiltinPassResourceSemantic : Core::uint8 {
GaussianSplatOtherBuffer, GaussianSplatOtherBuffer,
GaussianSplatColorBuffer, GaussianSplatColorBuffer,
GaussianSplatSHBuffer, GaussianSplatSHBuffer,
GaussianSplatChunkBuffer,
GaussianSplatViewDataBuffer, GaussianSplatViewDataBuffer,
BaseColorTexture, BaseColorTexture,
SourceColorTexture, SourceColorTexture,
@@ -73,6 +75,7 @@ struct BuiltinPassResourceBindingDesc {
struct BuiltinPassResourceBindingPlan { struct BuiltinPassResourceBindingPlan {
Containers::Array<BuiltinPassResourceBindingDesc> bindings; Containers::Array<BuiltinPassResourceBindingDesc> bindings;
Containers::Array<BuiltinPassResourceBindingDesc> materialBufferBindings; Containers::Array<BuiltinPassResourceBindingDesc> materialBufferBindings;
Containers::Array<BuiltinPassResourceBindingDesc> materialTextureBindings;
Core::uint32 maxSetIndex = 0; Core::uint32 maxSetIndex = 0;
Core::uint32 firstDescriptorSet = 0; Core::uint32 firstDescriptorSet = 0;
Core::uint32 descriptorSetCount = 0; Core::uint32 descriptorSetCount = 0;
@@ -80,6 +83,7 @@ struct BuiltinPassResourceBindingPlan {
bool usesTextures = false; bool usesTextures = false;
bool usesSamplers = false; bool usesSamplers = false;
bool usesMaterialBuffers = false; bool usesMaterialBuffers = false;
bool usesMaterialTextures = false;
PassResourceBindingLocation perObject = {}; PassResourceBindingLocation perObject = {};
PassResourceBindingLocation material = {}; PassResourceBindingLocation material = {};
PassResourceBindingLocation volumeField = {}; PassResourceBindingLocation volumeField = {};
@@ -93,6 +97,7 @@ struct BuiltinPassResourceBindingPlan {
PassResourceBindingLocation gaussianSplatOtherBuffer = {}; PassResourceBindingLocation gaussianSplatOtherBuffer = {};
PassResourceBindingLocation gaussianSplatColorBuffer = {}; PassResourceBindingLocation gaussianSplatColorBuffer = {};
PassResourceBindingLocation gaussianSplatSHBuffer = {}; PassResourceBindingLocation gaussianSplatSHBuffer = {};
PassResourceBindingLocation gaussianSplatChunkBuffer = {};
PassResourceBindingLocation gaussianSplatViewDataBuffer = {}; PassResourceBindingLocation gaussianSplatViewDataBuffer = {};
PassResourceBindingLocation baseColorTexture = {}; PassResourceBindingLocation baseColorTexture = {};
PassResourceBindingLocation sourceColorTexture = {}; PassResourceBindingLocation sourceColorTexture = {};
@@ -116,6 +121,7 @@ struct BuiltinPassResourceBindingPlan {
struct BuiltinPassSetLayoutMetadata { struct BuiltinPassSetLayoutMetadata {
std::vector<RHI::DescriptorSetLayoutBinding> bindings; std::vector<RHI::DescriptorSetLayoutBinding> bindings;
std::vector<BuiltinPassResourceBindingDesc> materialBufferBindings; std::vector<BuiltinPassResourceBindingDesc> materialBufferBindings;
std::vector<BuiltinPassResourceBindingDesc> materialTextureBindings;
RHI::DescriptorSetLayoutDesc layout = {}; RHI::DescriptorSetLayoutDesc layout = {};
RHI::DescriptorHeapType heapType = RHI::DescriptorHeapType::CBV_SRV_UAV; RHI::DescriptorHeapType heapType = RHI::DescriptorHeapType::CBV_SRV_UAV;
bool shaderVisible = false; bool shaderVisible = false;
@@ -126,6 +132,7 @@ struct BuiltinPassSetLayoutMetadata {
bool usesEnvironment = false; bool usesEnvironment = false;
bool usesPassConstants = false; bool usesPassConstants = false;
bool usesMaterialBuffers = false; bool usesMaterialBuffers = false;
bool usesMaterialTextures = false;
bool usesVolumeField = false; bool usesVolumeField = false;
bool usesGaussianSplatSortDistanceBuffer = false; bool usesGaussianSplatSortDistanceBuffer = false;
bool usesGaussianSplatOrderBuffer = false; bool usesGaussianSplatOrderBuffer = false;
@@ -133,6 +140,7 @@ struct BuiltinPassSetLayoutMetadata {
bool usesGaussianSplatOtherBuffer = false; bool usesGaussianSplatOtherBuffer = false;
bool usesGaussianSplatColorBuffer = false; bool usesGaussianSplatColorBuffer = false;
bool usesGaussianSplatSHBuffer = false; bool usesGaussianSplatSHBuffer = false;
bool usesGaussianSplatChunkBuffer = false;
bool usesGaussianSplatViewDataBuffer = false; bool usesGaussianSplatViewDataBuffer = false;
bool usesTexture = false; bool usesTexture = false;
bool usesBaseColorTexture = false; bool usesBaseColorTexture = false;
@@ -148,14 +156,16 @@ struct BuiltinPassSetLayoutMetadata {
BuiltinPassSetLayoutMetadata(const BuiltinPassSetLayoutMetadata& other) BuiltinPassSetLayoutMetadata(const BuiltinPassSetLayoutMetadata& other)
: bindings(other.bindings) : bindings(other.bindings)
, materialBufferBindings(other.materialBufferBindings) { , materialBufferBindings(other.materialBufferBindings)
, materialTextureBindings(other.materialTextureBindings) {
CopyFlagsFrom(other); CopyFlagsFrom(other);
SyncLayoutView(); SyncLayoutView();
} }
BuiltinPassSetLayoutMetadata(BuiltinPassSetLayoutMetadata&& other) noexcept BuiltinPassSetLayoutMetadata(BuiltinPassSetLayoutMetadata&& other) noexcept
: bindings(std::move(other.bindings)) : bindings(std::move(other.bindings))
, materialBufferBindings(std::move(other.materialBufferBindings)) { , materialBufferBindings(std::move(other.materialBufferBindings))
, materialTextureBindings(std::move(other.materialTextureBindings)) {
CopyFlagsFrom(other); CopyFlagsFrom(other);
SyncLayoutView(); SyncLayoutView();
other.layout = {}; other.layout = {};
@@ -165,6 +175,7 @@ struct BuiltinPassSetLayoutMetadata {
if (this != &other) { if (this != &other) {
bindings = other.bindings; bindings = other.bindings;
materialBufferBindings = other.materialBufferBindings; materialBufferBindings = other.materialBufferBindings;
materialTextureBindings = other.materialTextureBindings;
CopyFlagsFrom(other); CopyFlagsFrom(other);
SyncLayoutView(); SyncLayoutView();
} }
@@ -176,6 +187,7 @@ struct BuiltinPassSetLayoutMetadata {
if (this != &other) { if (this != &other) {
bindings = std::move(other.bindings); bindings = std::move(other.bindings);
materialBufferBindings = std::move(other.materialBufferBindings); materialBufferBindings = std::move(other.materialBufferBindings);
materialTextureBindings = std::move(other.materialTextureBindings);
CopyFlagsFrom(other); CopyFlagsFrom(other);
SyncLayoutView(); SyncLayoutView();
other.layout = {}; other.layout = {};
@@ -200,6 +212,7 @@ private:
usesEnvironment = other.usesEnvironment; usesEnvironment = other.usesEnvironment;
usesPassConstants = other.usesPassConstants; usesPassConstants = other.usesPassConstants;
usesMaterialBuffers = other.usesMaterialBuffers; usesMaterialBuffers = other.usesMaterialBuffers;
usesMaterialTextures = other.usesMaterialTextures;
usesVolumeField = other.usesVolumeField; usesVolumeField = other.usesVolumeField;
usesGaussianSplatSortDistanceBuffer = other.usesGaussianSplatSortDistanceBuffer; usesGaussianSplatSortDistanceBuffer = other.usesGaussianSplatSortDistanceBuffer;
usesGaussianSplatOrderBuffer = other.usesGaussianSplatOrderBuffer; usesGaussianSplatOrderBuffer = other.usesGaussianSplatOrderBuffer;
@@ -207,6 +220,7 @@ private:
usesGaussianSplatOtherBuffer = other.usesGaussianSplatOtherBuffer; usesGaussianSplatOtherBuffer = other.usesGaussianSplatOtherBuffer;
usesGaussianSplatColorBuffer = other.usesGaussianSplatColorBuffer; usesGaussianSplatColorBuffer = other.usesGaussianSplatColorBuffer;
usesGaussianSplatSHBuffer = other.usesGaussianSplatSHBuffer; usesGaussianSplatSHBuffer = other.usesGaussianSplatSHBuffer;
usesGaussianSplatChunkBuffer = other.usesGaussianSplatChunkBuffer;
usesGaussianSplatViewDataBuffer = other.usesGaussianSplatViewDataBuffer; usesGaussianSplatViewDataBuffer = other.usesGaussianSplatViewDataBuffer;
usesTexture = other.usesTexture; usesTexture = other.usesTexture;
usesBaseColorTexture = other.usesBaseColorTexture; usesBaseColorTexture = other.usesBaseColorTexture;

View File

@@ -100,6 +100,7 @@ private:
PassResourceBindingLocation gaussianSplatOtherBuffer = {}; PassResourceBindingLocation gaussianSplatOtherBuffer = {};
PassResourceBindingLocation gaussianSplatColorBuffer = {}; PassResourceBindingLocation gaussianSplatColorBuffer = {};
PassResourceBindingLocation gaussianSplatSHBuffer = {}; PassResourceBindingLocation gaussianSplatSHBuffer = {};
PassResourceBindingLocation gaussianSplatChunkBuffer = {};
PassResourceBindingLocation gaussianSplatViewDataBuffer = {}; PassResourceBindingLocation gaussianSplatViewDataBuffer = {};
}; };
@@ -142,6 +143,7 @@ private:
RHI::RHIResourceView* otherView = nullptr; RHI::RHIResourceView* otherView = nullptr;
RHI::RHIResourceView* colorView = nullptr; RHI::RHIResourceView* colorView = nullptr;
RHI::RHIResourceView* shView = nullptr; RHI::RHIResourceView* shView = nullptr;
RHI::RHIResourceView* chunkView = nullptr;
RHI::RHIResourceView* viewDataView = nullptr; RHI::RHIResourceView* viewDataView = nullptr;
}; };

View File

@@ -244,7 +244,8 @@ bool BuiltinGaussianSplatPass::PrepareGaussianSplatResources(
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) { cachedGaussianSplat->sh.shaderResourceView == nullptr ||
cachedGaussianSplat->chunks.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");
@@ -579,6 +580,7 @@ BuiltinGaussianSplatPass::PassResourceLayout* BuiltinGaussianSplatPass::GetOrCre
passLayout.gaussianSplatOtherBuffer = bindingPlan.gaussianSplatOtherBuffer; passLayout.gaussianSplatOtherBuffer = bindingPlan.gaussianSplatOtherBuffer;
passLayout.gaussianSplatColorBuffer = bindingPlan.gaussianSplatColorBuffer; passLayout.gaussianSplatColorBuffer = bindingPlan.gaussianSplatColorBuffer;
passLayout.gaussianSplatSHBuffer = bindingPlan.gaussianSplatSHBuffer; passLayout.gaussianSplatSHBuffer = bindingPlan.gaussianSplatSHBuffer;
passLayout.gaussianSplatChunkBuffer = bindingPlan.gaussianSplatChunkBuffer;
passLayout.gaussianSplatViewDataBuffer = bindingPlan.gaussianSplatViewDataBuffer; passLayout.gaussianSplatViewDataBuffer = bindingPlan.gaussianSplatViewDataBuffer;
if (!passLayout.perObject.IsValid()) { if (!passLayout.perObject.IsValid()) {
@@ -601,9 +603,10 @@ BuiltinGaussianSplatPass::PassResourceLayout* BuiltinGaussianSplatPass::GetOrCre
!passLayout.gaussianSplatOtherBuffer.IsValid() || !passLayout.gaussianSplatOtherBuffer.IsValid() ||
!passLayout.gaussianSplatColorBuffer.IsValid() || !passLayout.gaussianSplatColorBuffer.IsValid() ||
!passLayout.gaussianSplatSHBuffer.IsValid() || !passLayout.gaussianSplatSHBuffer.IsValid() ||
!passLayout.gaussianSplatChunkBuffer.IsValid() ||
!passLayout.gaussianSplatViewDataBuffer.IsValid()) { !passLayout.gaussianSplatViewDataBuffer.IsValid()) {
return failLayout( return failLayout(
"BuiltinGaussianSplatPass prepare-order pass requires sort distance, order, position, other, color, SH, and view-data gaussian splat buffer bindings"); "BuiltinGaussianSplatPass prepare-order pass requires sort distance, order, position, other, color, SH, chunk, 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() ||
@@ -936,6 +939,20 @@ BuiltinGaussianSplatPass::CachedDescriptorSet* BuiltinGaussianSplatPass::GetOrCr
} }
} }
if (setLayout.usesGaussianSplatChunkBuffer) {
if (cachedGaussianSplat.chunks.shaderResourceView == nullptr ||
!passLayout.gaussianSplatChunkBuffer.IsValid() ||
passLayout.gaussianSplatChunkBuffer.set != setIndex) {
return nullptr;
}
if (cachedDescriptorSet.chunkView != cachedGaussianSplat.chunks.shaderResourceView) {
cachedDescriptorSet.descriptorSet.set->Update(
passLayout.gaussianSplatChunkBuffer.binding,
cachedGaussianSplat.chunks.shaderResourceView);
}
}
if (setLayout.usesGaussianSplatViewDataBuffer) { if (setLayout.usesGaussianSplatViewDataBuffer) {
if (resolvedViewDataView == nullptr || if (resolvedViewDataView == nullptr ||
!passLayout.gaussianSplatViewDataBuffer.IsValid() || !passLayout.gaussianSplatViewDataBuffer.IsValid() ||
@@ -957,6 +974,7 @@ BuiltinGaussianSplatPass::CachedDescriptorSet* BuiltinGaussianSplatPass::GetOrCr
cachedDescriptorSet.otherView = cachedGaussianSplat.other.shaderResourceView; cachedDescriptorSet.otherView = cachedGaussianSplat.other.shaderResourceView;
cachedDescriptorSet.colorView = cachedGaussianSplat.color.shaderResourceView; cachedDescriptorSet.colorView = cachedGaussianSplat.color.shaderResourceView;
cachedDescriptorSet.shView = cachedGaussianSplat.sh.shaderResourceView; cachedDescriptorSet.shView = cachedGaussianSplat.sh.shaderResourceView;
cachedDescriptorSet.chunkView = cachedGaussianSplat.chunks.shaderResourceView;
cachedDescriptorSet.viewDataView = resolvedViewDataView; cachedDescriptorSet.viewDataView = resolvedViewDataView;
return &cachedDescriptorSet; return &cachedDescriptorSet;
} }
@@ -993,6 +1011,7 @@ void BuiltinGaussianSplatPass::DestroyPassResourceLayout(PassResourceLayout& pas
passLayout.gaussianSplatOtherBuffer = {}; passLayout.gaussianSplatOtherBuffer = {};
passLayout.gaussianSplatColorBuffer = {}; passLayout.gaussianSplatColorBuffer = {};
passLayout.gaussianSplatSHBuffer = {}; passLayout.gaussianSplatSHBuffer = {};
passLayout.gaussianSplatChunkBuffer = {};
passLayout.gaussianSplatViewDataBuffer = {}; passLayout.gaussianSplatViewDataBuffer = {};
} }
@@ -1018,7 +1037,8 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
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) { cachedGaussianSplat->sh.shaderResourceView == nullptr ||
cachedGaussianSplat->chunks.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");
} }
@@ -1109,6 +1129,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
setLayout.usesGaussianSplatOtherBuffer || setLayout.usesGaussianSplatOtherBuffer ||
setLayout.usesGaussianSplatColorBuffer || setLayout.usesGaussianSplatColorBuffer ||
setLayout.usesGaussianSplatSHBuffer || setLayout.usesGaussianSplatSHBuffer ||
setLayout.usesGaussianSplatChunkBuffer ||
setLayout.usesGaussianSplatViewDataBuffer)) { setLayout.usesGaussianSplatViewDataBuffer)) {
return fail("BuiltinGaussianSplatPass prepare-order failed: unexpected descriptor set layout"); return fail("BuiltinGaussianSplatPass prepare-order failed: unexpected descriptor set layout");
} }
@@ -1122,6 +1143,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
setLayout.usesGaussianSplatOtherBuffer || setLayout.usesGaussianSplatOtherBuffer ||
setLayout.usesGaussianSplatColorBuffer || setLayout.usesGaussianSplatColorBuffer ||
setLayout.usesGaussianSplatSHBuffer || setLayout.usesGaussianSplatSHBuffer ||
setLayout.usesGaussianSplatChunkBuffer ||
setLayout.usesGaussianSplatViewDataBuffer) setLayout.usesGaussianSplatViewDataBuffer)
? visibleGaussianSplat.gaussianSplat ? visibleGaussianSplat.gaussianSplat
: nullptr; : nullptr;

View File

@@ -1095,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(), 8u); EXPECT_EQ(pass->resources.Size(), 9u);
const ShaderResourceBindingDesc* perObject = const ShaderResourceBindingDesc* perObject =
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "PerObjectConstants"); shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "PerObjectConstants");
@@ -1147,6 +1147,16 @@ TEST(BuiltinForwardPipeline_Test, BuiltinGaussianSplatUtilitiesShaderUsesCompute
ResolveBuiltinPassResourceSemantic(*sh), ResolveBuiltinPassResourceSemantic(*sh),
BuiltinPassResourceSemantic::GaussianSplatSHBuffer); BuiltinPassResourceSemantic::GaussianSplatSHBuffer);
const ShaderResourceBindingDesc* chunks =
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "GaussianSplatChunks");
ASSERT_NE(chunks, nullptr);
EXPECT_EQ(chunks->type, ShaderResourceType::StructuredBuffer);
EXPECT_EQ(chunks->set, 2u);
EXPECT_EQ(chunks->binding, 4u);
EXPECT_EQ(
ResolveBuiltinPassResourceSemantic(*chunks),
BuiltinPassResourceSemantic::GaussianSplatChunkBuffer);
const ShaderResourceBindingDesc* sortDistances = const ShaderResourceBindingDesc* sortDistances =
shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "GaussianSplatSortDistances"); shader->FindPassResourceBinding("GaussianSplatPrepareOrder", "GaussianSplatSortDistances");
ASSERT_NE(sortDistances, nullptr); ASSERT_NE(sortDistances, nullptr);
@@ -1255,12 +1265,13 @@ 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(), 8u); ASSERT_EQ(plan.bindings.Size(), 9u);
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.gaussianSplatSHBuffer.IsValid());
EXPECT_TRUE(plan.gaussianSplatChunkBuffer.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());
@@ -1272,6 +1283,8 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
EXPECT_EQ(plan.gaussianSplatColorBuffer.binding, 2u); EXPECT_EQ(plan.gaussianSplatColorBuffer.binding, 2u);
EXPECT_EQ(plan.gaussianSplatSHBuffer.set, 2u); EXPECT_EQ(plan.gaussianSplatSHBuffer.set, 2u);
EXPECT_EQ(plan.gaussianSplatSHBuffer.binding, 3u); EXPECT_EQ(plan.gaussianSplatSHBuffer.binding, 3u);
EXPECT_EQ(plan.gaussianSplatChunkBuffer.set, 2u);
EXPECT_EQ(plan.gaussianSplatChunkBuffer.binding, 4u);
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);
@@ -1289,10 +1302,11 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
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[2].usesGaussianSplatSHBuffer);
EXPECT_TRUE(setLayouts[2].usesGaussianSplatChunkBuffer);
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(), 4u); ASSERT_EQ(setLayouts[2].bindings.size(), 5u);
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),
@@ -1306,6 +1320,9 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
EXPECT_EQ( EXPECT_EQ(
static_cast<DescriptorType>(setLayouts[2].bindings[3].type), static_cast<DescriptorType>(setLayouts[2].bindings[3].type),
DescriptorType::SRV); DescriptorType::SRV);
EXPECT_EQ(
static_cast<DescriptorType>(setLayouts[2].bindings[4].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);
@@ -1327,6 +1344,9 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoaded
EXPECT_EQ( EXPECT_EQ(
setLayouts[2].bindings[3].resourceDimension, setLayouts[2].bindings[3].resourceDimension,
ResourceViewDimension::StructuredBuffer); ResourceViewDimension::StructuredBuffer);
EXPECT_EQ(
setLayouts[2].bindings[4].resourceDimension,
ResourceViewDimension::StructuredBuffer);
EXPECT_EQ( EXPECT_EQ(
setLayouts[4].bindings[0].resourceDimension, setLayouts[4].bindings[0].resourceDimension,
ResourceViewDimension::StructuredBuffer); ResourceViewDimension::StructuredBuffer);
@@ -1424,9 +1444,10 @@ TEST(BuiltinForwardPipeline_Test, OpenGLPipelineLayoutUsesUnifiedStorageBufferBi
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.GetShaderResourceBindingPoint(2u, 3u), 3u); EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 3u), 3u);
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 0u), 4u); EXPECT_EQ(pipelineLayout.GetShaderResourceBindingPoint(2u, 4u), 4u);
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 1u), 5u); EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 0u), 5u);
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 2u), 6u); EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 1u), 6u);
EXPECT_EQ(pipelineLayout.GetUnorderedAccessBindingPoint(4u, 2u), 7u);
pipelineLayout.Shutdown(); pipelineLayout.Shutdown();
delete shader; delete shader;
@@ -1479,6 +1500,10 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesGaussianSplatU
d3d12Source, d3d12Source,
"StructuredBuffer<GaussianSplatSHData> GaussianSplatSH", "StructuredBuffer<GaussianSplatSHData> GaussianSplatSH",
"register(t3)")); "register(t3)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"StructuredBuffer<GaussianSplatChunkData> GaussianSplatChunks",
"register(t4)"));
EXPECT_TRUE(SourceContainsRegisterBinding( EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source, d3d12Source,
"RWStructuredBuffer<uint> GaussianSplatSortDistances", "RWStructuredBuffer<uint> GaussianSplatSortDistances",
@@ -1527,6 +1552,10 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesGaussianSplatU
vulkanSource, vulkanSource,
"StructuredBuffer<GaussianSplatSHData> GaussianSplatSH", "StructuredBuffer<GaussianSplatSHData> GaussianSplatSH",
"register(t3, space2)")); "register(t3, space2)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"StructuredBuffer<GaussianSplatChunkData> GaussianSplatChunks",
"register(t4, space2)"));
EXPECT_TRUE(SourceContainsRegisterBinding( EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource, vulkanSource,
"RWStructuredBuffer<uint> GaussianSplatSortDistances", "RWStructuredBuffer<uint> GaussianSplatSortDistances",
@@ -1596,13 +1625,16 @@ TEST(BuiltinForwardPipeline_Test, OpenGLRuntimeTranspilesGaussianSplatUtilitiesC
glslSource.find("layout(binding = 3, std430) readonly buffer type_StructuredBuffer_GaussianSplatSHData"), 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 type_RWStructuredBuffer_uint"), glslSource.find("layout(binding = 4, std430) readonly buffer type_StructuredBuffer_GaussianSplatChunkData"),
std::string::npos); std::string::npos);
EXPECT_NE( EXPECT_NE(
glslSource.find("layout(binding = 5, std430) buffer GaussianSplatOrderBuffer"), glslSource.find("layout(binding = 5, std430) buffer type_RWStructuredBuffer_uint"),
std::string::npos); std::string::npos);
EXPECT_NE( EXPECT_NE(
glslSource.find("layout(binding = 6, std430) buffer type_RWStructuredBuffer_GaussianSplatViewData"), glslSource.find("layout(binding = 6, std430) buffer GaussianSplatOrderBuffer"),
std::string::npos);
EXPECT_NE(
glslSource.find("layout(binding = 7, std430) buffer type_RWStructuredBuffer_GaussianSplatViewData"),
std::string::npos); std::string::npos);
delete shader; delete shader;