PowerVR平台的流控制——着色器优化

作者:Tom Lewis

今天我们要介绍的是新的文档网站中又一个知识点:着色器中的流控制和分支,这个系列涵盖了从mipmappingGPU负载均衡等一系列话题,我们很高兴大家能一直喜欢这些内容,从流量统计数据来看大家都会花一定的时间来浏览这个网站,这看起来太棒了。

对于那些不了解的用户, docs.imgtec.com这个网站为图形技术开发人员提供了丰富的资料,比如

那些正在使用PowerVR硬件进行开发的人员肯定会从这个网站受益匪浅,而且其他人也肯定能找到一些感兴趣的东西,为什么不打开网站看看呢?

前面的介绍告一段落,下面让我们了解一下PowerVR性能优化建议:着色器中的流控制。

介绍

我们先从好的消息开始:PowerVR硬件默认支持顶点元素和着色器片段的流控制,也就是说不需要显示的启用任何扩展。

太好了,那么什么是流控制呢?

其实流控制就是使用if、else、for等语句通过分支或循环控制着色器的执行路径,这通常会导致着色器中出现多个分支路径,这些分支路径是基于某种条件来执行的,在为CPU编程时流控制是一个非常基本的概念,但是由于GPU的高度并行特性,它在着色器中的处理要稍微复杂一些。

下面是一个分支处理的例子,PowerVR SDK提供了着色器片段处理的一个示例:GaussianBlur

mediump float imageCoordX = gl_FragCoord.x - 0.5;
mediump float windowWidth = config.x;
mediump float xPosition = imageCoordX / windowWidth;
mediump vec3 col = vec3(0.0);
if(xPosition < 0.5)
{
    col = texture(sOriginalTexture, vTexCoords[NumGaussianWeightsAndOffsets]).rgb;
}
else if(xPosition > 0.497 && xPosition < 0.503)
{
    col = vec3(1.0);
}
else
{
    col = Weights[0] * texture(sTexture, vTexCoords[0]).rgb +
          Weights[1] * texture(sTexture, vTexCoords[1]).rgb +
          Weights[2] * texture(sTexture, vTexCoords[2]).rgb +
          Weights[3] * texture(sTexture, vTexCoords[3]).rgb +
          Weights[4] * texture(sTexture, vTexCoords[4]).rgb +
          Weights[4] * texture(sTexture, vTexCoords[5]).rgb +
          Weights[3] * texture(sTexture, vTexCoords[6]).rgb +
          Weights[2] * texture(sTexture, vTexCoords[7]).rgb +
          Weights[1] * texture(sTexture, vTexCoords[8]).rgb +
          Weights[0] * texture(sTexture, vTexCoords[9]).rgb;
}
oColor = vec4(col , 1);

在上面的示例中,执行路径取决于xPosition,xPosition表示的是屏幕水平向的位置,因此可以使用条件分支对图像的后半部分执行不同的处理,这个分支的结果可以在下面的例子中清楚的看到。


一般来说当我们在着色器中讨论流控制时通常指的是一下两种情况:

静态流控制

在这种情况下着色器代码中会有两个或多个分支路径,这些分支路径是根据某个统一变量的值有条件的选择,统一变量在所有顶点元素/片段上是相同的,所以同一个着色器在一个绘制调用中会处理所有顶点元素和着色器片段。

静态流控制有时被用来将许多小的着色器合并成一个大的着色器(超级着色器),然后在运行时有条件的选择要执行的着色器,然而通常更好的解决方案是编译期间使用预处理指令从超级着色器生成多个着色器,这意味着你可以从单个源文件创建多个着色器。

动态流控制

这个有点复杂,同样动态流控制的着色器也有很多的分支执行路径,但是控制分支的条件在每个顶点元素或每个片段基础上都可能发生变化,通常要取决于纹理或顶点的属性,这意味着着色器可能不得不执行从一个顶点元素或片段到下一个顶点元素的不同路径。

为什么这是个问题呢?图形处理器的内核遵从单条指令、多数据架构(SIMD),这意味着内核中所有处理器必须在同一时间执行相同的指令,如果一个图形核心正在执行一组着色器的调用(例如当一个片段着色器正在处理一组片段时),那么所有的调用都必须遵循相同的路径,这意味着在分支执行的过程中处理器要花费一些时间来执行它们实际上并不需要的指令,这对性能的影响比静态流控制更加不可预测。

