refactor(rendering): formalize camera frame stage contracts
This commit is contained in:
@@ -102,31 +102,31 @@ bool CameraFramePlan::IsFinalOutputStageValid() const {
|
||||
}
|
||||
|
||||
bool CameraFramePlan::HasFrameStage(CameraFrameStage stage) const {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::PreScenePasses:
|
||||
return preScenePasses != nullptr;
|
||||
case CameraFrameStage::ShadowCaster:
|
||||
return shadowCaster.IsRequested() || directionalShadow.IsValid();
|
||||
case CameraFrameStage::DepthOnly:
|
||||
return request.depthOnly.IsRequested();
|
||||
case CameraFrameStage::MainScene:
|
||||
if (stage == CameraFrameStage::MainScene) {
|
||||
return true;
|
||||
case CameraFrameStage::PostProcess:
|
||||
return postProcess.IsRequested();
|
||||
case CameraFrameStage::FinalOutput:
|
||||
return finalOutput.IsRequested();
|
||||
case CameraFrameStage::ObjectId:
|
||||
}
|
||||
|
||||
if (IsCameraFrameSequenceStage(stage)) {
|
||||
return GetPassSequence(stage) != nullptr;
|
||||
}
|
||||
|
||||
switch (GetCameraFrameStageRequestKind(stage)) {
|
||||
case CameraFrameStageRequestKind::ShadowCaster:
|
||||
return shadowCaster.IsRequested() || directionalShadow.IsValid();
|
||||
case CameraFrameStageRequestKind::DepthOnly:
|
||||
return request.depthOnly.IsRequested();
|
||||
case CameraFrameStageRequestKind::ObjectId:
|
||||
return request.objectId.IsRequested();
|
||||
case CameraFrameStage::PostScenePasses:
|
||||
return postScenePasses != nullptr;
|
||||
case CameraFrameStage::OverlayPasses:
|
||||
return overlayPasses != nullptr;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RenderPassSequence* CameraFramePlan::GetPassSequence(CameraFrameStage stage) const {
|
||||
if (!IsCameraFrameSequenceStage(stage)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (stage) {
|
||||
case CameraFrameStage::PreScenePasses:
|
||||
return preScenePasses;
|
||||
@@ -144,10 +144,10 @@ RenderPassSequence* CameraFramePlan::GetPassSequence(CameraFrameStage stage) con
|
||||
}
|
||||
|
||||
const ScenePassRenderRequest* CameraFramePlan::GetScenePassRequest(CameraFrameStage stage) const {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::ShadowCaster:
|
||||
switch (GetCameraFrameStageRequestKind(stage)) {
|
||||
case CameraFrameStageRequestKind::ShadowCaster:
|
||||
return &shadowCaster;
|
||||
case CameraFrameStage::DepthOnly:
|
||||
case CameraFrameStageRequestKind::DepthOnly:
|
||||
return &request.depthOnly;
|
||||
default:
|
||||
return nullptr;
|
||||
@@ -155,7 +155,10 @@ const ScenePassRenderRequest* CameraFramePlan::GetScenePassRequest(CameraFrameSt
|
||||
}
|
||||
|
||||
const ObjectIdRenderRequest* CameraFramePlan::GetObjectIdRequest(CameraFrameStage stage) const {
|
||||
return stage == CameraFrameStage::ObjectId ? &request.objectId : nullptr;
|
||||
return GetCameraFrameStageRequestKind(stage) ==
|
||||
CameraFrameStageRequestKind::ObjectId
|
||||
? &request.objectId
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const RenderSurface& CameraFramePlan::GetMainSceneSurface() const {
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
#include "Components/CameraComponent.h"
|
||||
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameGraph/Executor.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
|
||||
#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h"
|
||||
#include "Rendering/RenderPipelineAsset.h"
|
||||
@@ -23,14 +19,6 @@ std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineAsset() {
|
||||
return Pipelines::CreateManagedOrDefaultScriptableRenderPipelineAsset();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateDefaultDepthOnlyPass() {
|
||||
return std::make_unique<Passes::BuiltinDepthOnlyPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateDefaultShadowCasterPass() {
|
||||
return std::make_unique<Passes::BuiltinShadowCasterPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPipeline> CreatePipelineFromAsset(
|
||||
const std::shared_ptr<const RenderPipelineAsset>& pipelineAsset) {
|
||||
if (pipelineAsset != nullptr) {
|
||||
@@ -85,40 +73,13 @@ CameraRenderer::CameraRenderer()
|
||||
}
|
||||
|
||||
CameraRenderer::CameraRenderer(std::unique_ptr<RenderPipeline> pipeline)
|
||||
: CameraRenderer(
|
||||
std::move(pipeline),
|
||||
std::make_unique<Passes::BuiltinObjectIdPass>(),
|
||||
CreateDefaultDepthOnlyPass(),
|
||||
CreateDefaultShadowCasterPass()) {
|
||||
}
|
||||
|
||||
CameraRenderer::CameraRenderer(
|
||||
std::unique_ptr<RenderPipeline> pipeline,
|
||||
std::unique_ptr<RenderPass> objectIdPass,
|
||||
std::unique_ptr<RenderPass> depthOnlyPass,
|
||||
std::unique_ptr<RenderPass> shadowCasterPass)
|
||||
: m_pipelineAsset(nullptr)
|
||||
, m_objectIdPass(std::move(objectIdPass))
|
||||
, m_depthOnlyPass(std::move(depthOnlyPass))
|
||||
, m_shadowCasterPass(std::move(shadowCasterPass))
|
||||
, m_directionalShadowRuntime(std::make_unique<DirectionalShadowRuntime>()) {
|
||||
if (m_objectIdPass == nullptr) {
|
||||
m_objectIdPass = std::make_unique<Passes::BuiltinObjectIdPass>();
|
||||
}
|
||||
if (m_depthOnlyPass == nullptr) {
|
||||
m_depthOnlyPass = CreateDefaultDepthOnlyPass();
|
||||
}
|
||||
if (m_shadowCasterPass == nullptr) {
|
||||
m_shadowCasterPass = CreateDefaultShadowCasterPass();
|
||||
}
|
||||
ResetPipeline(std::move(pipeline));
|
||||
}
|
||||
|
||||
CameraRenderer::CameraRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset)
|
||||
: m_pipelineAsset(std::move(pipelineAsset))
|
||||
, m_objectIdPass(std::make_unique<Passes::BuiltinObjectIdPass>())
|
||||
, m_depthOnlyPass(CreateDefaultDepthOnlyPass())
|
||||
, m_shadowCasterPass(CreateDefaultShadowCasterPass())
|
||||
, m_directionalShadowRuntime(std::make_unique<DirectionalShadowRuntime>()) {
|
||||
SetPipelineAsset(m_pipelineAsset);
|
||||
}
|
||||
@@ -127,15 +88,6 @@ CameraRenderer::~CameraRenderer() {
|
||||
if (m_pipeline) {
|
||||
m_pipeline->Shutdown();
|
||||
}
|
||||
if (m_objectIdPass != nullptr) {
|
||||
m_objectIdPass->Shutdown();
|
||||
}
|
||||
if (m_depthOnlyPass != nullptr) {
|
||||
m_depthOnlyPass->Shutdown();
|
||||
}
|
||||
if (m_shadowCasterPass != nullptr) {
|
||||
m_shadowCasterPass->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraRenderer::SetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
|
||||
@@ -148,39 +100,6 @@ void CameraRenderer::SetPipelineAsset(std::shared_ptr<const RenderPipelineAsset>
|
||||
ResetPipeline(CreatePipelineFromAsset(m_pipelineAsset));
|
||||
}
|
||||
|
||||
void CameraRenderer::SetObjectIdPass(std::unique_ptr<RenderPass> objectIdPass) {
|
||||
if (m_objectIdPass != nullptr) {
|
||||
m_objectIdPass->Shutdown();
|
||||
}
|
||||
|
||||
m_objectIdPass = std::move(objectIdPass);
|
||||
if (m_objectIdPass == nullptr) {
|
||||
m_objectIdPass = std::make_unique<Passes::BuiltinObjectIdPass>();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraRenderer::SetDepthOnlyPass(std::unique_ptr<RenderPass> depthOnlyPass) {
|
||||
if (m_depthOnlyPass != nullptr) {
|
||||
m_depthOnlyPass->Shutdown();
|
||||
}
|
||||
|
||||
m_depthOnlyPass = std::move(depthOnlyPass);
|
||||
if (m_depthOnlyPass == nullptr) {
|
||||
m_depthOnlyPass = CreateDefaultDepthOnlyPass();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraRenderer::SetShadowCasterPass(std::unique_ptr<RenderPass> shadowCasterPass) {
|
||||
if (m_shadowCasterPass != nullptr) {
|
||||
m_shadowCasterPass->Shutdown();
|
||||
}
|
||||
|
||||
m_shadowCasterPass = std::move(shadowCasterPass);
|
||||
if (m_shadowCasterPass == nullptr) {
|
||||
m_shadowCasterPass = CreateDefaultShadowCasterPass();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraRenderer::ResetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
|
||||
if (m_pipeline != nullptr) {
|
||||
m_pipeline->Shutdown();
|
||||
@@ -227,10 +146,7 @@ bool CameraRenderer::ExecuteRenderPlan(
|
||||
plan,
|
||||
shadowState,
|
||||
sceneData,
|
||||
m_pipeline.get(),
|
||||
m_objectIdPass.get(),
|
||||
m_depthOnlyPass.get(),
|
||||
m_shadowCasterPass.get());
|
||||
m_pipeline.get());
|
||||
}
|
||||
|
||||
bool CameraRenderer::Render(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Rendering/RenderPipeline.h>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -46,14 +47,8 @@ private:
|
||||
|
||||
struct CameraFrameExecutionState {
|
||||
RenderPipeline* pipeline = nullptr;
|
||||
RenderPass* objectIdPass = nullptr;
|
||||
RenderPass* depthOnlyPass = nullptr;
|
||||
RenderPass* shadowCasterPass = nullptr;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> preScenePasses;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> postProcessPasses;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> finalOutputPasses;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> postScenePasses;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> overlayPasses;
|
||||
std::array<std::unique_ptr<ScopedInitializedPassSequence>, kCameraFrameStageCount>
|
||||
sequenceStates = {};
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -16,19 +16,13 @@ bool ExecuteCameraFrameRenderGraphPlan(
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
RenderPipeline* pipeline,
|
||||
RenderPass* objectIdPass,
|
||||
RenderPass* depthOnlyPass,
|
||||
RenderPass* shadowCasterPass) {
|
||||
RenderPipeline* pipeline) {
|
||||
RenderGraph graph = {};
|
||||
RenderGraphBuilder graphBuilder(graph);
|
||||
RenderGraphBlackboard blackboard = {};
|
||||
|
||||
CameraFrameExecutionState executionState = {};
|
||||
executionState.pipeline = pipeline;
|
||||
executionState.objectIdPass = objectIdPass;
|
||||
executionState.depthOnlyPass = depthOnlyPass;
|
||||
executionState.shadowCasterPass = shadowCasterPass;
|
||||
|
||||
bool stageExecutionSucceeded = true;
|
||||
if (!RecordCameraFrameRenderGraphStages(
|
||||
|
||||
@@ -13,10 +13,7 @@ bool ExecuteCameraFrameRenderGraphPlan(
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
RenderPipeline* pipeline,
|
||||
RenderPass* objectIdPass,
|
||||
RenderPass* depthOnlyPass,
|
||||
RenderPass* shadowCasterPass);
|
||||
RenderPipeline* pipeline);
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
|
||||
@@ -28,20 +28,11 @@ bool EnsureInitializedPassSequence(
|
||||
std::unique_ptr<ScopedInitializedPassSequence>* ResolveStageSequenceState(
|
||||
CameraFrameStage stage,
|
||||
CameraFrameExecutionState& executionState) {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::PreScenePasses:
|
||||
return &executionState.preScenePasses;
|
||||
case CameraFrameStage::PostProcess:
|
||||
return &executionState.postProcessPasses;
|
||||
case CameraFrameStage::FinalOutput:
|
||||
return &executionState.finalOutputPasses;
|
||||
case CameraFrameStage::PostScenePasses:
|
||||
return &executionState.postScenePasses;
|
||||
case CameraFrameStage::OverlayPasses:
|
||||
return &executionState.overlayPasses;
|
||||
default:
|
||||
if (!IsCameraFrameSequenceStage(stage)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &executionState.sequenceStates[GetCameraFrameStageIndex(stage)];
|
||||
}
|
||||
|
||||
RenderPassGraphBeginCallback BuildSequenceBeginCallback(
|
||||
|
||||
@@ -90,6 +90,33 @@ CameraFrameRenderGraphSourceBinding BuildCameraFrameStageGraphSourceBinding(
|
||||
};
|
||||
}
|
||||
|
||||
const ScenePassRenderRequest* ResolveCameraFrameStageScenePassRequest(
|
||||
CameraFrameStage stage,
|
||||
const CameraFrameRenderGraphStageContext& context) {
|
||||
switch (GetCameraFrameStageRequestKind(stage)) {
|
||||
case CameraFrameStageRequestKind::ShadowCaster:
|
||||
return context.shadowState.shadowCasterRequest.IsRequested()
|
||||
? &context.shadowState.shadowCasterRequest
|
||||
: nullptr;
|
||||
case CameraFrameStageRequestKind::DepthOnly:
|
||||
return context.plan.request.depthOnly.IsRequested()
|
||||
? &context.plan.request.depthOnly
|
||||
: nullptr;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const ObjectIdRenderRequest* ResolveCameraFrameStageObjectIdRequest(
|
||||
CameraFrameStage stage,
|
||||
const CameraFrameRenderGraphStageContext& context) {
|
||||
return GetCameraFrameStageRequestKind(stage) ==
|
||||
CameraFrameStageRequestKind::ObjectId &&
|
||||
context.plan.request.objectId.IsRequested()
|
||||
? &context.plan.request.objectId
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
RenderSceneData BuildCameraFrameScenePassRequestSceneData(
|
||||
const ScenePassRenderRequest& request,
|
||||
const RenderSurface& requestSurface,
|
||||
@@ -130,15 +157,10 @@ RenderSceneData BuildCameraFrameStandaloneStageSceneData(
|
||||
CameraFrameStage stage,
|
||||
const CameraFrameRenderGraphStageContext& context,
|
||||
const RenderSurface& stageSurface) {
|
||||
if (stage == CameraFrameStage::ShadowCaster &&
|
||||
context.shadowState.shadowCasterRequest.IsRequested()) {
|
||||
return BuildCameraFrameScenePassRequestSceneData(
|
||||
context.shadowState.shadowCasterRequest,
|
||||
stageSurface,
|
||||
context.sceneData);
|
||||
}
|
||||
|
||||
if (const ScenePassRenderRequest* request = context.plan.GetScenePassRequest(stage);
|
||||
if (const ScenePassRenderRequest* request =
|
||||
ResolveCameraFrameStageScenePassRequest(
|
||||
stage,
|
||||
context);
|
||||
request != nullptr) {
|
||||
return BuildCameraFrameScenePassRequestSceneData(
|
||||
*request,
|
||||
@@ -152,16 +174,9 @@ RenderSceneData BuildCameraFrameStandaloneStageSceneData(
|
||||
RenderPass* ResolveCameraFrameStandaloneStagePass(
|
||||
CameraFrameStage stage,
|
||||
CameraFrameExecutionState& executionState) {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::ShadowCaster:
|
||||
return executionState.shadowCasterPass;
|
||||
case CameraFrameStage::DepthOnly:
|
||||
return executionState.depthOnlyPass;
|
||||
case CameraFrameStage::ObjectId:
|
||||
return executionState.objectIdPass;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return executionState.pipeline != nullptr
|
||||
? executionState.pipeline->GetCameraFrameStandalonePass(stage)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool InitializeCameraFrameStandaloneStagePass(
|
||||
@@ -184,22 +199,29 @@ bool ExecuteCameraFrameRecordedStagePass(
|
||||
const CameraFrameRenderGraphStageContext& context,
|
||||
CameraFrameExecutionState& executionState,
|
||||
const RenderPassContext& passContext) {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::ShadowCaster:
|
||||
if (IsCameraFrameScenePassRequestStage(stage)) {
|
||||
const ScenePassRenderRequest* const request =
|
||||
ResolveCameraFrameStageScenePassRequest(
|
||||
stage,
|
||||
context);
|
||||
if (request == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderPass* const standaloneStagePass =
|
||||
ResolveCameraFrameStandaloneStagePass(
|
||||
stage,
|
||||
executionState);
|
||||
return ExecuteCameraFrameScenePassRequestStage(
|
||||
executionState.shadowCasterPass,
|
||||
context.shadowState.shadowCasterRequest,
|
||||
standaloneStagePass,
|
||||
*request,
|
||||
context.plan.request.context,
|
||||
context.sceneData,
|
||||
passContext.surface);
|
||||
case CameraFrameStage::DepthOnly:
|
||||
return ExecuteCameraFrameScenePassRequestStage(
|
||||
executionState.depthOnlyPass,
|
||||
context.plan.request.depthOnly,
|
||||
context.plan.request.context,
|
||||
context.sceneData,
|
||||
passContext.surface);
|
||||
case CameraFrameStage::MainScene:
|
||||
}
|
||||
|
||||
if (GetCameraFrameStageExecutionKind(stage) ==
|
||||
CameraFrameStageExecutionKind::MainScenePipeline) {
|
||||
return executionState.pipeline != nullptr &&
|
||||
executionState.pipeline->Render(
|
||||
FrameExecutionContext(
|
||||
@@ -209,16 +231,26 @@ bool ExecuteCameraFrameRecordedStagePass(
|
||||
passContext.sourceSurface,
|
||||
passContext.sourceColorView,
|
||||
passContext.sourceColorState));
|
||||
case CameraFrameStage::ObjectId:
|
||||
return !context.plan.request.objectId.IsRequested() ||
|
||||
ExecuteCameraFrameStandaloneStagePass(
|
||||
executionState.objectIdPass,
|
||||
context.plan.request.context,
|
||||
passContext.surface,
|
||||
context.sceneData);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetCameraFrameStageRequestKind(stage) ==
|
||||
CameraFrameStageRequestKind::ObjectId) {
|
||||
if (ResolveCameraFrameStageObjectIdRequest(stage, context) == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderPass* const standaloneStagePass =
|
||||
ResolveCameraFrameStandaloneStagePass(
|
||||
stage,
|
||||
executionState);
|
||||
return ExecuteCameraFrameStandaloneStagePass(
|
||||
standaloneStagePass,
|
||||
context.plan.request.context,
|
||||
passContext.surface,
|
||||
context.sceneData);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderPassContext BuildCameraFrameStageGraphPassContext(
|
||||
|
||||
@@ -23,6 +23,14 @@ struct CameraFrameStageFallbackSurfaceResolution {
|
||||
CameraFrameRenderGraphSourceBinding BuildCameraFrameStageGraphSourceBinding(
|
||||
const CameraFrameStageGraphBuildState& stageState);
|
||||
|
||||
const ScenePassRenderRequest* ResolveCameraFrameStageScenePassRequest(
|
||||
CameraFrameStage stage,
|
||||
const CameraFrameRenderGraphStageContext& context);
|
||||
|
||||
const ObjectIdRenderRequest* ResolveCameraFrameStageObjectIdRequest(
|
||||
CameraFrameStage stage,
|
||||
const CameraFrameRenderGraphStageContext& context);
|
||||
|
||||
RenderSceneData BuildCameraFrameScenePassRequestSceneData(
|
||||
const ScenePassRenderRequest& request,
|
||||
const RenderSurface& requestSurface,
|
||||
|
||||
Reference in New Issue
Block a user