183 lines
6.0 KiB
C++
183 lines
6.0 KiB
C++
#include "Rendering/SceneRenderFeatureHost.h"
|
|
|
|
#include "Debug/Logger.h"
|
|
#include "Rendering/Internal/RenderGraphRecordingContextBuilders.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 =
|
|
Internal::CloneSceneRenderFeaturePassRenderGraphContext(
|
|
context,
|
|
BuildFeatureGraphPassName(
|
|
context.passName,
|
|
injectionPoint,
|
|
*featurePass,
|
|
featureIndex),
|
|
clearAttachments);
|
|
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
|