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