11
This commit is contained in:
76
docs/mirage_cross_platform_refactor.md
Normal file
76
docs/mirage_cross_platform_refactor.md
Normal 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% 下降。
|
||||
- **发布节奏**:Beta(v0.1-beta,启用开关,内部 dogfood);RC(v0.2-rc,禁用旧路径,beta 用户反馈);GA(v1.0,移除遗留代码,全面文档更新)。
|
||||
|
||||
## 尚需确认或缺失的信息
|
||||
- 目标平台清单(Windows 之外是否包含 Linux/X11、Wayland、macOS、移动端)。
|
||||
- 新平台的渲染后端偏好(Vulkan、Metal、OpenGL)及与 sokol 的集成策略。
|
||||
- 输入法与键盘布局要求(多语言支持、组合键需求)。
|
||||
- 示例与生产环境的期望验证范围(是否需要 headless 测试)。
|
||||
- CI 资源可用性(是否具备多平台 runner)与发布时间表。
|
||||
- 性能或延迟红线指标,用于衡量重构后回归。
|
||||
Reference in New Issue
Block a user