MaliGpu最佳实践

Arm Mali GPU Best Practices.pdf

Article structure

a pipeline of processing stages that includes the application, the graphics driver, and the various hardware stages inside the GPU itself.
应用层、图形驱动层、GPU内部各个硬件阶段

Best Practices

Do
Dont
Impact
▪ Higher application CPU load.
▪ Reduced performance if CPU limited.
Debugging
▪ Profile application CPU load.
▪ Trace API usage and count calls per frame.

应用程序阶段

  1. Draw call batching 批量DrawCall
    1. CPU提交的每条绘制指令,从CPU到GPU,通道成本是昂贵和固定的。经过用户空间到内核空间再到GPU驱动最后到GPU的CommandStream中。
    2. 方案是 batch批处理。非应用层的commandbuffer,对于使用相同render state的多个对象的多次drawcall,合并obj数据,公用一次draw。减少每帧的drawcall总数。合并使用相同渲染状态的绘制对象,一次提交。
    3. DO
      1. Batch。即使没有CPU、帧率问题,使用batch可reduce power
      2. 使用VAO绘制重复物体
      3. gles 一帧不要超过500drawcall 。vk 2000
    4. Don't
      1. 批处理的图形过多,会影响子物体剔除、渲染顺序受损(由近到远充分发挥Dtest)。解释:视锥剔除和遮挡剔除是粗粒度、模型级别的剔除。细粒度的是深度测试。在剔除前做batch会导致子物体剔除失败、以及绘制顺序错乱导致深度测试失败引起overdraw。
    5. Debugging
      1. Profile application CPU load.
      2. Trace API usage and count calls per frame.
  2. Draw call culling 剔除
    1. 调用render api前剔除是最高效的。只要调用api,至少要获取\计算裁剪空间坐标NDC,然后才能剔除图元。
    2. Do
      1. 视锥剔除
      2. 遮挡剔除
      3. Find a balance between batching and culling.
      4. 背面剔除
    3. Don't
      1. 不考虑空间把每个obj都发送到图形API。
    4. Debugging
      1. 确认已开背面剔除,并且剔除率至少要到50%。
      2. framedebug确认是否渲染大量不可见三角形。
  3. Draw call render order。基础款eayly-z就是深度测试么?
    1. 为保证 eayly-z-test能发挥效果减少重绘。从前到后绘制不透明物体(render all your opaque meshes first in a front-to-back render order), 然后从后往前绘制透明网格保证blend的正确性。then render your translucent meshes in a back-to-front render order over the top of the opaque geometry to ensure alpha blending works correctly. 仅仅是
    2. GPU内置的 Forward Pixel Kill, 技术。绘制两次,首次仅深度更新(低模),第二次 GL_EQUAL 模式进行颜色渲染 。
    3. do
      1. Render opaque objects in a front-to-back order.
      2. 绘制不透明物体时关闭blend测试。Render opaque objects with blending disabled.
    4. Dont 会引起early-zs失效的场景 (earlyz是自动开启的还是要手动开启)
      1. ▪ Use discard(glsl关键字 用于条件判断后丢弃像素) in the fragment shader; this forces late-zs.
      2. ▪ Use alpha-to-coverage; this forces late-zs.
      3. ▪ Write to fragment depth in the fragment shader; this forces late-zs.
    5. Debugging
      1. GPU performance 查看像素点重绘次数是否大于1次
      2. check the number of fragments requiring late- zs testing,
  4. Avoid depth prepasses
    1. Forward Pixel Kill。 重复绘制带来的无效像素点片段化减少的收益,比 造成顶点着色和内存带宽的开销 是更值得的。
    2. Impact
      1. 由于重复的draw调用,CPU负载更高。(what?重复调用是 驱动层内的行为么?不是GPU上的行为)
      2. 由于重复的几何体,顶点着色成本和内存带宽更高。
  5. OpenGL ES GPU pipelining
    1. 移动端GPU采用延迟渲染框架。
    2. Do
      1. 应当让GPU 满负荷工作,提高利用率。减少中间的气泡
      2. Pipeline any use of fences and query objects; don't wait on them too early. 使用fence机制,并且不要太早的开始等待。
    3. Don't
      1. synchronous behavior 。 glfinish() glReadPixels
  6. Vulkan GPU pipelining
  7. Pipelined resource updates
    1. gles对上开放的是一个同步接口,但底层执行是异步,gpu执行时,cpu修改资源,存在渲染正确性问题。比如VBO \ glTexturImage2D(TODO 是异步的么)

