244 lines
8.5 KiB
C++
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
|