【免费下载链接】SpektraLab
SpektraLab — a macOS film and print simulator. SwiftUI app + a Metal/C++ render engine, linked in, no Python at run time. A fork of andreavolpato/spektrafilm.
SpektraLab 是一款胶片与冲扫仿真工具:打开 RAW 文件,选择胶片与相纸,即可得到带颗粒、卤化银效应(halation)、显影滤镜的"物理冲印"结果。它的 macOS 版本把 C++ 渲染引擎直接链接进 SwiftUI 应用,而 Linux/Windows 版本则换了一套跨平台双进程架构:TypeScript 前端 + Rust 编写的 Tauri 核心 + 独立的 C++ 宿主进程spektralab-host。本文拆解这套架构的设计动机、线协议、容错与打包方式。
为什么要用双进程?GPU 驱动故障不该带走你的修改
在 macOS 上,引擎是进程内的(Metal 后端、直接链接)。换到 Linux/Windows 后,架构文档 HOST-PROTOCOL.md 开宗明义:改用进程边界是刻意为之,理由有三:
- 故障隔离——GPU 驱动崩溃只会带走
spektralab-host子进程,不会连累承载用户编辑的窗口; - 交叉编译友好——宿主用 MinGW 交叉编译为 Windows 可执行文件时,完全不涉及 Rust/WebView 的 ABI;
- 可恢复——前端能重启死掉的宿主,并凭借 sidecar 文件重新打开当前帧。
这份文档同时就是engine/host/与desktop/之间的契约:变更只允许"加法"(新方法、新可选字段),破坏性变更要同步提升hello里的protocol版本号。
三方分工:TypeScript 界面、Rust 中转、C++ 引擎宿主
整个应用可以拆成三层,各自只干一件事:
| 层 | 位置 | 职责 |
|---|---|---|
| TypeScript 界面 | desktop/src/ | React 画布、会话状态、菜单、导出页,全部 UI |
| Tauri 核心(Rust) | desktop/src-tauri/src/lib.rs | 窗口、启动宿主、按请求 ID 转发、文件与 sidecar 存取 |
| C++ 宿主(C++20) | engine/host/main.cpp | 引擎 C ABI 客户端:Vulkan 渲染、LibRaw 解码、图片读写 |
Rust 核心持有HostManager,负责宿主全生命周期:启动进程、发送hello、把 webview 的请求按 request-id 映射转发、把宿主主动发来的事件转成 Tauri 事件,并在宿主意外退出时自动重启,见 host.rs。
C++ 宿主的线程模型也值得一提:一个 reader 线程独占 stdin,它自己应答ping、cancel、shutdown,其余请求全部排队给单个 worker 线程按序处理。这样正在跑的渲染可以被取消,而忙碌的宿主依然能回答存活检查。
线协议:stdin/stdout 上的二进制帧,像素永远不过 JSON
两个进程之间走的是标准输入/输出上的定长前缀二进制帧(HOST-PROTOCOL.md §1):
u32 LE header_len —— 紧随其后的 UTF-8 JSON 头字节数 u32 LE payload_len —— JSON 之后的二进制负载字节数(可为 0) u8[header_len] —— JSON 头(method / params / result / error) u8[payload_len] —— 二进制负载(像素、缩略图等)- 请求:
{"id": 1, "method": "render", "params": {...}} - 响应:
{"id": 1, "ok": true, "result": {...}}或带error.code - 事件(无 id,主动上报):
{"event": "progress", ...}
协议刻意让 JSON 只承载控制信息,像素作为二进制 payload 直传。Rust 侧把整帧回复封装为一个二进制tauri::ipc::Response原样回给 webview(见 lib.rs 的 host_request),前端 tauriTransport.ts 再按同一协议拆开。开发阶段还有一个 mock-host,用 Node 实现同一套 stdio 帧格式,方便不碰真实引擎也能调试前端——这正体现了"先定契约、再写实现"的思路。
崩溃与重启:宿主死了,编辑还在
容错逻辑集中在 host.rs:
hello超时 45 秒;- 120 秒窗口内最多重启 3 次,避免对"根本起不来的宿主"无限循环;
- 宿主状态用四态机暴露给前端:
starting→ready(含hello回复)→restarting/failed(附宿主 stderr 尾部,"no Vulkan device" 就在那里显示)。
重启后,会话状态不丢:每张打开的照片都有 sidecar 文件(<文件名>-<路径sha256>.spektra.json),前端从 sidecar 重新open即可恢复。没有 Vulkan 驱动时,宿主仍会应答hello并报backend.available: false,此时probe/thumbnail依旧可用,用户看到的是一个说明原因的错误对话框,而不是闪退。
打包:sidecar 布局 + 静态链接,一目录自包含
构建脚本会把宿主连同引擎资源整理成自包含目录(HOST-PROTOCOL.md §4),例如:
build/host-linux-x64/ spektralab-host # Linux 宿主(静态 libstdc++/libgcc) engine/ # 烘焙资源 + vulkan/*.spv + io/sRGB.icc licenses/ # GPL / CC BY-SA / LibRaw / stb / volk 许可文本Tauri 打包时把对应目录复制进应用的resources/host/,运行时以spektralab-host --resources resources/host/engine启动。Windows 版从 Linux 用 MinGW-w64 交叉编译(工具链见 toolchain-mingw-w64.cmake),静态链接 libstdc++、libgcc、winpthread,最终可执行文件只导入系统 DLL;详细流程与测试方法见 LINUX_WINDOWS.md。最终产物:Linux 的 .deb(约 14.5 MB)、AppImage,Windows 的 NSIS 安装包(约 10 MB)。
如何验证:冒烟测试、单元与端到端
这套架构的每个层面都有对应的测试:
- 引擎层:
ctest里的 Vulkan 各 kernel 对照 float64 参考(engine/tests/gpu_vulkan_*.cpp)、LibRaw 集成测试; - 宿主线协议:host_smoke.py 端到端跑完每个方法、错误路径、取消、白平衡、EXIF 与 Unicode 路径;
- 前端:vitest 单元 + Rust
cargo test+ Playwright(tests/e2e/editor.spec.ts)在浏览器内 mock host 上验证布局与交互; - 真实宿主回归:realhost.test.ts 用环境变量门控,对打包好的宿主验证导出像素路径。
CPU 无独显的环境也有退路:Lavapipe(Mesa 的 CPU Vulkan)作为回退设备被宿主接受,并如实报告math_mode差异——性能降级,但功能不缺失。
小结
SpektraLab 的跨平台方案给同类项目提供了清晰范本:
- 契约先行——HOST-PROTOCOL.md 是引擎与前端唯一的合同,加法演进、版本号守卫;
- 进程边界换稳定性——把"可能带崩一切的 GPU/驱动"关进子进程,窗口状态靠 sidecar 持久化兜底;
- 二进制帧 + JSON 控制头——像素不过 JSON,控制信息可读可查;
- 静态链接 + 资源目录——一个目录自包含,交叉编译出的 Windows 包几乎零依赖;
- 多层测试兜底——从 shader 参考值到真实宿主冒烟,逐级验证。
如果你也想体验或参与,仓库可以这样获取:
git clone https://gitcode.com/gh_mirrors/sp/SpektraLab cd SpektraLab/desktop npm ci npm run dev:web # 仅前端 + 页面内 mock 宿主【免费下载链接】SpektraLab
SpektraLab — a macOS film and print simulator. SwiftUI app + a Metal/C++ render engine, linked in, no Python at run time. A fork of andreavolpato/spektrafilm.
相关推荐
MFCMouseEffect架构拆解:C++ MFC如何演进为Win/macOS/Linux跨平台鼠标特效引擎
MFCMouseEffect架构拆解:C++ MFC如何演进为Win/macOS/Linux跨平台鼠标特效引擎 MFCMouseEffect 是一款跨平台鼠标特
告别数据盲区:用开源工具解锁你的原神账号完整数据图谱
告别数据盲区:用开源工具解锁你的原神账号完整数据图谱 你是否曾好奇其他玩家的角色配置?是否想知道自己的深渊阵容还有多少优化空间?原神玩家数据查询工具为你提供了答
游戏开发Themer终极指南:如何一键实现Windows、macOS、Linux跨平台主题同步
Themer终极指南:如何一键实现Windows、macOS、Linux跨平台主题同步 🎨 你是否曾经为在不同操作系统间保持统一的视觉风格而烦恼?Themer
开发工具CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考