为什么每一帧都清除画布会提高性能?
为什么每一帧都清除画布会提高性能?
是否需要glClear
在绝大多数的渲染代码中,都会在每一帧绘制前去清空画布(OpenGL的glClear,或Metal的MTLLoadActionClear)。今天和一个朋友聊到这里,他就怀疑这是一个冗余操作,实际上他做渲染相关很久了,我没想到他竟然会觉得这是错的。我和他争论的焦点是每一帧都清空画布是否适合所有平台(我是做iOS,他做PC),他的核心论据是他声称以前看过一个论坛的文章,在GPU操作时尽量减少glClear是有益的。说实话他这么一说我就虚了,毕竟PC上的驱动版本繁杂,反而我有主观臆断的嫌疑,我几乎要被他说服。
转念一想,我记得WebKit就会在绘制前清空画布,这种级别的库应该不会犯错吧。休战一天后,我查了大量资料,确认每一帧绘制前清空画布是必要的。
glClear的实现
其实他说的论点也对,只是针对比较老板本的驱动才有效。
早期的实现,名副其实:它会写FBO对应的显存,改成你设定的值,在混合时一来一回显然这是一个比较重的操作。
目前的实现,名不副实:它只是标记对应的显存时clear状态,当后续的操作去读取时,会返回一个on-fly的值,这个值就是你的设定值。这个过程实际上并没有真的占用总线,因为没有什么实质的操作,在GPU上就完成了。
也就是说就算在IMR下,调不调glClear的差别不大,你就算调了,也只是多了一个标记内存的操作,这在硬件层面不算个事。但是在TBR/TBDR上,情况有所不同。
TBR/TBDR
在TBR/TBDR的GPU架构下,tile在每次渲染前会读取FBO的值,再这个基础上做绘制,最后把结果写到屏幕数据(或者是写到新的FBO)上。
这么做的原因是GPU默认你需要上一帧的画面,来完成混合等操作,这部分工作是在tile中完成的。
而glClear会省去tile读取上一帧数据的操作,也就是图中的第2个步骤。这样就少了一次GPU通过总线读显存的操作,这样会提升GPU帧率和减少GPU发热,毕竟移动端的显存带宽小是GPU操作的一大掣肘。
glClear很有必要
由上,在一个渲染模块中,每一帧渲染前都clear都是合理的,因为它在最差的情况下,也只是和不clear性能相当。