Unify camera frame graph resource binding helpers
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Core/Containers/String.h>
|
||||
#include <XCEngine/Rendering/Execution/CameraFramePlan.h>
|
||||
#include <XCEngine/Rendering/Execution/FrameExecutionContext.h>
|
||||
#include <XCEngine/Rendering/FrameData/RenderSceneData.h>
|
||||
#include <XCEngine/Rendering/Graph/RenderGraphBlackboard.h>
|
||||
@@ -27,6 +28,50 @@ struct CameraFrameRenderGraphResources {
|
||||
RenderGraphTextureHandle mainDirectionalShadow = {};
|
||||
};
|
||||
|
||||
inline CameraFrameRenderGraphSurfaceResources* ResolveCameraFrameRenderGraphStageSurfaceResources(
|
||||
CameraFrameRenderGraphResources& frameResources,
|
||||
CameraFrameStage stage) {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::MainScene:
|
||||
return &frameResources.mainScene;
|
||||
case CameraFrameStage::PostProcess:
|
||||
return &frameResources.postProcess;
|
||||
case CameraFrameStage::ObjectId:
|
||||
return &frameResources.objectId;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline const CameraFrameRenderGraphSurfaceResources* ResolveCameraFrameRenderGraphStageSurfaceResources(
|
||||
const CameraFrameRenderGraphResources& frameResources,
|
||||
CameraFrameStage stage) {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::MainScene:
|
||||
return &frameResources.mainScene;
|
||||
case CameraFrameStage::PostProcess:
|
||||
return &frameResources.postProcess;
|
||||
case CameraFrameStage::ObjectId:
|
||||
return &frameResources.objectId;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline const CameraFrameRenderGraphSurfaceResources* ResolveCameraFrameRenderGraphColorSourceResources(
|
||||
const CameraFrameRenderGraphResources& frameResources,
|
||||
CameraFrameColorSource source) {
|
||||
switch (source) {
|
||||
case CameraFrameColorSource::MainSceneColor:
|
||||
return &frameResources.mainScene;
|
||||
case CameraFrameColorSource::PostProcessColor:
|
||||
return &frameResources.postProcess;
|
||||
case CameraFrameColorSource::ExplicitSurface:
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline CameraFrameRenderGraphResources* TryGetCameraFrameRenderGraphResources(
|
||||
RenderGraphBlackboard* blackboard) {
|
||||
return blackboard != nullptr
|
||||
@@ -41,6 +86,41 @@ inline const CameraFrameRenderGraphResources* TryGetCameraFrameRenderGraphResour
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
inline RenderGraphTextureHandle ResolveCameraFrameRenderGraphColorSource(
|
||||
const CameraFrameRenderGraphResources& frameResources,
|
||||
CameraFrameColorSource source) {
|
||||
const CameraFrameRenderGraphSurfaceResources* const surfaceResources =
|
||||
ResolveCameraFrameRenderGraphColorSourceResources(frameResources, source);
|
||||
return surfaceResources != nullptr
|
||||
? surfaceResources->color
|
||||
: RenderGraphTextureHandle{};
|
||||
}
|
||||
|
||||
inline RenderGraphTextureHandle ResolveCameraFrameRenderGraphColorSource(
|
||||
const RenderGraphBlackboard* blackboard,
|
||||
CameraFrameColorSource source) {
|
||||
const CameraFrameRenderGraphResources* const frameResources =
|
||||
TryGetCameraFrameRenderGraphResources(blackboard);
|
||||
return frameResources != nullptr
|
||||
? ResolveCameraFrameRenderGraphColorSource(*frameResources, source)
|
||||
: RenderGraphTextureHandle{};
|
||||
}
|
||||
|
||||
inline void WriteCameraFrameRenderGraphStageSurfaceResources(
|
||||
CameraFrameRenderGraphResources& frameResources,
|
||||
CameraFrameStage stage,
|
||||
RenderGraphTextureHandle color,
|
||||
RenderGraphTextureHandle depth) {
|
||||
CameraFrameRenderGraphSurfaceResources* const surfaceResources =
|
||||
ResolveCameraFrameRenderGraphStageSurfaceResources(frameResources, stage);
|
||||
if (surfaceResources == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
surfaceResources->color = color;
|
||||
surfaceResources->depth = depth;
|
||||
}
|
||||
|
||||
struct RenderPipelineMainSceneRenderGraphContext {
|
||||
RenderGraphBuilder& graphBuilder;
|
||||
Containers::String passName = {};
|
||||
|
||||
@@ -608,8 +608,7 @@ RenderGraphTextureHandle ResolveStageOutputColorHandle(
|
||||
const Containers::String& stageName,
|
||||
const RenderPassContext& stagePassContext,
|
||||
const RenderGraphImportedSurface& outputSurface,
|
||||
RenderGraphBuilder& graphBuilder,
|
||||
CameraFrameRenderGraphResources& frameResources) {
|
||||
RenderGraphBuilder& graphBuilder) {
|
||||
if (stage == CameraFrameStage::MainScene &&
|
||||
plan.usesGraphManagedMainSceneColor) {
|
||||
return graphBuilder.CreateTransientTexture(
|
||||
@@ -621,37 +620,21 @@ RenderGraphTextureHandle ResolveStageOutputColorHandle(
|
||||
|
||||
if (stage == CameraFrameStage::PostProcess &&
|
||||
plan.usesGraphManagedPostProcessColor) {
|
||||
frameResources.postProcess.color =
|
||||
graphBuilder.CreateTransientTexture(
|
||||
stageName + ".Color",
|
||||
BuildFullscreenTransientTextureDesc(stagePassContext.surface));
|
||||
return frameResources.postProcess.color;
|
||||
return graphBuilder.CreateTransientTexture(
|
||||
stageName + ".Color",
|
||||
BuildFullscreenTransientTextureDesc(stagePassContext.surface));
|
||||
}
|
||||
|
||||
return GetPrimaryColorTexture(outputSurface);
|
||||
}
|
||||
|
||||
RenderGraphTextureHandle ResolveFrameResourceColorSource(
|
||||
const CameraFrameRenderGraphResources& frameResources,
|
||||
CameraFrameColorSource source) {
|
||||
switch (source) {
|
||||
case CameraFrameColorSource::MainSceneColor:
|
||||
return frameResources.mainScene.color;
|
||||
case CameraFrameColorSource::PostProcessColor:
|
||||
return frameResources.postProcess.color;
|
||||
case CameraFrameColorSource::ExplicitSurface:
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
FullscreenStageGraphBinding ResolveFullscreenStageGraphBinding(
|
||||
CameraFrameStage stage,
|
||||
const CameraFramePlan& plan,
|
||||
const RenderPassContext& stagePassContext,
|
||||
const RenderGraphImportedSurface& sourceSurface,
|
||||
RenderGraphTextureHandle outputColor,
|
||||
CameraFrameRenderGraphResources& frameResources) {
|
||||
const RenderGraphBlackboard* blackboard) {
|
||||
FullscreenStageGraphBinding binding = {};
|
||||
binding.sourceSurfaceTemplate = stagePassContext.sourceSurface;
|
||||
binding.sourceColorView = stagePassContext.sourceColorView;
|
||||
@@ -665,8 +648,8 @@ FullscreenStageGraphBinding ResolveFullscreenStageGraphBinding(
|
||||
binding.sourceColorView = nullptr;
|
||||
binding.sourceColorState = RHI::ResourceStates::PixelShaderResource;
|
||||
binding.sourceColor =
|
||||
ResolveFrameResourceColorSource(
|
||||
frameResources,
|
||||
ResolveCameraFrameRenderGraphColorSource(
|
||||
blackboard,
|
||||
plan.postProcessSource);
|
||||
}
|
||||
|
||||
@@ -677,8 +660,8 @@ FullscreenStageGraphBinding ResolveFullscreenStageGraphBinding(
|
||||
binding.sourceColorView = nullptr;
|
||||
binding.sourceColorState = RHI::ResourceStates::PixelShaderResource;
|
||||
binding.sourceColor =
|
||||
ResolveFrameResourceColorSource(
|
||||
frameResources,
|
||||
ResolveCameraFrameRenderGraphColorSource(
|
||||
blackboard,
|
||||
plan.finalOutputSource);
|
||||
}
|
||||
}
|
||||
@@ -979,25 +962,17 @@ bool ExecuteRenderGraphPlan(
|
||||
stageName,
|
||||
stagePassContext,
|
||||
outputSurface,
|
||||
graphBuilder,
|
||||
frameResources);
|
||||
graphBuilder);
|
||||
if (stage == CameraFrameStage::ShadowCaster &&
|
||||
shadowState.HasShadowSampling() &&
|
||||
outputSurface.depthTexture.IsValid()) {
|
||||
frameResources.mainDirectionalShadow = outputSurface.depthTexture;
|
||||
}
|
||||
if (stage == CameraFrameStage::MainScene) {
|
||||
frameResources.mainScene.color = stageOutputColor;
|
||||
frameResources.mainScene.depth = outputSurface.depthTexture;
|
||||
}
|
||||
if (stage == CameraFrameStage::PostProcess) {
|
||||
frameResources.postProcess.color = stageOutputColor;
|
||||
frameResources.postProcess.depth = outputSurface.depthTexture;
|
||||
}
|
||||
if (stage == CameraFrameStage::ObjectId) {
|
||||
frameResources.objectId.color = stageOutputColor;
|
||||
frameResources.objectId.depth = outputSurface.depthTexture;
|
||||
}
|
||||
WriteCameraFrameRenderGraphStageSurfaceResources(
|
||||
frameResources,
|
||||
stage,
|
||||
stageOutputColor,
|
||||
outputSurface.depthTexture);
|
||||
const RenderSurface stageSurfaceTemplate = stagePassContext.surface;
|
||||
const bool hasStageSourceSurface = stagePassContext.sourceSurface != nullptr;
|
||||
const RenderSurface stageSourceSurfaceTemplate =
|
||||
@@ -1020,7 +995,7 @@ bool ExecuteRenderGraphPlan(
|
||||
stagePassContext,
|
||||
sourceSurface,
|
||||
stageOutputColor,
|
||||
frameResources),
|
||||
&blackboard),
|
||||
sceneData,
|
||||
stageSequence,
|
||||
executionState,
|
||||
|
||||
@@ -759,6 +759,18 @@ public:
|
||||
|
||||
bool RecordRenderGraph(const RenderPassRenderGraphContext& context) override {
|
||||
m_state->eventLog.push_back(std::string("record:") + m_label);
|
||||
lastRecordedSourceColorTextureValid = context.sourceColorTexture.IsValid();
|
||||
lastRecordedRenderGraphBlackboard = context.blackboard != nullptr;
|
||||
if (const CameraFrameRenderGraphResources* frameResources =
|
||||
TryGetCameraFrameRenderGraphResources(context.blackboard)) {
|
||||
lastRecordedBlackboardMainSceneColorValid =
|
||||
frameResources->mainScene.color.IsValid();
|
||||
lastRecordedBlackboardPostProcessColorValid =
|
||||
frameResources->postProcess.color.IsValid();
|
||||
} else {
|
||||
lastRecordedBlackboardMainSceneColorValid = false;
|
||||
lastRecordedBlackboardPostProcessColorValid = false;
|
||||
}
|
||||
const bool writesColor =
|
||||
context.sourceSurface != nullptr ||
|
||||
!context.colorTargets.empty();
|
||||
@@ -815,6 +827,10 @@ public:
|
||||
bool lastSourceSurfaceAutoTransitionEnabled = true;
|
||||
XCEngine::RHI::RHIResourceView* lastSourceColorView = nullptr;
|
||||
XCEngine::RHI::ResourceStates lastSourceColorState = XCEngine::RHI::ResourceStates::Common;
|
||||
bool lastRecordedSourceColorTextureValid = false;
|
||||
bool lastRecordedRenderGraphBlackboard = false;
|
||||
bool lastRecordedBlackboardMainSceneColorValid = false;
|
||||
bool lastRecordedBlackboardPostProcessColorValid = false;
|
||||
};
|
||||
|
||||
RenderContext CreateValidContext() {
|
||||
@@ -1791,6 +1807,105 @@ TEST(CameraRenderer_Test, RecordsGraphCapableSinglePassSequenceStagesInDocumente
|
||||
EXPECT_FALSE(overlayPassRaw->lastSurfaceAutoTransitionEnabled);
|
||||
}
|
||||
|
||||
TEST(CameraRenderer_Test, ResolvesGraphManagedFullscreenSequenceSourcesFromFrameResources) {
|
||||
Scene scene("CameraRendererGraphManagedFullscreenSources");
|
||||
|
||||
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||
camera->SetPrimary(true);
|
||||
camera->SetDepth(3.0f);
|
||||
|
||||
auto state = std::make_shared<MockPipelineState>();
|
||||
state->supportsMainSceneRenderGraph = true;
|
||||
CameraRenderer renderer(std::make_unique<MockPipeline>(state));
|
||||
auto allocationState = std::make_shared<MockShadowAllocationState>();
|
||||
MockShadowDevice device(allocationState);
|
||||
MockShadowView colorView(
|
||||
allocationState,
|
||||
XCEngine::RHI::ResourceViewType::RenderTarget,
|
||||
XCEngine::RHI::Format::R8G8B8A8_UNorm,
|
||||
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||
MockShadowView depthView(
|
||||
allocationState,
|
||||
XCEngine::RHI::ResourceViewType::DepthStencil,
|
||||
XCEngine::RHI::Format::D24_UNorm_S8_UInt,
|
||||
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||
|
||||
auto postProcessPass = std::make_unique<TrackingPass>(state, "postProcess", true, true, true);
|
||||
TrackingPass* postProcessPassRaw = postProcessPass.get();
|
||||
RenderPassSequence postProcessPasses;
|
||||
postProcessPasses.AddPass(std::move(postProcessPass));
|
||||
|
||||
auto finalOutputPass = std::make_unique<TrackingPass>(state, "finalOutput", true, true, true);
|
||||
TrackingPass* finalOutputPassRaw = finalOutputPass.get();
|
||||
RenderPassSequence finalOutputPasses;
|
||||
finalOutputPasses.AddPass(std::move(finalOutputPass));
|
||||
|
||||
CameraRenderRequest request;
|
||||
request.scene = &scene;
|
||||
request.camera = camera;
|
||||
request.context = CreateValidContext();
|
||||
request.context.device = &device;
|
||||
request.surface = RenderSurface(320, 180);
|
||||
request.surface.SetColorAttachment(&colorView);
|
||||
request.surface.SetDepthAttachment(&depthView);
|
||||
request.cameraDepth = camera->GetDepth();
|
||||
request.postProcess.passes = &postProcessPasses;
|
||||
request.finalOutput.passes = &finalOutputPasses;
|
||||
request.finalOutput.destinationSurface = request.surface;
|
||||
|
||||
CameraFramePlan plan = CameraFramePlan::FromRequest(request);
|
||||
plan.usesGraphManagedMainSceneColor = true;
|
||||
plan.ConfigureGraphManagedMainSceneSurface();
|
||||
plan.usesGraphManagedPostProcessColor = true;
|
||||
plan.postProcessSource = CameraFrameColorSource::MainSceneColor;
|
||||
plan.finalOutputSource = CameraFrameColorSource::PostProcessColor;
|
||||
|
||||
ASSERT_TRUE(plan.IsPostProcessStageValid());
|
||||
ASSERT_TRUE(plan.IsFinalOutputStageValid());
|
||||
const bool renderResult = renderer.Render(plan);
|
||||
EXPECT_TRUE(renderResult);
|
||||
EXPECT_EQ(state->recordMainSceneCalls, 1);
|
||||
EXPECT_EQ(state->executeRecordedMainSceneCalls, 1);
|
||||
|
||||
EXPECT_EQ(
|
||||
state->eventLog,
|
||||
(std::vector<std::string>{
|
||||
"record:postProcess",
|
||||
"record:finalOutput",
|
||||
"pipelineGraph",
|
||||
"init:postProcess",
|
||||
"postProcess",
|
||||
"init:finalOutput",
|
||||
"finalOutput" }));
|
||||
|
||||
ASSERT_NE(postProcessPassRaw, nullptr);
|
||||
EXPECT_TRUE(postProcessPassRaw->lastRecordedRenderGraphBlackboard);
|
||||
EXPECT_TRUE(postProcessPassRaw->lastRecordedSourceColorTextureValid);
|
||||
EXPECT_TRUE(postProcessPassRaw->lastRecordedBlackboardMainSceneColorValid);
|
||||
EXPECT_NE(postProcessPassRaw->lastSourceColorView, nullptr);
|
||||
EXPECT_TRUE(postProcessPassRaw->lastHasSourceSurface);
|
||||
EXPECT_EQ(postProcessPassRaw->lastSourceSurfaceWidth, 320u);
|
||||
EXPECT_EQ(postProcessPassRaw->lastSourceSurfaceHeight, 180u);
|
||||
EXPECT_FALSE(postProcessPassRaw->lastSourceSurfaceAutoTransitionEnabled);
|
||||
EXPECT_EQ(
|
||||
postProcessPassRaw->lastSourceColorState,
|
||||
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||
|
||||
ASSERT_NE(finalOutputPassRaw, nullptr);
|
||||
EXPECT_TRUE(finalOutputPassRaw->lastRecordedRenderGraphBlackboard);
|
||||
EXPECT_TRUE(finalOutputPassRaw->lastRecordedSourceColorTextureValid);
|
||||
EXPECT_TRUE(finalOutputPassRaw->lastRecordedBlackboardPostProcessColorValid);
|
||||
EXPECT_NE(finalOutputPassRaw->lastSourceColorView, nullptr);
|
||||
EXPECT_TRUE(finalOutputPassRaw->lastHasSourceSurface);
|
||||
EXPECT_EQ(finalOutputPassRaw->lastSourceSurfaceWidth, 320u);
|
||||
EXPECT_EQ(finalOutputPassRaw->lastSourceSurfaceHeight, 180u);
|
||||
EXPECT_FALSE(finalOutputPassRaw->lastSourceSurfaceAutoTransitionEnabled);
|
||||
EXPECT_EQ(
|
||||
finalOutputPassRaw->lastSourceColorState,
|
||||
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||
}
|
||||
|
||||
TEST(CameraRenderer_Test, ExecutesShadowCasterAndDepthOnlyRequestsBeforeMainPipeline) {
|
||||
Scene scene("CameraRendererDepthAndShadowScene");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user