Graph-ify camera pass sequences

This commit is contained in:
2026-04-14 18:56:04 +08:00
parent 4c79554050
commit e77dbe40b1
2 changed files with 360 additions and 151 deletions

View File

@@ -779,10 +779,13 @@ public:
m_state->eventLog.push_back(m_label);
lastSurfaceWidth = context.surface.GetRenderAreaWidth();
lastSurfaceHeight = context.surface.GetRenderAreaHeight();
lastSurfaceAutoTransitionEnabled = context.surface.IsAutoTransitionEnabled();
lastHasSourceSurface = context.sourceSurface != nullptr;
if (context.sourceSurface != nullptr) {
lastSourceSurfaceWidth = context.sourceSurface->GetRenderAreaWidth();
lastSourceSurfaceHeight = context.sourceSurface->GetRenderAreaHeight();
lastSourceSurfaceAutoTransitionEnabled =
context.sourceSurface->IsAutoTransitionEnabled();
}
lastSourceColorView = context.sourceColorView;
lastSourceColorState = context.sourceColorState;
@@ -803,9 +806,11 @@ private:
public:
uint32_t lastSurfaceWidth = 0;
uint32_t lastSurfaceHeight = 0;
bool lastSurfaceAutoTransitionEnabled = true;
bool lastHasSourceSurface = false;
uint32_t lastSourceSurfaceWidth = 0;
uint32_t lastSourceSurfaceHeight = 0;
bool lastSourceSurfaceAutoTransitionEnabled = true;
XCEngine::RHI::RHIResourceView* lastSourceColorView = nullptr;
XCEngine::RHI::ResourceStates lastSourceColorState = XCEngine::RHI::ResourceStates::Common;
};
@@ -1676,6 +1681,114 @@ TEST(CameraRenderer_Test, ExecutesFormalFrameStagesInDocumentedOrder) {
"overlay" }));
}
TEST(CameraRenderer_Test, RecordsGraphCapableSinglePassSequenceStagesInDocumentedOrder) {
Scene scene("CameraRendererGraphSinglePassSequenceStages");
GameObject* cameraObject = scene.CreateGameObject("Camera");
auto* camera = cameraObject->AddComponent<CameraComponent>();
camera->SetPrimary(true);
camera->SetDepth(3.0f);
auto state = std::make_shared<MockPipelineState>();
CameraRenderer renderer(std::make_unique<MockPipeline>(state));
auto prePass = std::make_unique<TrackingPass>(state, "pre", true, true, true);
TrackingPass* prePassRaw = prePass.get();
RenderPassSequence prePasses;
prePasses.AddPass(std::move(prePass));
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));
auto postPass = std::make_unique<TrackingPass>(state, "post", true, true, true);
TrackingPass* postPassRaw = postPass.get();
RenderPassSequence postPasses;
postPasses.AddPass(std::move(postPass));
auto overlayPass = std::make_unique<TrackingPass>(state, "overlay", true, true, true);
TrackingPass* overlayPassRaw = overlayPass.get();
RenderPassSequence overlayPasses;
overlayPasses.AddPass(std::move(overlayPass));
CameraRenderRequest request;
request.scene = &scene;
request.camera = camera;
request.context = CreateValidContext();
request.surface = RenderSurface(320, 180);
request.surface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(3));
request.cameraDepth = camera->GetDepth();
request.preScenePasses = &prePasses;
request.postProcess.passes = &postProcessPasses;
request.finalOutput.passes = &finalOutputPasses;
request.postScenePasses = &postPasses;
request.overlayPasses = &overlayPasses;
request.postProcess.sourceSurface = RenderSurface(256, 128);
request.postProcess.sourceSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(4));
request.postProcess.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(40);
request.postProcess.destinationSurface = RenderSurface(320, 180);
request.postProcess.destinationSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(5));
request.finalOutput.sourceSurface = request.postProcess.destinationSurface;
request.finalOutput.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(50);
request.finalOutput.destinationSurface = request.surface;
ASSERT_TRUE(renderer.Render(CameraFramePlan::FromRequest(request)));
EXPECT_EQ(
state->eventLog,
(std::vector<std::string>{
"record:pre",
"record:postProcess",
"record:finalOutput",
"record:post",
"record:overlay",
"init:pre",
"pre",
"pipeline",
"init:postProcess",
"postProcess",
"init:finalOutput",
"finalOutput",
"init:post",
"post",
"init:overlay",
"overlay" }));
ASSERT_NE(prePassRaw, nullptr);
EXPECT_TRUE(prePassRaw->lastHasSourceSurface == false);
EXPECT_FALSE(prePassRaw->lastSurfaceAutoTransitionEnabled);
ASSERT_NE(postProcessPassRaw, nullptr);
EXPECT_TRUE(postProcessPassRaw->lastHasSourceSurface);
EXPECT_EQ(postProcessPassRaw->lastSourceSurfaceWidth, 256u);
EXPECT_EQ(postProcessPassRaw->lastSourceSurfaceHeight, 128u);
EXPECT_FALSE(postProcessPassRaw->lastSourceSurfaceAutoTransitionEnabled);
EXPECT_EQ(postProcessPassRaw->lastSourceColorView, reinterpret_cast<XCEngine::RHI::RHIResourceView*>(40));
EXPECT_EQ(
postProcessPassRaw->lastSourceColorState,
XCEngine::RHI::ResourceStates::PixelShaderResource);
EXPECT_FALSE(postProcessPassRaw->lastSurfaceAutoTransitionEnabled);
ASSERT_NE(finalOutputPassRaw, nullptr);
EXPECT_TRUE(finalOutputPassRaw->lastHasSourceSurface);
EXPECT_EQ(finalOutputPassRaw->lastSourceSurfaceWidth, 320u);
EXPECT_EQ(finalOutputPassRaw->lastSourceSurfaceHeight, 180u);
EXPECT_FALSE(finalOutputPassRaw->lastSourceSurfaceAutoTransitionEnabled);
EXPECT_EQ(finalOutputPassRaw->lastSourceColorView, reinterpret_cast<XCEngine::RHI::RHIResourceView*>(50));
EXPECT_EQ(
finalOutputPassRaw->lastSourceColorState,
XCEngine::RHI::ResourceStates::PixelShaderResource);
EXPECT_FALSE(finalOutputPassRaw->lastSurfaceAutoTransitionEnabled);
ASSERT_NE(postPassRaw, nullptr);
EXPECT_FALSE(postPassRaw->lastSurfaceAutoTransitionEnabled);
ASSERT_NE(overlayPassRaw, nullptr);
EXPECT_FALSE(overlayPassRaw->lastSurfaceAutoTransitionEnabled);
}
TEST(CameraRenderer_Test, ExecutesShadowCasterAndDepthOnlyRequestsBeforeMainPipeline) {
Scene scene("CameraRendererDepthAndShadowScene");