Split camera frame render-graph stage recording helpers
This commit is contained in:
@@ -536,8 +536,13 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/CameraRenderer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphExecution.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphExecution.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStageRuntime.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStageRecording.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStageRecording.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStageSequenceRecording.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStageSequenceRecording.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStagePassRecording.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStagePassRecording.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStageState.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphStageState.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/Internal/CameraFrameRenderGraphSurfaceUtils.h
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStagePassRecording.h"
|
||||
|
||||
#include "Debug/Logger.h"
|
||||
#include "Rendering/Execution/CameraFrameRenderGraphStagePolicy.h"
|
||||
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageRuntime.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageState.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphSurfaceUtils.h"
|
||||
#include "Rendering/Graph/RenderGraph.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
namespace {
|
||||
|
||||
bool InitializeStandalonePass(
|
||||
RenderPass* pass,
|
||||
const RenderContext& context) {
|
||||
if (pass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pass->Initialize(context)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
pass->Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderSceneData BuildScenePassRequestSceneData(
|
||||
const ScenePassRenderRequest& request,
|
||||
const RenderSurface& requestSurface,
|
||||
const RenderSceneData& baseSceneData) {
|
||||
RenderSceneData sceneData = baseSceneData;
|
||||
if (request.hasCameraDataOverride) {
|
||||
sceneData.cameraData = request.cameraDataOverride;
|
||||
}
|
||||
|
||||
sceneData.cameraData.viewportWidth = requestSurface.GetRenderAreaWidth();
|
||||
sceneData.cameraData.viewportHeight = requestSurface.GetRenderAreaHeight();
|
||||
sceneData.cameraData.clearFlags = request.clearFlags;
|
||||
if (request.hasClearColorOverride) {
|
||||
sceneData.cameraData.clearColor = request.clearColorOverride;
|
||||
}
|
||||
|
||||
return sceneData;
|
||||
}
|
||||
|
||||
bool ExecuteScenePassRequest(
|
||||
RenderPass* pass,
|
||||
const ScenePassRenderRequest& request,
|
||||
const RenderContext& context,
|
||||
const RenderSceneData& baseSceneData,
|
||||
const RenderSurface* surfaceOverride = nullptr) {
|
||||
if (!request.IsRequested()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!InitializeStandalonePass(pass, context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RenderSurface& requestSurface =
|
||||
surfaceOverride != nullptr ? *surfaceOverride : request.surface;
|
||||
const RenderSceneData sceneData =
|
||||
BuildScenePassRequestSceneData(
|
||||
request,
|
||||
requestSurface,
|
||||
baseSceneData);
|
||||
|
||||
const RenderPassContext passContext = {
|
||||
context,
|
||||
requestSurface,
|
||||
sceneData,
|
||||
nullptr,
|
||||
nullptr,
|
||||
RHI::ResourceStates::Common
|
||||
};
|
||||
return pass->Execute(passContext);
|
||||
}
|
||||
|
||||
bool ExecuteStandalonePass(
|
||||
RenderPass* pass,
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface,
|
||||
const RenderSceneData& sceneData) {
|
||||
if (pass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InitializeStandalonePass(pass, context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RenderPassContext passContext = {
|
||||
context,
|
||||
surface,
|
||||
sceneData,
|
||||
nullptr,
|
||||
nullptr,
|
||||
RHI::ResourceStates::Common
|
||||
};
|
||||
return pass->Execute(passContext);
|
||||
}
|
||||
|
||||
RenderSceneData BuildStandaloneStageSceneData(
|
||||
CameraFrameStage stage,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& baseSceneData,
|
||||
const RenderSurface& stageSurface) {
|
||||
if (stage == CameraFrameStage::ShadowCaster &&
|
||||
shadowState.shadowCasterRequest.IsRequested()) {
|
||||
return BuildScenePassRequestSceneData(
|
||||
shadowState.shadowCasterRequest,
|
||||
stageSurface,
|
||||
baseSceneData);
|
||||
}
|
||||
|
||||
if (const ScenePassRenderRequest* request = plan.GetScenePassRequest(stage);
|
||||
request != nullptr) {
|
||||
return BuildScenePassRequestSceneData(
|
||||
*request,
|
||||
stageSurface,
|
||||
baseSceneData);
|
||||
}
|
||||
|
||||
return baseSceneData;
|
||||
}
|
||||
|
||||
RenderPass* ResolveStandaloneStagePass(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExecuteRecordedFrameStage(
|
||||
CameraFrameStage stage,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
const RenderPassContext& passContext) {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::ShadowCaster:
|
||||
return ExecuteScenePassRequest(
|
||||
executionState.shadowCasterPass,
|
||||
shadowState.shadowCasterRequest,
|
||||
plan.request.context,
|
||||
sceneData,
|
||||
&passContext.surface);
|
||||
case CameraFrameStage::DepthOnly:
|
||||
return ExecuteScenePassRequest(
|
||||
executionState.depthOnlyPass,
|
||||
plan.request.depthOnly,
|
||||
plan.request.context,
|
||||
sceneData,
|
||||
&passContext.surface);
|
||||
case CameraFrameStage::MainScene:
|
||||
return executionState.pipeline != nullptr &&
|
||||
executionState.pipeline->Render(
|
||||
FrameExecutionContext(
|
||||
plan.request.context,
|
||||
passContext.surface,
|
||||
sceneData,
|
||||
passContext.sourceSurface,
|
||||
passContext.sourceColorView,
|
||||
passContext.sourceColorState));
|
||||
case CameraFrameStage::ObjectId:
|
||||
return !plan.request.objectId.IsRequested() ||
|
||||
ExecuteStandalonePass(
|
||||
executionState.objectIdPass,
|
||||
plan.request.context,
|
||||
passContext.surface,
|
||||
sceneData);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool TryRecordCameraFrameStageStandaloneRenderGraphPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled) {
|
||||
RenderPass* const standaloneStagePass =
|
||||
ResolveStandaloneStagePass(stageState.stage, executionState);
|
||||
if (standaloneStagePass == nullptr ||
|
||||
!standaloneStagePass->SupportsRenderGraph()) {
|
||||
handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
handled = true;
|
||||
const RenderSceneData stageSceneData =
|
||||
BuildStandaloneStageSceneData(
|
||||
stageState.stage,
|
||||
plan,
|
||||
shadowState,
|
||||
sceneData,
|
||||
stageState.surfaceTemplate);
|
||||
const RenderPassGraphBeginCallback beginStandalonePass =
|
||||
[&, standaloneStagePass](const RenderPassContext&) -> bool {
|
||||
if (!InitializeStandalonePass(
|
||||
standaloneStagePass,
|
||||
plan.request.context)) {
|
||||
stageExecutionSucceeded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
const RenderPassRenderGraphContext standalonePassContext = {
|
||||
graphBuilder,
|
||||
stageState.stageName,
|
||||
plan.request.context,
|
||||
stageSceneData,
|
||||
stageState.surfaceTemplate,
|
||||
stageState.hasSourceSurface
|
||||
? &stageState.sourceSurfaceTemplate
|
||||
: nullptr,
|
||||
stageState.sourceColorView,
|
||||
stageState.sourceColorState,
|
||||
GetPrimaryColorTexture(stageState.sourceSurface),
|
||||
std::vector<RenderGraphTextureHandle>{ stageState.outputColor },
|
||||
stageState.outputSurface.depthTexture,
|
||||
&stageExecutionSucceeded,
|
||||
beginStandalonePass,
|
||||
{},
|
||||
&blackboard
|
||||
};
|
||||
if (!standaloneStagePass->RecordRenderGraph(standalonePassContext)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
Containers::String("CameraRenderer::Render failed: RenderPass::RecordRenderGraph returned false for ") +
|
||||
stageState.stageName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryRecordCameraFrameMainSceneGraphPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled) {
|
||||
if (stageState.stage != CameraFrameStage::MainScene ||
|
||||
executionState.pipeline == nullptr ||
|
||||
!executionState.pipeline->SupportsMainSceneRenderGraph()) {
|
||||
handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
handled = true;
|
||||
const RenderPipelineMainSceneRenderGraphContext mainSceneContext = {
|
||||
graphBuilder,
|
||||
stageState.stageName,
|
||||
plan.request.context,
|
||||
sceneData,
|
||||
stageState.surfaceTemplate,
|
||||
stageState.hasSourceSurface
|
||||
? &stageState.sourceSurfaceTemplate
|
||||
: nullptr,
|
||||
stageState.sourceColorView,
|
||||
stageState.sourceColorState,
|
||||
std::vector<RenderGraphTextureHandle>{ stageState.outputColor },
|
||||
stageState.outputSurface.depthTexture,
|
||||
&stageExecutionSucceeded,
|
||||
&blackboard
|
||||
};
|
||||
if (!executionState.pipeline->RecordMainSceneRenderGraph(mainSceneContext)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"CameraRenderer::Render failed: RenderPipeline::RecordMainSceneRenderGraph returned false");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddCameraFrameStageFallbackRasterPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
bool& stageExecutionSucceeded) {
|
||||
const CameraFrameStageGraphBuildState capturedStageState = stageState;
|
||||
graphBuilder.AddRasterPass(
|
||||
capturedStageState.stageName,
|
||||
[&, capturedStageState](RenderGraphPassBuilder& passBuilder) {
|
||||
if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage)) {
|
||||
ReadRenderGraphColorSurface(passBuilder, capturedStageState.sourceSurface);
|
||||
WriteRenderGraphColorSurface(passBuilder, capturedStageState.outputSurface);
|
||||
} else {
|
||||
ReadRenderGraphSurface(passBuilder, capturedStageState.sourceSurface);
|
||||
WriteRenderGraphSurface(passBuilder, capturedStageState.outputSurface);
|
||||
}
|
||||
passBuilder.SetExecuteCallback(
|
||||
[&, capturedStageState](
|
||||
const RenderGraphExecutionContext& executionContext) {
|
||||
if (!stageExecutionSucceeded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const RenderSurface* resolvedSourceSurface =
|
||||
capturedStageState.hasSourceSurface
|
||||
? &capturedStageState.sourceSurfaceTemplate
|
||||
: nullptr;
|
||||
RHI::RHIResourceView* resolvedSourceColorView =
|
||||
capturedStageState.sourceColorView;
|
||||
RHI::ResourceStates resolvedSourceColorState =
|
||||
capturedStageState.sourceColorState;
|
||||
RenderSurface graphManagedSourceSurface = {};
|
||||
if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage) &&
|
||||
capturedStageState.hasSourceSurface &&
|
||||
CanUseGraphManagedImportedSurface(
|
||||
capturedStageState.sourceSurface,
|
||||
executionContext)) {
|
||||
graphManagedSourceSurface =
|
||||
BuildGraphManagedImportedSurface(
|
||||
capturedStageState.sourceSurfaceTemplate,
|
||||
RHI::ResourceStates::PixelShaderResource,
|
||||
RHI::ResourceStates::PixelShaderResource);
|
||||
resolvedSourceSurface = &graphManagedSourceSurface;
|
||||
resolvedSourceColorState = RHI::ResourceStates::PixelShaderResource;
|
||||
}
|
||||
|
||||
const RenderSurface* resolvedOutputSurface =
|
||||
&capturedStageState.surfaceTemplate;
|
||||
RenderSurface graphManagedOutputSurface = {};
|
||||
if (CanUseGraphManagedImportedSurface(
|
||||
capturedStageState.outputSurface,
|
||||
executionContext)) {
|
||||
graphManagedOutputSurface =
|
||||
BuildGraphManagedPassSurface(
|
||||
capturedStageState.surfaceTemplate);
|
||||
resolvedOutputSurface = &graphManagedOutputSurface;
|
||||
}
|
||||
|
||||
const RenderPassContext passContextOverride = {
|
||||
plan.request.context,
|
||||
*resolvedOutputSurface,
|
||||
sceneData,
|
||||
resolvedSourceSurface,
|
||||
resolvedSourceColorView,
|
||||
resolvedSourceColorState
|
||||
};
|
||||
stageExecutionSucceeded = ExecuteRecordedFrameStage(
|
||||
capturedStageState.stage,
|
||||
plan,
|
||||
shadowState,
|
||||
sceneData,
|
||||
executionState,
|
||||
passContextOverride);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
struct CameraFrameExecutionState;
|
||||
struct CameraFramePlan;
|
||||
struct CameraFrameStageGraphBuildState;
|
||||
struct DirectionalShadowExecutionState;
|
||||
struct RenderSceneData;
|
||||
class RenderGraphBuilder;
|
||||
class RenderGraphBlackboard;
|
||||
|
||||
bool TryRecordCameraFrameStageStandaloneRenderGraphPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled);
|
||||
|
||||
bool TryRecordCameraFrameMainSceneGraphPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled);
|
||||
|
||||
void AddCameraFrameStageFallbackRasterPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
bool& stageExecutionSucceeded);
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -1,664 +1,19 @@
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageRecording.h"
|
||||
|
||||
#include "Debug/Logger.h"
|
||||
#include "Rendering/Execution/CameraFrameRenderGraphResources.h"
|
||||
#include "Rendering/Execution/CameraFrameRenderGraphStagePolicy.h"
|
||||
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStagePassRecording.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageRuntime.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageSequenceRecording.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageState.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphSurfaceUtils.h"
|
||||
#include "Rendering/Graph/RenderGraph.h"
|
||||
#include "Rendering/Graph/RenderGraphCompiler.h"
|
||||
#include "Rendering/Graph/RenderGraphExecutor.h"
|
||||
#include "Rendering/Internal/RenderPassGraphUtils.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
namespace {
|
||||
|
||||
bool InitializeStandalonePass(
|
||||
RenderPass* pass,
|
||||
const RenderContext& context) {
|
||||
if (pass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pass->Initialize(context)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
pass->Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderSceneData BuildScenePassRequestSceneData(
|
||||
const ScenePassRenderRequest& request,
|
||||
const RenderSurface& requestSurface,
|
||||
const RenderSceneData& baseSceneData) {
|
||||
RenderSceneData sceneData = baseSceneData;
|
||||
if (request.hasCameraDataOverride) {
|
||||
sceneData.cameraData = request.cameraDataOverride;
|
||||
}
|
||||
|
||||
sceneData.cameraData.viewportWidth = requestSurface.GetRenderAreaWidth();
|
||||
sceneData.cameraData.viewportHeight = requestSurface.GetRenderAreaHeight();
|
||||
sceneData.cameraData.clearFlags = request.clearFlags;
|
||||
if (request.hasClearColorOverride) {
|
||||
sceneData.cameraData.clearColor = request.clearColorOverride;
|
||||
}
|
||||
|
||||
return sceneData;
|
||||
}
|
||||
|
||||
bool ExecuteScenePassRequest(
|
||||
RenderPass* pass,
|
||||
const ScenePassRenderRequest& request,
|
||||
const RenderContext& context,
|
||||
const RenderSceneData& baseSceneData,
|
||||
const RenderSurface* surfaceOverride = nullptr) {
|
||||
if (!request.IsRequested()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!InitializeStandalonePass(pass, context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RenderSurface& requestSurface =
|
||||
surfaceOverride != nullptr ? *surfaceOverride : request.surface;
|
||||
const RenderSceneData sceneData =
|
||||
BuildScenePassRequestSceneData(
|
||||
request,
|
||||
requestSurface,
|
||||
baseSceneData);
|
||||
|
||||
const RenderPassContext passContext = {
|
||||
context,
|
||||
requestSurface,
|
||||
sceneData,
|
||||
nullptr,
|
||||
nullptr,
|
||||
RHI::ResourceStates::Common
|
||||
};
|
||||
return pass->Execute(passContext);
|
||||
}
|
||||
|
||||
bool ExecuteStandalonePass(
|
||||
RenderPass* pass,
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface,
|
||||
const RenderSceneData& sceneData) {
|
||||
if (pass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InitializeStandalonePass(pass, context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RenderPassContext passContext = {
|
||||
context,
|
||||
surface,
|
||||
sceneData,
|
||||
nullptr,
|
||||
nullptr,
|
||||
RHI::ResourceStates::Common
|
||||
};
|
||||
return pass->Execute(passContext);
|
||||
}
|
||||
|
||||
RenderSceneData BuildStandaloneStageSceneData(
|
||||
CameraFrameStage stage,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& baseSceneData,
|
||||
const RenderSurface& stageSurface) {
|
||||
if (stage == CameraFrameStage::ShadowCaster &&
|
||||
shadowState.shadowCasterRequest.IsRequested()) {
|
||||
return BuildScenePassRequestSceneData(
|
||||
shadowState.shadowCasterRequest,
|
||||
stageSurface,
|
||||
baseSceneData);
|
||||
}
|
||||
|
||||
if (const ScenePassRenderRequest* request = plan.GetScenePassRequest(stage);
|
||||
request != nullptr) {
|
||||
return BuildScenePassRequestSceneData(
|
||||
*request,
|
||||
stageSurface,
|
||||
baseSceneData);
|
||||
}
|
||||
|
||||
return baseSceneData;
|
||||
}
|
||||
|
||||
bool EnsureInitializedPassSequence(
|
||||
std::unique_ptr<ScopedInitializedPassSequence>& activeSequence,
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context) {
|
||||
if (activeSequence == nullptr) {
|
||||
activeSequence = std::make_unique<ScopedInitializedPassSequence>(sequence, context);
|
||||
}
|
||||
|
||||
return activeSequence->IsReady();
|
||||
}
|
||||
RenderPass* ResolveStandaloneStagePass(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordSequencePass(
|
||||
RenderPass& pass,
|
||||
const RenderPassRenderGraphContext& context,
|
||||
const Internal::RenderPassGraphIO& io) {
|
||||
return pass.SupportsRenderGraph()
|
||||
? pass.RecordRenderGraph(context)
|
||||
: Internal::RecordRasterRenderPass(pass, context, io);
|
||||
}
|
||||
|
||||
bool ExecuteRecordedFrameStage(
|
||||
CameraFrameStage stage,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
const RenderPassContext& passContext) {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::ShadowCaster:
|
||||
return ExecuteScenePassRequest(
|
||||
executionState.shadowCasterPass,
|
||||
shadowState.shadowCasterRequest,
|
||||
plan.request.context,
|
||||
sceneData,
|
||||
&passContext.surface);
|
||||
case CameraFrameStage::DepthOnly:
|
||||
return ExecuteScenePassRequest(
|
||||
executionState.depthOnlyPass,
|
||||
plan.request.depthOnly,
|
||||
plan.request.context,
|
||||
sceneData,
|
||||
&passContext.surface);
|
||||
case CameraFrameStage::MainScene:
|
||||
return executionState.pipeline != nullptr &&
|
||||
executionState.pipeline->Render(
|
||||
FrameExecutionContext(
|
||||
plan.request.context,
|
||||
passContext.surface,
|
||||
sceneData,
|
||||
passContext.sourceSurface,
|
||||
passContext.sourceColorView,
|
||||
passContext.sourceColorState));
|
||||
case CameraFrameStage::ObjectId:
|
||||
return !plan.request.objectId.IsRequested() ||
|
||||
ExecuteStandalonePass(
|
||||
executionState.objectIdPass,
|
||||
plan.request.context,
|
||||
passContext.surface,
|
||||
sceneData);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordRegularPassSequenceStage(
|
||||
CameraFrameStage stage,
|
||||
const Containers::String& stageName,
|
||||
const RenderPassContext& stagePassContext,
|
||||
const RenderGraphImportedSurface& outputSurface,
|
||||
const RenderSceneData& sceneData,
|
||||
RenderPassSequence* stageSequence,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded) {
|
||||
if (stageSequence == nullptr || stageSequence->GetPassCount() == 0u) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<ScopedInitializedPassSequence>* const activeSequence =
|
||||
ResolveStageSequenceState(stage, executionState);
|
||||
RenderPassSequence* const sequence = stageSequence;
|
||||
const RenderContext* const renderContext = &stagePassContext.renderContext;
|
||||
const RenderPassGraphBeginCallback beginSequencePass =
|
||||
[&, activeSequence, sequence, renderContext](const RenderPassContext&) -> bool {
|
||||
if (activeSequence == nullptr ||
|
||||
!EnsureInitializedPassSequence(
|
||||
*activeSequence,
|
||||
sequence,
|
||||
*renderContext)) {
|
||||
stageExecutionSucceeded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
const bool writesColor = GetPrimaryColorTexture(outputSurface).IsValid();
|
||||
const bool writesDepth = outputSurface.depthTexture.IsValid();
|
||||
|
||||
for (size_t passIndex = 0u; passIndex < stageSequence->GetPassCount(); ++passIndex) {
|
||||
RenderPass* const pass = stageSequence->GetPass(passIndex);
|
||||
if (pass == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Containers::String passName =
|
||||
stageSequence->GetPassCount() == 1u
|
||||
? stageName
|
||||
: BuildRenderGraphSequencePassName(stageName, passIndex);
|
||||
const RenderPassRenderGraphContext passContext = {
|
||||
graphBuilder,
|
||||
passName,
|
||||
stagePassContext.renderContext,
|
||||
sceneData,
|
||||
stagePassContext.surface,
|
||||
stagePassContext.sourceSurface,
|
||||
stagePassContext.sourceColorView,
|
||||
stagePassContext.sourceColorState,
|
||||
{},
|
||||
outputSurface.colorTextures,
|
||||
outputSurface.depthTexture,
|
||||
&stageExecutionSucceeded,
|
||||
beginSequencePass,
|
||||
{},
|
||||
&blackboard
|
||||
};
|
||||
if (!RecordSequencePass(
|
||||
*pass,
|
||||
passContext,
|
||||
{
|
||||
false,
|
||||
writesColor,
|
||||
writesDepth
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RecordFullscreenPassSequenceStage(
|
||||
CameraFrameStage stage,
|
||||
const Containers::String& stageName,
|
||||
const RenderPassContext& stagePassContext,
|
||||
const CameraFrameRenderGraphSourceBinding& binding,
|
||||
RenderGraphTextureHandle finalOutputColor,
|
||||
const RenderSceneData& sceneData,
|
||||
RenderPassSequence* stageSequence,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded) {
|
||||
if (stageSequence == nullptr || stageSequence->GetPassCount() == 0u) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<ScopedInitializedPassSequence>* const activeSequence =
|
||||
ResolveStageSequenceState(stage, executionState);
|
||||
RenderPassSequence* const sequence = stageSequence;
|
||||
const RenderContext* const renderContext = &stagePassContext.renderContext;
|
||||
const RenderPassGraphBeginCallback beginSequencePass =
|
||||
[&, activeSequence, sequence, renderContext](const RenderPassContext&) -> bool {
|
||||
if (activeSequence == nullptr ||
|
||||
!EnsureInitializedPassSequence(
|
||||
*activeSequence,
|
||||
sequence,
|
||||
*renderContext)) {
|
||||
stageExecutionSucceeded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
RenderGraphTextureHandle currentSourceColor = binding.sourceColor;
|
||||
const RenderGraphTextureDesc transientDesc =
|
||||
BuildFullscreenTransientTextureDesc(stagePassContext.surface);
|
||||
|
||||
for (size_t passIndex = 0u; passIndex < stageSequence->GetPassCount(); ++passIndex) {
|
||||
RenderPass* const pass = stageSequence->GetPass(passIndex);
|
||||
if (pass == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool isLastPass = (passIndex + 1u) == stageSequence->GetPassCount();
|
||||
const Containers::String passName =
|
||||
stageSequence->GetPassCount() == 1u
|
||||
? stageName
|
||||
: BuildRenderGraphSequencePassName(stageName, passIndex);
|
||||
const RenderGraphTextureHandle passOutputColor =
|
||||
isLastPass
|
||||
? finalOutputColor
|
||||
: graphBuilder.CreateTransientTexture(
|
||||
passName + ".Color",
|
||||
transientDesc);
|
||||
const RenderSurface* const sourceSurfaceTemplate =
|
||||
passIndex == 0u
|
||||
? binding.sourceSurfaceTemplate
|
||||
: &stagePassContext.surface;
|
||||
RHI::RHIResourceView* const sourceColorView =
|
||||
passIndex == 0u
|
||||
? binding.sourceColorView
|
||||
: nullptr;
|
||||
const RHI::ResourceStates sourceColorState =
|
||||
passIndex == 0u
|
||||
? binding.sourceColorState
|
||||
: RHI::ResourceStates::PixelShaderResource;
|
||||
const RenderPassRenderGraphContext passContext = {
|
||||
graphBuilder,
|
||||
passName,
|
||||
stagePassContext.renderContext,
|
||||
sceneData,
|
||||
stagePassContext.surface,
|
||||
sourceSurfaceTemplate,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
currentSourceColor,
|
||||
std::vector<RenderGraphTextureHandle>{ passOutputColor },
|
||||
{},
|
||||
&stageExecutionSucceeded,
|
||||
beginSequencePass,
|
||||
{},
|
||||
&blackboard
|
||||
};
|
||||
if (!RecordSequencePass(
|
||||
*pass,
|
||||
passContext,
|
||||
{
|
||||
true,
|
||||
true,
|
||||
false
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
currentSourceColor = passOutputColor;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryRecordCameraFrameStageSequence(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled) {
|
||||
if (stageState.stageSequence == nullptr) {
|
||||
handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
handled = true;
|
||||
const RenderPassContext stagePassContext =
|
||||
BuildCameraFrameStageGraphPassContext(plan, stageState, sceneData);
|
||||
const bool recordResult =
|
||||
IsCameraFrameFullscreenSequenceStage(stageState.stage)
|
||||
? RecordFullscreenPassSequenceStage(
|
||||
stageState.stage,
|
||||
stageState.stageName,
|
||||
stagePassContext,
|
||||
ResolveCameraFrameFullscreenStageGraphSourceBinding(
|
||||
plan,
|
||||
stageState.stage,
|
||||
stageState.surfaceTemplate,
|
||||
stagePassContext.sourceSurface,
|
||||
stagePassContext.sourceColorView,
|
||||
stagePassContext.sourceColorState,
|
||||
GetPrimaryColorTexture(stageState.sourceSurface),
|
||||
&blackboard),
|
||||
stageState.outputColor,
|
||||
sceneData,
|
||||
stageState.stageSequence,
|
||||
executionState,
|
||||
graphBuilder,
|
||||
blackboard,
|
||||
stageExecutionSucceeded)
|
||||
: RecordRegularPassSequenceStage(
|
||||
stageState.stage,
|
||||
stageState.stageName,
|
||||
stagePassContext,
|
||||
stageState.outputSurface,
|
||||
sceneData,
|
||||
stageState.stageSequence,
|
||||
executionState,
|
||||
graphBuilder,
|
||||
blackboard,
|
||||
stageExecutionSucceeded);
|
||||
if (!recordResult) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
Containers::String("CameraRenderer::Render failed: pass-sequence graph recording returned false for ") +
|
||||
stageState.stageName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryRecordCameraFrameStageStandaloneRenderGraphPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled) {
|
||||
RenderPass* const standaloneStagePass =
|
||||
ResolveStandaloneStagePass(stageState.stage, executionState);
|
||||
if (standaloneStagePass == nullptr ||
|
||||
!standaloneStagePass->SupportsRenderGraph()) {
|
||||
handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
handled = true;
|
||||
const RenderSceneData stageSceneData =
|
||||
BuildStandaloneStageSceneData(
|
||||
stageState.stage,
|
||||
plan,
|
||||
shadowState,
|
||||
sceneData,
|
||||
stageState.surfaceTemplate);
|
||||
const RenderPassGraphBeginCallback beginStandalonePass =
|
||||
[&, standaloneStagePass](const RenderPassContext&) -> bool {
|
||||
if (!InitializeStandalonePass(
|
||||
standaloneStagePass,
|
||||
plan.request.context)) {
|
||||
stageExecutionSucceeded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
const RenderPassRenderGraphContext standalonePassContext = {
|
||||
graphBuilder,
|
||||
stageState.stageName,
|
||||
plan.request.context,
|
||||
stageSceneData,
|
||||
stageState.surfaceTemplate,
|
||||
stageState.hasSourceSurface
|
||||
? &stageState.sourceSurfaceTemplate
|
||||
: nullptr,
|
||||
stageState.sourceColorView,
|
||||
stageState.sourceColorState,
|
||||
GetPrimaryColorTexture(stageState.sourceSurface),
|
||||
std::vector<RenderGraphTextureHandle>{ stageState.outputColor },
|
||||
stageState.outputSurface.depthTexture,
|
||||
&stageExecutionSucceeded,
|
||||
beginStandalonePass,
|
||||
{},
|
||||
&blackboard
|
||||
};
|
||||
if (!standaloneStagePass->RecordRenderGraph(standalonePassContext)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
Containers::String("CameraRenderer::Render failed: RenderPass::RecordRenderGraph returned false for ") +
|
||||
stageState.stageName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryRecordCameraFrameMainSceneGraphPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled) {
|
||||
if (stageState.stage != CameraFrameStage::MainScene ||
|
||||
executionState.pipeline == nullptr ||
|
||||
!executionState.pipeline->SupportsMainSceneRenderGraph()) {
|
||||
handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
handled = true;
|
||||
const RenderPipelineMainSceneRenderGraphContext mainSceneContext = {
|
||||
graphBuilder,
|
||||
stageState.stageName,
|
||||
plan.request.context,
|
||||
sceneData,
|
||||
stageState.surfaceTemplate,
|
||||
stageState.hasSourceSurface
|
||||
? &stageState.sourceSurfaceTemplate
|
||||
: nullptr,
|
||||
stageState.sourceColorView,
|
||||
stageState.sourceColorState,
|
||||
std::vector<RenderGraphTextureHandle>{ stageState.outputColor },
|
||||
stageState.outputSurface.depthTexture,
|
||||
&stageExecutionSucceeded,
|
||||
&blackboard
|
||||
};
|
||||
if (!executionState.pipeline->RecordMainSceneRenderGraph(mainSceneContext)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"CameraRenderer::Render failed: RenderPipeline::RecordMainSceneRenderGraph returned false");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddCameraFrameStageFallbackRasterPass(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
bool& stageExecutionSucceeded) {
|
||||
const CameraFrameStageGraphBuildState capturedStageState = stageState;
|
||||
graphBuilder.AddRasterPass(
|
||||
capturedStageState.stageName,
|
||||
[&, capturedStageState](RenderGraphPassBuilder& passBuilder) {
|
||||
if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage)) {
|
||||
ReadRenderGraphColorSurface(passBuilder, capturedStageState.sourceSurface);
|
||||
WriteRenderGraphColorSurface(passBuilder, capturedStageState.outputSurface);
|
||||
} else {
|
||||
ReadRenderGraphSurface(passBuilder, capturedStageState.sourceSurface);
|
||||
WriteRenderGraphSurface(passBuilder, capturedStageState.outputSurface);
|
||||
}
|
||||
passBuilder.SetExecuteCallback(
|
||||
[&, capturedStageState](
|
||||
const RenderGraphExecutionContext& executionContext) {
|
||||
if (!stageExecutionSucceeded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const RenderSurface* resolvedSourceSurface =
|
||||
capturedStageState.hasSourceSurface
|
||||
? &capturedStageState.sourceSurfaceTemplate
|
||||
: nullptr;
|
||||
RHI::RHIResourceView* resolvedSourceColorView =
|
||||
capturedStageState.sourceColorView;
|
||||
RHI::ResourceStates resolvedSourceColorState =
|
||||
capturedStageState.sourceColorState;
|
||||
RenderSurface graphManagedSourceSurface = {};
|
||||
if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage) &&
|
||||
capturedStageState.hasSourceSurface &&
|
||||
CanUseGraphManagedImportedSurface(
|
||||
capturedStageState.sourceSurface,
|
||||
executionContext)) {
|
||||
graphManagedSourceSurface =
|
||||
BuildGraphManagedImportedSurface(
|
||||
capturedStageState.sourceSurfaceTemplate,
|
||||
RHI::ResourceStates::PixelShaderResource,
|
||||
RHI::ResourceStates::PixelShaderResource);
|
||||
resolvedSourceSurface = &graphManagedSourceSurface;
|
||||
resolvedSourceColorState = RHI::ResourceStates::PixelShaderResource;
|
||||
}
|
||||
|
||||
const RenderSurface* resolvedOutputSurface =
|
||||
&capturedStageState.surfaceTemplate;
|
||||
RenderSurface graphManagedOutputSurface = {};
|
||||
if (CanUseGraphManagedImportedSurface(
|
||||
capturedStageState.outputSurface,
|
||||
executionContext)) {
|
||||
graphManagedOutputSurface =
|
||||
BuildGraphManagedPassSurface(
|
||||
capturedStageState.surfaceTemplate);
|
||||
resolvedOutputSurface = &graphManagedOutputSurface;
|
||||
}
|
||||
|
||||
const RenderPassContext passContextOverride = {
|
||||
plan.request.context,
|
||||
*resolvedOutputSurface,
|
||||
sceneData,
|
||||
resolvedSourceSurface,
|
||||
resolvedSourceColorView,
|
||||
resolvedSourceColorState
|
||||
};
|
||||
stageExecutionSucceeded = ExecuteRecordedFrameStage(
|
||||
capturedStageState.stage,
|
||||
plan,
|
||||
shadowState,
|
||||
sceneData,
|
||||
executionState,
|
||||
passContextOverride);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool ExecuteCameraFrameRenderGraphStages(
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowExecutionState& shadowState,
|
||||
@@ -681,7 +36,6 @@ bool ExecuteCameraFrameRenderGraphStages(
|
||||
|
||||
RenderGraphImportedTextureRegistry importedTextures = {};
|
||||
bool stageExecutionSucceeded = true;
|
||||
stageExecutionSucceeded = true;
|
||||
for (const CameraFrameStageInfo& stageInfo : kOrderedCameraFrameStages) {
|
||||
if (!plan.HasFrameStage(stageInfo.stage) &&
|
||||
stageInfo.stage != CameraFrameStage::MainScene) {
|
||||
|
||||
@@ -4,63 +4,10 @@
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Rendering/RenderPipeline.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
struct CameraFrameRenderGraphResources;
|
||||
struct DirectionalShadowExecutionState;
|
||||
class RenderGraphBuilder;
|
||||
class RenderGraphBlackboard;
|
||||
|
||||
class ScopedInitializedPassSequence {
|
||||
public:
|
||||
ScopedInitializedPassSequence(
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context)
|
||||
: m_sequence(sequence) {
|
||||
if (m_sequence == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sequence->Initialize(context)) {
|
||||
m_failed = true;
|
||||
m_sequence->Shutdown();
|
||||
m_sequence = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedInitializedPassSequence(const ScopedInitializedPassSequence&) = delete;
|
||||
ScopedInitializedPassSequence& operator=(const ScopedInitializedPassSequence&) = delete;
|
||||
|
||||
~ScopedInitializedPassSequence() {
|
||||
// Request-owned pass sequences may record GPU work that executes only after the
|
||||
// caller closes/submits the command list. Do not destroy sequence-owned GPU
|
||||
// resources here; the sequence owner must shut them down explicitly when the
|
||||
// sequence is no longer needed.
|
||||
}
|
||||
|
||||
bool IsReady() const {
|
||||
return !m_failed;
|
||||
}
|
||||
|
||||
private:
|
||||
RenderPassSequence* m_sequence = nullptr;
|
||||
bool m_failed = false;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
bool ExecuteCameraFrameRenderGraphStages(
|
||||
const CameraFramePlan& plan,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Rendering/RenderPipeline.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
class ScopedInitializedPassSequence {
|
||||
public:
|
||||
ScopedInitializedPassSequence(
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context)
|
||||
: m_sequence(sequence) {
|
||||
if (m_sequence == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sequence->Initialize(context)) {
|
||||
m_failed = true;
|
||||
m_sequence->Shutdown();
|
||||
m_sequence = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedInitializedPassSequence(const ScopedInitializedPassSequence&) = delete;
|
||||
ScopedInitializedPassSequence& operator=(const ScopedInitializedPassSequence&) = delete;
|
||||
|
||||
~ScopedInitializedPassSequence() {
|
||||
// Request-owned pass sequences may record GPU work that executes only after the
|
||||
// caller closes/submits the command list. Do not destroy sequence-owned GPU
|
||||
// resources here; the sequence owner must shut them down explicitly when the
|
||||
// sequence is no longer needed.
|
||||
}
|
||||
|
||||
bool IsReady() const {
|
||||
return !m_failed;
|
||||
}
|
||||
|
||||
private:
|
||||
RenderPassSequence* m_sequence = nullptr;
|
||||
bool m_failed = false;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -0,0 +1,298 @@
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageSequenceRecording.h"
|
||||
|
||||
#include "Debug/Logger.h"
|
||||
#include "Rendering/Execution/CameraFrameRenderGraphStagePolicy.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageRuntime.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageState.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameRenderGraphSurfaceUtils.h"
|
||||
#include "Rendering/Graph/RenderGraph.h"
|
||||
#include "Rendering/Internal/RenderPassGraphUtils.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
namespace {
|
||||
|
||||
bool EnsureInitializedPassSequence(
|
||||
std::unique_ptr<ScopedInitializedPassSequence>& activeSequence,
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context) {
|
||||
if (activeSequence == nullptr) {
|
||||
activeSequence =
|
||||
std::make_unique<ScopedInitializedPassSequence>(sequence, context);
|
||||
}
|
||||
|
||||
return activeSequence->IsReady();
|
||||
}
|
||||
|
||||
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:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordSequencePass(
|
||||
RenderPass& pass,
|
||||
const RenderPassRenderGraphContext& context,
|
||||
const Internal::RenderPassGraphIO& io) {
|
||||
return pass.SupportsRenderGraph()
|
||||
? pass.RecordRenderGraph(context)
|
||||
: Internal::RecordRasterRenderPass(pass, context, io);
|
||||
}
|
||||
|
||||
bool RecordRegularPassSequenceStage(
|
||||
CameraFrameStage stage,
|
||||
const Containers::String& stageName,
|
||||
const RenderPassContext& stagePassContext,
|
||||
const RenderGraphImportedSurface& outputSurface,
|
||||
const RenderSceneData& sceneData,
|
||||
RenderPassSequence* stageSequence,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded) {
|
||||
if (stageSequence == nullptr || stageSequence->GetPassCount() == 0u) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<ScopedInitializedPassSequence>* const activeSequence =
|
||||
ResolveStageSequenceState(stage, executionState);
|
||||
RenderPassSequence* const sequence = stageSequence;
|
||||
const RenderContext* const renderContext = &stagePassContext.renderContext;
|
||||
const RenderPassGraphBeginCallback beginSequencePass =
|
||||
[&, activeSequence, sequence, renderContext](const RenderPassContext&) -> bool {
|
||||
if (activeSequence == nullptr ||
|
||||
!EnsureInitializedPassSequence(
|
||||
*activeSequence,
|
||||
sequence,
|
||||
*renderContext)) {
|
||||
stageExecutionSucceeded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
const bool writesColor = GetPrimaryColorTexture(outputSurface).IsValid();
|
||||
const bool writesDepth = outputSurface.depthTexture.IsValid();
|
||||
|
||||
for (size_t passIndex = 0u; passIndex < stageSequence->GetPassCount(); ++passIndex) {
|
||||
RenderPass* const pass = stageSequence->GetPass(passIndex);
|
||||
if (pass == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Containers::String passName =
|
||||
stageSequence->GetPassCount() == 1u
|
||||
? stageName
|
||||
: BuildRenderGraphSequencePassName(stageName, passIndex);
|
||||
const RenderPassRenderGraphContext passContext = {
|
||||
graphBuilder,
|
||||
passName,
|
||||
stagePassContext.renderContext,
|
||||
sceneData,
|
||||
stagePassContext.surface,
|
||||
stagePassContext.sourceSurface,
|
||||
stagePassContext.sourceColorView,
|
||||
stagePassContext.sourceColorState,
|
||||
{},
|
||||
outputSurface.colorTextures,
|
||||
outputSurface.depthTexture,
|
||||
&stageExecutionSucceeded,
|
||||
beginSequencePass,
|
||||
{},
|
||||
&blackboard
|
||||
};
|
||||
if (!RecordSequencePass(
|
||||
*pass,
|
||||
passContext,
|
||||
{
|
||||
false,
|
||||
writesColor,
|
||||
writesDepth
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RecordFullscreenPassSequenceStage(
|
||||
CameraFrameStage stage,
|
||||
const Containers::String& stageName,
|
||||
const RenderPassContext& stagePassContext,
|
||||
const CameraFrameRenderGraphSourceBinding& binding,
|
||||
RenderGraphTextureHandle finalOutputColor,
|
||||
const RenderSceneData& sceneData,
|
||||
RenderPassSequence* stageSequence,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded) {
|
||||
if (stageSequence == nullptr || stageSequence->GetPassCount() == 0u) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<ScopedInitializedPassSequence>* const activeSequence =
|
||||
ResolveStageSequenceState(stage, executionState);
|
||||
RenderPassSequence* const sequence = stageSequence;
|
||||
const RenderContext* const renderContext = &stagePassContext.renderContext;
|
||||
const RenderPassGraphBeginCallback beginSequencePass =
|
||||
[&, activeSequence, sequence, renderContext](const RenderPassContext&) -> bool {
|
||||
if (activeSequence == nullptr ||
|
||||
!EnsureInitializedPassSequence(
|
||||
*activeSequence,
|
||||
sequence,
|
||||
*renderContext)) {
|
||||
stageExecutionSucceeded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
RenderGraphTextureHandle currentSourceColor = binding.sourceColor;
|
||||
const RenderGraphTextureDesc transientDesc =
|
||||
BuildFullscreenTransientTextureDesc(stagePassContext.surface);
|
||||
|
||||
for (size_t passIndex = 0u; passIndex < stageSequence->GetPassCount(); ++passIndex) {
|
||||
RenderPass* const pass = stageSequence->GetPass(passIndex);
|
||||
if (pass == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool isLastPass = (passIndex + 1u) == stageSequence->GetPassCount();
|
||||
const Containers::String passName =
|
||||
stageSequence->GetPassCount() == 1u
|
||||
? stageName
|
||||
: BuildRenderGraphSequencePassName(stageName, passIndex);
|
||||
const RenderGraphTextureHandle passOutputColor =
|
||||
isLastPass
|
||||
? finalOutputColor
|
||||
: graphBuilder.CreateTransientTexture(
|
||||
passName + ".Color",
|
||||
transientDesc);
|
||||
const RenderSurface* const sourceSurfaceTemplate =
|
||||
passIndex == 0u
|
||||
? binding.sourceSurfaceTemplate
|
||||
: &stagePassContext.surface;
|
||||
RHI::RHIResourceView* const sourceColorView =
|
||||
passIndex == 0u
|
||||
? binding.sourceColorView
|
||||
: nullptr;
|
||||
const RHI::ResourceStates sourceColorState =
|
||||
passIndex == 0u
|
||||
? binding.sourceColorState
|
||||
: RHI::ResourceStates::PixelShaderResource;
|
||||
const RenderPassRenderGraphContext passContext = {
|
||||
graphBuilder,
|
||||
passName,
|
||||
stagePassContext.renderContext,
|
||||
sceneData,
|
||||
stagePassContext.surface,
|
||||
sourceSurfaceTemplate,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
currentSourceColor,
|
||||
std::vector<RenderGraphTextureHandle>{ passOutputColor },
|
||||
{},
|
||||
&stageExecutionSucceeded,
|
||||
beginSequencePass,
|
||||
{},
|
||||
&blackboard
|
||||
};
|
||||
if (!RecordSequencePass(
|
||||
*pass,
|
||||
passContext,
|
||||
{
|
||||
true,
|
||||
true,
|
||||
false
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
currentSourceColor = passOutputColor;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool TryRecordCameraFrameStageSequence(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled) {
|
||||
if (stageState.stageSequence == nullptr) {
|
||||
handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
handled = true;
|
||||
const RenderPassContext stagePassContext =
|
||||
BuildCameraFrameStageGraphPassContext(plan, stageState, sceneData);
|
||||
const bool recordResult =
|
||||
IsCameraFrameFullscreenSequenceStage(stageState.stage)
|
||||
? RecordFullscreenPassSequenceStage(
|
||||
stageState.stage,
|
||||
stageState.stageName,
|
||||
stagePassContext,
|
||||
ResolveCameraFrameFullscreenStageGraphSourceBinding(
|
||||
plan,
|
||||
stageState.stage,
|
||||
stageState.surfaceTemplate,
|
||||
stagePassContext.sourceSurface,
|
||||
stagePassContext.sourceColorView,
|
||||
stagePassContext.sourceColorState,
|
||||
GetPrimaryColorTexture(stageState.sourceSurface),
|
||||
&blackboard),
|
||||
stageState.outputColor,
|
||||
sceneData,
|
||||
stageState.stageSequence,
|
||||
executionState,
|
||||
graphBuilder,
|
||||
blackboard,
|
||||
stageExecutionSucceeded)
|
||||
: RecordRegularPassSequenceStage(
|
||||
stageState.stage,
|
||||
stageState.stageName,
|
||||
stagePassContext,
|
||||
stageState.outputSurface,
|
||||
sceneData,
|
||||
stageState.stageSequence,
|
||||
executionState,
|
||||
graphBuilder,
|
||||
blackboard,
|
||||
stageExecutionSucceeded);
|
||||
if (!recordResult) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
Containers::String("CameraRenderer::Render failed: pass-sequence graph recording returned false for ") +
|
||||
stageState.stageName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
struct CameraFrameExecutionState;
|
||||
struct CameraFramePlan;
|
||||
struct CameraFrameStageGraphBuildState;
|
||||
struct RenderSceneData;
|
||||
class RenderGraphBuilder;
|
||||
class RenderGraphBlackboard;
|
||||
|
||||
bool TryRecordCameraFrameStageSequence(
|
||||
const CameraFrameStageGraphBuildState& stageState,
|
||||
const CameraFramePlan& plan,
|
||||
const RenderSceneData& sceneData,
|
||||
CameraFrameExecutionState& executionState,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
RenderGraphBlackboard& blackboard,
|
||||
bool& stageExecutionSucceeded,
|
||||
bool& handled);
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user