Files
XCEngine/engine/src/Rendering/Pipelines/BuiltinForwardSceneRecorder.cpp

244 lines
8.5 KiB
C++

#include <XCEngine/Rendering/Pipelines/BuiltinForwardSceneRecorder.h>
#include "Debug/Logger.h"
#include "Rendering/Pipelines/Internal/BuiltinForwardSceneSetup.h"
#include <XCEngine/Rendering/Execution/CameraFrameRenderGraphFrameData.h>
#include <XCEngine/Rendering/Graph/RenderGraphRecordingContext.h>
#include <XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h>
#include <XCEngine/Rendering/RenderPipelineStageGraphContract.h>
#include <memory>
#include <utility>
#include <vector>
namespace XCEngine {
namespace Rendering {
namespace Pipelines {
struct BuiltinForwardSceneRecorderState {
bool initialized = false;
};
namespace {
bool ScenePhaseSamplesMainDirectionalShadow(ScenePhase scenePhase) {
return scenePhase == ScenePhase::Opaque ||
scenePhase == ScenePhase::Transparent;
}
} // namespace
BuiltinForwardSceneRecorder::BuiltinForwardSceneRecorder(
BuiltinForwardPipeline& pipeline,
const RenderPipelineStageRenderGraphContext& context)
: m_pipeline(pipeline)
, m_context(context)
, m_graphManagedSurface(
BuildRenderGraphManagedSurfaceTemplate(context.surfaceTemplate))
, m_state(std::make_shared<BuiltinForwardSceneRecorderState>()) {
const CameraFrameRenderGraphResources* const frameResources =
TryGetCameraFrameRenderGraphResources(context.blackboard);
if (frameResources != nullptr) {
m_mainDirectionalShadowTexture = frameResources->mainDirectionalShadow;
}
}
BuiltinForwardSceneRecorder::~BuiltinForwardSceneRecorder() = default;
SceneRenderFeaturePassBeginCallback
BuiltinForwardSceneRecorder::BuildBeginRecordedPassCallback(
bool* executionSucceeded) const {
BuiltinForwardPipeline& pipeline = m_pipeline;
const std::shared_ptr<BuiltinForwardSceneRecorderState> state = m_state;
return [&pipeline, state, executionSucceeded](
const RenderPassContext& passContext,
bool clearAttachments) -> bool {
if (executionSucceeded != nullptr &&
!(*executionSucceeded)) {
return false;
}
if (!state->initialized) {
if (!pipeline.Initialize(passContext.renderContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardSceneRecorder failed during execution: Initialize returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return false;
}
const FrameExecutionContext executionContext(
passContext.renderContext,
passContext.surface,
passContext.sceneData,
passContext.sourceSurface,
passContext.sourceColorView,
passContext.sourceColorState);
if (!pipeline.m_forwardSceneFeatureHost.Prepare(executionContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardSceneRecorder failed during execution: SceneRenderFeatureHost::Prepare returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return false;
}
state->initialized = true;
}
if (!pipeline.BeginForwardScenePass(
passContext,
clearAttachments)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardSceneRecorder failed during execution: BeginForwardScenePass returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return false;
}
return true;
};
}
SceneRenderFeaturePassEndCallback
BuiltinForwardSceneRecorder::BuildEndRecordedPassCallback() const {
BuiltinForwardPipeline& pipeline = m_pipeline;
return [&pipeline](const RenderPassContext& passContext) {
pipeline.EndForwardScenePass(passContext);
};
}
bool BuiltinForwardSceneRecorder::RecordDefaultScene() {
if (m_context.stage != CameraFrameStage::MainScene) {
return false;
}
for (const Internal::ForwardSceneStep& step :
Internal::GetBuiltinForwardSceneSteps()) {
if (step.type == Internal::ForwardSceneStepType::InjectionPoint) {
if (!RecordInjectionPoint(step.injectionPoint)) {
return false;
}
continue;
}
if (!RecordScenePhase(step.scenePhase)) {
return false;
}
}
return true;
}
bool BuiltinForwardSceneRecorder::RecordScenePhase(
ScenePhase scenePhase) {
if (m_context.stage != CameraFrameStage::MainScene) {
return false;
}
const RenderPipelineStageRenderGraphContext graphContext =
BuildGraphContext();
const bool clearAttachments = m_clearAttachments;
const SceneRenderFeaturePassBeginCallback beginRecordedPass =
BuildBeginRecordedPassCallback(graphContext.executionSucceeded);
const SceneRenderFeaturePassEndCallback endRecordedPass =
BuildEndRecordedPassCallback();
const RenderPassGraphBeginCallback beginPhasePass =
[beginRecordedPass, clearAttachments](
const RenderPassContext& passContext) {
return beginRecordedPass(
passContext,
clearAttachments);
};
const std::vector<RenderGraphTextureHandle> additionalReadTextures =
ScenePhaseSamplesMainDirectionalShadow(scenePhase) &&
m_mainDirectionalShadowTexture.IsValid()
? std::vector<RenderGraphTextureHandle>{ m_mainDirectionalShadowTexture }
: std::vector<RenderGraphTextureHandle>{};
if (!::XCEngine::Rendering::RecordRenderPipelineStagePhasePass(
graphContext,
scenePhase,
[&pipeline = m_pipeline, scenePhase](
const RenderPassContext& passContext) {
const FrameExecutionContext executionContext(
passContext.renderContext,
passContext.surface,
passContext.sceneData,
passContext.sourceSurface,
passContext.sourceColorView,
passContext.sourceColorState);
const ScenePhaseExecutionContext scenePhaseExecutionContext =
pipeline.BuildScenePhaseExecutionContext(
executionContext,
scenePhase);
return pipeline.ExecuteBuiltinScenePhase(
scenePhaseExecutionContext);
},
beginPhasePass,
endRecordedPass,
additionalReadTextures)) {
return false;
}
m_clearAttachments = false;
return true;
}
bool BuiltinForwardSceneRecorder::RecordInjectionPoint(
SceneRenderInjectionPoint injectionPoint) {
if (m_context.stage != CameraFrameStage::MainScene) {
return false;
}
const RenderPipelineStageRenderGraphContext graphContext =
BuildGraphContext();
const SceneRenderFeaturePassBeginCallback beginRecordedPass =
BuildBeginRecordedPassCallback(graphContext.executionSucceeded);
const SceneRenderFeaturePassEndCallback endRecordedPass =
BuildEndRecordedPassCallback();
bool recordedAnyPass = false;
if (!::XCEngine::Rendering::RecordRenderPipelineStageFeaturePasses(
graphContext,
m_pipeline.m_forwardSceneFeatureHost,
injectionPoint,
m_clearAttachments,
beginRecordedPass,
endRecordedPass,
&recordedAnyPass)) {
return false;
}
if (recordedAnyPass) {
m_clearAttachments = false;
}
return true;
}
RenderPipelineStageRenderGraphContext
BuiltinForwardSceneRecorder::BuildGraphContext() const {
const RenderGraphRecordingContext baseRecordingContext =
BuildRenderGraphRecordingContext(m_context);
RenderGraphRecordingContextBuildParams recordingParams = {};
recordingParams.surface = &m_graphManagedSurface;
recordingParams.overrideSourceBinding = true;
recordingParams.sourceBinding =
BuildRenderGraphRecordingSourceBinding(baseRecordingContext);
const RenderGraphRecordingContext recordingContext =
BuildRenderGraphRecordingContext(
baseRecordingContext,
std::move(recordingParams));
return BuildRenderPipelineStageRenderGraphContext(
recordingContext,
m_context.stage);
}
} // namespace Pipelines
} // namespace Rendering
} // namespace XCEngine