Files
XCEngine/engine/src/Rendering/SceneRenderFeatureHost.cpp

194 lines
6.3 KiB
C++
Raw Normal View History

#include "Rendering/SceneRenderFeatureHost.h"
#include "Debug/Logger.h"
#include <string>
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<SceneRenderFeaturePass> 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<SceneRenderFeaturePass>& 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<SceneRenderFeaturePass>& 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<SceneRenderFeaturePass>& 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.colorTargets,
context.depthTarget,
context.mainDirectionalShadowTexture,
clearAttachments,
context.executionSucceeded,
context.beginPassCallback,
context.endPassCallback
};
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<SceneRenderFeaturePass>& 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