This commit is contained in:
2025-10-14 09:53:36 +08:00
parent f8de8be68e
commit bfad8b571f

View File

@@ -0,0 +1,76 @@
# Mirage 跨平台重构方案
## 项目背景与现状
- **模块分层**: [CMakeLists.txt](CMakeLists.txt:45) 明确自底向上的依赖序列sokol → mirage_config → mirage_image → mirage_core → mirage_platform → mirage_render → mirage_widget → mirage_app符合 UI 框架 layered 设计。
- **平台窗口抽象**: [IWindow](src/mirage_platform/include/mirage_platform/window.h:21) 提供完整的跨平台接口,但当前仅有 [WindowsWindow](src/mirage_platform/src/windows/windows_window.cpp:19) 实现,且未暴露平台选择机制。
- **渲染层耦合**: [mwindow::impl](src/mirage_widget/src/window/mwindow_impl.cpp:40) 依赖 [platform_window](src/mirage_render/src/platform_window/platform_window.h:7) 及其 Windows 后端,绕过 mirage_platform导致 UI 层直接绑定 Windows/Direct3D。
- **输入与 IME**: [WindowsInputManager](src/mirage_platform/src/windows/windows_input.cpp:18) 与 [WindowsIMEManager](src/mirage_platform/src/windows/windows_ime.cpp:22) 未与 widget 层事件总线解耦,仍由 [windows_window_event_handler](src/mirage_render/src/platform_window/windows/windows_window_event.cpp:396) 直接触发。
- **事件循环**: [platform_window::poll_events](src/mirage_render/src/platform_window/windows/windows_window.cpp:189) 与 [mirage_platform::poll_events](src/mirage_platform/src/windows/windows_window.cpp:401) 重复实现,且全局窗口集合通过静态数组维护,缺乏生命周期管理。
- **渲染上下文**: [mirage_render_context::create_window_state](src/mirage_render/src/render/render_context.h:131) 仅返回 [windows_render_state](src/mirage_render/src/render/windows/windows_render_state.cpp:28),而 [windows_mirage_render_context::init](src/mirage_render/src/render/windows/windows_render_context.cpp:14) 硬编码 D3D11缺乏可插拔后端。
## 主要问题、风险和影响
| 问题 | 影响 | 相关位置 |
| --- | --- | --- |
| 平台抽象未贯通UI 仍依赖渲染层 Windows 实现 | 阻碍引入 macOS/Linux 后端,导致模块边界失效 | [mwindow::impl](src/mirage_widget/src/window/mwindow_impl.cpp:40)、[platform_window](src/mirage_render/src/platform_window/platform_window.h:7) |
| 事件与输入栈重复实现 | 维护成本高,行为不一致风险大 | [windows_window_event_handler](src/mirage_render/src/platform_window/windows/windows_window_event.cpp:396)、[mirage_platform::poll_events](src/mirage_platform/src/windows/windows_window.cpp:401) |
| 资源与生命周期缺乏统一管理 | 多窗口或重建交换链时易泄漏或崩溃 | [windows_render_state::rebuild_swapchain](src/mirage_render/src/render/windows/windows_render_state.cpp:164)、静态窗口集合 |
| 构建开关仅考虑 Windows | 其他平台编译链无法建立,限制 CI | [CMakeLists.txt](CMakeLists.txt:47)、[mirage_platform/CMakeLists.txt](src/mirage_platform/CMakeLists.txt:9) |
补充风险:当前 Direct3D 专用路径使得渲染接口与平台抽象紧耦合,一旦在 UI 层更换平台实现,需要同时改动渲染层,违背分层初衷。
## 重构目标与衡量标准
- **目标一:平台层统一抽象**
- 指标:`mirage_widget` 仅通过 `mirage_platform` 接口访问窗口与事件;编译期禁用直接包含 `platform_window`
- 验证CI 静态检查与 include 依赖审计,确保 Widget 模块无 `platform_window` 依赖。
- **目标二:输入与 IME 管线解耦**
- 指标:事件流经统一队列,`mirage_platform::poll_events` 成为唯一入口;至少一个 Widget 示例可接收键鼠与 IME 事件。
- 验证:自动化 UI smoke test记录事件分发链路。
- **目标三:渲染上下文可插拔**
- 指标:新增 `mirage_render_context` 工厂支持注入不同后端Windows D3D11、占位 Mock新增后端无需修改 Widget 层。
- 验证Mock 后端单元测试;示例应用在 Mock 模式下通过逻辑帧。
- **目标四:跨平台构建基础**
- 指标:提供最小 Linux/macOS stub窗口/输入空实现CI 完成配置与编译;新增 CMake 选项 `MIRAGE_PLATFORM=Windows|Stub`
- 验证CI 在 Stub 平台运行配置与构建流程。
## 实施路线与优先级
| 阶段 | 重点 | 依赖 | 预期产出 | 潜在阻碍 |
| --- | --- | --- | --- | --- |
| P0 架构冻结 | 梳理公共接口、定义禁用路径 | 需完成设计评审 | 迁移指南、include 审计报告 | 历史代码依赖 [platform_window](src/mirage_render/src/platform_window/platform_window.h:7) |
| P1 平台层整合 | 引入 `mirage_platform` 工厂,替换 Widget 中的窗口创建流程 | P0 | 平台抽象接口实现、统一事件泵 | 需要保持现有渲染上下文兼容 |
| P2 输入与 IME 重构 | 将事件派发由 `windows_window_event_handler` 转至 `mirage_platform` | P1 | 统一事件队列、IME 光标同步工具 | IME 组合态测试成本高 |
| P3 渲染上下文插件化 | 拆分 D3D11 实现、定义后端注册表 | P1 | D3D11 后端与 Stub 后端、配置选项 | 需同步更新 shader 初始化 |
| P4 验证与回归 | 构建测试矩阵、性能与回退脚本 | P0-P3 | CI job、性能基准、回滚流程 | GPU 驱动差异导致的不确定性 |
```mermaid
flowchart TD
UIWidgets[UI Widgets] --> PlatformAbstraction[Platform Abstraction]
PlatformAbstraction --> EventBus[Event Bus]
PlatformAbstraction --> RenderBridge[Render Bridge]
EventBus --> InputIME[Input IME Processors]
RenderBridge --> GPUBackend[GPU Backend]
InputIME --> UIWidgets
```
## 风险缓解、回滚、测试与发布计划
- **风险缓解**
- 维护双轨实现:在 P1-P3 间保持旧 `platform_window` 开关,允许按模块回退。
- 引入契约测试:为 `mirage_platform` 接口编写最小集成测试,确保多后端一致行为。
- 文档与培训:同步更新模块依赖图与代码示例,降低团队理解成本。
- **回滚策略**
- 按阶段封装开关,使用 CMake 选项 `MIRAGE_USE_LEGACY_PLATFORM` 快速恢复旧逻辑。
- 保留旧事件泵与渲染环境初始化代码至最终阶段后再清理,确保可编译回退。
- **测试与发布计划**
- **单元测试**:覆盖率目标 >85%;针对 `mirage_platform` 接口编写 mock-based 测试,包括 IWindow 生命周期方法、IInputManager 事件转换、IIMEManager 处理器注册/分发;渲染工厂测试验证后端注入与销毁无泄漏。
- **集成测试**:扩展 example/main.cpp 为测试套件模拟多窗口场景验证事件泵一致性IME 测试使用自动化脚本注入中文输入序列,检查 composition/clear 事件完整性;渲染集成测试覆盖 swapchain 重建与 texture 上传路径。
- **端到端测试**:在 CI 中运行 headless 模式Stub 平台)验证逻辑帧完整性;在 Windows runner 上对比前后版本的 UI 交互录像,量化输入延迟(目标 <16ms
- **性能与稳定性**:基准测试包括 1000 帧渲染循环(测量 FPS/内存峰值);负载测试模拟高频 IME 输入与鼠标事件洪水;稳定性检查运行 24h 无崩溃。
- **CI/CD 集成**:新增 GitHub Actions 多平台矩阵Windows/Stubs每个 PR 强制单元+集成测试通过;性能回归警报阈值设为 10% 下降。
- **发布节奏**Betav0.1-beta启用开关内部 dogfoodRCv0.2-rc禁用旧路径beta 用户反馈GAv1.0,移除遗留代码,全面文档更新)。
## 尚需确认或缺失的信息
- 目标平台清单Windows 之外是否包含 Linux/X11、Wayland、macOS、移动端
- 新平台的渲染后端偏好Vulkan、Metal、OpenGL及与 sokol 的集成策略。
- 输入法与键盘布局要求(多语言支持、组合键需求)。
- 示例与生产环境的期望验证范围(是否需要 headless 测试)。
- CI 资源可用性(是否具备多平台 runner与发布时间表。
- 性能或延迟红线指标,用于衡量重构后回归。