Extract scene viewport render pass bundle

This commit is contained in:
2026-04-04 17:53:36 +08:00
parent 5295ef3718
commit 0807b5a753
6 changed files with 204 additions and 30 deletions

View File

@@ -90,6 +90,7 @@ add_executable(${PROJECT_NAME} WIN32
src/Viewport/SceneViewportOrientationGizmo.cpp
src/Viewport/SceneViewportOverlayBuilder.cpp
src/Viewport/SceneViewportOverlayFrameCache.cpp
src/Viewport/SceneViewportRenderPassBundle.cpp
src/Viewport/SceneViewportOverlaySpriteResources.cpp
src/Viewport/SceneViewportOverlayProviders.cpp
src/Viewport/Passes/SceneViewportEditorOverlayPass.cpp

View File

@@ -0,0 +1,43 @@
#include "Viewport/SceneViewportRenderPassBundle.h"
namespace XCEngine {
namespace Editor {
void SceneViewportRenderPassBundle::Shutdown() {
m_overlayRenderer.Shutdown();
m_selectionOutlineRenderer.Shutdown();
m_gridRenderer.Shutdown();
}
SceneViewportRenderPlanBuildResult SceneViewportRenderPassBundle::BuildRenderPlan(
const ViewportRenderTargets& targets,
const SceneViewportOverlayData& overlay,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportOverlayFrameData& editorOverlayFrameData,
bool debugSelectionMask) {
return BuildSceneViewportRenderPlan(
targets,
overlay,
selectedObjectIds,
editorOverlayFrameData,
[this](const SceneViewportGridPassData& data) {
return CreateSceneViewportGridPass(m_gridRenderer, data);
},
[this](
RHI::RHIResourceView* objectIdTextureView,
const std::vector<uint64_t>& selectionIds,
const SceneViewportSelectionOutlineStyle& style) {
return CreateSceneViewportSelectionOutlinePass(
m_selectionOutlineRenderer,
objectIdTextureView,
selectionIds,
style);
},
[this](const SceneViewportOverlayFrameData& frameData) {
return CreateSceneViewportEditorOverlayPass(m_overlayRenderer, frameData);
},
debugSelectionMask);
}
} // namespace Editor
} // namespace XCEngine

View File

@@ -0,0 +1,31 @@
#pragma once
#include "Passes/SceneViewportEditorOverlayPass.h"
#include "Passes/SceneViewportGridPass.h"
#include "Passes/SceneViewportSelectionOutlinePass.h"
#include "SceneViewportRenderPlan.h"
namespace XCEngine {
namespace Editor {
class SceneViewportRenderPassBundle {
public:
~SceneViewportRenderPassBundle() = default;
void Shutdown();
SceneViewportRenderPlanBuildResult BuildRenderPlan(
const ViewportRenderTargets& targets,
const SceneViewportOverlayData& overlay,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportOverlayFrameData& editorOverlayFrameData,
bool debugSelectionMask = false);
private:
SceneViewportGridPassRenderer m_gridRenderer;
SceneViewportSelectionOutlinePassRenderer m_selectionOutlineRenderer;
SceneViewportEditorOverlayPassRenderer m_overlayRenderer;
};
} // namespace Editor
} // namespace XCEngine

View File

@@ -4,14 +4,12 @@
#include "Core/ISceneManager.h"
#include "Core/ISelectionManager.h"
#include "IViewportHostService.h"
#include "Passes/SceneViewportEditorOverlayPass.h"
#include "Passes/SceneViewportGridPass.h"
#include "Passes/SceneViewportSelectionOutlinePass.h"
#include "SceneViewportCameraController.h"
#include "SceneViewportEditorOverlayData.h"
#include "SceneViewportOverlayFrameCache.h"
#include "SceneViewportOverlayHandleBuilder.h"
#include "SceneViewportOverlayBuilder.h"
#include "SceneViewportRenderPassBundle.h"
#include "SceneViewportRenderPlan.h"
#include "ViewportHostRenderFlowUtils.h"
#include "ViewportHostRenderTargets.h"
@@ -78,9 +76,7 @@ public:
entry = {};
}
m_sceneViewportSelectionOutlineRenderer.Shutdown();
m_sceneViewportGridRenderer.Shutdown();
m_sceneViewportEditorOverlayRenderer.Shutdown();
m_sceneViewportRenderPassBundle.Shutdown();
m_sceneViewCamera = {};
ResetSceneViewportOverlayFrameCacheState(m_sceneViewEditorOverlayFrameCache);
m_sceneViewTransformGizmoOverlayState = {};
@@ -507,31 +503,11 @@ private:
const SceneViewportOverlayFrameData& editorOverlayFrameData =
GetSceneViewEditorOverlayFrameData(context);
SceneViewportRenderPlanBuildResult renderPlan =
BuildSceneViewportRenderPlan(
m_sceneViewportRenderPassBundle.BuildRenderPlan(
entry.renderTargets,
outState.overlay,
selectedObjectIds,
editorOverlayFrameData,
[this](const SceneViewportGridPassData& data) {
return CreateSceneViewportGridPass(
m_sceneViewportGridRenderer,
data);
},
[this](
RHI::RHIResourceView* objectIdTextureView,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportSelectionOutlineStyle& style) {
return CreateSceneViewportSelectionOutlinePass(
m_sceneViewportSelectionOutlineRenderer,
objectIdTextureView,
selectedObjectIds,
style);
},
[this](const SceneViewportOverlayFrameData& frameData) {
return CreateSceneViewportEditorOverlayPass(
m_sceneViewportEditorOverlayRenderer,
frameData);
},
kDebugSceneSelectionMask);
outState.renderPlan = std::move(renderPlan.plan);
if (renderPlan.warningStatusText != nullptr) {
@@ -732,9 +708,7 @@ private:
SceneViewportTransformGizmoOverlayState m_sceneViewTransformGizmoOverlayState = {};
SceneViewportOverlayFrameCacheState m_sceneViewEditorOverlayFrameCache = {};
bool m_sceneViewTransformGizmoOverlayDirty = false;
SceneViewportGridPassRenderer m_sceneViewportGridRenderer;
SceneViewportSelectionOutlinePassRenderer m_sceneViewportSelectionOutlineRenderer;
SceneViewportEditorOverlayPassRenderer m_sceneViewportEditorOverlayRenderer;
SceneViewportRenderPassBundle m_sceneViewportRenderPassBundle;
};
} // namespace Editor

