Add gaussian splat integration baseline
This commit is contained in:
@@ -52,6 +52,12 @@ std::vector<const DescriptorSetLayoutBinding*> GatherBindingsOfTypeSorted(
|
||||
return bindings;
|
||||
}
|
||||
|
||||
bool UsesOpenGLStorageBufferBinding(const DescriptorSetLayoutBinding& binding) {
|
||||
return binding.resourceDimension == ResourceViewDimension::Buffer ||
|
||||
binding.resourceDimension == ResourceViewDimension::StructuredBuffer ||
|
||||
binding.resourceDimension == ResourceViewDimension::RawBuffer;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool OpenGLPipelineLayout::Initialize(const RHIPipelineLayoutDesc& desc) {
|
||||
@@ -93,6 +99,7 @@ bool OpenGLPipelineLayout::Initialize(const RHIPipelineLayoutDesc& desc) {
|
||||
|
||||
uint32_t nextCBVBindingPoint = 0;
|
||||
uint32_t nextSRVBindingPoint = 0;
|
||||
uint32_t nextStorageBufferBindingPoint = 0;
|
||||
uint32_t nextUAVBindingPoint = 0;
|
||||
uint32_t nextSamplerBindingPoint = 0;
|
||||
|
||||
@@ -100,34 +107,42 @@ bool OpenGLPipelineLayout::Initialize(const RHIPipelineLayoutDesc& desc) {
|
||||
const DescriptorSetLayoutDesc& setLayout = m_desc.setLayouts[setIndex];
|
||||
SetBindingPointMapping& mapping = m_setBindingPointMappings[setIndex];
|
||||
|
||||
const auto appendBindings =
|
||||
[&setLayout](
|
||||
DescriptorType type,
|
||||
std::unordered_map<uint32_t, uint32_t>& bindingPoints,
|
||||
uint32_t& nextBindingPoint) {
|
||||
const auto bindings = GatherBindingsOfTypeSorted(setLayout, type);
|
||||
for (const DescriptorSetLayoutBinding* binding : bindings) {
|
||||
bindingPoints[binding->binding] = nextBindingPoint;
|
||||
nextBindingPoint += binding->count > 0 ? binding->count : 1u;
|
||||
}
|
||||
};
|
||||
const auto appendBindings = [&setLayout, &nextStorageBufferBindingPoint](
|
||||
DescriptorType type,
|
||||
std::unordered_map<uint32_t, uint32_t>& bindingPoints,
|
||||
uint32_t& nextBindingPoint,
|
||||
bool useStorageBufferNamespace) {
|
||||
const auto bindings = GatherBindingsOfTypeSorted(setLayout, type);
|
||||
for (const DescriptorSetLayoutBinding* binding : bindings) {
|
||||
uint32_t& resolvedNextBindingPoint =
|
||||
useStorageBufferNamespace && UsesOpenGLStorageBufferBinding(*binding)
|
||||
? nextStorageBufferBindingPoint
|
||||
: nextBindingPoint;
|
||||
bindingPoints[binding->binding] = resolvedNextBindingPoint;
|
||||
resolvedNextBindingPoint += binding->count > 0 ? binding->count : 1u;
|
||||
}
|
||||
};
|
||||
|
||||
appendBindings(
|
||||
DescriptorType::CBV,
|
||||
mapping.constantBufferBindingPoints,
|
||||
nextCBVBindingPoint);
|
||||
nextCBVBindingPoint,
|
||||
false);
|
||||
appendBindings(
|
||||
DescriptorType::SRV,
|
||||
mapping.shaderResourceBindingPoints,
|
||||
nextSRVBindingPoint);
|
||||
nextSRVBindingPoint,
|
||||
true);
|
||||
appendBindings(
|
||||
DescriptorType::UAV,
|
||||
mapping.unorderedAccessBindingPoints,
|
||||
nextUAVBindingPoint);
|
||||
nextUAVBindingPoint,
|
||||
true);
|
||||
appendBindings(
|
||||
DescriptorType::Sampler,
|
||||
mapping.samplerBindingPoints,
|
||||
nextSamplerBindingPoint);
|
||||
nextSamplerBindingPoint,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,6 +268,7 @@ inline bool TryBuildRuntimeShaderBindings(
|
||||
Core::uint32 nextTextureRegister = 0;
|
||||
Core::uint32 nextSamplerRegister = 0;
|
||||
Core::uint32 nextUnorderedAccessRegister = 0;
|
||||
Core::uint32 nextStorageBufferRegister = 0;
|
||||
for (Resources::ShaderResourceBindingDesc& binding : outBindings) {
|
||||
binding.set = 0;
|
||||
switch (binding.type) {
|
||||
@@ -276,15 +277,25 @@ inline bool TryBuildRuntimeShaderBindings(
|
||||
break;
|
||||
case Resources::ShaderResourceType::Texture2D:
|
||||
case Resources::ShaderResourceType::TextureCube:
|
||||
binding.binding = nextTextureRegister++;
|
||||
break;
|
||||
case Resources::ShaderResourceType::StructuredBuffer:
|
||||
case Resources::ShaderResourceType::RawBuffer:
|
||||
binding.binding = nextTextureRegister++;
|
||||
binding.binding =
|
||||
backend == Resources::ShaderBackend::OpenGL
|
||||
? nextStorageBufferRegister++
|
||||
: nextTextureRegister++;
|
||||
break;
|
||||
case Resources::ShaderResourceType::Sampler:
|
||||
binding.binding = nextSamplerRegister++;
|
||||
break;
|
||||
case Resources::ShaderResourceType::RWStructuredBuffer:
|
||||
case Resources::ShaderResourceType::RWRawBuffer:
|
||||
binding.binding =
|
||||
backend == Resources::ShaderBackend::OpenGL
|
||||
? nextStorageBufferRegister++
|
||||
: nextUnorderedAccessRegister++;
|
||||
break;
|
||||
default:
|
||||
binding.binding = nextUnorderedAccessRegister++;
|
||||
break;
|
||||
|
||||
@@ -205,6 +205,9 @@ bool BuiltinGaussianSplatPass::PrepareGaussianSplatResources(
|
||||
const RenderContext& context,
|
||||
const RenderSceneData& sceneData) {
|
||||
if (!EnsureInitialized(context)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinGaussianSplatPass::PrepareGaussianSplatResources failed: EnsureInitialized returned false");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -220,10 +223,16 @@ bool BuiltinGaussianSplatPass::PrepareGaussianSplatResources(
|
||||
cachedGaussianSplat->positions.shaderResourceView == nullptr ||
|
||||
cachedGaussianSplat->other.shaderResourceView == nullptr ||
|
||||
cachedGaussianSplat->color.shaderResourceView == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinGaussianSplatPass::PrepareGaussianSplatResources failed: gaussian splat GPU cache incomplete");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_passResources == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinGaussianSplatPass::PrepareGaussianSplatResources failed: pass resources missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -232,7 +241,12 @@ bool BuiltinGaussianSplatPass::PrepareGaussianSplatResources(
|
||||
workingSet == nullptr ||
|
||||
workingSet->sortDistances.unorderedAccessView == nullptr ||
|
||||
workingSet->orderIndices.shaderResourceView == nullptr ||
|
||||
workingSet->orderIndices.unorderedAccessView == nullptr) {
|
||||
workingSet->orderIndices.unorderedAccessView == nullptr ||
|
||||
workingSet->viewData.shaderResourceView == nullptr ||
|
||||
workingSet->viewData.unorderedAccessView == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinGaussianSplatPass::PrepareGaussianSplatResources failed: working-set allocation incomplete");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -527,18 +541,19 @@ BuiltinGaussianSplatPass::PassResourceLayout* BuiltinGaussianSplatPass::GetOrCre
|
||||
return failLayout("BuiltinGaussianSplatPass requires a Material resource binding");
|
||||
}
|
||||
if (!passLayout.gaussianSplatOrderBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatPositionBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatOtherBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatColorBuffer.IsValid()) {
|
||||
!passLayout.gaussianSplatViewDataBuffer.IsValid()) {
|
||||
return failLayout(
|
||||
"BuiltinGaussianSplatPass draw pass requires order, position, other, and color gaussian splat buffer bindings");
|
||||
"BuiltinGaussianSplatPass draw pass requires order and view-data gaussian splat buffer bindings");
|
||||
}
|
||||
} else if (usage == PassLayoutUsage::PrepareOrder) {
|
||||
if (!passLayout.gaussianSplatSortDistanceBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatOrderBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatPositionBuffer.IsValid()) {
|
||||
!passLayout.gaussianSplatPositionBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatOtherBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatColorBuffer.IsValid() ||
|
||||
!passLayout.gaussianSplatViewDataBuffer.IsValid()) {
|
||||
return failLayout(
|
||||
"BuiltinGaussianSplatPass prepare-order pass requires sort distance, order, and position gaussian splat buffer bindings");
|
||||
"BuiltinGaussianSplatPass prepare-order pass requires sort distance, order, position, other, color, and view-data gaussian splat buffer bindings");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,6 +675,10 @@ RHI::RHIPipelineState* BuiltinGaussianSplatPass::GetOrCreateComputePipelineState
|
||||
sceneData.globalShaderKeywords);
|
||||
RHI::RHIPipelineState* pipelineState = context.device->CreateComputePipelineState(pipelineDesc);
|
||||
if (pipelineState == nullptr || !pipelineState->IsValid()) {
|
||||
const Containers::String error =
|
||||
Containers::String("BuiltinGaussianSplatPass failed to create compute pipeline state for pass '") +
|
||||
resolvedShaderPass.passName + "'";
|
||||
Debug::Logger::Get().Error(Debug::LogCategory::Rendering, error.CStr());
|
||||
if (pipelineState != nullptr) {
|
||||
pipelineState->Shutdown();
|
||||
delete pipelineState;
|
||||
@@ -718,6 +737,9 @@ BuiltinGaussianSplatPass::CachedDescriptorSet* BuiltinGaussianSplatPass::GetOrCr
|
||||
CachedDescriptorSet& cachedDescriptorSet = m_dynamicDescriptorSets[key];
|
||||
if (cachedDescriptorSet.descriptorSet.set == nullptr) {
|
||||
if (!CreateOwnedDescriptorSet(setLayout, cachedDescriptorSet.descriptorSet)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinGaussianSplatPass failed to allocate descriptor set");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -921,17 +943,22 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
const RenderContext& context,
|
||||
const RenderSceneData& sceneData,
|
||||
const VisibleGaussianSplatItem& visibleGaussianSplat) {
|
||||
auto fail = [](const char* message) -> bool {
|
||||
Debug::Logger::Get().Error(Debug::LogCategory::Rendering, message);
|
||||
return false;
|
||||
};
|
||||
|
||||
if (visibleGaussianSplat.gameObject == nullptr ||
|
||||
visibleGaussianSplat.gaussianSplat == nullptr ||
|
||||
!visibleGaussianSplat.gaussianSplat->IsValid() ||
|
||||
m_passResources == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: invalid visible gaussian splat item");
|
||||
}
|
||||
|
||||
const RenderResourceCache::CachedGaussianSplat* cachedGaussianSplat =
|
||||
m_resourceCache.GetOrCreateGaussianSplat(m_device, visibleGaussianSplat.gaussianSplat);
|
||||
if (cachedGaussianSplat == nullptr || cachedGaussianSplat->positions.shaderResourceView == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: gaussian splat GPU cache is incomplete");
|
||||
}
|
||||
|
||||
Internal::BuiltinGaussianSplatPassResources::WorkingSet* workingSet = nullptr;
|
||||
@@ -939,13 +966,15 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
workingSet == nullptr ||
|
||||
workingSet->sortDistances.unorderedAccessView == nullptr ||
|
||||
workingSet->orderIndices.unorderedAccessView == nullptr ||
|
||||
workingSet->orderIndices.shaderResourceView == nullptr) {
|
||||
return false;
|
||||
workingSet->orderIndices.shaderResourceView == nullptr ||
|
||||
workingSet->viewData.unorderedAccessView == nullptr ||
|
||||
workingSet->viewData.shaderResourceView == nullptr) {
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: working set allocation is incomplete");
|
||||
}
|
||||
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolvePrepareOrderShaderPass(sceneData);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: utilities shader pass was not resolved");
|
||||
}
|
||||
|
||||
PassLayoutKey passLayoutKey = {};
|
||||
@@ -958,7 +987,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
PassLayoutUsage::PrepareOrder);
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreateComputePipelineState(context, sceneData);
|
||||
if (passLayout == nullptr || pipelineState == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: compute pipeline setup was not created");
|
||||
}
|
||||
|
||||
RHI::RHICommandList* commandList = context.commandList;
|
||||
@@ -979,6 +1008,14 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
workingSet->orderIndices.currentState = RHI::ResourceStates::UnorderedAccess;
|
||||
}
|
||||
|
||||
if (workingSet->viewData.currentState != RHI::ResourceStates::UnorderedAccess) {
|
||||
commandList->TransitionBarrier(
|
||||
workingSet->viewData.unorderedAccessView,
|
||||
workingSet->viewData.currentState,
|
||||
RHI::ResourceStates::UnorderedAccess);
|
||||
workingSet->viewData.currentState = RHI::ResourceStates::UnorderedAccess;
|
||||
}
|
||||
|
||||
commandList->SetPipelineState(pipelineState);
|
||||
|
||||
const PerObjectConstants perObjectConstants = {
|
||||
@@ -986,7 +1023,13 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
sceneData.cameraData.view,
|
||||
visibleGaussianSplat.localToWorld.Transpose(),
|
||||
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
||||
Math::Vector4(sceneData.cameraData.worldUp, 0.0f)
|
||||
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
||||
Math::Vector4(
|
||||
static_cast<float>(sceneData.cameraData.viewportWidth),
|
||||
static_cast<float>(sceneData.cameraData.viewportHeight),
|
||||
sceneData.cameraData.viewportWidth > 0u ? 1.0f / static_cast<float>(sceneData.cameraData.viewportWidth) : 0.0f,
|
||||
sceneData.cameraData.viewportHeight > 0u ? 1.0f / static_cast<float>(sceneData.cameraData.viewportHeight) : 0.0f),
|
||||
Math::Vector4(static_cast<float>(cachedGaussianSplat->splatCount), 0.0f, 0.0f, 0.0f)
|
||||
};
|
||||
|
||||
if (passLayout->descriptorSetCount > 0u) {
|
||||
@@ -994,7 +1037,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
for (Core::uint32 descriptorOffset = 0u; descriptorOffset < passLayout->descriptorSetCount; ++descriptorOffset) {
|
||||
const Core::uint32 setIndex = passLayout->firstDescriptorSet + descriptorOffset;
|
||||
if (setIndex >= passLayout->setLayouts.size()) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: descriptor set index overflow");
|
||||
}
|
||||
|
||||
const BuiltinPassSetLayoutMetadata& setLayout = passLayout->setLayouts[setIndex];
|
||||
@@ -1005,8 +1048,11 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
if (!(setLayout.usesPerObject ||
|
||||
setLayout.usesGaussianSplatSortDistanceBuffer ||
|
||||
setLayout.usesGaussianSplatOrderBuffer ||
|
||||
setLayout.usesGaussianSplatPositionBuffer)) {
|
||||
return false;
|
||||
setLayout.usesGaussianSplatPositionBuffer ||
|
||||
setLayout.usesGaussianSplatOtherBuffer ||
|
||||
setLayout.usesGaussianSplatColorBuffer ||
|
||||
setLayout.usesGaussianSplatViewDataBuffer)) {
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: unexpected descriptor set layout");
|
||||
}
|
||||
|
||||
const Core::uint64 objectId =
|
||||
@@ -1014,7 +1060,10 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
const Resources::GaussianSplat* gaussianSplatKey =
|
||||
(setLayout.usesGaussianSplatSortDistanceBuffer ||
|
||||
setLayout.usesGaussianSplatOrderBuffer ||
|
||||
setLayout.usesGaussianSplatPositionBuffer)
|
||||
setLayout.usesGaussianSplatPositionBuffer ||
|
||||
setLayout.usesGaussianSplatOtherBuffer ||
|
||||
setLayout.usesGaussianSplatColorBuffer ||
|
||||
setLayout.usesGaussianSplatViewDataBuffer)
|
||||
? visibleGaussianSplat.gaussianSplat
|
||||
: nullptr;
|
||||
|
||||
@@ -1033,13 +1082,13 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
workingSet->orderIndices.unorderedAccessView,
|
||||
workingSet->viewData.unorderedAccessView);
|
||||
if (cachedDescriptorSet == nullptr || cachedDescriptorSet->descriptorSet.set == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: dynamic descriptor set resolution failed");
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* descriptorSet = cachedDescriptorSet->descriptorSet.set;
|
||||
if (setLayout.usesPerObject) {
|
||||
if (!passLayout->perObject.IsValid() || passLayout->perObject.set != setIndex) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass prepare-order failed: per-object binding is invalid");
|
||||
}
|
||||
|
||||
descriptorSet->WriteConstant(
|
||||
@@ -1070,6 +1119,11 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
|
||||
RHI::ResourceStates::UnorderedAccess,
|
||||
RHI::ResourceStates::NonPixelShaderResource);
|
||||
workingSet->orderIndices.currentState = RHI::ResourceStates::NonPixelShaderResource;
|
||||
commandList->TransitionBarrier(
|
||||
workingSet->viewData.shaderResourceView,
|
||||
RHI::ResourceStates::UnorderedAccess,
|
||||
RHI::ResourceStates::NonPixelShaderResource);
|
||||
workingSet->viewData.currentState = RHI::ResourceStates::NonPixelShaderResource;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1078,10 +1132,15 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
const RenderSurface& surface,
|
||||
const RenderSceneData& sceneData,
|
||||
const VisibleGaussianSplatItem& visibleGaussianSplat) {
|
||||
auto fail = [](const char* message) -> bool {
|
||||
Debug::Logger::Get().Error(Debug::LogCategory::Rendering, message);
|
||||
return false;
|
||||
};
|
||||
|
||||
if (visibleGaussianSplat.gameObject == nullptr ||
|
||||
visibleGaussianSplat.gaussianSplat == nullptr ||
|
||||
!visibleGaussianSplat.gaussianSplat->IsValid()) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: invalid visible gaussian splat item");
|
||||
}
|
||||
|
||||
const RenderResourceCache::CachedGaussianSplat* cachedGaussianSplat =
|
||||
@@ -1090,28 +1149,29 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
cachedGaussianSplat->positions.shaderResourceView == nullptr ||
|
||||
cachedGaussianSplat->other.shaderResourceView == nullptr ||
|
||||
cachedGaussianSplat->color.shaderResourceView == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: gaussian splat GPU cache is incomplete");
|
||||
}
|
||||
|
||||
if (m_passResources == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: pass resources were not initialized");
|
||||
}
|
||||
|
||||
Internal::BuiltinGaussianSplatPassResources::WorkingSet* workingSet = nullptr;
|
||||
if (!m_passResources->EnsureWorkingSet(m_device, visibleGaussianSplat, workingSet) ||
|
||||
workingSet == nullptr ||
|
||||
workingSet->orderIndices.shaderResourceView == nullptr) {
|
||||
return false;
|
||||
workingSet->orderIndices.shaderResourceView == nullptr ||
|
||||
workingSet->viewData.shaderResourceView == nullptr) {
|
||||
return fail("BuiltinGaussianSplatPass draw failed: working set allocation is incomplete");
|
||||
}
|
||||
|
||||
const Resources::Material* material = ResolveGaussianSplatMaterial(visibleGaussianSplat);
|
||||
if (material == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: gaussian splat material could not be resolved");
|
||||
}
|
||||
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveGaussianSplatShaderPass(sceneData, material);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: draw shader pass was not resolved");
|
||||
}
|
||||
|
||||
PassLayoutKey passLayoutKey = {};
|
||||
@@ -1124,12 +1184,12 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
PassLayoutUsage::Draw);
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, surface, sceneData, material);
|
||||
if (passLayout == nullptr || pipelineState == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: graphics pipeline setup was not created");
|
||||
}
|
||||
|
||||
const MaterialConstantPayloadView materialConstants = ResolveSchemaMaterialConstantPayload(material);
|
||||
if (!materialConstants.IsValid()) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: material constant payload is invalid");
|
||||
}
|
||||
|
||||
RHI::RHICommandList* commandList = context.commandList;
|
||||
@@ -1140,7 +1200,13 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
sceneData.cameraData.view,
|
||||
visibleGaussianSplat.localToWorld.Transpose(),
|
||||
Math::Vector4(sceneData.cameraData.worldRight, 0.0f),
|
||||
Math::Vector4(sceneData.cameraData.worldUp, 0.0f)
|
||||
Math::Vector4(sceneData.cameraData.worldUp, 0.0f),
|
||||
Math::Vector4(
|
||||
static_cast<float>(sceneData.cameraData.viewportWidth),
|
||||
static_cast<float>(sceneData.cameraData.viewportHeight),
|
||||
sceneData.cameraData.viewportWidth > 0u ? 1.0f / static_cast<float>(sceneData.cameraData.viewportWidth) : 0.0f,
|
||||
sceneData.cameraData.viewportHeight > 0u ? 1.0f / static_cast<float>(sceneData.cameraData.viewportHeight) : 0.0f),
|
||||
Math::Vector4(static_cast<float>(cachedGaussianSplat->splatCount), 0.0f, 0.0f, 0.0f)
|
||||
};
|
||||
|
||||
if (passLayout->descriptorSetCount > 0u) {
|
||||
@@ -1148,7 +1214,7 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
for (Core::uint32 descriptorOffset = 0u; descriptorOffset < passLayout->descriptorSetCount; ++descriptorOffset) {
|
||||
const Core::uint32 setIndex = passLayout->firstDescriptorSet + descriptorOffset;
|
||||
if (setIndex >= passLayout->setLayouts.size()) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: descriptor set index overflow");
|
||||
}
|
||||
|
||||
const BuiltinPassSetLayoutMetadata& setLayout = passLayout->setLayouts[setIndex];
|
||||
@@ -1159,11 +1225,8 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
if (!(setLayout.usesPerObject ||
|
||||
setLayout.usesMaterial ||
|
||||
setLayout.usesGaussianSplatOrderBuffer ||
|
||||
setLayout.usesGaussianSplatPositionBuffer ||
|
||||
setLayout.usesGaussianSplatOtherBuffer ||
|
||||
setLayout.usesGaussianSplatColorBuffer ||
|
||||
setLayout.usesGaussianSplatSHBuffer)) {
|
||||
return false;
|
||||
setLayout.usesGaussianSplatViewDataBuffer)) {
|
||||
return fail("BuiltinGaussianSplatPass draw failed: unexpected descriptor set layout");
|
||||
}
|
||||
|
||||
const Core::uint64 objectId =
|
||||
@@ -1172,10 +1235,7 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
setLayout.usesMaterial ? material : nullptr;
|
||||
const Resources::GaussianSplat* gaussianSplatKey =
|
||||
(setLayout.usesGaussianSplatOrderBuffer ||
|
||||
setLayout.usesGaussianSplatPositionBuffer ||
|
||||
setLayout.usesGaussianSplatOtherBuffer ||
|
||||
setLayout.usesGaussianSplatColorBuffer ||
|
||||
setLayout.usesGaussianSplatSHBuffer)
|
||||
setLayout.usesGaussianSplatViewDataBuffer)
|
||||
? visibleGaussianSplat.gaussianSplat
|
||||
: nullptr;
|
||||
|
||||
@@ -1194,13 +1254,13 @@ bool BuiltinGaussianSplatPass::DrawVisibleGaussianSplat(
|
||||
workingSet->orderIndices.shaderResourceView,
|
||||
workingSet->viewData.shaderResourceView);
|
||||
if (cachedDescriptorSet == nullptr || cachedDescriptorSet->descriptorSet.set == nullptr) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: dynamic descriptor set resolution failed");
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* descriptorSet = cachedDescriptorSet->descriptorSet.set;
|
||||
if (setLayout.usesPerObject) {
|
||||
if (!passLayout->perObject.IsValid() || passLayout->perObject.set != setIndex) {
|
||||
return false;
|
||||
return fail("BuiltinGaussianSplatPass draw failed: per-object binding is invalid");
|
||||
}
|
||||
|
||||
descriptorSet->WriteConstant(
|
||||
|
||||
Reference in New Issue
Block a user