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.
应用程序阶段
- Draw call batching 批量DrawCall
- CPU提交的每条绘制指令,从CPU到GPU,通道成本是昂贵和固定的。经过用户空间到内核空间再到GPU驱动最后到GPU的CommandStream中。
- 方案是 batch批处理。非应用层的commandbuffer,对于使用相同render state的多个对象的多次drawcall,合并obj数据,公用一次draw。减少每帧的drawcall总数。合并使用相同渲染状态的绘制对象,一次提交。
- DO
- Batch。即使没有CPU、帧率问题,使用batch可reduce power
- 使用VAO绘制重复物体
- gles 一帧不要超过500drawcall 。vk 2000
- Don't
- 批处理的图形过多,会影响子物体剔除、渲染顺序受损(由近到远充分发挥Dtest)。解释:视锥剔除和遮挡剔除是粗粒度、模型级别的剔除。细粒度的是深度测试。在剔除前做batch会导致子物体剔除失败、以及绘制顺序错乱导致深度测试失败引起overdraw。
- Debugging
- Profile application CPU load.
- Trace API usage and count calls per frame.
- Draw call culling 剔除
- 调用render api前剔除是最高效的。只要调用api,至少要获取\计算裁剪空间坐标NDC,然后才能剔除图元。
- Do
- 视锥剔除
- 遮挡剔除
- Find a balance between batching and culling.
- 背面剔除
- Don't
- 不考虑空间把每个obj都发送到图形API。
- Debugging
- 确认已开背面剔除,并且剔除率至少要到50%。
- framedebug确认是否渲染大量不可见三角形。
- Draw call render order。基础款eayly-z就是深度测试么?
- 为保证 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. 仅仅是
- GPU内置的 Forward Pixel Kill, 技术。绘制两次,首次仅深度更新(低模),第二次 GL_EQUAL 模式进行颜色渲染 。
- do
- Render opaque objects in a front-to-back order.
- 绘制不透明物体时关闭blend测试。Render opaque objects with blending disabled.
- Dont 会引起early-zs失效的场景 (earlyz是自动开启的还是要手动开启)
- ▪ Use discard(glsl关键字 用于条件判断后丢弃像素) in the fragment shader; this forces late-zs.
- ▪ Use alpha-to-coverage; this forces late-zs.
- ▪ Write to fragment depth in the fragment shader; this forces late-zs.
- Debugging
- GPU performance 查看像素点重绘次数是否大于1次
- check the number of fragments requiring late- zs testing,
- Avoid depth prepasses
- Forward Pixel Kill。 重复绘制带来的无效像素点片段化减少的收益,比 造成顶点着色和内存带宽的开销 是更值得的。
- Impact
- 由于重复的draw调用,CPU负载更高。(what?重复调用是 驱动层内的行为么?不是GPU上的行为)
- 由于重复的几何体,顶点着色成本和内存带宽更高。
- OpenGL ES GPU pipelining
- 移动端GPU采用延迟渲染框架。
- Do
- 应当让GPU 满负荷工作,提高利用率。减少中间的气泡
- Pipeline any use of fences and query objects; don't wait on them too early. 使用fence机制,并且不要太早的开始等待。
- Don't
- synchronous behavior 。 glfinish() glReadPixels
- Vulkan GPU pipelining
- Pipelined resource updates
- gles对上开放的是一个同步接口,但底层执行是异步,gpu执行时,cpu修改资源,存在渲染正确性问题。比如VBO \ glTexturImage2D(TODO 是异步的么)
CPU overheads
- Shader compilation
- 着色器的编译和链接is expensive 昂贵。
- DO
- 可以在游戏加载阶段进行。预编译。
- 使用pipeline cache
- Serialize the pipeline cache to disk
- Dont:
- 要避免在交互阶段进行。
- Rely on the Android blob cache for interactive compile and link performance {TODO what android blob }
- DO
- 着色器的编译和链接is expensive 昂贵。
- Pipeline creation
- Allocating memory
- OpenGL ES CPU memory mapping
Vertex shading
- Index draw calls
- allow more reuse of vertices 使用drawElements 更多的重用顶点,可以更高效。
- Do
- Don't
- 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中找到稀疏的顶点也是损耗
- Index buffer encoding
- ▪ 使用尽可能低精度的索引数据类型来减少索引列表大小。
- Attribute precision 精度
- 合适的精度,从而节约带宽并提高性能 including 8-bit, 16-bit, and packed formats such as RGB10_A2.
- DO
- 顶点位置精度用FP32,保证几何定位准确性
- 其他属性从低精度,节省动画资源包体积和带宽。
- Dont
- Upload FP32 data into a buffer and then read it as a mediump attribute
- Attribute layout
- Good buffer layout can maximize the benefit of this geometry pipeline.
- DO
- 多使用EBO drawElements
- 使用交错步幅紧凑的结构
- Varying precision
- 精度的收益,一次是由顶点着色器写入,另一次是由片段着色器读取.
- mediump(大部分场景)\highp(Texture coordinates for large textures) 有各自的最佳场景。
- dont
- 不要用和场景不匹配的精度,最好用mediump。
- 不要在VS申请Varying,但是FS中不使用。
- Impact
- Increased GPU memory bandwidth. 减少gpu内存带宽
- Reduced vertex shader and fragment shader performance. 增加shader的性能
- Triangle density
- vertext的带宽和处理成本要比fragment的处理高一个量级。所以要覆盖尽可能多的像素点,用于分摊成本。
- DO
- 每个图元要至少覆盖10~20个fragment
- 使用LOD,距离远的物体用低精度低三角化更简单的网格。
- 为了获得更好的光照效果,不是一味的增加模型精度,而是使用法线贴图烘焙技术。贴图还是走ASTC压缩问题。
- Dont
- 不要绘制微小三角形
- Instanced vertex buffers
- ▪ Use a single interleaved vertex buffer for all instance data.
Tessellation
- Tessellation
- 曲面细分
Geometry shading
Tiling
- Effective triangulation
- 因为tiling是1616 片段光栅化最小单位是22的,,用更少的三角形覆盖必要的像素点。减少小三角、窄长三角。
- DO
- 最好是等边三角形。最大化类面积与边缘长度的比率,
- Dont
- 不要使用triangle fans ,因为中心具有非常高的三角形密度,给个三角形的像素覆盖率低,2*2碎片浪费多。
- Debuging
- Graphics Debugger包含网格可视化工具
Fragment shading
- Efficient render passes
- 过程的开始是,初始化gpu内的 tile memory,最终才会写入到主存。中间过程是不可见的。
-
do
- claer 附件color/depth/stencil 是清理tilememory的最快方式
- use scissor box 绘制局部区域。
- 过程的开始是,初始化gpu内的 tile memory,最终才会写入到主存。中间过程是不可见的。
- Multisampling
- mobliegpu的 mass是很高效的,因为tile足够小可以全部on chip gpu memory ,不依赖主存。
- DO
- 使用4*4的MSAA,它不贵。
- EXT_multisampled_render_to_texture 开启渲染到纹理抗锯齿的扩展。不要使用glBlitFramebuffer做多重采样。
- Multipass rendering[vulkan_only]
- 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的输入,不需访问主存。
- HDR rendering
- Stencil updates
- Blending
- 在mali上很快因为是on-clip-memory
- do
- 不透明时关闭混合
- 关注混合层数
- 透明和不透明分开绘制
- dont
- Use blending on floating point framebuffers.
Buffers
- Buffer update
Textures
- Sampling performance
- 低精度、双线性插值、使用纹理、分辨率要低
Image processing
- GPU用于计算时,不要放弃
Shader code
- Minimize precision
- Use for inputs, outputs, variables, and samplers where possible.
- Vectorize code
- Vectorize memory access
- Manual optimization
- Use the built-in function library where possible
- Branches
- 分支是昂贵的,遇到分支会执行多次,最终组合出结果,因为gpu的core资源的富裕的。
System integration
- EGL buffer preservation
- rendering starts with a full screen blit from the window surface for frame n in to the window surface for frame n+1. 这个copy是低效的么?
- Android blob cache size
- 序列化 缓存 shader compilation and linkage
- do
- 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
对应技术点 问题
优化方案
问题
CPU bound 限制
GPU
顶点着色
片段着色
带宽
延迟架构中gles的gl调用的buffer是在gpu内,vk的调用有nativeapi层的cmdbuffer机制,减少类用户空间到内核空间以及驱动层的链路成本,减少类CPU损耗。
CPU Bound
减少drawcall类型
合并同类drawcall,数据合并