CPU overheads

  1. Shader compilation
    1. 着色器的编译和链接is expensive 昂贵。
      1. DO
        1. 可以在游戏加载阶段进行。预编译。
        2. 使用pipeline cache
        3. Serialize the pipeline cache to disk
      2. Dont:
        1. 要避免在交互阶段进行。
        2. Rely on the Android blob cache for interactive compile and link performance {TODO what android blob }
  2. Pipeline creation
  3. Allocating memory
  4. OpenGL ES CPU memory mapping

Vertex shading

  1. Index draw calls
    1. allow more reuse of vertices 使用drawElements 更多的重用顶点,可以更高效。
    2. Do
    3. Don't
      1. Implement geometry level-of-detail (LOD) by sparsely sampling vertices from the full detail mesh; create a contiguous set of vertices for each detail level required. 不推荐这种方式实现LOD么? 因为索引太稀疏了导致从海量VBO中找到稀疏的顶点也是损耗
  2. Index buffer encoding
    1. ▪ 使用尽可能低精度的索引数据类型来减少索引列表大小。
  3. Attribute precision 精度
    1. 合适的精度,从而节约带宽并提高性能 including 8-bit, 16-bit, and packed formats such as RGB10_A2.
    2. DO
      1. 顶点位置精度用FP32,保证几何定位准确性
      2. 其他属性从低精度,节省动画资源包体积和带宽。
    3. Dont
      1. Upload FP32 data into a buffer and then read it as a mediump attribute
  4. Attribute layout
    1. Good buffer layout can maximize the benefit of this geometry pipeline.
    2. DO
      1. 多使用EBO drawElements
      2. 使用交错步幅紧凑的结构
  5. Varying precision
    1. 精度的收益,一次是由顶点着色器写入,另一次是由片段着色器读取.
    2. mediump(大部分场景)\highp(Texture coordinates for large textures) 有各自的最佳场景。
    3. dont
      1. 不要用和场景不匹配的精度,最好用mediump。
      2. 不要在VS申请Varying,但是FS中不使用。
    4. Impact
      1. Increased GPU memory bandwidth. 减少gpu内存带宽
      2. Reduced vertex shader and fragment shader performance. 增加shader的性能
  6. Triangle density
    1. vertext的带宽和处理成本要比fragment的处理高一个量级。所以要覆盖尽可能多的像素点,用于分摊成本。
    2. DO
      1. 每个图元要至少覆盖10~20个fragment
      2. 使用LOD,距离远的物体用低精度低三角化更简单的网格。
      3. 为了获得更好的光照效果,不是一味的增加模型精度,而是使用法线贴图烘焙技术。贴图还是走ASTC压缩问题。
    3. Dont
      1. 不要绘制微小三角形
  7. Instanced vertex buffers
    1. ▪ Use a single interleaved vertex buffer for all instance data.

Tessellation

  1. Tessellation
    1. 曲面细分

Geometry shading

Tiling

  1. Effective triangulation
    1. 因为tiling是1616 片段光栅化最小单位是22的,,用更少的三角形覆盖必要的像素点。减少小三角、窄长三角。
    2. DO
      1. 最好是等边三角形。最大化类面积与边缘长度的比率,
    3. Dont
      1. 不要使用triangle fans ,因为中心具有非常高的三角形密度,给个三角形的像素覆盖率低,2*2碎片浪费多。
    4. Debuging
      1. Graphics Debugger包含网格可视化工具

