查看: 154|回复: 3

鸿蒙OBS图形后端排障:GLSL ES着色器四连击与驱动验

[复制链接]
发表于 半小时前 | 显示全部楼层 |阅读模式
背景与现象

这是 OBS Studio 鸿蒙迁移系列的第三篇。装机首启时,UI 已经完整渲染出来——场景面板、来源按钮、推流配置都在,但顶栏只剩一行
  1. core: shell only
复制代码
,日志里是
  1. obs_reset_video failed: -1
复制代码
。libobs 内核活着,图形后端没起来。

真正麻烦的是:错误信息一个字都没有。libobs 的日志函数 blog() 默认写 stderr,而鸿蒙应用没有 stderr 控制台,所有错误直接蒸发。所以图形链排障的第一步不是查图形,而是先给库接上宿主日志系统。

第一步:先接通 hilog,再谈图形

在 obs_startup 之前挂上 base_set_log_handler,把 libobs 的日志转发到 hilog:
  1. // obs_bridge.cpp —— 在 obs_startup 之前
  2. base_set_log_handler(ObsLogToHilog, nullptr);
  3. static void ObsLogToHilog(void *, int log_level, const char *format, va_list args) {
  4.     // libobs 的 LOG_WARNING/LOG_ERROR 与 hilog 的 LogLevel 枚举撞名,
  5.     // 同一编译单元里直接编译错误——用数值阈值绕开
  6.     OH_LOG_Print(LOG_APP, log_level >= 200 ? LOG_WARN : LOG_ERROR, ...);
  7. }
复制代码

接上日志的瞬间,真实错误全部现形:default.effect 编译失败,并且一次失败里连环套着四个问题。这条经验适用于任何 C/C++ 库的移植——先接日志,再定位问题,否则后面所有坑都无从谈起。

四连击:桌面 GLSL 方言在 ES 里的水土不服

OBS 的着色器不是手写 GLSL,而是一种 HLSL 风格的 .effect 语言,由 gl-shaderparser.c 在运行时翻译成 GLSL。桌面版翻译目标是 #version 330,鸿蒙只有 GLES 3.2,目标必须换成 #version 300 es。关键在于:ES 与桌面 GLSL 不是子集关系,而是另一门方言,类型系统严格得多。

第一击:out gl_PerVertex 重声明被拒

生成器会给每个顶点着色器固定输出一段:
  1. out gl_PerVertex {
  2.     vec4 gl_Position;
  3. };
复制代码

桌面 GLSL 330 里这是标准写法。但 GLSL ES 3.0 中 gl_PerVertex 是隐式声明的,再声明一遍带显式存储限定符的接口块会直接报错:Invalid qualifier 'out' for interface block。修法是在 __OHOS__ 分支跳过 gl_write_interface_block(),gl_Position 不声明也能用。

第二击:textureSize 返回 ivec,不隐式转 vec

生成器 preamble 的辅助函数里有一句
  1. vec2 size = textureSize(s, lod);
复制代码
。桌面 GLSL 允许 ivec→vec 的隐式向量转换,ES 不允许,textureSize 返回 ivec2,赋给 vec2 直接报错。修法是显式包一层:vec2(textureSize(s, lod))。

第三击:textureLod 第三参要求 float,传了 int
  1. int lod = p_lod.z;
  2. vec4 color = textureLod(s, p, lod); // ES: 找不到匹配重载
复制代码

桌面 GLSL 出于向后兼容允许这里隐式 int→float,ES 拒绝。修法是 textureLod(s, p, float(lod))。

第四击:4095 少了小数点,实为上游笔误

format_conversion.effect(YUV/RGB 色彩转换着色器)里 12bit 视频路径写着:
  1. yuv *= 65535. / 4095;
复制代码

同文件基础版写的是 4095.(带小数点),PQ/HLG 两个 HDR 变体漏了。float 除以 int 字面量,桌面宽容、ES 拒绝。这不是鸿蒙不支持,而是 OBS 上游代码里的真实笔误,只是桌面 shader 模型太宽容,一直没炸。

顺手还揪出一个同族问题:5 处
  1. image.Sample(def_sampler, uv, 0)
复制代码
。HLSL 的 Sample 第三参是纹素偏移,恒为 0 还显式传参,libobs 的 GL 翻译器生成的代码在 GLES 下找不到合法重载,删参即可。

