refactor: extract scene viewport post-pass planning
This commit is contained in:
77
editor/src/Viewport/SceneViewportPostPassPlan.h
Normal file
77
editor/src/Viewport/SceneViewportPostPassPlan.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
enum class SceneViewportPostPassStep : uint8_t {
|
||||
SelectionMask,
|
||||
ColorToRenderTarget,
|
||||
InfiniteGrid,
|
||||
SelectionOutline,
|
||||
ColorToShaderResource,
|
||||
SelectionMaskDebug
|
||||
};
|
||||
|
||||
struct SceneViewportPostPassPlanInput {
|
||||
bool overlayValid = false;
|
||||
bool hasSelection = false;
|
||||
bool debugSelectionMask = false;
|
||||
bool hasSelectionMaskRenderTarget = false;
|
||||
bool hasSelectionMaskShaderView = false;
|
||||
};
|
||||
|
||||
struct SceneViewportPostPassPlan {
|
||||
bool valid = false;
|
||||
bool usesSelectionMaskSurface = false;
|
||||
bool usesSelectionMaskShaderView = false;
|
||||
std::vector<SceneViewportPostPassStep> steps;
|
||||
};
|
||||
|
||||
inline SceneViewportPostPassPlan BuildSceneViewportPostPassPlan(
|
||||
const SceneViewportPostPassPlanInput& input) {
|
||||
SceneViewportPostPassPlan plan = {};
|
||||
if (!input.overlayValid) {
|
||||
return plan;
|
||||
}
|
||||
|
||||
plan.valid = true;
|
||||
|
||||
if (input.hasSelection && input.debugSelectionMask) {
|
||||
plan.steps = {
|
||||
SceneViewportPostPassStep::ColorToRenderTarget,
|
||||
SceneViewportPostPassStep::SelectionMaskDebug,
|
||||
SceneViewportPostPassStep::ColorToShaderResource
|
||||
};
|
||||
return plan;
|
||||
}
|
||||
|
||||
const bool canRenderSelectionMask =
|
||||
input.hasSelection &&
|
||||
input.hasSelectionMaskRenderTarget &&
|
||||
input.hasSelectionMaskShaderView;
|
||||
const bool canRenderSelectionOutline =
|
||||
canRenderSelectionMask &&
|
||||
input.hasSelectionMaskShaderView;
|
||||
|
||||
if (canRenderSelectionMask) {
|
||||
plan.usesSelectionMaskSurface = true;
|
||||
plan.usesSelectionMaskShaderView = true;
|
||||
plan.steps.push_back(SceneViewportPostPassStep::SelectionMask);
|
||||
}
|
||||
|
||||
plan.steps.push_back(SceneViewportPostPassStep::ColorToRenderTarget);
|
||||
plan.steps.push_back(SceneViewportPostPassStep::InfiniteGrid);
|
||||
|
||||
if (canRenderSelectionOutline) {
|
||||
plan.steps.push_back(SceneViewportPostPassStep::SelectionOutline);
|
||||
}
|
||||
|
||||
plan.steps.push_back(SceneViewportPostPassStep::ColorToShaderResource);
|
||||
return plan;
|
||||
}
|
||||
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "SceneViewportPicker.h"
|
||||
#include "SceneViewportCameraController.h"
|
||||
#include "SceneViewportInfiniteGridPass.h"
|
||||
#include "SceneViewportPostPassPlan.h"
|
||||
#include "SceneViewportSelectionMaskPass.h"
|
||||
#include "SceneViewportSelectionOutlinePass.h"
|
||||
#include "SceneViewportSelectionUtils.h"
|
||||
@@ -534,59 +535,35 @@ private:
|
||||
const Rendering::RenderCameraData& cameraData,
|
||||
const std::vector<Rendering::VisibleRenderItem>& selectionRenderables,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
if (!overlay.valid) {
|
||||
const bool hasSelection = !selectionRenderables.empty();
|
||||
const bool hasSelectionMaskRenderTarget = entry.selectionMaskView != nullptr;
|
||||
const bool hasSelectionMaskShaderView = entry.selectionMaskShaderView != nullptr;
|
||||
|
||||
if (hasSelection &&
|
||||
!kDebugSceneSelectionMask &&
|
||||
(!hasSelectionMaskRenderTarget || !hasSelectionMaskShaderView)) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask target is unavailable");
|
||||
}
|
||||
|
||||
const SceneViewportPostPassPlan plan = BuildSceneViewportPostPassPlan({
|
||||
overlay.valid,
|
||||
hasSelection,
|
||||
kDebugSceneSelectionMask,
|
||||
hasSelectionMaskRenderTarget,
|
||||
hasSelectionMaskShaderView
|
||||
});
|
||||
if (!plan.valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool hasSelection = !selectionRenderables.empty();
|
||||
if (hasSelection && kDebugSceneSelectionMask) {
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneColorToRenderTarget",
|
||||
[&entry](const Rendering::RenderPassContext& context) {
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.colorView,
|
||||
context.surface.GetColorStateAfter(),
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
entry.colorState = RHI::ResourceStates::RenderTarget;
|
||||
return true;
|
||||
}));
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionMaskDebug",
|
||||
[this, &entry, &cameraData, &selectionRenderables](
|
||||
const Rendering::RenderPassContext& context) {
|
||||
const float debugClearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
RHI::RHIResourceView* colorView = entry.colorView;
|
||||
context.renderContext.commandList->SetRenderTargets(1, &colorView, entry.depthView);
|
||||
context.renderContext.commandList->ClearRenderTarget(colorView, debugClearColor);
|
||||
|
||||
const bool rendered = m_sceneSelectionMaskPass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
cameraData,
|
||||
selectionRenderables);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask debug pass failed");
|
||||
}
|
||||
return rendered;
|
||||
}));
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneColorToShaderResource",
|
||||
[&entry](const Rendering::RenderPassContext& context) {
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.colorView,
|
||||
RHI::ResourceStates::RenderTarget,
|
||||
context.surface.GetColorStateAfter());
|
||||
entry.colorState = context.surface.GetColorStateAfter();
|
||||
return true;
|
||||
}));
|
||||
return true;
|
||||
Rendering::RenderSurface selectionMaskSurface = {};
|
||||
if (plan.usesSelectionMaskSurface) {
|
||||
selectionMaskSurface = BuildSelectionMaskSurface(entry);
|
||||
}
|
||||
|
||||
if (hasSelection) {
|
||||
if (entry.selectionMaskView == nullptr || entry.selectionMaskShaderView == nullptr) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask target is unavailable");
|
||||
} else {
|
||||
Rendering::RenderSurface selectionMaskSurface = BuildSelectionMaskSurface(entry);
|
||||
for (const SceneViewportPostPassStep step : plan.steps) {
|
||||
switch (step) {
|
||||
case SceneViewportPostPassStep::SelectionMask:
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionMask",
|
||||
[this, &entry, selectionMaskSurface, &cameraData, &selectionRenderables](
|
||||
@@ -618,57 +595,85 @@ private:
|
||||
entry.selectionMaskState = RHI::ResourceStates::PixelShaderResource;
|
||||
return rendered;
|
||||
}));
|
||||
break;
|
||||
case SceneViewportPostPassStep::ColorToRenderTarget:
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneColorToRenderTarget",
|
||||
[&entry](const Rendering::RenderPassContext& context) {
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.colorView,
|
||||
context.surface.GetColorStateAfter(),
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
entry.colorState = RHI::ResourceStates::RenderTarget;
|
||||
return true;
|
||||
}));
|
||||
break;
|
||||
case SceneViewportPostPassStep::InfiniteGrid:
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneInfiniteGrid",
|
||||
[this, overlay, &entry](const Rendering::RenderPassContext& context) {
|
||||
const bool rendered = m_sceneGridPass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
overlay);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene grid pass failed");
|
||||
}
|
||||
return rendered;
|
||||
}));
|
||||
break;
|
||||
case SceneViewportPostPassStep::SelectionOutline:
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionOutline",
|
||||
[this, &entry](const Rendering::RenderPassContext& context) {
|
||||
const bool rendered = m_sceneSelectionOutlinePass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
entry.selectionMaskShaderView);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection outline pass failed");
|
||||
}
|
||||
return rendered;
|
||||
}));
|
||||
break;
|
||||
case SceneViewportPostPassStep::ColorToShaderResource:
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneColorToShaderResource",
|
||||
[&entry](const Rendering::RenderPassContext& context) {
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.colorView,
|
||||
RHI::ResourceStates::RenderTarget,
|
||||
context.surface.GetColorStateAfter());
|
||||
entry.colorState = context.surface.GetColorStateAfter();
|
||||
return true;
|
||||
}));
|
||||
break;
|
||||
case SceneViewportPostPassStep::SelectionMaskDebug:
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionMaskDebug",
|
||||
[this, &entry, &cameraData, &selectionRenderables](
|
||||
const Rendering::RenderPassContext& context) {
|
||||
const float debugClearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
RHI::RHIResourceView* colorView = entry.colorView;
|
||||
context.renderContext.commandList->SetRenderTargets(1, &colorView, entry.depthView);
|
||||
context.renderContext.commandList->ClearRenderTarget(colorView, debugClearColor);
|
||||
|
||||
const bool rendered = m_sceneSelectionMaskPass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
cameraData,
|
||||
selectionRenderables);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask debug pass failed");
|
||||
}
|
||||
return rendered;
|
||||
}));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneColorToRenderTarget",
|
||||
[&entry](const Rendering::RenderPassContext& context) {
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.colorView,
|
||||
context.surface.GetColorStateAfter(),
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
entry.colorState = RHI::ResourceStates::RenderTarget;
|
||||
return true;
|
||||
}));
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneInfiniteGrid",
|
||||
[this, overlay, &entry](const Rendering::RenderPassContext& context) {
|
||||
const bool rendered = m_sceneGridPass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
overlay);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene grid pass failed");
|
||||
}
|
||||
return rendered;
|
||||
}));
|
||||
|
||||
if (hasSelection && entry.selectionMaskShaderView != nullptr) {
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionOutline",
|
||||
[this, &entry](const Rendering::RenderPassContext& context) {
|
||||
const bool rendered = m_sceneSelectionOutlinePass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
entry.selectionMaskShaderView);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection outline pass failed");
|
||||
}
|
||||
return rendered;
|
||||
}));
|
||||
}
|
||||
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneColorToShaderResource",
|
||||
[&entry](const Rendering::RenderPassContext& context) {
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.colorView,
|
||||
RHI::ResourceStates::RenderTarget,
|
||||
context.surface.GetColorStateAfter());
|
||||
entry.colorState = context.surface.GetColorStateAfter();
|
||||
return true;
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user