Introduce CameraRenderRequest scheduling and fix Vulkan build

This commit is contained in:
2026-03-27 16:57:04 +08:00
parent a72f9f7f05
commit dbec62608c
13 changed files with 605 additions and 21 deletions

View File

@@ -7,6 +7,7 @@
#include <XCEngine/Scene/Scene.h>
#include <memory>
#include <vector>
using namespace XCEngine::Components;
using namespace XCEngine::Rendering;
@@ -21,6 +22,7 @@ struct MockPipelineState {
uint32_t lastSurfaceHeight = 0;
CameraComponent* lastCamera = nullptr;
size_t lastVisibleItemCount = 0;
std::vector<CameraComponent*> renderedCameras;
};
class MockPipeline final : public RenderPipeline {
@@ -47,6 +49,7 @@ public:
m_state->lastSurfaceHeight = surface.GetHeight();
m_state->lastCamera = sceneData.camera;
m_state->lastVisibleItemCount = sceneData.visibleItems.size();
m_state->renderedCameras.push_back(sceneData.camera);
return true;
}
@@ -80,8 +83,14 @@ TEST(CameraRenderer_Test, UsesOverrideCameraAndSurfaceSizeWhenSubmittingScene) {
auto state = std::make_shared<MockPipelineState>();
CameraRenderer renderer(std::make_unique<MockPipeline>(state));
const RenderSurface surface(640, 480);
ASSERT_TRUE(renderer.Render(scene, overrideCamera, CreateValidContext(), surface));
CameraRenderRequest request;
request.scene = &scene;
request.camera = overrideCamera;
request.context = CreateValidContext();
request.surface = RenderSurface(640, 480);
request.cameraDepth = overrideCamera->GetDepth();
ASSERT_TRUE(renderer.Render(request));
EXPECT_EQ(state->renderCalls, 1);
EXPECT_EQ(state->lastSurfaceWidth, 640u);
EXPECT_EQ(state->lastSurfaceHeight, 480u);
@@ -90,6 +99,37 @@ TEST(CameraRenderer_Test, UsesOverrideCameraAndSurfaceSizeWhenSubmittingScene) {
EXPECT_EQ(state->lastVisibleItemCount, 0u);
}
TEST(SceneRenderer_Test, BuildsSingleExplicitRequestFromSelectedCamera) {
Scene scene("SceneRendererRequestScene");
GameObject* lowCameraObject = scene.CreateGameObject("LowCamera");
auto* lowCamera = lowCameraObject->AddComponent<CameraComponent>();
lowCamera->SetPrimary(true);
lowCamera->SetDepth(1.0f);
GameObject* highCameraObject = scene.CreateGameObject("HighCamera");
auto* highCamera = highCameraObject->AddComponent<CameraComponent>();
highCamera->SetPrimary(true);
highCamera->SetDepth(5.0f);
SceneRenderer renderer;
const RenderContext context = CreateValidContext();
const RenderSurface surface(320, 180);
const std::vector<CameraRenderRequest> defaultRequests =
renderer.BuildRenderRequests(scene, nullptr, context, surface);
ASSERT_EQ(defaultRequests.size(), 1u);
EXPECT_EQ(defaultRequests[0].camera, highCamera);
EXPECT_EQ(defaultRequests[0].cameraDepth, 5.0f);
EXPECT_EQ(defaultRequests[0].surface.GetWidth(), 320u);
EXPECT_EQ(defaultRequests[0].surface.GetHeight(), 180u);
const std::vector<CameraRenderRequest> overrideRequests =
renderer.BuildRenderRequests(scene, lowCamera, context, surface);
ASSERT_EQ(overrideRequests.size(), 1u);
EXPECT_EQ(overrideRequests[0].camera, lowCamera);
}
TEST(SceneRenderer_Test, ForwardsPipelineLifetimeAndRenderCallsToCameraRenderer) {
Scene scene("SceneRendererScene");
@@ -125,3 +165,37 @@ TEST(SceneRenderer_Test, ForwardsPipelineLifetimeAndRenderCallsToCameraRenderer)
EXPECT_EQ(initialState->shutdownCalls, 1);
EXPECT_EQ(replacementState->shutdownCalls, 1);
}
TEST(SceneRenderer_Test, SortsManualCameraRequestsByDepthBeforeRendering) {
Scene scene("SceneRendererManualRequests");
GameObject* farCameraObject = scene.CreateGameObject("FarCamera");
auto* farCamera = farCameraObject->AddComponent<CameraComponent>();
farCamera->SetPrimary(true);
farCamera->SetDepth(10.0f);
GameObject* nearCameraObject = scene.CreateGameObject("NearCamera");
auto* nearCamera = nearCameraObject->AddComponent<CameraComponent>();
nearCamera->SetPrimary(false);
nearCamera->SetDepth(1.0f);
auto state = std::make_shared<MockPipelineState>();
SceneRenderer renderer(std::make_unique<MockPipeline>(state));
CameraRenderRequest farRequest;
farRequest.scene = &scene;
farRequest.camera = farCamera;
farRequest.context = CreateValidContext();
farRequest.surface = RenderSurface(800, 600);
farRequest.cameraDepth = farCamera->GetDepth();
CameraRenderRequest nearRequest = farRequest;
nearRequest.camera = nearCamera;
nearRequest.cameraDepth = nearCamera->GetDepth();
const std::vector<CameraRenderRequest> requests = { farRequest, nearRequest };
ASSERT_TRUE(renderer.Render(requests));
ASSERT_EQ(state->renderedCameras.size(), 2u);
EXPECT_EQ(state->renderedCameras[0], nearCamera);
EXPECT_EQ(state->renderedCameras[1], farCamera);
}