MALI Tile-based rendering简单原理介绍(

2020-07-21  本文已影响0人  雄关漫道从头越

MALI Tile-based rendering简单原理介绍

写在最前

关于mali的架构的一点深入了解,将现有的GPU的基本流程和mali的做对比,提出其中的优点与缺点。原文地址:https://developer.arm.com/graphics/developer-guides/tile-based-rendering

传统GPU

传统GPU的架构一般被称为Immediate mode GPU.主要的流程就是vertex shader 和 fragment shader顺序执行,伪代码如下:

for draw in renderPass:
    for primitive in draw:
        for vertex in primitive:
            execute_vertex_shader(vertex)
        for fragment in primitive:
            execute_fragment_shader(fragment)

数据流是这样的:

传统GPU

优点

主要优点就是vertex的输出能够留在片上,可以被下一阶段直接快速读取。

缺点

如果有很大的图形(主要是三角形)需要被渲染,那framebuffer就会很大,比如对于整个屏幕的颜色渲染或者深度渲染就会消耗很多存储资源,但是片上是没有这么多资源的,因此就要频繁读取DDR。很多和当前frame有关的操作( 比如blending, depth testing 或者 stencil testing)都需要读取这个working set,因此需要的带宽是很大的,并且这样能耗也很高,对于移动设备来说,这种方式很不利于设备运行。

Tile-based GPU

因此mali的GPU提出了Tile-based概念,就是将图像分成16*16的小块。分小块进行渲染,最后写入到DDR,就能够减少读写DDR的频率,进而解决上述问题。不过分块需要知道整个图像的几何学信息,所以操作分成了两步:

  1. 第一步执行几何学相关的操作,并产生tile list.
  2. 第二步对每一个tile执行fragment操作,完成之后写入内存

伪代码如下:

# Pass one
for draw in renderPass:
    for primitive in draw:
        for vertex in primitive:
            execute_vertex_shader(vertex)
        append_tile_list(primitive)

# Pass two
for tile in renderPass:
    for primitive in tile:
        for fragment in primitive:
            execute_fragment_shader(fragment)

数据流如下:

maliGPU

优点

显而易见,解决了传统模型的带宽问题,因为fragment shader每次都是读取一个小块放在片上,不需要频繁读取内存,直到最后操作完成,再写入内存。甚至还能够通过压缩tile的方法进一步减少对于内存的读写。另外在图像有一些区域固定不动的时候,通过调用函数判断tile是否相同,减少重复的渲染。

缺点

这个操作需要在vertex阶段之后,将输出的几何数据写入到DDR,然后才被fragment shader读取。这之间也就是tile写入DDR的开销和fragment shader渲染读取DDR开销的平衡。另外还有一些操作(比如tessellation)也不适用于Tile-based GPU。

总结

现在屏显的分辨率越来越大从1080p到1440p再到4K,可以遇见的,mali这种架构将在未来大规模使用。

不过也有一些陷阱,开发者需要避开。首先是要合理设置render pass以充分利用这种架构的特点;其次要了解这种几何学分割所能得到的好处。

上一篇下一篇

猜你喜欢

热点阅读