Add dynamic render backend adapter scaffold
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# 动态渲染后端拆分计划
|
||||
|
||||
## 目标
|
||||
|
||||
将当前强绑定 OpenGL 的渲染实现拆成可动态加载的后端库,使主程序只依赖一个轻量适配器:
|
||||
|
||||
- OpenGL 后端封装到私有动态库。
|
||||
- Vulkan 后端封装到独立动态库。
|
||||
- 后端库内部继续使用 C++ 实现。
|
||||
- 后端库对外只导出 C ABI。
|
||||
- C ABI 使用不透明 handle 表示 C++ 对象。
|
||||
- 每个 C 函数对应一个后端类成员函数。
|
||||
- 构造函数导出为特殊 create 函数,析构函数导出为特殊 destroy 函数。
|
||||
- 主程序适配器构造时按配置显式加载后端库并调用 create/init,析构时调用 destroy 并卸载库。
|
||||
|
||||
## 命名约束
|
||||
|
||||
用户期望后端名为 `libgl.so` 和 `libvulkan.so`。Linux 系统上 `libGL.so`/`libgl.so` 容易和系统 OpenGL loader 混淆,因此工程实现应优先使用私有库名或私有目录,例如:
|
||||
|
||||
- `liboakgl.so`
|
||||
- `liboakvulkan.so`
|
||||
- 或 `render_backends/libgl.so`、`render_backends/libvulkan.so`
|
||||
|
||||
适配器只从 Oak 私有后端目录查找,避免加载到系统图形库。
|
||||
|
||||
## 阶段 1:OpenGL 动态后端骨架
|
||||
|
||||
- 新增稳定 C ABI 头:`app/render/backend/renderbackend_c.h`。
|
||||
- 新增 `DynamicRenderer` 适配器,继承现有 `Renderer`,内部用 `QLibrary` 加载后端。
|
||||
- 将现有 `OpenGLRenderer` 包装成 OpenGL 后端导出函数。
|
||||
- `RenderManager` 按 `GraphicsBackend` 选择加载 OpenGL 或 Vulkan 后端。
|
||||
- 在 Vulkan 后端未实现前,请求 Vulkan 时加载占位后端或回退 OpenGL,并记录明确 warning。
|
||||
|
||||
## 阶段 2:两层适配器 ABI
|
||||
|
||||
本计划不是把 OpenGL 代码用 C 重写。动态库一侧继续保留现有 C++ `OpenGLRenderer`/未来 `VulkanRenderer` 实现,只在导出边界增加一层 C wrapper;主程序和渲染进程一侧再用 `DynamicRenderer` 把 C 函数封回 C++ `Renderer` 接口。
|
||||
|
||||
第一阶段 C ABI 可以用 `void *` 承载现有 C++ 对象指针,例如 `QVariant`、`VideoParams`、`ShaderCode`、`Texture`、`AcceleratedJob`。C 函数内部只做类型转换并调用对应 C++ 成员函数。这样两侧代码都不用大改,但有一个前提:后端库和主程序必须用同一套头文件、编译器 ABI 和 Qt/FFmpeg/OpenFX 依赖构建。
|
||||
|
||||
长期要把 ABI 稳定下来时,再逐步引入更明确的 C 结构,避免跨库暴露 Qt/C++ 类型:
|
||||
|
||||
- texture handle:`OakBackendTextureHandle`
|
||||
- shader handle:`OakBackendShaderHandle`
|
||||
- video params C struct:宽、高、depth、pixel format、channel count、linesize
|
||||
- shader code C struct:vertex/fragment 字符串
|
||||
- blit job C struct:输入 texture handle、uniform 数组、输出 texture handle
|
||||
- readback/upload 使用裸指针和 stride
|
||||
|
||||
这一步是 ABI 稳定化,不是把后端内部实现改成 C。
|
||||
|
||||
## 阶段 2.5:最小化 OpenGL 后端链接边界
|
||||
|
||||
当前工程大量代码和静态依赖被编译进 `libolive-editor` object 库。直接把整个 object 库塞进 `liboakgl.so` 会带来两个问题:
|
||||
|
||||
- 非 PIC 静态依赖会阻塞共享库链接,例如 `KDDockWidgets`。
|
||||
- 主程序和后端库会复制全局状态,增加配置、cache、单例和 Qt meta-object 的一致性风险。
|
||||
|
||||
因此动态后端接管默认 renderer 前,需要把 OpenGL 后端库的链接边界收敛到最小集合:
|
||||
|
||||
- 后端库只拥有 OpenGL/Vulkan native 操作和必要的后端私有状态。
|
||||
- 主程序侧保留项目、节点、任务、cache、OpenFX host 等 editor 状态。
|
||||
- 如果某个后端函数需要主程序创建 `Texture` 或访问 cache,用 C callback table 从后端回调主程序,而不是把完整 editor 链进后端库。
|
||||
- `OAK_ENABLE_DYNAMIC_RENDER_BACKEND` 打开前必须完成最小链接边界拆分并通过 CI。
|
||||
|
||||
## 阶段 3:Vulkan 后端
|
||||
|
||||
- 新增 Vulkan 后端库。
|
||||
- 实现 Vulkan instance/device/swapchain 或 offscreen image 管理。
|
||||
- 实现 texture 创建、上传、下载、shader 编译/缓存、blit、clear、flush。
|
||||
- 提供 OpenGL 辅助格式转换函数的 Vulkan 替代版本。
|
||||
- 确认 CPU readback、proxy preview、scope、thumbnail/cache 输出一致。
|
||||
|
||||
## 阶段 4:Viewer 双后端
|
||||
|
||||
- 当前 viewer display 基于 OpenGL widget 和 GL texture id。
|
||||
- 新增 backend-neutral viewer path。
|
||||
- OpenGL 使用现有 `QOpenGLWidget/QOpenGLWindow`。
|
||||
- Vulkan 使用 `QVulkanWindow` 或 Qt RHI/QRhi 显示路径。
|
||||
- Viewer 只消费后端 texture handle 或 readback frame,不直接假设 GL texture id。
|
||||
|
||||
## 阶段 5:OpenFX 处理边界
|
||||
|
||||
- OpenFX 插件 OpenGL 渲染路径保留 OpenGL 依赖,不强行改写。
|
||||
- 格式转换、readback、upload 等辅助函数移入后端库。
|
||||
- Vulkan 后端提供等价辅助函数。
|
||||
- 如果某个 OFX 插件必须走 OpenGL,则在 Vulkan 项目里明确使用 OpenGL 兼容路径或回退。
|
||||
|
||||
## 完成标准
|
||||
|
||||
- 主程序不直接 new `OpenGLRenderer` 作为默认渲染路径,而是通过动态后端适配器创建。
|
||||
- OpenGL 后端库可单独构建、加载、初始化、销毁。
|
||||
- 用户能在配置中选择 OpenGL/Vulkan。
|
||||
- Vulkan 未实现完整 renderer 前,请求 Vulkan 不崩溃,并有明确回退。
|
||||
- 手工测试计划覆盖 OpenGL/Vulkan 选择、重启持久化、回退、viewer、proxy、scope、导出。
|
||||
@@ -361,7 +361,7 @@
|
||||
|
||||
## 10. 图形后端选择测试
|
||||
|
||||
当前版本允许用户在 Preferences 中选择 OpenGL 或 Vulkan。注意:Vulkan 入口目前是实验性图形 API 请求和后续 VulkanRenderer 的接入点;时间线/viewer 渲染仍应安全回退到现有 OpenGL renderer。因此测试重点是“用户可选择、设置可持久化、Vulkan 请求不破坏现有渲染、失败可回退”。
|
||||
当前版本允许用户在 Preferences 中选择 OpenGL 或 Vulkan。注意:Vulkan 入口目前是实验性图形 API 请求和后续 VulkanRenderer 的接入点;默认构建下时间线/viewer 渲染仍应安全回退到现有 OpenGL renderer。动态后端适配器通过 `OAK_ENABLE_DYNAMIC_RENDER_BACKEND` 实验开关接入,测试重点是“用户可选择、设置可持久化、Vulkan 请求不破坏现有渲染、失败可回退”。
|
||||
|
||||
### 10.1 默认 OpenGL 后端
|
||||
|
||||
@@ -411,6 +411,34 @@
|
||||
|
||||
通过标准:Vulkan 请求状态下代理、Scope、调色不崩溃;切回 OpenGL 后项目状态一致;两种选择下导出默认仍使用原片。
|
||||
|
||||
### 10.6 动态 OpenGL 后端加载
|
||||
|
||||
1. 使用开启 `OAK_ENABLE_DYNAMIC_RENDER_BACKEND` 的实验构建。
|
||||
2. 确认应用目录存在 Oak 私有 OpenGL 后端库,例如 `liboakgl.so`、`liboakgl.dylib` 或 `oakgl.dll`。
|
||||
3. 在 Preferences 中选择 OpenGL 并重启。
|
||||
4. 导入 `color_chart.mov`,播放、拖动时间线并打开 Scope。
|
||||
5. 关闭应用,确认退出过程没有崩溃。
|
||||
|
||||
通过标准:日志显示动态 OpenGL 后端加载成功;viewer、Scope、调色和播放行为与默认 OpenGL 路径一致;退出时执行 destroy/unload 无崩溃。
|
||||
|
||||
### 10.7 动态后端缺失或损坏
|
||||
|
||||
1. 使用开启 `OAK_ENABLE_DYNAMIC_RENDER_BACKEND` 的实验构建。
|
||||
2. 临时移走或重命名 Oak 私有 OpenGL 后端库。
|
||||
3. 启动 Oak 并打开一个已有项目。
|
||||
4. 观察日志、Preferences 和播放行为。
|
||||
|
||||
通过标准:应用不能静默崩溃;日志明确说明后端库加载失败;用户能够恢复库文件或切回默认构建继续打开项目。
|
||||
|
||||
### 10.8 Vulkan 动态后端占位
|
||||
|
||||
1. 使用开启 `OAK_ENABLE_DYNAMIC_RENDER_BACKEND` 的实验构建。
|
||||
2. 在 Preferences 中选择 Vulkan 并重启。
|
||||
3. 如果 `liboakvulkan` 尚未实现,观察回退行为。
|
||||
4. 切回 OpenGL 并重启。
|
||||
|
||||
通过标准:Vulkan 后端未实现时不崩溃;日志明确说明 Vulkan 后端缺失并回退或拒绝初始化;切回 OpenGL 后项目可播放。
|
||||
|
||||
## 缺陷记录模板
|
||||
|
||||
每个失败项记录以下信息:
|
||||
|
||||
Reference in New Issue
Block a user