refactor(rendering): add srp host stage recorder bridge
This commit is contained in:
@@ -416,6 +416,15 @@ struct MockPipelineAssetState {
|
||||
FinalColorSettings defaultFinalColorSettings = {};
|
||||
};
|
||||
|
||||
struct MockStageRecorderState {
|
||||
int initializeCalls = 0;
|
||||
int shutdownCalls = 0;
|
||||
int recordMainSceneCalls = 0;
|
||||
bool supportsMainSceneRenderGraph = false;
|
||||
bool recordMainSceneResult = true;
|
||||
bool lastReceivedRenderGraphBlackboard = false;
|
||||
};
|
||||
|
||||
class MockPipeline final : public RenderPipeline {
|
||||
public:
|
||||
explicit MockPipeline(std::shared_ptr<MockPipelineState> state)
|
||||
@@ -592,6 +601,37 @@ private:
|
||||
std::shared_ptr<MockPipelineState> m_state;
|
||||
};
|
||||
|
||||
class MockStageRecorder final : public RenderPipelineStageRecorder {
|
||||
public:
|
||||
explicit MockStageRecorder(std::shared_ptr<MockStageRecorderState> state)
|
||||
: m_state(std::move(state)) {
|
||||
}
|
||||
|
||||
bool Initialize(const RenderContext&) override {
|
||||
++m_state->initializeCalls;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shutdown() override {
|
||||
++m_state->shutdownCalls;
|
||||
}
|
||||
|
||||
bool SupportsStageRenderGraph(CameraFrameStage stage) const override {
|
||||
return SupportsCameraFramePipelineGraphRecording(stage) &&
|
||||
m_state->supportsMainSceneRenderGraph;
|
||||
}
|
||||
|
||||
bool RecordStageRenderGraph(
|
||||
const RenderPipelineStageRenderGraphContext& context) override {
|
||||
++m_state->recordMainSceneCalls;
|
||||
m_state->lastReceivedRenderGraphBlackboard = context.blackboard != nullptr;
|
||||
return m_state->recordMainSceneResult;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<MockStageRecorderState> m_state;
|
||||
};
|
||||
|
||||
template <typename PassT, typename... Args>
|
||||
PassT* InstallStandaloneStagePass(
|
||||
RenderPipeline& pipeline,
|
||||
@@ -623,6 +663,34 @@ private:
|
||||
std::shared_ptr<MockPipelineAssetState> m_state;
|
||||
};
|
||||
|
||||
struct MockManagedRenderPipelineBridgeState {
|
||||
int createStageRecorderCalls = 0;
|
||||
Pipelines::ManagedRenderPipelineAssetDescriptor lastDescriptor = {};
|
||||
std::shared_ptr<MockStageRecorderState> lastCreatedStageRecorderState;
|
||||
};
|
||||
|
||||
class MockManagedRenderPipelineBridge final
|
||||
: public Pipelines::ManagedRenderPipelineBridge {
|
||||
public:
|
||||
explicit MockManagedRenderPipelineBridge(
|
||||
std::shared_ptr<MockManagedRenderPipelineBridgeState> state)
|
||||
: m_state(std::move(state)) {
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPipelineStageRecorder> CreateStageRecorder(
|
||||
const Pipelines::ManagedRenderPipelineAssetDescriptor& descriptor) const override {
|
||||
++m_state->createStageRecorderCalls;
|
||||
m_state->lastDescriptor = descriptor;
|
||||
m_state->lastCreatedStageRecorderState =
|
||||
std::make_shared<MockStageRecorderState>();
|
||||
return std::make_unique<MockStageRecorder>(
|
||||
m_state->lastCreatedStageRecorderState);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<MockManagedRenderPipelineBridgeState> m_state;
|
||||
};
|
||||
|
||||
class MockObjectIdPass final : public RenderPass {
|
||||
public:
|
||||
MockObjectIdPass(
|
||||
@@ -3755,6 +3823,75 @@ TEST(ScriptableRenderPipelineHost_Test, ForwardsRendererLifetimeAndFrameRenderin
|
||||
EXPECT_EQ(replacementState->shutdownCalls, 1);
|
||||
}
|
||||
|
||||
TEST(ScriptableRenderPipelineHost_Test, PrefersStageRecorderBeforeFallbackRenderer) {
|
||||
auto rendererState = std::make_shared<MockPipelineState>();
|
||||
auto initialRecorderState = std::make_shared<MockStageRecorderState>();
|
||||
auto replacementRecorderState = std::make_shared<MockStageRecorderState>();
|
||||
|
||||
rendererState->supportsMainSceneRenderGraph = true;
|
||||
initialRecorderState->supportsMainSceneRenderGraph = true;
|
||||
replacementRecorderState->supportsMainSceneRenderGraph = true;
|
||||
|
||||
{
|
||||
Pipelines::ScriptableRenderPipelineHost host(
|
||||
std::make_unique<MockPipeline>(rendererState));
|
||||
|
||||
auto initialRecorder =
|
||||
std::make_unique<MockStageRecorder>(initialRecorderState);
|
||||
MockStageRecorder* initialRecorderRaw = initialRecorder.get();
|
||||
host.SetStageRecorder(std::move(initialRecorder));
|
||||
EXPECT_EQ(host.GetStageRecorder(), initialRecorderRaw);
|
||||
|
||||
auto replacementRecorder =
|
||||
std::make_unique<MockStageRecorder>(replacementRecorderState);
|
||||
MockStageRecorder* replacementRecorderRaw = replacementRecorder.get();
|
||||
host.SetStageRecorder(std::move(replacementRecorder));
|
||||
|
||||
EXPECT_EQ(initialRecorderState->shutdownCalls, 1);
|
||||
EXPECT_EQ(host.GetStageRecorder(), replacementRecorderRaw);
|
||||
|
||||
Scene scene("ScriptableRenderPipelineRecorderScene");
|
||||
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||
camera->SetPrimary(true);
|
||||
camera->SetDepth(1.0f);
|
||||
|
||||
const RenderContext context = CreateValidContext();
|
||||
const RenderSurface surface(800, 600);
|
||||
RenderSceneData sceneData =
|
||||
CreateSceneDataForCamera(scene, *camera, surface);
|
||||
RenderGraph graph = {};
|
||||
RenderGraphBuilder graphBuilder(graph);
|
||||
RenderGraphBlackboard blackboard = {};
|
||||
bool executionSucceeded = true;
|
||||
const RenderPipelineStageRenderGraphContext graphContext = {
|
||||
graphBuilder,
|
||||
"MainScene",
|
||||
CameraFrameStage::MainScene,
|
||||
context,
|
||||
sceneData,
|
||||
surface,
|
||||
nullptr,
|
||||
nullptr,
|
||||
XCEngine::RHI::ResourceStates::Common,
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
&executionSucceeded,
|
||||
&blackboard
|
||||
};
|
||||
|
||||
EXPECT_TRUE(host.SupportsStageRenderGraph(CameraFrameStage::MainScene));
|
||||
EXPECT_TRUE(host.RecordStageRenderGraph(graphContext));
|
||||
EXPECT_EQ(replacementRecorderState->recordMainSceneCalls, 1);
|
||||
EXPECT_TRUE(replacementRecorderState->lastReceivedRenderGraphBlackboard);
|
||||
EXPECT_EQ(rendererState->recordMainSceneCalls, 0);
|
||||
}
|
||||
|
||||
EXPECT_EQ(rendererState->shutdownCalls, 1);
|
||||
EXPECT_EQ(replacementRecorderState->shutdownCalls, 1);
|
||||
}
|
||||
|
||||
TEST(ScriptableRenderPipelineHostAsset_Test, CreatesHostFromRendererAssetAndForwardsDefaults) {
|
||||
auto assetState = std::make_shared<MockPipelineAssetState>();
|
||||
assetState->defaultFinalColorSettings.outputTransferMode =
|
||||
@@ -3784,6 +3921,41 @@ TEST(ScriptableRenderPipelineHostAsset_Test, CreatesHostFromRendererAssetAndForw
|
||||
EXPECT_EQ(assetState->createCalls, 1);
|
||||
}
|
||||
|
||||
TEST(ManagedScriptableRenderPipelineAsset_Test, CreatesHostWithStageRecorderFromManagedBridge) {
|
||||
Pipelines::ClearManagedRenderPipelineBridge();
|
||||
|
||||
const Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = {
|
||||
"GameScripts",
|
||||
"Gameplay",
|
||||
"ManagedRenderPipelineProbeAsset"
|
||||
};
|
||||
auto bridgeState = std::make_shared<MockManagedRenderPipelineBridgeState>();
|
||||
Pipelines::SetManagedRenderPipelineBridge(
|
||||
std::make_shared<MockManagedRenderPipelineBridge>(bridgeState));
|
||||
|
||||
{
|
||||
Pipelines::ManagedScriptableRenderPipelineAsset asset(descriptor);
|
||||
std::unique_ptr<RenderPipeline> pipeline = asset.CreatePipeline();
|
||||
ASSERT_NE(pipeline, nullptr);
|
||||
|
||||
auto* host =
|
||||
dynamic_cast<Pipelines::ScriptableRenderPipelineHost*>(pipeline.get());
|
||||
ASSERT_NE(host, nullptr);
|
||||
EXPECT_NE(host->GetPipelineRenderer(), nullptr);
|
||||
EXPECT_NE(host->GetStageRecorder(), nullptr);
|
||||
EXPECT_EQ(bridgeState->createStageRecorderCalls, 1);
|
||||
EXPECT_EQ(bridgeState->lastDescriptor.assemblyName, "GameScripts");
|
||||
EXPECT_EQ(bridgeState->lastDescriptor.namespaceName, "Gameplay");
|
||||
EXPECT_EQ(bridgeState->lastDescriptor.className, "ManagedRenderPipelineProbeAsset");
|
||||
|
||||
ASSERT_NE(bridgeState->lastCreatedStageRecorderState, nullptr);
|
||||
bridgeState->lastCreatedStageRecorderState->supportsMainSceneRenderGraph = true;
|
||||
EXPECT_TRUE(host->SupportsStageRenderGraph(CameraFrameStage::MainScene));
|
||||
}
|
||||
|
||||
Pipelines::ClearManagedRenderPipelineBridge();
|
||||
}
|
||||
|
||||
TEST(CameraRenderer_Test, DefaultPipelineAssetUsesManagedSelectionWhenPresent) {
|
||||
const Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = {
|
||||
"GameScripts",
|
||||
|
||||
Reference in New Issue
Block a user