#include "Rendering/SceneRenderFeatureHost.h" #include "Debug/Logger.h" #include namespace XCEngine { namespace Rendering { namespace { Containers::String BuildFeatureGraphPassName( const Containers::String& basePassName, SceneRenderInjectionPoint injectionPoint, const SceneRenderFeaturePass& featurePass, size_t featureIndex) { std::string name = basePassName.CStr(); if (!name.empty()) { name += '.'; } name += ToString(injectionPoint); name += '.'; name += featurePass.GetName() != nullptr ? featurePass.GetName() : "FeaturePass"; name += '.'; name += std::to_string(featureIndex); return Containers::String(name.c_str()); } } // namespace void SceneRenderFeatureHost::AddFeaturePass(std::unique_ptr featurePass) { if (featurePass != nullptr) { m_featurePasses.push_back(std::move(featurePass)); } } size_t SceneRenderFeatureHost::GetFeaturePassCount() const { return m_featurePasses.size(); } SceneRenderFeaturePass* SceneRenderFeatureHost::GetFeaturePass(size_t index) const { return index < m_featurePasses.size() ? m_featurePasses[index].get() : nullptr; } bool SceneRenderFeatureHost::Initialize(const RenderContext& context) { size_t initializedCount = 0u; for (const std::unique_ptr& featurePassOwner : m_featurePasses) { SceneRenderFeaturePass* featurePass = featurePassOwner.get(); if (featurePass == nullptr) { continue; } if (featurePass->Initialize(context)) { ++initializedCount; continue; } Debug::Logger::Get().Error( Debug::LogCategory::Rendering, (Containers::String("SceneRenderFeatureHost initialize failed: ") + featurePass->GetName()).CStr()); for (size_t shutdownIndex = initializedCount; shutdownIndex > 0u; --shutdownIndex) { SceneRenderFeaturePass* initializedPass = m_featurePasses[shutdownIndex - 1u].get(); if (initializedPass != nullptr) { initializedPass->Shutdown(); } } return false; } return true; } void SceneRenderFeatureHost::Shutdown() { for (auto featurePassIt = m_featurePasses.rbegin(); featurePassIt != m_featurePasses.rend(); ++featurePassIt) { if (*featurePassIt != nullptr) { (*featurePassIt)->Shutdown(); } } } bool SceneRenderFeatureHost::Prepare(const FrameExecutionContext& executionContext) const { for (const std::unique_ptr& featurePassOwner : m_featurePasses) { SceneRenderFeaturePass* featurePass = featurePassOwner.get(); if (featurePass == nullptr || !featurePass->IsActive(executionContext.sceneData)) { continue; } if (!featurePass->Prepare(executionContext)) { Debug::Logger::Get().Error( Debug::LogCategory::Rendering, (Containers::String("SceneRenderFeatureHost prepare failed: ") + featurePass->GetName()).CStr()); return false; } } return true; } bool SceneRenderFeatureHost::Record( const SceneRenderFeaturePassRenderGraphContext& context, SceneRenderInjectionPoint injectionPoint, bool* recordedAnyPass) const { bool hasRecordedPass = false; bool clearAttachments = context.clearAttachments; for (size_t featureIndex = 0u; featureIndex < m_featurePasses.size(); ++featureIndex) { const std::unique_ptr& featurePassOwner = m_featurePasses[featureIndex]; SceneRenderFeaturePass* featurePass = featurePassOwner.get(); if (featurePass == nullptr || !featurePass->SupportsInjectionPoint(injectionPoint) || !featurePass->IsActive(context.sceneData)) { continue; } const SceneRenderFeaturePassRenderGraphContext featureContext = { context.graphBuilder, BuildFeatureGraphPassName( context.passName, injectionPoint, *featurePass, featureIndex), context.renderContext, context.sceneData, context.surface, context.sourceSurface, context.sourceColorView, context.sourceColorState, context.sourceColorTexture, context.colorTargets, context.depthTarget, clearAttachments, context.executionSucceeded, context.beginPassCallback, context.endPassCallback, context.blackboard }; if (!featurePass->RecordRenderGraph(featureContext)) { Debug::Logger::Get().Error( Debug::LogCategory::Rendering, (Containers::String("SceneRenderFeatureHost record failed at injection point '") + ToString(injectionPoint) + "': " + featurePass->GetName()).CStr()); if (recordedAnyPass != nullptr) { *recordedAnyPass = hasRecordedPass; } return false; } hasRecordedPass = true; clearAttachments = false; } if (recordedAnyPass != nullptr) { *recordedAnyPass = hasRecordedPass; } return true; } bool SceneRenderFeatureHost::Execute( const FrameExecutionContext& executionContext, SceneRenderInjectionPoint injectionPoint) const { const RenderPassContext passContext = BuildRenderPassContext(executionContext); for (const std::unique_ptr& featurePassOwner : m_featurePasses) { SceneRenderFeaturePass* featurePass = featurePassOwner.get(); if (featurePass == nullptr || !featurePass->SupportsInjectionPoint(injectionPoint) || !featurePass->IsActive(executionContext.sceneData)) { continue; } if (!featurePass->Execute(passContext)) { Debug::Logger::Get().Error( Debug::LogCategory::Rendering, (Containers::String("SceneRenderFeatureHost execute failed at injection point '") + ToString(injectionPoint) + "': " + featurePass->GetName()).CStr()); return false; } } return true; } } // namespace Rendering } // namespace XCEngine