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