天天看点

Android上的CPU和GPU是共享内存,为什么有的手机从GPU读取数据还是很慢?

Refrence

  1. https://www.zhihu.com/question/398806158
  2. https://docs.aws.amazon.com/zh_cn/lumberyard/latest/userguide/ios-android-performance-guidelines.html

Q:

读取方式:双pbo读取 openGLES3
读取格式:1920*1080的RGBA数据
测试结果(每帧拷贝平均耗时):
魅蓝note3(Helio P10):140ms
华为mate30(麒麟990):13ms
三星s10+(骁龙855):2ms
           

A:

  1. 目前移动GPU架构通常也有GMEM(GPU 内存),虽然很小,只有1M,而且通常是复杂的场景中才会调用,简单场景下是不走GMEM的,即大部分场景下是共享RAM。
  2. CPU与GPU共用RAM,但不总是共用Buffer。如果调用Map函数,此时才会GPU与CPU共用Buffer,map函数是很快的,远小于1ms。
  3. 尽管共用RAM,但仍然存在2次传输。也会受限于CPU频率与AXI总线带宽。
    • CPU->GPU: GPU通过AXI bus读取textures(比如这个1080P的buffer),shaders等;
    • GPU->CPU: GPU渲染后直接写回DDR,这个buffer称为FrameBuffer;
  4. glTexImage2D上传纹理和CPU频率关系较大。我在865平台验证glTexImage2D时,频率调高与正常模式下差距非常大,720P的时间分别为3ms与40ms。

    glTexImage2D ( GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, buf_y );

  5. 可以将CPU频率调高验证一下,但题主使用了PBO,可能一定程度上减小了CPU频率的影响。

拓展:

GPU 内存 (GMEM)

GPU 内存 (GMEM) 是一种优化,它在 GPU 上使用本地内存来减少 CPU 和 GPU 之间大型纹理的传输。GMEM 可以在以下模式下运行(具体取决于移动设备支持的模式):

  • 256 位模式 — 引擎可以将 3 个 GBuffer 渲染目标和深度或模具存储在本地 GPU 像素内存中,同时执行初步 Z 通道、生成 GBuffer、延迟贴花以及延迟雨和雪通道。此模式还在渲染器的延迟着色通道期间将漫反射和高光累积纹理存储在本地 GPU 像素内存中。
  • 128 位模式 — 此模式在渲染器的延迟着色通道期间将漫反射和高光累积纹理存储在本地 GPU 像素内存中。与 256 位模式相比,128 位模式提供的性能提升更少。但是,利用 128 位模式,您可以启用在使用 256 位模式时不可用的特定渲染功能。
  • 禁用 — 此模式表示 GMEM 不受支持或已在配置文件中禁用。

渲染器使用以下两个 OpenGL 扩展来确定 Android 设备支持哪个 GMEM 模式:

  • Framebuffer fetch(256 位模式)
  • Pixel Local Storage(128 位模式)