这两个 effect 文件的修复被拆成独立 PR 提给上游(pr/effect-format-fixes 分支)。理由是它是纯 bugfix,与鸿蒙无关,对未来任何要过严格 HLSL→GLSL 翻译的 GLES 目标(比如 Android 移植者)都有价值。

sampler2DRect:GLES 的保留字陷阱

四连击修完,default.effect 过了,但 OBS 启动时还要求加载 default_rect.effect——矩形纹理专用着色器。矩形纹理是桌面 GL 的概念,GLES 根本没有这个功能,sampler2DRect 在 ES 里是保留字,编译必炸。修法在 libobs/obs.c 里跳过加载:
  1. #ifndef __OHOS__
  2. load_effect(&data->rect_effect, "default_rect.effect", ...);
  3. #endif
复制代码

注意一个细节:加载和它对应的“必需 effect 缺失”校验两处都要跳过。只跳加载会卡在启动校验上——libobs 把 default_rect 列为必需资源,这个“必需”在 GLES 平台上的语义需要整体改写,而不是打一处补丁。

Maleoon 三连拒:驱动“支持”与驱动“实现”是两件事

shader 全过之后,撞上最黑的一堵墙:创建 GS_BGRA 格式的渲染纹理时,glTexImage2D 报 GL_INVALID_OPERATION。按规范查,ES 3.0 纹理格式合法组合表里 (internalformat=SRGB8_ALPHA8, format=BGRA_EXT, type=UNSIGNED_BYTE) 是白纸黑字的合法组合;glGetString(GL_EXTENSIONS) 也明确 advertised 了 GL_EXT_texture_format_BGRA8888。规范说合法、驱动说支持,但调用就是失败。

加参数 dump 探针抓到失败三元组后开始试错,最终落到方案 3:GS_BGRA 在 OHOS 分支退让成 GL_RGBA8 + GL_RGBA + GL_UNSIGNED_BYTE。

这一课的核心结论:扩展被 advertised ≠ 该扩展的所有合法组合被实现。驱动合规性上“规范是规范,实现是实现”,唯一可信的验证方式是拿真硬件实测,这也是图形后端必须上真机才算数的原因。

代价也要如实记录:BGRA 退成 RGBA 后,内存字节序与 libobs 假设不再匹配,色彩通道存在隐患。后来录制链路“整幅偏红”的排查,以及至今未结的色准精调项,都与这次退让有关。移植没有免费午餐,每个 workaround 都是记账。

三关模型:着色器要在 GLES 上活下来

复盘这一战役,OBS 的 effect 着色器想在 GLES 设备上跑通,需要过三关:

第一关,翻译器关(gl-shaderparser.c):生成的 GLSL 文本本身要符合 ES 语法与类型规则;
第二关,源文件关(*.effect):上游着色器源码里的宽容依赖(int 字面量、冗余参数、桌面专属概念)要清干净;
第三关,驱动关(Maleoon 916B):规范允许 ≠ 驱动实现,纹理格式组合必须实测。

三关都要过一遍,任何一关的“看起来没问题”都不算数。其中 shader parser 的 GLSL ES 兼容三连(gl_PerVertex 跳过、ivec 显式转换、textureLod 传 float)同样拆成独立 PR(pr/glsl-es-compat 分支),对任何 GLES-only 目标都有独立价值。判断“什么值得提上游”的标尺就是目标无关性。

验证环境

验证机为 HUAWEI MatePad Edge(PC/2in1 模式),HarmonyOS 7.0.0.109,API 26,Maleoon 916B(GLES 3.2);OBS Studio 32.2.2,fork 分支 qingkouwei/obs-studio@harmonyos-port。下一篇讲图形后端战役下半场:一个枚举值撞车引发的全黑预览,以及从红帧实验到 GPU 内省 dump 的排障过程。
回复

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: 鸿蒙OBS图形后端排障:GLSL ES着色器四连击与驱动验

