Files
XCEngine/docs/plan/NewEditor_SystemAudit_2026-04-22.md

147 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NewEditor System Audit
Date: 2026-04-22
## 1. Scope
本次审计目标不是继续“猜一个点然后修一个点”,而是重新检查 `new_editor`
当前还残留哪些:
1. 旧代码或旧语义残留
2. 冗余控制路径
3. 临时性/补丁式结构
4. 边界没有收口干净的模块职责
审计重点覆盖:
- `app/Platform/Win32`
- `app/Rendering/D3D12`
- `app/Rendering/Viewport`
- `app/Composition`
- `WindowManager`
## 2. Confirmed Closed Items
这轮审计先确认了已经真正收掉的历史链路,避免把已经解决的问题重复列为风险:
1. `new_editor` 中已无活跃的 `D2D / Direct2D / D3D11On12 / NativeRenderer / WindowInterop`
主窗口链路。
2. `D3D12UiRenderer` 已不再保留活跃的 `legacy/indexed` 双路径 UI geometry 提交。
3. 启动截图策略已经不再由旧的渲染层壳子控制,`Rendering/Native` 活 include 路径已清空。
这说明上一轮 D3D12 / 截图职责收口本身是有效的。
## 3. Primary Findings
### 3.1 High: frame execution still has multiple live owners
`RenderFrame()` 现在不是单点驱动,而是同时被多条路径直接调用:
- [EditorWindow.cpp:612](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\EditorWindow.cpp#L612)
- [EditorWindow.cpp:654](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\EditorWindow.cpp#L654)
- [EditorWindowChromeController.cpp:431](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\EditorWindowChromeController.cpp#L431)
- [EditorWindowChromeController.cpp:912](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\EditorWindowChromeController.cpp#L912)
- [EditorWindowHostRuntime.cpp:237](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowHostRuntime.cpp#L237)
- [EditorWindowMessageDispatcher.cpp:62](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowMessageDispatcher.cpp#L62)
- [EditorWindowMessageDispatcher.cpp:402](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowMessageDispatcher.cpp#L402)
- [EditorWindowMessageDispatcher.cpp:411](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowMessageDispatcher.cpp#L411)
- [EditorWindowMessageDispatcher.cpp:419](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowMessageDispatcher.cpp#L419)
- [EditorWindowMessageDispatcher.cpp:439](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowMessageDispatcher.cpp#L439)
根本问题不是“调用次数多”,而是“帧驱动权不唯一”:
1. 主循环在主动渲染。
2. `WM_PAINT` 在同步渲染。
3. `WM_SIZE / WM_DPICHANGED / WM_EXITSIZEMOVE` 在消息里同步渲染。
4. `EditorWindowChromeController` 在窗口过渡操作里直接同步渲染。
这会导致:
1. 帧生成/Present 时机不再只有一个真实来源。
2. `EditorWindowFrameTransferRequests` 的处理顺序在不同入口下不一致。
3. resize / maximize / drag-restore 时Chrome 层直接拥有渲染副作用。
4. 输入、布局、Present、窗口消息之间很难建立稳定时序。
这不是局部实现细节,而是当前 `new_editor` 最明显的未收口架构问题。
### 3.2 High: window destruction lifecycle still has multiple owners
窗口销毁收尾现在仍然散落在多处:
- [EditorWindowHostRuntime.cpp:172](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowHostRuntime.cpp#L172)
- [EditorWindowHostRuntime.cpp:194](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowHostRuntime.cpp#L194)
- [EditorWindowHostRuntime.cpp:262](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowHostRuntime.cpp#L262)
- [EditorWindowMessageDispatcher.cpp:428](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowMessageDispatcher.cpp#L428)
- [EditorWindowMessageDispatcher.cpp:452](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowMessageDispatcher.cpp#L452)
- [EditorWindowWorkspaceCoordinator.cpp:221](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowWorkspaceCoordinator.cpp#L221)
- [EditorWindowWorkspaceCoordinator.cpp:267](D:\Xuanchi\Main\XCEngine\new_editor\app\Platform\Win32\WindowManager\EditorWindowWorkspaceCoordinator.cpp#L267)
当前重复动作包括:
1. `window.Shutdown()`
2. `DestroyWindow(hwnd)`
3. `window.MarkDestroyed()`
4.`m_windows` 中 erase
根本问题是native window death、runtime shutdown、workspace removal、host container erase
没有一个唯一所有者。
这会导致:
1. 生命周期语义只能靠“现在碰巧没炸”维持,而不是靠明确边界维持。
2. 工具窗口、弹出窗口、独立面板窗口的关闭行为仍然容易反复回归。
3. `WorkspaceCoordinator` 直接复制 host runtime 的 destroy 逻辑,说明边界没有收口。
这条问题和之前的“关子窗口把主窗口带走”属于同一类根因:生命周期控制权分裂。
### 3.3 Medium: EditorShellRuntime is still a monolithic per-frame god-object
[EditorShellRuntime.cpp:549](D:\Xuanchi\Main\XCEngine\new_editor\app\Composition\EditorShellRuntime.cpp#L549)
开始的 `EditorShellRuntime::Update(...)` 仍然在一个单元里同时承担:
1. shell definition 构建
2. workspace/session 同步
3. dock host interaction 更新
4. viewport request / frame 应用
5. hosted panel input 分发
6. hierarchy / project / color picker / inspector / console 更新
7. status / command focus / trace 同步
同一个 update 内还存在多次会话同步与定义重建:
- [EditorShellRuntime.cpp:580](D:\Xuanchi\Main\XCEngine\new_editor\app\Composition\EditorShellRuntime.cpp#L580)
- [EditorShellRuntime.cpp:582](D:\Xuanchi\Main\XCEngine\new_editor\app\Composition\EditorShellRuntime.cpp#L582)
- [EditorShellRuntime.cpp:605](D:\Xuanchi\Main\XCEngine\new_editor\app\Composition\EditorShellRuntime.cpp#L605)
- [EditorShellRuntime.cpp:607](D:\Xuanchi\Main\XCEngine\new_editor\app\Composition\EditorShellRuntime.cpp#L607)
- [EditorShellRuntime.cpp:629](D:\Xuanchi\Main\XCEngine\new_editor\app\Composition\EditorShellRuntime.cpp#L629)
- [EditorShellRuntime.cpp:672](D:\Xuanchi\Main\XCEngine\new_editor\app\Composition\EditorShellRuntime.cpp#L672)
这不是“旧链路残留”,但它是当前最明显的未拆分核心耦合点。它会导致:
1. 任意一个 panel / dock / viewport 变更都容易影响整帧更新流程。
2. 输入问题、状态问题、布局问题、面板问题很难局部定位。
3. 后续继续做性能/交互优化时,改动面会被这个 god-object 放大。
## 4. Non-Findings
以下命中已确认不是这轮要处理的“旧代码/临时方案”问题:
1. 普通 `fallback` 参数或默认值。
2. `DirectWrite``D3D12UiTextSystem` 中的文本栅格化使用。
3. 视口 pass 中的 `fallbackState`,它表示材质渲染状态默认值,不是旧主窗口链路。
## 5. Audit Conclusion
截至本次审计,`new_editor` 不是“还有一堆 D2D 遗留没删干净”,那条主线已经基本收掉了。
当前剩余最关键的两个系统级问题是:
1. 帧驱动权没有单点收口。
2. 窗口销毁权没有单点收口。
如果后续继续做系统级收口,优先级应该是:
1. 先把 frame scheduling / present / transfer request 统一到一个唯一驱动源。
2. 再把 window close / destroy / shutdown / erase 统一到一个唯一生命周期所有者。
3. 最后再拆 `EditorShellRuntime` 这个 per-frame god-object。