From bfad8b571f3b414a956417e8df797029354f831b Mon Sep 17 00:00:00 2001 From: nanako <469449812@qq.com> Date: Tue, 14 Oct 2025 09:53:36 +0800 Subject: [PATCH] 11 --- docs/mirage_cross_platform_refactor.md | 76 ++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/mirage_cross_platform_refactor.md diff --git a/docs/mirage_cross_platform_refactor.md b/docs/mirage_cross_platform_refactor.md new file mode 100644 index 0000000..2a1876d --- /dev/null +++ b/docs/mirage_cross_platform_refactor.md @@ -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)与发布时间表。 +- 性能或延迟红线指标,用于衡量重构后回归。 \ No newline at end of file