PowerVR GPU的性能建议

我们介绍了关于流控制的一些内容,下面是我们的一些建议:

在条件分支中避免舍弃一些情况

在使用PowerVR平台进行开发时通常最好避免舍弃一些分支情况,在片段着色器中舍弃功能则否定了PowerVR TBDR架构的一些关键优势。

这主要影响隐藏表面的去除(HSR),因为这个操作假设一个不透明的对象的所有碎片元素都被绘制出来,遮挡它们后面的所有对象。如果片段可能被丢弃在片段着色器中,硬件功能就不可能再这样做了,这意味着GPU必须等到片段着色器完成后才能确定哪些片段是可见的,这将是基于分片延迟渲染技术(TBDR)的“延迟”功能失效,并可能降低PowerVR上应用程序的性能。

我们的建议是采用Alpha混合渲染技术

避免在条件分支中对纹理资源进行采样操作(仅限PowerVR Series5和Series5XT系列)

我们使用PowerVR Series5和Series5XT系列开发时要避免在分支上对纹理进行读取操作,在动态分支执行中使用采样器可以作为依赖的纹理资源读取。

当用于采样纹理的坐标依赖于着色器中的某些计算而不是随机变化时将会执行依赖纹理的读取操作,在正常的纹理资源读取操作中,硬件可以在片段着色器启动之前获取纹理数据,从而减少采样操作的延迟。在对依赖纹理的读取中无法提前预测纹理坐标,因此无法预读取纹理数据,从而导致更大的延迟,这对性能会有明显的影响。

从PowerVR Series6系列开始,依赖纹理资源的读取变得更加高效,因此这对于整个架构来说并不重要,但是当你试图优化应用程序时每一点性能的提升都会有所帮助。

尝试试用分支控制来省去一些不必要的操作

最后使用条件分支来省去一些不必要的操作是非常好的主意,这将在大量满足条件的情况下对性能产生更大的影响。

面向OpenGL ES 3.0的着色器优化

如果你正在使用OpenGL ES 3.0图形库并希望优化着色器的一些分支,那么很有必要了解下这个扩展:GL_EXT_shader_group_vote。

为了说明这个扩展如何工作的,我们先来看一下基本的分支操作:

if (condition)
    result = do_fast_path();
else
    result = do_general_path();

如前文所述,图形处理器内核中的着色器调用集必须执行相同的代码路径,在上面的示例中,如果该组中单个调用的条件为True,那么就在该特定调用上执行do_fast_path()操作,这使得其他的调用在等待do_fast_path()返回时处于休眠状态,一旦do_fast_path()返回一个值,其余的调用就可以调用do_general_path()操作了。

这样操作代价有一点儿大,因为着色器通过执行快速路径和常规路径会浪费资源,相反我们可以修正上述代码使用新的内置函数,具体扩展如下:

if (allInvocationsEXT(condition))
    result = do_fast_path();
else
    result = do_general_path();

函数allInvocationsEXT()只在整个调用集满足给定条件时才返回True,这非常有用,因为它将返回组中所有调用的值,限制组中只能执行do_fast_path()或do_general_path(),但不能同时执行这两种方法。

GL_EXT_shader_group_vote还提供了其他两个内置函数,比如alInvocationsEXT(),它在同一组中的所有调用中返回相同的值。

具体如下:

  • anyInvocationEXT(bool value)-如果组中至少有一个调用的值为True,那么就返回True。
  • allInvocationsEqualEXT(bool value) – 如果组中所有调用的值相同,那么则返回True。

总结….

想要了解更多关于PowerVR 性能建议和其他开发相关的讯息,请访问我们的文档网站docs.imgtech.com,我们会定期更新网站内容。

也可以在我们的论坛社区留言反馈您的建议。

大家还可以在推特上关注@tom_detech获得最新的开发者技术相关的新闻,或者关注@powervrinsider获取PowerVR技术最新的内容。

原文链接:https://www.imgtec.com/blog/flow-control-on-powervr-optimising-shaders/

声明:本文为原创文章,转载需注明作者、出处及原文链接,否则,本网站将保留追究其法律责任的权利。

推荐阅读