feat(rendering): add managed fullscreen stage recording seam

This commit is contained in:
2026-04-17 22:58:39 +08:00
parent ed9b5178f8
commit b9f78c29b8
10 changed files with 541 additions and 9 deletions

View File

@@ -55,9 +55,13 @@ struct MockPipelineState {
int configureDirectionalShadowExecutionStateCalls = 0;
int renderCalls = 0;
int recordMainSceneCalls = 0;
int recordPostProcessCalls = 0;
int recordFinalOutputCalls = 0;
int executeRecordedMainSceneCalls = 0;
bool renderResult = true;
bool supportsMainSceneRenderGraph = false;
bool supportsPostProcessRenderGraph = false;
bool supportsFinalOutputRenderGraph = false;
bool recordMainSceneResult = true;
bool lastSurfaceAutoTransitionEnabled = true;
uint32_t lastSurfaceWidth = 0;
@@ -490,13 +494,33 @@ public:
}
bool SupportsStageRenderGraph(CameraFrameStage stage) const override {
return SupportsCameraFramePipelineGraphRecording(stage) &&
m_state->supportsMainSceneRenderGraph;
switch (stage) {
case CameraFrameStage::MainScene:
return m_state->supportsMainSceneRenderGraph;
case CameraFrameStage::PostProcess:
return m_state->supportsPostProcessRenderGraph;
case CameraFrameStage::FinalOutput:
return m_state->supportsFinalOutputRenderGraph;
default:
return false;
}
}
bool RecordStageRenderGraph(
const RenderPipelineStageRenderGraphContext& context) override {
++m_state->recordMainSceneCalls;
switch (context.stage) {
case CameraFrameStage::MainScene:
++m_state->recordMainSceneCalls;
break;
case CameraFrameStage::PostProcess:
++m_state->recordPostProcessCalls;
break;
case CameraFrameStage::FinalOutput:
++m_state->recordFinalOutputCalls;
break;
default:
break;
}
m_state->lastReceivedRenderGraphBlackboard = context.blackboard != nullptr;
if (const CameraFrameRenderGraphResources* frameResources =
TryGetCameraFrameRenderGraphResources(context.blackboard)) {
@@ -2143,6 +2167,69 @@ TEST(CameraRenderer_Test, ResolvesGraphManagedFullscreenSequenceSourcesFromFrame
XCEngine::RHI::ResourceStates::PixelShaderResource);
}
TEST(CameraRenderer_Test, PrefersPipelineStageRecordingOverLegacyPostProcessSequence) {
Scene scene("CameraRendererManagedPostProcessScene");
GameObject* cameraObject = scene.CreateGameObject("Camera");
auto* camera = cameraObject->AddComponent<CameraComponent>();
camera->SetPrimary(true);
auto state = std::make_shared<MockPipelineState>();
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);
state->supportsMainSceneRenderGraph = true;
state->supportsPostProcessRenderGraph = true;
CameraRenderer renderer(std::make_unique<MockPipeline>(state));
auto postProcessPass =
std::make_unique<TrackingPass>(state, "postProcess", true, true, true);
TrackingPass* const postProcessPassRaw = postProcessPass.get();
RenderPassSequence postProcessPasses;
postProcessPasses.AddPass(std::move(postProcessPass));
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.postProcess.destinationSurface = request.surface;
CameraFramePlan plan = CameraFramePlan::FromRequest(request);
plan.colorChain.usesGraphManagedSceneColor = true;
plan.ConfigureGraphManagedSceneSurface();
plan.colorChain.postProcess.source = CameraFrameColorSource::MainSceneColor;
ASSERT_TRUE(plan.IsPostProcessStageValid());
ASSERT_TRUE(renderer.Render(plan));
EXPECT_EQ(state->recordMainSceneCalls, 1);
EXPECT_EQ(state->recordPostProcessCalls, 1);
EXPECT_EQ(
state->eventLog,
(std::vector<std::string>{
"pipelineGraph",
"pipelineGraph" }));
ASSERT_NE(postProcessPassRaw, nullptr);
EXPECT_FALSE(postProcessPassRaw->lastRecordedRenderGraphBlackboard);
EXPECT_EQ(postProcessPassRaw->lastSurfaceWidth, 0u);
EXPECT_EQ(postProcessPassRaw->lastSurfaceHeight, 0u);
}
TEST(CameraRenderer_Test, ExecutesShadowCasterAndDepthOnlyRequestsBeforeMainPipeline) {
Scene scene("CameraRendererDepthAndShadowScene");