Fix scene selection outline mask path

This commit is contained in:
2026-04-09 05:16:04 +08:00
parent c48311eaaf
commit 2084412010
29 changed files with 1250 additions and 56 deletions

View File

@@ -190,6 +190,7 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportSelectionOutlineStyleApplies
TEST(ViewportRenderFlowUtilsTest, ApplySceneRenderRequestSetupAttachesOptionalPassesAndObjectIdSurface) {
DummyResourceView depthView(ResourceViewType::DepthStencil, Format::D24_UNorm_S8_UInt);
DummyResourceView objectIdDepthView(ResourceViewType::DepthStencil, Format::D24_UNorm_S8_UInt);
DummyResourceView objectIdView(ResourceViewType::RenderTarget);
DummyResourceView objectIdShaderView(ResourceViewType::ShaderResource);
@@ -197,6 +198,7 @@ TEST(ViewportRenderFlowUtilsTest, ApplySceneRenderRequestSetupAttachesOptionalPa
targets.width = 800;
targets.height = 600;
targets.depthView = &depthView;
targets.objectIdDepthView = &objectIdDepthView;
targets.objectIdView = &objectIdView;
targets.objectIdShaderView = &objectIdShaderView;
targets.objectIdState = ResourceStates::Common;
@@ -217,7 +219,7 @@ TEST(ViewportRenderFlowUtilsTest, ApplySceneRenderRequestSetupAttachesOptionalPa
EXPECT_TRUE(request.objectId.IsRequested());
ASSERT_EQ(request.objectId.surface.GetColorAttachments().size(), 1u);
EXPECT_EQ(request.objectId.surface.GetColorAttachments()[0], &objectIdView);
EXPECT_EQ(request.objectId.surface.GetDepthAttachment(), &depthView);
EXPECT_EQ(request.objectId.surface.GetDepthAttachment(), &objectIdDepthView);
const auto requestArea = request.surface.GetRenderArea();
const auto objectIdArea = request.objectId.surface.GetRenderArea();
@@ -247,9 +249,18 @@ TEST(ViewportRenderFlowUtilsTest, ApplySceneRenderRequestSetupSkipsUnavailableOp
}
TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanCollectsPostSceneAndOverlayPasses) {
DummyResourceView depthView(ResourceViewType::DepthStencil, Format::D24_UNorm_S8_UInt);
DummyResourceView depthShaderView(ResourceViewType::ShaderResource, Format::D24_UNorm_S8_UInt);
DummyResourceView selectionMaskView(ResourceViewType::RenderTarget);
DummyResourceView selectionMaskShaderView(ResourceViewType::ShaderResource);
DummyResourceView objectIdShaderView(ResourceViewType::ShaderResource);
ViewportRenderTargets targets = {};
targets.depthView = &depthView;
targets.depthShaderView = &depthShaderView;
targets.selectionMaskView = &selectionMaskView;
targets.selectionMaskShaderView = &selectionMaskShaderView;
targets.objectIdShaderView = &objectIdShaderView;
const SceneViewportOverlayData overlay = CreateValidOverlay();
@@ -274,11 +285,16 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanCollectsPostSceneA
return std::make_unique<NoopRenderPass>();
},
[&selectionOutlinePassFactoryCallCount](
RHIResourceView* objectIdTextureView,
ViewportRenderTargets* outlineTargets,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportSelectionOutlineStyle& style) {
++selectionOutlinePassFactoryCallCount;
EXPECT_NE(objectIdTextureView, nullptr);
EXPECT_NE(outlineTargets, nullptr);
if (outlineTargets == nullptr) {
return std::unique_ptr<NoopRenderPass>();
}
EXPECT_NE(outlineTargets->selectionMaskShaderView, nullptr);
EXPECT_NE(outlineTargets->depthShaderView, nullptr);
EXPECT_EQ(selectedObjectIds.size(), 2u);
EXPECT_FLOAT_EQ(style.outlineWidthPixels, 2.0f);
return std::make_unique<NoopRenderPass>();
@@ -301,6 +317,7 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanCollectsPostSceneA
TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanSkipsRhiOverlayPassWhenFrameContainsOnlySceneIcons) {
const SceneViewportOverlayData overlay = CreateValidOverlay();
ViewportRenderTargets targets = {};
SceneViewportOverlayFrameData editorOverlayFrameData = {};
editorOverlayFrameData.overlay = overlay;
@@ -310,7 +327,7 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanSkipsRhiOverlayPas
size_t overlayFactoryCallCount = 0u;
const auto result = BuildSceneViewportRenderPlan(
{},
targets,
overlay,
{},
editorOverlayFrameData,
@@ -318,7 +335,7 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanSkipsRhiOverlayPas
return std::make_unique<NoopRenderPass>();
},
[](
RHIResourceView*,
ViewportRenderTargets*,
const std::vector<uint64_t>&,
const SceneViewportSelectionOutlineStyle&) {
return std::make_unique<NoopRenderPass>();
@@ -337,8 +354,9 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanSkipsRhiOverlayPas
TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanWarnsWhenSelectionOutlineCannotAccessObjectIdTexture) {
const SceneViewportOverlayData overlay = CreateValidOverlay();
ViewportRenderTargets targets = {};
const auto result = BuildSceneViewportRenderPlan(
{},
targets,
overlay,
{ 42u },
{},
@@ -346,7 +364,7 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanWarnsWhenSelection
return std::make_unique<NoopRenderPass>();
},
[](
RHIResourceView*,
ViewportRenderTargets*,
const std::vector<uint64_t>&,
const SceneViewportSelectionOutlineStyle&) {
return std::make_unique<NoopRenderPass>();
@@ -357,11 +375,12 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanWarnsWhenSelection
false);
EXPECT_EQ(result.plan.postScenePasses.GetPassCount(), 1u);
EXPECT_STREQ(result.warningStatusText, "Scene object id shader view is unavailable");
EXPECT_STREQ(result.warningStatusText, "Scene selection outline resources are unavailable");
}
TEST(ViewportRenderFlowUtilsTest, ApplySceneViewportRenderPlanAttachesPlannedPassesAndClearState) {
DummyResourceView depthView(ResourceViewType::DepthStencil, Format::D24_UNorm_S8_UInt);
DummyResourceView objectIdDepthView(ResourceViewType::DepthStencil, Format::D24_UNorm_S8_UInt);
DummyResourceView objectIdView(ResourceViewType::RenderTarget);
DummyResourceView objectIdShaderView(ResourceViewType::ShaderResource);
@@ -369,6 +388,7 @@ TEST(ViewportRenderFlowUtilsTest, ApplySceneViewportRenderPlanAttachesPlannedPas
targets.width = 800;
targets.height = 600;
targets.depthView = &depthView;
targets.objectIdDepthView = &objectIdDepthView;
targets.objectIdView = &objectIdView;
targets.objectIdShaderView = &objectIdShaderView;
@@ -395,14 +415,19 @@ TEST(ViewportRenderFlowUtilsTest, ApplySceneViewportRenderPlanAttachesPlannedPas
TEST(ViewportRenderFlowUtilsTest, MarkSceneRenderSuccessMovesTargetsToShaderResourceState) {
DummyResourceView depthView(ResourceViewType::DepthStencil, Format::D24_UNorm_S8_UInt);
DummyResourceView objectIdView(ResourceViewType::RenderTarget);
DummyResourceView objectIdDepthView(ResourceViewType::DepthStencil, Format::D24_UNorm_S8_UInt);
DummyResourceView selectionMaskView(ResourceViewType::RenderTarget);
ViewportRenderTargets targets = {};
targets.width = 640;
targets.height = 360;
targets.depthView = &depthView;
targets.objectIdDepthView = &objectIdDepthView;
targets.objectIdView = &objectIdView;
targets.selectionMaskView = &selectionMaskView;
targets.colorState = ResourceStates::Common;
targets.objectIdState = ResourceStates::Common;
targets.selectionMaskState = ResourceStates::Common;
XCEngine::Rendering::CameraRenderRequest request = {};
request.surface = RenderSurface(640, 360);
@@ -411,16 +436,19 @@ TEST(ViewportRenderFlowUtilsTest, MarkSceneRenderSuccessMovesTargetsToShaderReso
MarkSceneViewportRenderSuccess(targets, request);
EXPECT_EQ(targets.colorState, ResourceStates::PixelShaderResource);
EXPECT_EQ(targets.objectIdState, ResourceStates::PixelShaderResource);
EXPECT_EQ(targets.selectionMaskState, ResourceStates::PixelShaderResource);
EXPECT_TRUE(targets.hasValidObjectIdFrame);
ViewportRenderTargets noObjectIdTargets = {};
noObjectIdTargets.colorState = ResourceStates::Common;
noObjectIdTargets.objectIdState = ResourceStates::Common;
noObjectIdTargets.selectionMaskState = ResourceStates::Common;
XCEngine::Rendering::CameraRenderRequest noObjectIdRequest = {};
MarkSceneViewportRenderSuccess(noObjectIdTargets, noObjectIdRequest);
EXPECT_EQ(noObjectIdTargets.colorState, ResourceStates::PixelShaderResource);
EXPECT_EQ(noObjectIdTargets.objectIdState, ResourceStates::PixelShaderResource);
EXPECT_EQ(noObjectIdTargets.selectionMaskState, ResourceStates::PixelShaderResource);
EXPECT_FALSE(noObjectIdTargets.hasValidObjectIdFrame);
}