Align rendering orchestration with camera stack plans
This commit is contained in:
@@ -71,6 +71,7 @@ struct MockPipelineState {
|
||||
int recordPostProcessCalls = 0;
|
||||
int recordFinalOutputCalls = 0;
|
||||
int executeRecordedMainSceneCalls = 0;
|
||||
int finishCameraStackRenderingCalls = 0;
|
||||
bool renderResult = true;
|
||||
bool supportsMainSceneRenderGraph = false;
|
||||
bool supportsPostProcessRenderGraph = false;
|
||||
@@ -112,6 +113,7 @@ struct MockPipelineState {
|
||||
std::vector<CameraComponent*> renderedCameras;
|
||||
std::vector<RenderClearFlags> renderedClearFlags;
|
||||
std::vector<XCEngine::Math::Color> renderedClearColors;
|
||||
std::vector<size_t> finishedCameraStackSizes;
|
||||
std::vector<std::string> eventLog;
|
||||
};
|
||||
|
||||
@@ -764,6 +766,13 @@ public:
|
||||
return m_state->renderResult;
|
||||
}
|
||||
|
||||
void FinishCameraStackRendering(
|
||||
const CameraStackFramePlan& stackPlan) override {
|
||||
++m_state->finishCameraStackRenderingCalls;
|
||||
m_state->finishedCameraStackSizes.push_back(
|
||||
stackPlan.cameraPlans.size());
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<MockPipelineState> m_state;
|
||||
};
|
||||
@@ -3420,15 +3429,65 @@ TEST(SceneRenderer_Test, RendersBaseCamerasBeforeOverlayCamerasAndResolvesAutoCl
|
||||
ASSERT_EQ(plans.size(), 3u);
|
||||
EXPECT_EQ(plans[0].request.camera, earlyBaseCamera);
|
||||
EXPECT_EQ(plans[0].request.cameraStackOrder, 0u);
|
||||
EXPECT_NE(plans[0].request.cameraStackId, 0u);
|
||||
EXPECT_EQ(plans[0].request.clearFlags, RenderClearFlags::All);
|
||||
EXPECT_EQ(plans[1].request.camera, lateBaseCamera);
|
||||
EXPECT_EQ(plans[1].request.cameraStackOrder, 0u);
|
||||
EXPECT_NE(plans[1].request.cameraStackId, 0u);
|
||||
EXPECT_NE(
|
||||
plans[0].request.cameraStackId,
|
||||
plans[1].request.cameraStackId);
|
||||
EXPECT_EQ(plans[1].request.clearFlags, RenderClearFlags::Depth);
|
||||
EXPECT_EQ(plans[2].request.camera, overlayCamera);
|
||||
EXPECT_EQ(plans[2].request.cameraStackOrder, 1u);
|
||||
EXPECT_EQ(
|
||||
plans[2].request.cameraStackId,
|
||||
plans[1].request.cameraStackId);
|
||||
EXPECT_EQ(plans[2].request.clearFlags, RenderClearFlags::Depth);
|
||||
}
|
||||
|
||||
TEST(SceneRenderer_Test, BuildsRootCameraStackFramePlansFromSceneRequests) {
|
||||
Scene scene("SceneRendererCameraStackFramePlanScene");
|
||||
|
||||
GameObject* firstBaseCameraObject = scene.CreateGameObject("FirstBaseCamera");
|
||||
auto* firstBaseCamera = firstBaseCameraObject->AddComponent<CameraComponent>();
|
||||
firstBaseCamera->SetDepth(1.0f);
|
||||
firstBaseCamera->SetStackType(CameraStackType::Base);
|
||||
|
||||
GameObject* secondBaseCameraObject = scene.CreateGameObject("SecondBaseCamera");
|
||||
auto* secondBaseCamera = secondBaseCameraObject->AddComponent<CameraComponent>();
|
||||
secondBaseCamera->SetDepth(2.0f);
|
||||
secondBaseCamera->SetStackType(CameraStackType::Base);
|
||||
|
||||
GameObject* overlayCameraObject = scene.CreateGameObject("OverlayCamera");
|
||||
auto* overlayCamera = overlayCameraObject->AddComponent<CameraComponent>();
|
||||
overlayCamera->SetDepth(3.0f);
|
||||
overlayCamera->SetStackType(CameraStackType::Overlay);
|
||||
|
||||
SceneRenderer renderer;
|
||||
const std::vector<CameraStackFramePlan> stackPlans =
|
||||
renderer.BuildStackFramePlans(
|
||||
scene,
|
||||
nullptr,
|
||||
CreateValidContext(),
|
||||
RenderSurface(640, 360));
|
||||
|
||||
ASSERT_EQ(stackPlans.size(), 2u);
|
||||
ASSERT_EQ(stackPlans[0].cameraPlans.size(), 1u);
|
||||
EXPECT_EQ(stackPlans[0].cameraPlans[0].request.camera, firstBaseCamera);
|
||||
EXPECT_TRUE(stackPlans[0].HasBaseCamera());
|
||||
EXPECT_FALSE(stackPlans[0].IsOverlayOnly());
|
||||
|
||||
ASSERT_EQ(stackPlans[1].cameraPlans.size(), 2u);
|
||||
EXPECT_EQ(stackPlans[1].cameraPlans[0].request.camera, secondBaseCamera);
|
||||
EXPECT_EQ(stackPlans[1].cameraPlans[1].request.camera, overlayCamera);
|
||||
EXPECT_TRUE(stackPlans[1].HasBaseCamera());
|
||||
EXPECT_FALSE(stackPlans[1].IsOverlayOnly());
|
||||
EXPECT_EQ(
|
||||
stackPlans[1].cameraPlans[1].request.cameraStackId,
|
||||
stackPlans[1].cameraPlans[0].request.cameraStackId);
|
||||
}
|
||||
|
||||
TEST(SceneRenderer_Test, PreservesSceneTraversalOrderForEqualPriorityCameras) {
|
||||
Scene scene("SceneRendererStableSceneOrder");
|
||||
|
||||
@@ -4531,6 +4590,55 @@ TEST(RenderPipelineHost_Test, ForwardsPipelineAssetLifetimeAndRenderCallsToCamer
|
||||
EXPECT_EQ(replacementState->shutdownCalls, 1);
|
||||
}
|
||||
|
||||
TEST(RenderPipelineHost_Test, RendersCameraStackFramePlansAsSingleStackLifetime) {
|
||||
Scene scene("RenderPipelineHostStackPlans");
|
||||
|
||||
GameObject* baseCameraObject = scene.CreateGameObject("BaseCamera");
|
||||
auto* baseCamera = baseCameraObject->AddComponent<CameraComponent>();
|
||||
baseCamera->SetDepth(1.0f);
|
||||
baseCamera->SetStackType(CameraStackType::Base);
|
||||
|
||||
GameObject* overlayCameraObject = scene.CreateGameObject("OverlayCamera");
|
||||
auto* overlayCamera = overlayCameraObject->AddComponent<CameraComponent>();
|
||||
overlayCamera->SetDepth(2.0f);
|
||||
overlayCamera->SetStackType(CameraStackType::Overlay);
|
||||
|
||||
CameraRenderRequest baseRequest = {};
|
||||
baseRequest.scene = &scene;
|
||||
baseRequest.camera = baseCamera;
|
||||
baseRequest.context = CreateValidContext();
|
||||
baseRequest.surface = RenderSurface(800, 600);
|
||||
baseRequest.cameraStackId = 42u;
|
||||
baseRequest.cameraDepth = baseCamera->GetDepth();
|
||||
baseRequest.cameraStackOrder = 0u;
|
||||
baseRequest.clearFlags = RenderClearFlags::All;
|
||||
|
||||
CameraRenderRequest overlayRequest = baseRequest;
|
||||
overlayRequest.camera = overlayCamera;
|
||||
overlayRequest.cameraDepth = overlayCamera->GetDepth();
|
||||
overlayRequest.cameraStackOrder = 1u;
|
||||
overlayRequest.clearFlags = RenderClearFlags::Depth;
|
||||
|
||||
auto state = std::make_shared<MockPipelineState>();
|
||||
RenderPipelineHost host(MakeMockPipelineAsset(state));
|
||||
|
||||
const std::vector<CameraStackFramePlan> stackPlans =
|
||||
host.BuildStackFramePlans({ baseRequest, overlayRequest });
|
||||
ASSERT_EQ(stackPlans.size(), 1u);
|
||||
ASSERT_EQ(stackPlans[0].cameraPlans.size(), 2u);
|
||||
EXPECT_EQ(stackPlans[0].cameraStackId, 42u);
|
||||
EXPECT_EQ(stackPlans[0].cameraPlans[0].request.camera, baseCamera);
|
||||
EXPECT_EQ(stackPlans[0].cameraPlans[1].request.camera, overlayCamera);
|
||||
|
||||
ASSERT_TRUE(host.Render(stackPlans));
|
||||
ASSERT_EQ(state->renderedCameras.size(), 2u);
|
||||
EXPECT_EQ(state->renderedCameras[0], baseCamera);
|
||||
EXPECT_EQ(state->renderedCameras[1], overlayCamera);
|
||||
EXPECT_EQ(state->finishCameraStackRenderingCalls, 1);
|
||||
ASSERT_EQ(state->finishedCameraStackSizes.size(), 1u);
|
||||
EXPECT_EQ(state->finishedCameraStackSizes[0], 2u);
|
||||
}
|
||||
|
||||
TEST(RenderPipelineHost_Test, SortsManualFramePlansByDepthBeforeRendering) {
|
||||
Scene scene("RenderPipelineHostManualRequests");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user