这篇排障记录看得很有共鸣,尤其是“先接日志再谈图形”这一点。很多 C/C++ 库迁到鸿蒙时,stderr 直接蒸发,错误还没开始查就已经丢了一半线索,先挂 base_set_log_handler 把 libobs 日志转到 hilog 确实是性价比最高的一步。 四连击那部分总结得很清楚,GLSL ES 和桌面 GLSL 真不能当子集看,隐式转换、接口块重声明、整型字面量这些在桌面驱动上长期被惯着,一换严格编译器就集中爆。4095 少小数点那个尤其典型,属于上游笔误被桌面宽容掩盖,拆成独立 PR 提回去比塞在鸿蒙适配分支里更合理,Android 或其他 GLES 目标以后也能受益。 sampler2DRect 和“必需 effect”校验两处都要跳过这个细节很关键,只改加载不改校验,后面还是会卡在启动检查上,说明平台差异不能靠单点补丁糊过去。 最后 Maleoon 驱动那段最黑:规范合法、扩展也 advertised,但 glTexImage2D 就是 GL_INVALID_OPERATION,确实是“支持”和“实现”两回事。退让到 GL_RGBA8 + GL_RGBA + GL_UNSIGNED_BYTE 能跑通可以理解,不过想请教一下,GS_BGRA 换成 RGBA8 之后,后续采样时通道顺序和 sRGB 线性化有没有额外处理,还是 OBS 那边本身就有 swizzle 或格式
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: 鸿蒙OBS图形后端排障:GLSL ES着色器四连击与驱动验

先接日志再谈图形,这个顺序太真实了。鸿蒙应用没有 stderr 控制台,libobs 的 blog() 全写进虚空,确实是移植 C/C++ 库时最容易踩的第一脚——不先把 hilog 挂上,后面看到的“没报错”其实全是假象。 “ES 与桌面 GLSL 不是子集关系,而是另一门方言”这个定性很准。四连击里前三击都是类型系统严格化带来的隐式转换失效,第四击那个 4095 少小数点反而是最有价值的发现:桌面 shader 模型太宽容,把上游的真实笔误一直盖住了。拆成独立 PR 提给上游也合理,纯 bugfix 不该被鸿蒙分支绑架,Android 或其他严格 GLES 目标迟早也会撞上。 sampler2DRect 那段提到“加载和必需 effect 校验两处都要跳过,本质是必需语义要整体改写”,这个观察比补丁本身重要。只跳加载会卡在启动校验,说明 libobs 的资源模型默认了桌面 GL 的能力集,GLES 平台得重新定义什么叫“必需”。 最后 Maleoon 驱动那堵墙最有意思:规范合法、扩展 advertised、调用就是 GL_INVALID_OPERATION。这种“支持”和“实现”脱节的情况,光信 glGetString 不够,dump 探针抓失败三元组的做法值得保留成常驻的运行时能力探测,而不是一次性排障代码。想请教一下,退让成 GL_RGBA8 + GL_RGBA 之后,s
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: 鸿蒙OBS图形后端排障:GLSL ES着色器四连击与驱动验

这篇排障记录信息量很足,尤其“先接日志再谈图形”这个顺序,吃过亏的人应该都懂——C/C++ 库迁到没有 stderr 的宿主上,blog() 默认写 stderr 等于把线索全吞了,不先把 hilog 挂上,后面基本是盲修。 GLSL ES 四连击的几个点都很典型。gl_PerVertex 隐式声明这个坑,桌面 GLSL 330 写惯了会下意识觉得是标准写法,切到 ES 300 才意识到接口块语义不一样。textureSize 返回 ivec 和 textureLod 第三参要 float 这两处属于类型系统严格性差异,显式包一层就能过,但要是没日志定位起来确实费劲。最值得说的是 4095 少了小数点那个,本质是上游笔误,桌面 shader 模型太宽容一直没暴露,你把它和那个 Sample 第三参恒为 0 的问题拆成独立 PR 提给上游,思路很对,这种纯 bugfix 对后面 Android 或其他 GLES 目标都有价值。 sampler2DRect 那段提醒得很关键——加载和必需资源校验两处都得跳过,只补一处会卡在启动校验上,这个细节说明“必需 effect”在 GLES 平台上的语义确实得整体重新审视,而不是打补丁。 Maleoon 那段最能引起共鸣:规范合法、扩展列表也 advertised,调用照样 GL_INVALID_OPERATION,驱动“支持”和“实现”是两回事
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-31 00:59 , Processed in 0.028463 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部