Introduce native render pipeline host
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <XCEngine/RHI/RHITexture.h>
|
||||
#include <XCEngine/Core/Math/Vector4.h>
|
||||
#include <XCEngine/Rendering/Execution/CameraRenderer.h>
|
||||
#include <XCEngine/Rendering/Execution/RenderPipelineHost.h>
|
||||
#include <XCEngine/Rendering/Graph/RenderGraph.h>
|
||||
#include <XCEngine/Rendering/RenderPipelineAsset.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
@@ -3468,6 +3469,139 @@ TEST(SceneRenderer_Test, ForwardsPipelineLifetimeAndRenderCallsToCameraRenderer)
|
||||
EXPECT_EQ(replacementState->shutdownCalls, 1);
|
||||
}
|
||||
|
||||
TEST(RenderPipelineHost_Test, BuildsFramePlansFromRequestsUsingPipelineAssetDefaults) {
|
||||
Scene scene("RenderPipelineHostBuildPlans");
|
||||
|
||||
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||
camera->SetPrimary(true);
|
||||
camera->SetDepth(2.0f);
|
||||
|
||||
FinalColorOverrideSettings cameraOverrides = {};
|
||||
cameraOverrides.overrideExposureValue = true;
|
||||
cameraOverrides.exposureValue = 1.8f;
|
||||
camera->SetFinalColorOverrides(cameraOverrides);
|
||||
|
||||
auto assetState = std::make_shared<MockPipelineAssetState>();
|
||||
assetState->defaultFinalColorSettings.outputTransferMode =
|
||||
FinalColorOutputTransferMode::LinearToSRGB;
|
||||
assetState->defaultFinalColorSettings.exposureMode =
|
||||
FinalColorExposureMode::Fixed;
|
||||
assetState->defaultFinalColorSettings.exposureValue = 1.25f;
|
||||
|
||||
CameraRenderRequest request = {};
|
||||
request.scene = &scene;
|
||||
request.camera = camera;
|
||||
request.context = CreateValidContext();
|
||||
request.surface = RenderSurface(640, 360);
|
||||
request.cameraDepth = camera->GetDepth();
|
||||
request.clearFlags = RenderClearFlags::All;
|
||||
|
||||
RenderPipelineHost host(std::make_shared<MockPipelineAsset>(assetState));
|
||||
const std::vector<CameraFramePlan> plans =
|
||||
host.BuildFramePlans({ request });
|
||||
|
||||
ASSERT_EQ(plans.size(), 1u);
|
||||
const CameraFramePlan& plan = plans[0];
|
||||
EXPECT_TRUE(plan.finalColorPolicy.hasPipelineDefaults);
|
||||
EXPECT_TRUE(plan.finalColorPolicy.hasCameraOverrides);
|
||||
EXPECT_EQ(
|
||||
plan.finalColorPolicy.outputTransferMode,
|
||||
FinalColorOutputTransferMode::LinearToSRGB);
|
||||
EXPECT_EQ(
|
||||
plan.finalColorPolicy.exposureMode,
|
||||
FinalColorExposureMode::Fixed);
|
||||
EXPECT_FLOAT_EQ(plan.finalColorPolicy.exposureValue, 1.8f);
|
||||
}
|
||||
|
||||
TEST(RenderPipelineHost_Test, ForwardsPipelineLifetimeAndRenderCallsToCameraRenderer) {
|
||||
Scene scene("RenderPipelineHostScene");
|
||||
|
||||
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||
camera->SetPrimary(true);
|
||||
camera->SetDepth(2.0f);
|
||||
|
||||
auto initialState = std::make_shared<MockPipelineState>();
|
||||
auto replacementState = std::make_shared<MockPipelineState>();
|
||||
|
||||
{
|
||||
auto initialPipeline = std::make_unique<MockPipeline>(initialState);
|
||||
MockPipeline* initialPipelineRaw = initialPipeline.get();
|
||||
RenderPipelineHost host(std::move(initialPipeline));
|
||||
EXPECT_EQ(host.GetPipeline(), initialPipelineRaw);
|
||||
|
||||
auto replacementPipeline = std::make_unique<MockPipeline>(replacementState);
|
||||
MockPipeline* replacementPipelineRaw = replacementPipeline.get();
|
||||
host.SetPipeline(std::move(replacementPipeline));
|
||||
|
||||
EXPECT_EQ(initialState->shutdownCalls, 1);
|
||||
EXPECT_EQ(host.GetPipeline(), replacementPipelineRaw);
|
||||
|
||||
CameraRenderRequest request = {};
|
||||
request.scene = &scene;
|
||||
request.camera = camera;
|
||||
request.context = CreateValidContext();
|
||||
request.surface = RenderSurface(800, 600);
|
||||
request.cameraDepth = camera->GetDepth();
|
||||
request.clearFlags = RenderClearFlags::All;
|
||||
|
||||
const std::vector<CameraFramePlan> plans =
|
||||
host.BuildFramePlans({ request });
|
||||
ASSERT_EQ(plans.size(), 1u);
|
||||
ASSERT_TRUE(host.Render(plans));
|
||||
EXPECT_EQ(replacementState->renderCalls, 1);
|
||||
EXPECT_EQ(replacementState->lastSurfaceWidth, 800u);
|
||||
EXPECT_EQ(replacementState->lastSurfaceHeight, 600u);
|
||||
EXPECT_EQ(replacementState->lastCamera, camera);
|
||||
}
|
||||
|
||||
EXPECT_EQ(initialState->shutdownCalls, 1);
|
||||
EXPECT_EQ(replacementState->shutdownCalls, 1);
|
||||
}
|
||||
|
||||
TEST(RenderPipelineHost_Test, SortsManualFramePlansByDepthBeforeRendering) {
|
||||
Scene scene("RenderPipelineHostManualRequests");
|
||||
|
||||
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>();
|
||||
RenderPipelineHost host(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();
|
||||
farRequest.cameraStackOrder = 1;
|
||||
farRequest.clearFlags = RenderClearFlags::None;
|
||||
|
||||
CameraRenderRequest nearRequest = farRequest;
|
||||
nearRequest.camera = nearCamera;
|
||||
nearRequest.cameraDepth = nearCamera->GetDepth();
|
||||
nearRequest.cameraStackOrder = 0;
|
||||
nearRequest.clearFlags = RenderClearFlags::Depth;
|
||||
|
||||
const std::vector<CameraFramePlan> plans =
|
||||
host.BuildFramePlans({ farRequest, nearRequest });
|
||||
ASSERT_TRUE(host.Render(plans));
|
||||
ASSERT_EQ(state->renderedCameras.size(), 2u);
|
||||
ASSERT_EQ(state->renderedClearFlags.size(), 2u);
|
||||
EXPECT_EQ(state->renderedCameras[0], nearCamera);
|
||||
EXPECT_EQ(state->renderedClearFlags[0], RenderClearFlags::Depth);
|
||||
EXPECT_EQ(state->renderedCameras[1], farCamera);
|
||||
EXPECT_EQ(state->renderedClearFlags[1], RenderClearFlags::None);
|
||||
}
|
||||
|
||||
TEST(SceneRenderer_Test, CreatesPipelineInstancesFromPipelineAssetsAndShutsDownReplacedPipelines) {
|
||||
Scene scene("SceneRendererAssetScene");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user