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

290 lines
9.3 KiB
C++

#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h"
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
#include "Rendering/Passes/BuiltinObjectIdPass.h"
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
namespace XCEngine {
namespace Rendering {
namespace Pipelines {
namespace {
std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineRendererAsset() {
static const std::shared_ptr<const RenderPipelineAsset> s_defaultRendererAsset =
std::make_shared<BuiltinForwardPipelineAsset>();
return s_defaultRendererAsset;
}
std::unique_ptr<RenderPipelineRenderer> CreatePipelineRendererFromAsset(
const std::shared_ptr<const RenderPipelineAsset>& pipelineRendererAsset) {
const std::shared_ptr<const RenderPipelineAsset> resolvedAsset =
pipelineRendererAsset != nullptr
? pipelineRendererAsset
: CreateDefaultPipelineRendererAsset();
if (resolvedAsset != nullptr) {
if (std::unique_ptr<RenderPipeline> pipeline = resolvedAsset->CreatePipeline()) {
return pipeline;
}
}
return std::make_unique<BuiltinForwardPipeline>();
}
} // namespace
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost()
: ScriptableRenderPipelineHost(CreateDefaultPipelineRendererAsset()) {
}
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost(
std::unique_ptr<RenderPipelineRenderer> pipelineRenderer) {
ResetPipelineRenderer(std::move(pipelineRenderer));
}
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost(
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset)
: m_pipelineRendererAsset(
pipelineRendererAsset != nullptr
? std::move(pipelineRendererAsset)
: CreateDefaultPipelineRendererAsset()) {
ResetPipelineRenderer(
CreatePipelineRendererFromAsset(m_pipelineRendererAsset));
}
ScriptableRenderPipelineHost::~ScriptableRenderPipelineHost() {
Shutdown();
}
void ScriptableRenderPipelineHost::SetStageRecorder(
std::unique_ptr<RenderPipelineStageRecorder> stageRecorder) {
ResetStageRecorder(std::move(stageRecorder));
}
void ScriptableRenderPipelineHost::SetPipelineRenderer(
std::unique_ptr<RenderPipelineRenderer> pipelineRenderer) {
m_pipelineRendererAsset.reset();
ResetPipelineRenderer(std::move(pipelineRenderer));
}
void ScriptableRenderPipelineHost::SetPipelineRendererAsset(
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset) {
m_pipelineRendererAsset =
pipelineRendererAsset != nullptr
? std::move(pipelineRendererAsset)
: CreateDefaultPipelineRendererAsset();
ResetPipelineRenderer(
CreatePipelineRendererFromAsset(m_pipelineRendererAsset));
}
bool ScriptableRenderPipelineHost::Initialize(const RenderContext& context) {
return EnsureInitialized(context);
}
void ScriptableRenderPipelineHost::Shutdown() {
if (m_stageRecorder != nullptr) {
m_stageRecorder->Shutdown();
}
if (m_pipelineRenderer != nullptr) {
m_pipelineRenderer->Shutdown();
}
ShutdownCameraFrameStandalonePasses();
ResetInitializationState();
}
bool ScriptableRenderPipelineHost::SupportsStageRenderGraph(
CameraFrameStage stage) const {
return (m_stageRecorder != nullptr &&
m_stageRecorder->SupportsStageRenderGraph(stage)) ||
(m_pipelineRenderer != nullptr &&
m_pipelineRenderer->SupportsStageRenderGraph(stage));
}
bool ScriptableRenderPipelineHost::RecordStageRenderGraph(
const RenderPipelineStageRenderGraphContext& context) {
if (!EnsureInitialized(context.renderContext)) {
return false;
}
if (m_stageRecorder != nullptr &&
m_stageRecorder->SupportsStageRenderGraph(context.stage)) {
if (m_stageRecorder->RecordStageRenderGraph(context)) {
return true;
}
}
return m_pipelineRenderer != nullptr &&
m_pipelineRenderer->RecordStageRenderGraph(context);
}
bool ScriptableRenderPipelineHost::Render(
const FrameExecutionContext& executionContext) {
if (!EnsureInitialized(executionContext.renderContext)) {
return false;
}
return m_pipelineRenderer != nullptr &&
m_pipelineRenderer->Render(executionContext);
}
bool ScriptableRenderPipelineHost::Render(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) {
if (!EnsureInitialized(context)) {
return false;
}
return m_pipelineRenderer != nullptr &&
m_pipelineRenderer->Render(context, surface, sceneData);
}
bool ScriptableRenderPipelineHost::EnsureInitialized(const RenderContext& context) {
if (!context.IsValid() || m_pipelineRenderer == nullptr) {
return false;
}
const bool hasInitializationContext =
m_initializedDevice != nullptr ||
m_pipelineRendererInitialized ||
m_stageRecorderInitialized;
if (hasInitializationContext &&
(m_initializedDevice != context.device ||
m_initializedBackendType != context.backendType)) {
ShutdownInitializedComponents();
}
if (!m_pipelineRendererInitialized) {
if (!m_pipelineRenderer->Initialize(context)) {
m_pipelineRenderer->Shutdown();
ClearInitializationContextIfNoComponentsAreInitialized();
return false;
}
m_pipelineRendererInitialized = true;
m_initializedDevice = context.device;
m_initializedBackendType = context.backendType;
}
if (m_stageRecorder != nullptr &&
!m_stageRecorderInitialized) {
if (!m_stageRecorder->Initialize(context)) {
m_stageRecorder->Shutdown();
ShutdownInitializedComponents();
return false;
}
m_stageRecorderInitialized = true;
m_initializedDevice = context.device;
m_initializedBackendType = context.backendType;
}
return true;
}
void ScriptableRenderPipelineHost::ShutdownInitializedComponents() {
if (m_stageRecorderInitialized &&
m_stageRecorder != nullptr) {
m_stageRecorder->Shutdown();
}
if (m_pipelineRendererInitialized &&
m_pipelineRenderer != nullptr) {
m_pipelineRenderer->Shutdown();
}
ResetInitializationState();
}
void ScriptableRenderPipelineHost::ResetInitializationState() {
m_initializedDevice = nullptr;
m_initializedBackendType = RHI::RHIType::D3D12;
m_pipelineRendererInitialized = false;
m_stageRecorderInitialized = false;
}
void ScriptableRenderPipelineHost::ClearInitializationContextIfNoComponentsAreInitialized() {
if (!m_pipelineRendererInitialized &&
!m_stageRecorderInitialized) {
m_initializedDevice = nullptr;
m_initializedBackendType = RHI::RHIType::D3D12;
}
}
void ScriptableRenderPipelineHost::ResetStageRecorder(
std::unique_ptr<RenderPipelineStageRecorder> stageRecorder) {
if (m_stageRecorder != nullptr) {
m_stageRecorder->Shutdown();
}
m_stageRecorder = std::move(stageRecorder);
m_stageRecorderInitialized = false;
ClearInitializationContextIfNoComponentsAreInitialized();
}
void ScriptableRenderPipelineHost::ResetPipelineRenderer(
std::unique_ptr<RenderPipelineRenderer> pipelineRenderer) {
if (m_pipelineRenderer != nullptr) {
m_pipelineRenderer->Shutdown();
}
m_pipelineRenderer = std::move(pipelineRenderer);
if (m_pipelineRenderer == nullptr) {
if (m_pipelineRendererAsset == nullptr) {
m_pipelineRendererAsset = CreateDefaultPipelineRendererAsset();
}
m_pipelineRenderer =
CreatePipelineRendererFromAsset(m_pipelineRendererAsset);
}
m_pipelineRendererInitialized = false;
ClearInitializationContextIfNoComponentsAreInitialized();
}
ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset()
: ScriptableRenderPipelineHostAsset(CreateDefaultPipelineRendererAsset()) {
}
ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset(
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset)
: m_pipelineRendererAsset(
pipelineRendererAsset != nullptr
? std::move(pipelineRendererAsset)
: CreateDefaultPipelineRendererAsset()) {
}
std::unique_ptr<RenderPipeline> ScriptableRenderPipelineHostAsset::CreatePipeline() const {
std::unique_ptr<RenderPipeline> pipeline =
std::make_unique<ScriptableRenderPipelineHost>(
m_pipelineRendererAsset);
if (pipeline != nullptr) {
ConfigurePipeline(*pipeline);
}
return pipeline;
}
void ScriptableRenderPipelineHostAsset::ConfigurePipeline(
RenderPipeline& pipeline) const {
pipeline.SetCameraFrameStandalonePass(
CameraFrameStage::ObjectId,
std::make_unique<Passes::BuiltinObjectIdPass>());
pipeline.SetCameraFrameStandalonePass(
CameraFrameStage::DepthOnly,
std::make_unique<Passes::BuiltinDepthOnlyPass>());
pipeline.SetCameraFrameStandalonePass(
CameraFrameStage::ShadowCaster,
std::make_unique<Passes::BuiltinShadowCasterPass>());
}
FinalColorSettings ScriptableRenderPipelineHostAsset::GetDefaultFinalColorSettings() const {
return m_pipelineRendererAsset != nullptr
? m_pipelineRendererAsset->GetDefaultFinalColorSettings()
: FinalColorSettings{};
}
} // namespace Pipelines
} // namespace Rendering
} // namespace XCEngine