Fragment shading

  1. Efficient render passes
    1. 过程的开始是,初始化gpu内的 tile memory,最终才会写入到主存。中间过程是不可见的。
      移动端TBR
    2. do

      1. claer 附件color/depth/stencil 是清理tilememory的最快方式
      2. use scissor box 绘制局部区域。
  2. Multisampling
    1. mobliegpu的 mass是很高效的,因为tile足够小可以全部on chip gpu memory ,不依赖主存。
    2. DO
      1. 使用4*4的MSAA,它不贵。
      2. EXT_multisampled_render_to_texture 开启渲染到纹理抗锯齿的扩展。不要使用glBlitFramebuffer做多重采样。
  3. Multipass rendering[vulkan_only]
    1. A major feature of Vulkan is multipass rendering 。 Mali GPUs are able to take color attachments and depth attachments from one subpass and use them as input attachments in a later subpass without going via main memory. color和depth作为下个renderpass的输入,不需访问主存。
  4. HDR rendering
  5. Stencil updates
  6. Blending
    1. 在mali上很快因为是on-clip-memory
    2. do
      1. 不透明时关闭混合
      2. 关注混合层数
      3. 透明和不透明分开绘制
    3. dont
      1. Use blending on floating point framebuffers.

Buffers

  1. Buffer update

Textures

  1. Sampling performance
    1. 低精度、双线性插值、使用纹理、分辨率要低

Image processing

  1. GPU用于计算时,不要放弃

Shader code

  1. Minimize precision
    1. Use for inputs, outputs, variables, and samplers where possible.
  2. Vectorize code
  3. Vectorize memory access
  4. Manual optimization
    1. Use the built-in function library where possible
  5. Branches
    1. 分支是昂贵的,遇到分支会执行多次,最终组合出结果,因为gpu的core资源的富裕的。

System integration

  1. EGL buffer preservation
    1. rendering starts with a full screen blit from the window surface for frame n in to the window surface for frame n+1. 这个copy是低效的么?
  2. Android blob cache size
    1. 序列化 缓存 shader compilation and linkage
    2. do
      1. Increase the size of the Android blob cache; for example, to 512KB or 1MB per application

ARM_Tools_Profiling_and_Debugging_your_Games_on_Mobile_Platforms.pdf

图形是让事物看起来很好。优化就是用最少的计算工作量使事情看起来很好。优化对于计算能力和内存带宽受限的移动设备来说尤为重要,以节省能源。

对于图形应用程序,这通常意味着修改应用程序以使其更快、效果更好。fast、better、电能、内存、包体积。
一致的帧速率通常比高帧速率更重要。与相对较低但一致的帧速率相比,变化的帧速率给人的印象更差。

渲染层和游戏逻辑层脱离。比如pico如果不跟手。

从业务层可感知的 指标

Optimization can have different objectives, such as:
• Increase the frame rate.
• Make content more detailed.
• Reduce power consumption.
— Use less memory bandwidth.
— Use fewer clock cycles per frame.
• Reduce memory foot print.
• Reduce download size.

不同的优化之间经常是关联的。
优化为高帧率然后以低帧率运行,这样可减少power

对应技术点 问题

优化方案

问题

Graphic性能优化主要存在的问题

CPU bound 限制

GPU
顶点着色
片段着色
带宽

延迟架构和同步架构的区别在于是否串行

延迟架构中gles的gl调用的buffer是在gpu内,vk的调用有nativeapi层的cmdbuffer机制,减少类用户空间到内核空间以及驱动层的链路成本,减少类CPU损耗。

CPU Bound
减少drawcall类型
合并同类drawcall,数据合并

手段

How to reduce the CPU and system workload
Fragment Bound and Bandwidth Optimizations
Overdraw

你可能感兴趣的:(MaliGpu最佳实践)