【问题标题】:How best to access ARCore video frame in compute shader如何在计算着色器中最好地访问 ARCore 视频帧
【发布时间】:2020-04-15 13:27:49
【问题描述】:

我正在实施一项技术,该技术使用 ARCore(当前为 1.16.0)以及 OpenGL ES 3.2 计算着色器中的自定义图像处理。

有两种方法可以从计算着色器访问视频帧,但都有缺点:

  1. 使用Session.setCameraTextureName() 这似乎是一个自然的选择,因为我让 ARCore 为我将数据放入 OpenGL 纹理中。但是它在 RGBA 中,这可能意味着在我获取数据之前发生了不需要的有损转换。此外,由于它是 GL_TEXTURE_EXTERNAL_OES 纹理,我无法直接访问像素(使用imageLoad()),必须通过采样器。此外,在我测试过的设备上,每个 CameraConfig 的纹理分辨率都是 1080,这对于我的计算算法来说太大了,需要缩减。
  2. 使用Frame.acquireCameraImage() 这里的优点是我在 YCbCr 中获得图像,大概跳过了有损转换步骤,并且我可以选择合适的分辨率。缺点是我需要拨打两个glTexSubImage2D() 电话。

(有趣的是,在三星 S8 和 A3 上,所有配置的纹理分辨率为 1920x1080,图像分辨率为 640x480、1280x720 和 1920x1080。)

ARCore + 计算似乎有点灰色地带。欢迎任何关于哪个是更好选择的建议,但请引用来源。 :)

编辑:根据反馈添加一些具体问题:

  • 从主存中的 YCbCr 图像到 RGBA OpenGL ES 纹理一般在后台使用什么路径?
  • 这条路径比glTexSubImage2D()快吗?
  • 无论我是否设置会话的纹理名称,我都要为此支付计算成本吗?
  • 主内存 YCbCr 图像是否总是在转换链中出现在 RGBA 纹理之前?

【问题讨论】:

  • 没有“正确答案”。正如您自己所说,这两种方法都有缺点。目前尚不清楚您对“更好”的定义是什么——色彩准确度、性能、内存带宽、开发时间?
  • 只有真正的答案 - 两者都尝试,并为您的用例衡量“更好”。
  • @solidpixel,好点,我需要澄清我所说的“更好”是什么意思。但是我不同意测量是找出答案的唯一真正选择。以近乎最优的方式实现这两条路径并在我所针对的数千台 Android 设备中的一个重要子集上进行测量是一项艰巨的任务。从一些关于如何设计视频捕获系统的基本事实开始是很有意义的,例如。 ARCore 的视频纹理是否通常通过比 glTexSubImage2D 更快的路径上传,以及主存 YCbCr 图像是否总是在转换链中的 RGBA 纹理之前。

标签: android opengl-es gpgpu arcore


【解决方案1】:

从主存中的 YCbCr 图像到 RGBA OpenGL ES 纹理一般在后台使用什么路径?

使用GL_TEXTURE_EXTERNAL_OES 基本上是零拷贝访问。 GPU 可以直接访问相机/视频块写入的 YUV 图像。颜色转换发生在飞行中;这样做可能会有一些 GPU 开销——这将取决于硬件——但没有在内存中创建第二个 RGB 副本。多少开销 - 现代移动 GPU 可以非常有效地做到这一点,但较旧的移动 GPU 可能需要 2 倍于两个平面 YUV 的纹理成本。

这条路径比 glTexSubImage2D() 快吗?

一般来说,是的,这就是存在直接访问路径的原因。但是,您必须在一种情况下而不是另一种情况下注入额外的下采样,这一事实并不能使这成为一个明显的“正确答案”。

另请注意,费用不同。直接 YUV-RGB 转换会产生 GPU 成本。纹理上传会产生 CPU 成本。根据您设备的相对 CPU/GPU 性能以及应用程序的其余部分使用的资源,其中一个可能比另一个痛苦少。

无论我是否设置会话的纹理名称,我是否为此支付了计算成本?

没有。访问纹理时,在采样器中完成 YUV 到 RGB 的转换。

主存 YCbCr 图像是否总是在转换链中出现在 RGBA 纹理之前?

RGBA 纹理完全是虚拟的 - 它不存在于内存中。

所有配置的纹理分辨率为 1920x1080,图像分辨率为 640x480、1280x720 和 1920x1080。

请注意,相机 HAL 层中有很多特定于供应商的“魔法”。无法说低分辨率图像是如何创建的。它们可以由相机直接以较低的分辨率生成,也可以由供应商 HAL 在单独的通道中缩小(如果相机不能直接执行,通常使用硬件缩放器)。

【讨论】:

  • 谢谢@solidpixel,这很有帮助。一个后续问题:在许多可用的 ARCore 相机配置中,(虚拟)纹理分辨率高于(主内存)图像分辨率。由于您暗示低分辨率主内存图像直接来自相机 HAL,这是否意味着虚拟 GLES 纹理是该图像的放大版本,还是来自相机 HAL 的图像有多个版本?
  • 不确定是否诚实;我从未使用过其中的 AR 部分,我只知道其中的图形 API 部分。 ARCore 文档讨论了“CPU 分辨率”和“GPU 分辨率”。听起来 GPU 分辨率始终是 1080p,并且它必须仍然在主内存中某处,以便 GPU 访问它...
猜你喜欢
  • 2022-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多