refactor: route scene view passes through camera renderer
This commit is contained in:
@@ -114,15 +114,23 @@ inline ViewportRenderFallbackPolicy BuildGameViewportRenderFailurePolicy(
|
||||
|
||||
inline void ApplySceneViewportRenderRequestSetup(
|
||||
const ViewportRenderTargets& targets,
|
||||
const Rendering::BuiltinSceneViewPostProcessRequest* builtinSceneViewPostProcess,
|
||||
Rendering::RenderPassSequence* postPasses,
|
||||
Rendering::CameraRenderRequest& request) {
|
||||
request.postScenePasses = nullptr;
|
||||
request.objectId = {};
|
||||
request.builtinSceneViewPostProcess = {};
|
||||
|
||||
if (postPasses != nullptr && postPasses->GetPassCount() > 0) {
|
||||
request.postScenePasses = postPasses;
|
||||
}
|
||||
|
||||
if (builtinSceneViewPostProcess != nullptr &&
|
||||
builtinSceneViewPostProcess->IsRequested()) {
|
||||
request.builtinSceneViewPostProcess = *builtinSceneViewPostProcess;
|
||||
request.builtinSceneViewPostProcess.objectIdTextureView = targets.objectIdShaderView;
|
||||
}
|
||||
|
||||
if (targets.objectIdView == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <XCEngine/RHI/RHIResourceView.h>
|
||||
#include <XCEngine/RHI/RHITexture.h>
|
||||
#include <XCEngine/Rendering/Passes/BuiltinInfiniteGridPass.h>
|
||||
#include <XCEngine/Rendering/Passes/BuiltinSceneViewPostPassSequenceBuilder.h>
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/Rendering/SceneRenderer.h>
|
||||
@@ -92,7 +91,6 @@ public:
|
||||
m_sceneViewLastRenderContext = {};
|
||||
m_device = nullptr;
|
||||
m_backend = nullptr;
|
||||
m_sceneViewPostPassBuilder.Shutdown();
|
||||
m_sceneRenderer.reset();
|
||||
}
|
||||
|
||||
@@ -280,7 +278,7 @@ private:
|
||||
|
||||
struct SceneViewportRenderState {
|
||||
SceneViewportOverlayData overlay = {};
|
||||
Rendering::RenderPassSequence postPasses;
|
||||
Rendering::BuiltinSceneViewPostProcessRequest builtinSceneViewPostProcess = {};
|
||||
std::vector<uint64_t> selectedObjectIds;
|
||||
};
|
||||
|
||||
@@ -412,32 +410,28 @@ private:
|
||||
policy.clearColor.a);
|
||||
}
|
||||
|
||||
bool BuildSceneViewPostPassSequence(
|
||||
void BuildSceneViewBuiltinPostProcessRequest(
|
||||
ViewportEntry& entry,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
Rendering::Passes::ObjectIdOutlineStyle outlineStyle = {};
|
||||
outlineStyle.outlineColor = Math::Color(1.0f, 0.4f, 0.0f, 1.0f);
|
||||
outlineStyle.outlineWidthPixels = 2.0f;
|
||||
outlineStyle.debugSelectionMask = kDebugSceneSelectionMask;
|
||||
|
||||
const Rendering::Passes::BuiltinSceneViewPostPassSequenceBuildResult result =
|
||||
m_sceneViewPostPassBuilder.Build(
|
||||
{
|
||||
BuildInfiniteGridPassData(overlay),
|
||||
entry.renderTargets.objectIdShaderView,
|
||||
selectedObjectIds,
|
||||
outlineStyle
|
||||
},
|
||||
outPostPasses);
|
||||
|
||||
if (result.missingObjectIdTextureViewForSelection &&
|
||||
!kDebugSceneSelectionMask) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene object id shader view is unavailable");
|
||||
Rendering::BuiltinSceneViewPostProcessRequest& outRequest) {
|
||||
if (!overlay.valid) {
|
||||
outRequest = {};
|
||||
return;
|
||||
}
|
||||
|
||||
return result.valid;
|
||||
outRequest.gridPassData = BuildInfiniteGridPassData(overlay);
|
||||
outRequest.selectedObjectIds = selectedObjectIds;
|
||||
outRequest.outlineStyle = {};
|
||||
outRequest.outlineStyle.outlineColor = Math::Color(1.0f, 0.4f, 0.0f, 1.0f);
|
||||
outRequest.outlineStyle.outlineWidthPixels = 2.0f;
|
||||
outRequest.outlineStyle.debugSelectionMask = kDebugSceneSelectionMask;
|
||||
|
||||
if (!selectedObjectIds.empty() &&
|
||||
!kDebugSceneSelectionMask &&
|
||||
entry.renderTargets.objectIdShaderView == nullptr) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene object id shader view is unavailable");
|
||||
}
|
||||
}
|
||||
|
||||
void BuildSceneViewportRenderState(
|
||||
@@ -452,12 +446,11 @@ private:
|
||||
}
|
||||
|
||||
outState.selectedObjectIds = context.GetSelectionManager().GetSelectedEntities();
|
||||
|
||||
BuildSceneViewPostPassSequence(
|
||||
BuildSceneViewBuiltinPostProcessRequest(
|
||||
entry,
|
||||
outState.overlay,
|
||||
outState.selectedObjectIds,
|
||||
outState.postPasses);
|
||||
outState.builtinSceneViewPostProcess);
|
||||
}
|
||||
|
||||
bool RenderSceneViewportEntry(
|
||||
@@ -502,7 +495,8 @@ private:
|
||||
|
||||
ApplySceneViewportRenderRequestSetup(
|
||||
entry.renderTargets,
|
||||
&sceneState.postPasses,
|
||||
&sceneState.builtinSceneViewPostProcess,
|
||||
nullptr,
|
||||
requests[0]);
|
||||
requests[0].hasClearColorOverride = true;
|
||||
requests[0].clearColorOverride = Math::Color(0.27f, 0.27f, 0.27f, 1.0f);
|
||||
@@ -657,7 +651,6 @@ private:
|
||||
Rendering::RenderContext m_sceneViewLastRenderContext = {};
|
||||
std::array<ViewportEntry, 2> m_entries = {};
|
||||
SceneViewCameraState m_sceneViewCamera;
|
||||
Rendering::Passes::BuiltinSceneViewPostPassSequenceBuilder m_sceneViewPostPassBuilder;
|
||||
};
|
||||
|
||||
} // namespace Editor
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Rendering/Passes/BuiltinInfiniteGridPass.h>
|
||||
#include <XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h>
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Rendering/RenderCameraData.h>
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
@@ -30,12 +32,24 @@ struct ObjectIdRenderRequest {
|
||||
}
|
||||
};
|
||||
|
||||
struct BuiltinSceneViewPostProcessRequest {
|
||||
Passes::InfiniteGridPassData gridPassData = {};
|
||||
RHI::RHIResourceView* objectIdTextureView = nullptr;
|
||||
std::vector<uint64_t> selectedObjectIds = {};
|
||||
Passes::ObjectIdOutlineStyle outlineStyle = {};
|
||||
|
||||
bool IsRequested() const {
|
||||
return gridPassData.valid;
|
||||
}
|
||||
};
|
||||
|
||||
struct CameraRenderRequest {
|
||||
const Components::Scene* scene = nullptr;
|
||||
Components::CameraComponent* camera = nullptr;
|
||||
RenderContext context;
|
||||
RenderSurface surface;
|
||||
ObjectIdRenderRequest objectId;
|
||||
BuiltinSceneViewPostProcessRequest builtinSceneViewPostProcess;
|
||||
float cameraDepth = 0.0f;
|
||||
uint8_t cameraStackOrder = 0;
|
||||
RenderClearFlags clearFlags = RenderClearFlags::All;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <XCEngine/Rendering/CameraRenderRequest.h>
|
||||
#include <XCEngine/Rendering/ObjectIdPass.h>
|
||||
#include <XCEngine/Rendering/Passes/BuiltinSceneViewPostPassSequenceBuilder.h>
|
||||
#include <XCEngine/Rendering/RenderPipeline.h>
|
||||
|
||||
#include <memory>
|
||||
@@ -43,6 +44,7 @@ private:
|
||||
std::shared_ptr<const RenderPipelineAsset> m_pipelineAsset;
|
||||
std::unique_ptr<RenderPipeline> m_pipeline;
|
||||
std::unique_ptr<ObjectIdPass> m_objectIdPass;
|
||||
Passes::BuiltinSceneViewPostPassSequenceBuilder m_builtinSceneViewPostProcessBuilder;
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -86,6 +86,7 @@ CameraRenderer::~CameraRenderer() {
|
||||
if (m_objectIdPass != nullptr) {
|
||||
m_objectIdPass->Shutdown();
|
||||
}
|
||||
m_builtinSceneViewPostProcessBuilder.Shutdown();
|
||||
}
|
||||
|
||||
void CameraRenderer::SetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
|
||||
@@ -135,6 +136,11 @@ bool CameraRenderer::Render(
|
||||
!request.objectId.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
if (request.builtinSceneViewPostProcess.IsRequested() &&
|
||||
request.builtinSceneViewPostProcess.objectIdTextureView != nullptr &&
|
||||
!request.objectId.IsRequested()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderSceneData sceneData = m_sceneExtractor.ExtractForCamera(
|
||||
*request.scene,
|
||||
@@ -195,6 +201,36 @@ bool CameraRenderer::Render(
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderPassSequence builtinSceneViewPostPasses = {};
|
||||
bool builtinSceneViewPostPassesInitialized = false;
|
||||
if (request.builtinSceneViewPostProcess.IsRequested()) {
|
||||
const Passes::BuiltinSceneViewPostPassSequenceBuildResult buildResult =
|
||||
m_builtinSceneViewPostProcessBuilder.Build(
|
||||
{
|
||||
request.builtinSceneViewPostProcess.gridPassData,
|
||||
request.builtinSceneViewPostProcess.objectIdTextureView,
|
||||
request.builtinSceneViewPostProcess.selectedObjectIds,
|
||||
request.builtinSceneViewPostProcess.outlineStyle
|
||||
},
|
||||
builtinSceneViewPostPasses);
|
||||
if (!buildResult.valid ||
|
||||
!InitializePassSequence(
|
||||
&builtinSceneViewPostPasses,
|
||||
request.context,
|
||||
builtinSceneViewPostPassesInitialized)) {
|
||||
ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized);
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
if (!builtinSceneViewPostPasses.Execute(passContext)) {
|
||||
ShutdownPassSequence(&builtinSceneViewPostPasses, builtinSceneViewPostPassesInitialized);
|
||||
ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized);
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ShutdownPassSequence(&builtinSceneViewPostPasses, builtinSceneViewPostPassesInitialized);
|
||||
ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized);
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
|
||||
|
||||
@@ -438,6 +438,31 @@ TEST(CameraRenderer_Test, ShutsDownSequencesWhenPostPassInitializationFails) {
|
||||
"shutdown:pre" }));
|
||||
}
|
||||
|
||||
TEST(CameraRenderer_Test, RejectsBuiltinSceneViewPostProcessThatCannotProduceFreshObjectIdData) {
|
||||
Scene scene("CameraRendererSceneViewPostProcessValidationScene");
|
||||
|
||||
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||
camera->SetPrimary(true);
|
||||
camera->SetDepth(4.0f);
|
||||
|
||||
auto state = std::make_shared<MockPipelineState>();
|
||||
CameraRenderer renderer(std::make_unique<MockPipeline>(state));
|
||||
|
||||
CameraRenderRequest request;
|
||||
request.scene = &scene;
|
||||
request.camera = camera;
|
||||
request.context = CreateValidContext();
|
||||
request.surface = RenderSurface(512, 512);
|
||||
request.cameraDepth = camera->GetDepth();
|
||||
request.builtinSceneViewPostProcess.gridPassData.valid = true;
|
||||
request.builtinSceneViewPostProcess.objectIdTextureView =
|
||||
reinterpret_cast<XCEngine::RHI::RHIResourceView*>(1);
|
||||
|
||||
EXPECT_FALSE(renderer.Render(request));
|
||||
EXPECT_TRUE(state->eventLog.empty());
|
||||
}
|
||||
|
||||
TEST(SceneRenderer_Test, BuildsSortedRequestsForAllUsableCamerasAndHonorsOverrideCamera) {
|
||||
Scene scene("SceneRendererRequestScene");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user