View File

@@ -19,6 +19,7 @@ set(EDITOR_TEST_SOURCES
test_scene_viewport_transform_gizmo_coordinator.cpp
test_scene_viewport_shader_paths.cpp
test_scene_viewport_overlay_frame_cache.cpp
test_scene_viewport_render_pass_bundle.cpp
test_scene_viewport_overlay_sprite_resources.cpp
test_scene_viewport_overlay_renderer.cpp
test_scene_viewport_overlay_providers.cpp
@@ -52,8 +53,12 @@ set(EDITOR_TEST_SOURCES
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOrientationGizmo.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayBuilder.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayFrameCache.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportRenderPassBundle.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlaySpriteResources.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayProviders.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/Passes/SceneViewportGridPass.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/Passes/SceneViewportEditorOverlayPass.cpp
)
if(XCENGINE_ENABLE_MONO_SCRIPTING AND TARGET xcengine_managed_assemblies)
@@ -82,6 +87,7 @@ target_link_libraries(editor_tests PRIVATE
target_include_directories(editor_tests PRIVATE
${CMAKE_SOURCE_DIR}/engine/include
${CMAKE_SOURCE_DIR}/editor/src
${CMAKE_SOURCE_DIR}/editor/src/Viewport
${CMAKE_BINARY_DIR}/_deps/imgui-src
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends
)

View File

@@ -0,0 +1,119 @@
#include <gtest/gtest.h>
#include "Viewport/SceneViewportEditorOverlayData.h"
#include "Viewport/SceneViewportRenderPassBundle.h"
namespace {
using XCEngine::Editor::SceneViewportOverlayData;
using XCEngine::Editor::SceneViewportOverlayFrameData;
using XCEngine::Editor::SceneViewportOverlayLinePrimitive;
using XCEngine::Editor::SceneViewportRenderPassBundle;
using XCEngine::Editor::ViewportRenderTargets;
using XCEngine::RHI::Format;
using XCEngine::RHI::RHIResourceView;
using XCEngine::RHI::ResourceViewDimension;
using XCEngine::RHI::ResourceViewType;
class DummyResourceView final : public RHIResourceView {
public:
explicit DummyResourceView(
ResourceViewType viewType = ResourceViewType::RenderTarget,
Format format = Format::R8G8B8A8_UNorm)
: m_viewType(viewType)
, m_format(format) {
}
void Shutdown() override {
}
void* GetNativeHandle() override {
return nullptr;
}
bool IsValid() const override {
return true;
}
ResourceViewType GetViewType() const override {
return m_viewType;
}
ResourceViewDimension GetDimension() const override {
return ResourceViewDimension::Texture2D;
}
Format GetFormat() const override {
return m_format;
}
private:
ResourceViewType m_viewType = ResourceViewType::RenderTarget;
Format m_format = Format::R8G8B8A8_UNorm;
};
SceneViewportOverlayData CreateValidOverlay() {
SceneViewportOverlayData overlay = {};
overlay.valid = true;
overlay.cameraPosition = XCEngine::Math::Vector3(1.0f, 2.0f, 3.0f);
overlay.cameraForward = XCEngine::Math::Vector3::Forward();
overlay.cameraRight = XCEngine::Math::Vector3::Right();
overlay.cameraUp = XCEngine::Math::Vector3::Up();
overlay.verticalFovDegrees = 70.0f;
overlay.nearClipPlane = 0.1f;
overlay.farClipPlane = 500.0f;
overlay.orbitDistance = 9.0f;
return overlay;
}
SceneViewportOverlayFrameData CreateOverlayFrameDataWithLine(const SceneViewportOverlayData& overlay) {
SceneViewportOverlayFrameData frameData = {};
frameData.overlay = overlay;
SceneViewportOverlayLinePrimitive& line = frameData.worldLines.emplace_back();
line.startWorld = XCEngine::Math::Vector3::Zero();
line.endWorld = XCEngine::Math::Vector3::Right();
line.color = XCEngine::Math::Color::White();
return frameData;
}
TEST(SceneViewportRenderPassBundleTest, BuildRenderPlanCreatesGridOutlineAndOverlayPasses) {
DummyResourceView objectIdShaderView(ResourceViewType::ShaderResource);
ViewportRenderTargets targets = {};
targets.objectIdShaderView = &objectIdShaderView;
const SceneViewportOverlayData overlay = CreateValidOverlay();
const SceneViewportOverlayFrameData editorOverlayFrameData =
CreateOverlayFrameDataWithLine(overlay);
SceneViewportRenderPassBundle bundle;
const auto result = bundle.BuildRenderPlan(
targets,
overlay,
{ 7u, 11u },
editorOverlayFrameData,
false);
EXPECT_EQ(result.plan.postScenePasses.GetPassCount(), 2u);
EXPECT_EQ(result.plan.overlayPasses.GetPassCount(), 1u);
EXPECT_EQ(result.warningStatusText, nullptr);
}
TEST(SceneViewportRenderPassBundleTest, BuildRenderPlanReportsMissingObjectIdShaderView) {
const SceneViewportOverlayData overlay = CreateValidOverlay();
SceneViewportRenderPassBundle bundle;
const auto result = bundle.BuildRenderPlan(
{},
overlay,
{ 42u },
{},
false);
EXPECT_EQ(result.plan.postScenePasses.GetPassCount(), 1u);
EXPECT_EQ(result.plan.overlayPasses.GetPassCount(), 0u);
EXPECT_STREQ(result.warningStatusText, "Scene object id shader view is unavailable");
}
} // namespace