Graph-ify forward feature injection points

This commit is contained in:
2026-04-14 16:49:06 +08:00
parent a4c48c1b3f
commit 2a9264cfe4
9 changed files with 861 additions and 119 deletions

View File

@@ -2,6 +2,7 @@
#include "Debug/Logger.h"
#include "Rendering/Graph/RenderGraph.h"
#include "Rendering/Pipelines/Internal/BuiltinForwardSceneSetup.h"
#include "RHI/RHICommandList.h"
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
#include "Rendering/RenderSurface.h"
@@ -60,36 +61,24 @@ RenderSurface BuildGraphManagedForwardSceneSurface(const RenderSurface& template
return surface;
}
struct ForwardSceneGraphSegmentDesc {
const char* suffix = "";
size_t beginStepIndex = 0u;
size_t endStepIndex = 0u;
bool clearAttachments = false;
bool samplesMainDirectionalShadow = false;
};
struct ForwardSceneGraphExecutionState {
bool initialized = false;
};
const std::array<ForwardSceneGraphSegmentDesc, 3>& GetForwardSceneGraphSegments() {
static constexpr std::array<ForwardSceneGraphSegmentDesc, 3> kSegments = {{
{ "Opaque", 0u, 3u, true, true },
{ "Skybox", 3u, 6u, false, false },
{ "Transparent", 6u, 9u, false, true }
}};
return kSegments;
}
Containers::String BuildForwardSceneSegmentPassName(
Containers::String BuildForwardScenePhasePassName(
const Containers::String& baseName,
const char* suffix) {
ScenePhase scenePhase) {
std::string name = baseName.CStr();
name += '.';
name += suffix != nullptr ? suffix : "Segment";
name += ToString(scenePhase);
return Containers::String(name.c_str());
}
bool ScenePhaseSamplesMainDirectionalShadow(ScenePhase scenePhase) {
return scenePhase == ScenePhase::Opaque ||
scenePhase == ScenePhase::Transparent;
}
} // namespace
bool BuiltinForwardPipeline::ShouldSampleMainDirectionalShadowMap(const RenderSceneData& sceneData) {
@@ -119,14 +108,108 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
bool* const executionSucceeded = context.executionSucceeded;
const std::shared_ptr<ForwardSceneGraphExecutionState> graphExecutionState =
std::make_shared<ForwardSceneGraphExecutionState>();
const SceneRenderFeaturePassBeginCallback beginRecordedPass =
[this,
graphExecutionState,
renderContext,
sceneData,
sourceSurface,
sourceColorView,
sourceColorState,
executionSucceeded](
const RenderPassContext& passContext,
bool clearAttachments) -> bool {
if (executionSucceeded != nullptr && !(*executionSucceeded)) {
return false;
}
for (const ForwardSceneGraphSegmentDesc& segment : GetForwardSceneGraphSegments()) {
const Containers::String segmentPassName =
BuildForwardSceneSegmentPassName(passName, segment.suffix);
if (!graphExecutionState->initialized) {
if (!Initialize(*renderContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardPipeline::RecordMainSceneRenderGraph failed during execution: Initialize returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return false;
}
const FrameExecutionContext executionContext(
*renderContext,
passContext.surface,
*sceneData,
sourceSurface,
sourceColorView,
sourceColorState);
if (!m_forwardSceneFeatureHost.Prepare(executionContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardPipeline::RecordMainSceneRenderGraph failed during execution: SceneRenderFeatureHost::Prepare returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return false;
}
graphExecutionState->initialized = true;
}
if (!BeginForwardScenePass(passContext, clearAttachments)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardPipeline::RecordMainSceneRenderGraph failed during execution: BeginForwardScenePass returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return false;
}
return true;
};
const SceneRenderFeaturePassEndCallback endRecordedPass =
[this](const RenderPassContext& passContext) {
EndForwardScenePass(passContext);
};
bool clearAttachments = true;
for (const Pipelines::Internal::ForwardSceneStep& step : Pipelines::Internal::GetBuiltinForwardSceneSteps()) {
if (step.type == Pipelines::Internal::ForwardSceneStepType::InjectionPoint) {
const SceneRenderFeaturePassRenderGraphContext featureContext = {
context.graphBuilder,
passName,
*renderContext,
*sceneData,
surfaceTemplate,
sourceSurface,
sourceColorView,
sourceColorState,
colorTargets,
depthTarget,
mainDirectionalShadowTexture,
clearAttachments,
executionSucceeded,
beginRecordedPass,
endRecordedPass
};
bool recordedAnyPass = false;
if (!m_forwardSceneFeatureHost.Record(
featureContext,
step.injectionPoint,
&recordedAnyPass)) {
return false;
}
if (recordedAnyPass) {
clearAttachments = false;
}
continue;
}
const Containers::String phasePassName =
BuildForwardScenePhasePassName(passName, step.scenePhase);
context.graphBuilder.AddRasterPass(
segmentPassName,
phasePassName,
[this,
graphExecutionState,
surfaceTemplate,
renderContext,
sceneData,
@@ -137,78 +220,67 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
depthTarget,
mainDirectionalShadowTexture,
executionSucceeded,
segment](
beginRecordedPass,
endRecordedPass,
clearAttachments,
scenePhase = step.scenePhase](
RenderGraphPassBuilder& passBuilder) {
for (RenderGraphTextureHandle colorTarget : colorTargets) {
if (colorTarget.IsValid()) {
passBuilder.WriteTexture(colorTarget);
for (RenderGraphTextureHandle colorTarget : colorTargets) {
if (colorTarget.IsValid()) {
passBuilder.WriteTexture(colorTarget);
}
}
}
if (depthTarget.IsValid()) {
passBuilder.WriteDepthTexture(depthTarget);
}
if (segment.samplesMainDirectionalShadow &&
mainDirectionalShadowTexture.IsValid()) {
passBuilder.ReadTexture(mainDirectionalShadowTexture);
}
if (depthTarget.IsValid()) {
passBuilder.WriteDepthTexture(depthTarget);
}
if (ScenePhaseSamplesMainDirectionalShadow(scenePhase) &&
mainDirectionalShadowTexture.IsValid()) {
passBuilder.ReadTexture(mainDirectionalShadowTexture);
}
passBuilder.SetExecuteCallback(
[this,
graphExecutionState,
surfaceTemplate,
renderContext,
sceneData,
sourceSurface,
sourceColorView,
sourceColorState,
executionSucceeded,
segment](
const RenderGraphExecutionContext&) {
if (executionSucceeded != nullptr && !(*executionSucceeded)) {
return;
}
const FrameExecutionContext executionContext(
*renderContext,
surfaceTemplate,
*sceneData,
sourceSurface,
sourceColorView,
sourceColorState);
if (!graphExecutionState->initialized) {
if (!Initialize(*renderContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardPipeline::RecordMainSceneRenderGraph failed during execution: Initialize returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
passBuilder.SetExecuteCallback(
[this,
surfaceTemplate,
renderContext,
sceneData,
sourceSurface,
sourceColorView,
sourceColorState,
executionSucceeded,
beginRecordedPass,
endRecordedPass,
clearAttachments,
scenePhase](
const RenderGraphExecutionContext&) {
if (executionSucceeded != nullptr && !(*executionSucceeded)) {
return;
}
if (!m_forwardSceneFeatureHost.Prepare(executionContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"BuiltinForwardPipeline::RecordMainSceneRenderGraph failed during execution: SceneRenderFeatureHost::Prepare returned false");
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
const FrameExecutionContext executionContext(
*renderContext,
surfaceTemplate,
*sceneData,
sourceSurface,
sourceColorView,
sourceColorState);
const RenderPassContext passContext =
BuildRenderPassContext(executionContext);
if (!beginRecordedPass(passContext, clearAttachments)) {
return;
}
graphExecutionState->initialized = true;
}
const bool renderResult =
ExecuteForwardSceneSegmentPass(
executionContext,
segment.beginStepIndex,
segment.endStepIndex,
segment.clearAttachments);
if (executionSucceeded != nullptr) {
*executionSucceeded = renderResult;
}
});
const ScenePhaseExecutionContext scenePhaseExecutionContext =
BuildScenePhaseExecutionContext(executionContext, scenePhase);
const bool renderResult =
ExecuteBuiltinScenePhase(scenePhaseExecutionContext);
endRecordedPass(passContext);
if (executionSucceeded != nullptr) {
*executionSucceeded = renderResult;
}
});
});
clearAttachments = false;
}
return true;