5.7 KiB
5.7 KiB
NewEditor 宿主重构计划
目标
把 new_editor 当前的窗口宿主从“功能可运行的过渡方案”收敛成可长期演进的 Editor 宿主架构,核心目标如下:
- 主显示链最终统一到纯 D3D12。
- 窗口线程只负责消息和状态,不承担 GPU 重活。
- live resize 必须真实更新,但不能再走同步阻塞窗口线程的路径。
- Editor shell 和 Scene/Game viewport 统一纳入宿主合成层。
- 当前
D3D11On12 + D2D只允许作为过渡路径,不能继续加深耦合。
当前问题
1. 宿主职责混在 Application
当前 Application 同时承担:
- Win32 消息调度
- 宿主运行时状态
- resize / dpi / deferred render 调度
- editor 状态更新
- present 前后的宿主控制
这会导致宿主问题难以单独定位和演进。
2. 主显示链过厚
当前主路径仍然依赖:
- D3D12 viewport 渲染
- swapchain backbuffer
- D3D11On12 wrapped resource
- D2D 绘制 shell
- present
这条链在 live resize、frame pacing、backbuffer 生命周期上都偏重。
3. resize 热路径仍然偏保守
虽然已经把 WM_SIZE 从直接同步 resize 调整为 deferred render 触发,但 resize 热路径里仍存在:
- backbuffer interop target 重建
- swapchain resize
- 资源生命周期收束
这还不是最终架构。
重构阶段
阶段 1:宿主分层
目标
先把结构理顺,停止继续把宿主逻辑堆进 Application。
任务
- 拆出宿主运行时状态对象。
- 拆出窗口消息调度与 deferred render 调度。
- 让
Application只保留 editor 业务更新与高层协作职责。 - 为后续 HostRenderer / HostCompositor 留清晰边界。
完成标准
- resize / dpi / deferred render / interactive resize 状态不再散落在
Application成员里。 Application的宿主状态字段明显减少。- 现有功能与布局不回退。
阶段 2:建立 HostRenderer / HostCompositor 边界
目标
把宿主渲染拆成明确两层:
HostRenderer责任:device / queue / swapchain / backbuffer / fence / presentHostCompositor责任:把 shell draw data、viewport texture、icon/text 统一合成到 backbuffer
任务
- 停止让
NativeRenderer既像窗口绘制器又像过渡 compositor。 - 把“主窗口显示”和“UI 绘制命令解释”职责显式拆开。
- 为纯 D3D12 compositor 做接口准备。
完成标准
HostRenderer不依赖 D2D 语义。HostCompositor成为唯一的宿主 UI 合成入口。- 现有
NativeRenderer明确退化为过渡层或 fallback。
阶段 3:主显示链切换到纯 D3D12
目标
去掉 D3D11On12 + D2D 在主显示链中的核心地位。
任务
- shell 矩形、线条、图像、文字统一进入 D3D12 UI compositor。
- Scene/Game viewport 作为普通 SRV 输入参与同一条 compositor pass。
- backbuffer 只通过 D3D12 呈现。
完成标准
- 主窗口显示不再依赖 D2D。
- resize 时不再重建 D3D11On12 backbuffer interop target。
new_editor主显示链可在没有 D3D11On12 的条件下工作。
阶段 4:重写 resize 状态机
目标
做到真实 live resize,但不阻塞窗口线程。
任务
WM_SIZE只更新最新目标尺寸。- render tick 只消费最新尺寸,不处理过期尺寸。
- resize 不允许在消息处理里做 GPU 等待。
- resize / present / viewport surface 生命周期统一到宿主状态机。
完成标准
- 拖动窗口边界时不黑屏。
- 不出现黑白垃圾区。
- 窗口拖动体感明显优于当前实现。
阶段 5:去掉 resize 路径里的全队列等待
目标
去掉当前最重的同步点。
任务
- 改成 per-backbuffer / per-frame 生命周期管理。
- 只等待必须退休的资源代际。
- 禁止 resize 路径里的整队列 idle 等待。
完成标准
- resize 期间 CPU/GPU 同步明显减少。
- live resize 手感继续改善。
阶段 6:viewport 生命周期收口
目标
让 Scene/Game viewport 与外层宿主真正解耦。
任务
- viewport render target 长期存活,不跟着宿主链大拆大建。
- 宿主 compositor 只采样 viewport 结果,不干预其内部资源生命周期。
- Scene/Game 在 interactive resize 期间保持稳定。
完成标准
- viewport 不再因宿主 resize 逻辑出现黑屏或闪烁。
- 宿主和 viewport 各自职责明确。
执行顺序
- 先完成阶段 1。
- 然后搭好阶段 2 的 HostRenderer / HostCompositor 边界。
- 再推进阶段 3,切主显示链到纯 D3D12。
- 最后做阶段 4、5、6 的性能与生命周期收口。
当前落点
当前阶段 1 已完成,阶段 2 已开始收口:
- 已新增
HostRuntimeState,把宿主 DPI / interactive resize / pending resize / deferred render 状态从Application中抽离。 - 已新增
WindowMessageDispatcher,把WndProc中的宿主消息调度与 deferred render 调度拆到Host层。 - 已把
D3D12WindowRenderLoop从悬空 helper 升级为主窗口帧编排入口,开始统一BeginFrame / viewport render / UI present / fallback / resize interop这条链。 - 已把 viewport render target 资源工厂从
ProductViewportRenderTargets.h收成独立 manager,ProductViewportHostService只保留请求/返回 frame 的业务外壳。 - 已把 shader resource descriptor 分配职责从
D3D12WindowRenderer抽到独立的D3D12ShaderResourceDescriptorAllocator,减少窗口呈现器的非 swapchain 职责。 - 下一步进入阶段 2 主体:继续拆
NativeRenderer中的窗口互操作 / present 组合路径,把 D2D UI 光栅化与 D3D11On12 窗口合成进一步分离。