2026-04-15 01:33:42 +08:00
|
|
|
#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h"
|
|
|
|
|
|
2026-04-15 15:14:06 +08:00
|
|
|
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
|
|
|
|
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
|
|
|
|
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
2026-04-15 01:33:42 +08:00
|
|
|
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
|
|
|
|
|
|
|
|
|
namespace XCEngine {
|
|
|
|
|
namespace Rendering {
|
|
|
|
|
namespace Pipelines {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineRendererAsset() {
|
2026-04-15 01:33:42 +08:00
|
|
|
static const std::shared_ptr<const RenderPipelineAsset> s_defaultRendererAsset =
|
|
|
|
|
std::make_shared<BuiltinForwardPipelineAsset>();
|
|
|
|
|
return s_defaultRendererAsset;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
std::unique_ptr<RenderPipelineRenderer> CreatePipelineRendererFromAsset(
|
|
|
|
|
const std::shared_ptr<const RenderPipelineAsset>& pipelineRendererAsset) {
|
2026-04-15 01:33:42 +08:00
|
|
|
const std::shared_ptr<const RenderPipelineAsset> resolvedAsset =
|
2026-04-15 20:00:30 +08:00
|
|
|
pipelineRendererAsset != nullptr
|
|
|
|
|
? pipelineRendererAsset
|
|
|
|
|
: CreateDefaultPipelineRendererAsset();
|
2026-04-15 01:33:42 +08:00
|
|
|
if (resolvedAsset != nullptr) {
|
|
|
|
|
if (std::unique_ptr<RenderPipeline> pipeline = resolvedAsset->CreatePipeline()) {
|
|
|
|
|
return pipeline;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_unique<BuiltinForwardPipeline>();
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:14:06 +08:00
|
|
|
void InstallDefaultStandaloneStagePasses(RenderPipeline& pipeline) {
|
|
|
|
|
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>());
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 01:33:42 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost()
|
2026-04-15 20:00:30 +08:00
|
|
|
: ScriptableRenderPipelineHost(CreateDefaultPipelineRendererAsset()) {
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost(
|
2026-04-15 20:00:30 +08:00
|
|
|
std::unique_ptr<RenderPipelineRenderer> pipelineRenderer) {
|
2026-04-15 15:14:06 +08:00
|
|
|
InstallDefaultStandaloneStagePasses(*this);
|
2026-04-15 20:00:30 +08:00
|
|
|
ResetPipelineRenderer(std::move(pipelineRenderer));
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost(
|
2026-04-15 20:00:30 +08:00
|
|
|
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset)
|
|
|
|
|
: m_pipelineRendererAsset(
|
|
|
|
|
pipelineRendererAsset != nullptr
|
|
|
|
|
? std::move(pipelineRendererAsset)
|
|
|
|
|
: CreateDefaultPipelineRendererAsset()) {
|
2026-04-15 15:14:06 +08:00
|
|
|
InstallDefaultStandaloneStagePasses(*this);
|
2026-04-15 20:00:30 +08:00
|
|
|
ResetPipelineRenderer(
|
|
|
|
|
CreatePipelineRendererFromAsset(m_pipelineRendererAsset));
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScriptableRenderPipelineHost::~ScriptableRenderPipelineHost() {
|
|
|
|
|
Shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:07:52 +08:00
|
|
|
void ScriptableRenderPipelineHost::SetStageRecorder(
|
|
|
|
|
std::unique_ptr<RenderPipelineStageRecorder> stageRecorder) {
|
|
|
|
|
ResetStageRecorder(std::move(stageRecorder));
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
void ScriptableRenderPipelineHost::SetPipelineRenderer(
|
|
|
|
|
std::unique_ptr<RenderPipelineRenderer> pipelineRenderer) {
|
|
|
|
|
m_pipelineRendererAsset.reset();
|
|
|
|
|
ResetPipelineRenderer(std::move(pipelineRenderer));
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
void ScriptableRenderPipelineHost::SetPipelineRendererAsset(
|
|
|
|
|
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset) {
|
|
|
|
|
m_pipelineRendererAsset =
|
|
|
|
|
pipelineRendererAsset != nullptr
|
|
|
|
|
? std::move(pipelineRendererAsset)
|
|
|
|
|
: CreateDefaultPipelineRendererAsset();
|
|
|
|
|
ResetPipelineRenderer(
|
|
|
|
|
CreatePipelineRendererFromAsset(m_pipelineRendererAsset));
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ScriptableRenderPipelineHost::Initialize(const RenderContext& context) {
|
2026-04-15 21:15:39 +08:00
|
|
|
return EnsureInitialized(context);
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScriptableRenderPipelineHost::Shutdown() {
|
2026-04-15 20:07:52 +08:00
|
|
|
if (m_stageRecorder != nullptr) {
|
|
|
|
|
m_stageRecorder->Shutdown();
|
|
|
|
|
}
|
2026-04-15 20:00:30 +08:00
|
|
|
if (m_pipelineRenderer != nullptr) {
|
|
|
|
|
m_pipelineRenderer->Shutdown();
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
2026-04-15 15:14:06 +08:00
|
|
|
ShutdownCameraFrameStandalonePasses();
|
2026-04-15 21:15:39 +08:00
|
|
|
ResetInitializationState();
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 19:31:52 +08:00
|
|
|
bool ScriptableRenderPipelineHost::SupportsStageRenderGraph(
|
|
|
|
|
CameraFrameStage stage) const {
|
2026-04-15 20:07:52 +08:00
|
|
|
return (m_stageRecorder != nullptr &&
|
|
|
|
|
m_stageRecorder->SupportsStageRenderGraph(stage)) ||
|
|
|
|
|
(m_pipelineRenderer != nullptr &&
|
|
|
|
|
m_pipelineRenderer->SupportsStageRenderGraph(stage));
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 19:31:52 +08:00
|
|
|
bool ScriptableRenderPipelineHost::RecordStageRenderGraph(
|
|
|
|
|
const RenderPipelineStageRenderGraphContext& context) {
|
2026-04-15 21:15:39 +08:00
|
|
|
if (!EnsureInitialized(context.renderContext)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:07:52 +08:00
|
|
|
if (m_stageRecorder != nullptr &&
|
|
|
|
|
m_stageRecorder->SupportsStageRenderGraph(context.stage)) {
|
|
|
|
|
return m_stageRecorder->RecordStageRenderGraph(context);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
return m_pipelineRenderer != nullptr &&
|
|
|
|
|
m_pipelineRenderer->RecordStageRenderGraph(context);
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ScriptableRenderPipelineHost::Render(
|
|
|
|
|
const FrameExecutionContext& executionContext) {
|
2026-04-15 21:15:39 +08:00
|
|
|
if (!EnsureInitialized(executionContext.renderContext)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
return m_pipelineRenderer != nullptr &&
|
|
|
|
|
m_pipelineRenderer->Render(executionContext);
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ScriptableRenderPipelineHost::Render(
|
|
|
|
|
const RenderContext& context,
|
|
|
|
|
const RenderSurface& surface,
|
|
|
|
|
const RenderSceneData& sceneData) {
|
2026-04-15 21:15:39 +08:00
|
|
|
if (!EnsureInitialized(context)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
return m_pipelineRenderer != nullptr &&
|
|
|
|
|
m_pipelineRenderer->Render(context, surface, sceneData);
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 21:15:39 +08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:07:52 +08:00
|
|
|
void ScriptableRenderPipelineHost::ResetStageRecorder(
|
|
|
|
|
std::unique_ptr<RenderPipelineStageRecorder> stageRecorder) {
|
|
|
|
|
if (m_stageRecorder != nullptr) {
|
|
|
|
|
m_stageRecorder->Shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_stageRecorder = std::move(stageRecorder);
|
2026-04-15 21:15:39 +08:00
|
|
|
m_stageRecorderInitialized = false;
|
|
|
|
|
ClearInitializationContextIfNoComponentsAreInitialized();
|
2026-04-15 20:07:52 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
void ScriptableRenderPipelineHost::ResetPipelineRenderer(
|
|
|
|
|
std::unique_ptr<RenderPipelineRenderer> pipelineRenderer) {
|
|
|
|
|
if (m_pipelineRenderer != nullptr) {
|
|
|
|
|
m_pipelineRenderer->Shutdown();
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 20:00:30 +08:00
|
|
|
m_pipelineRenderer = std::move(pipelineRenderer);
|
|
|
|
|
if (m_pipelineRenderer == nullptr) {
|
|
|
|
|
if (m_pipelineRendererAsset == nullptr) {
|
|
|
|
|
m_pipelineRendererAsset = CreateDefaultPipelineRendererAsset();
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
2026-04-15 20:00:30 +08:00
|
|
|
m_pipelineRenderer =
|
|
|
|
|
CreatePipelineRendererFromAsset(m_pipelineRendererAsset);
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
2026-04-15 21:15:39 +08:00
|
|
|
|
|
|
|
|
m_pipelineRendererInitialized = false;
|
|
|
|
|
ClearInitializationContextIfNoComponentsAreInitialized();
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset()
|
2026-04-15 20:00:30 +08:00
|
|
|
: ScriptableRenderPipelineHostAsset(CreateDefaultPipelineRendererAsset()) {
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset(
|
2026-04-15 20:00:30 +08:00
|
|
|
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset)
|
|
|
|
|
: m_pipelineRendererAsset(
|
|
|
|
|
pipelineRendererAsset != nullptr
|
|
|
|
|
? std::move(pipelineRendererAsset)
|
|
|
|
|
: CreateDefaultPipelineRendererAsset()) {
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<RenderPipeline> ScriptableRenderPipelineHostAsset::CreatePipeline() const {
|
|
|
|
|
return std::make_unique<ScriptableRenderPipelineHost>(
|
2026-04-15 20:00:30 +08:00
|
|
|
m_pipelineRendererAsset);
|
2026-04-15 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FinalColorSettings ScriptableRenderPipelineHostAsset::GetDefaultFinalColorSettings() const {
|
2026-04-15 20:00:30 +08:00
|
|
|
return m_pipelineRendererAsset != nullptr
|
|
|
|
|
? m_pipelineRendererAsset->GetDefaultFinalColorSettings()
|
2026-04-15 01:33:42 +08:00
|
|
|
: FinalColorSettings{};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Pipelines
|
|
|
|
|
} // namespace Rendering
|
|
|
|
|
} // namespace XCEngine
|