高通Adreno架构应用优化(1)

24 篇文章 11 订阅
16 篇文章 13 订阅

本文开始介绍各种技巧,以帮助优化OpenGL ES应用程序和Adreno体系结构。

初始化期间构建管道

与构建Vulkan一样,着色器的编译和链接是一个耗时的过程。利用管道缓存并创建派生管道。

使用内置

内置函数是OpenGL ES着色语言规范的重要组成部分,应该始终优先于编写自定义实现。这些功能通常是针对特定的着色器配置文件和针对其的硬件功能进行了优化着色器已编译。结果,它们通常比任何其他实现都快。

gl_VertexID和gl_InstanceID已按照GL_KHR_vulkan_glsl扩展名删除,但gl_InstanceIndex可用。glPosition,gl_PointSize,gl_ClipDistance,gl_CullDistance在非碎片阶段可用。有关对Vulkan中的GLSL内置插件所做的更改的详细信息,请参考GL_KHR_vulkan扩展。

使用适当的数据类型

在代码中使用最合适的数据类型可以使编译器和驱动程序优化代码,包括配对的着色器指令。使用vec4数据类型而不是float可能会阻止编译器执行优化。小错误可能会对性能产生重大影响。

另一个示例是以下代码应采用单个指令槽:int4 ResultOfA(int4 a){返回+ 1; } 现在假设在代码中引入了一个小错误。例如,浮点数使用常数值1.0,这不是适当的数据类型。

int4 ResultOfA(int4 a){返回+ 1.0;}
该代码现在可以占用八个指令槽。变量a转换为vec4,然后,加法是在浮点数中完成的。最后,将结果转换回返回类型int4。

Pack标量常量

将标量常数打包到由四个通道组成的向量中可大大改善硬件获取效率。对于动画系统,这会增加
可用的骨头去皮。

考虑以下代码:

loat scale, bias;
vec4 a = Pos * scale + bias;

通过如下更改代码,可能会减少一条指令,因为编译器可以将行优化为更有效的指令(疯狂):

vec2 scaleNbias;
vec4 a = Pos * scaleNbias.x + scaleNbias.y;

保持着色器长度合理

太长的着色器可能会导致效率低下。如果需要在其中包含许多指令槽相对于纹理获取次数的着色器,请考虑将算法分为几个
部分。由算法的一部分生成的值可以稍后被另一部分重用存储到纹理中,然后通过纹理提取进行检索。但是,这种方法可能是在内存带宽方面昂贵。使用三线性,各向异性过滤,宽纹理格式,3D和立方体贴图纹理,纹理投影,具有不同梯度的纹理查找Lod或像素四边形上的渐变也可能会增加纹理采样时间并减少整体利益。

有效地采样纹理

为避免纹理停顿,请遵循以下规则:

  • 避免随机访问-硬件在2x2片段的块上运行,因此着色器是如果它们访问单个块中的相邻纹理像素,则效率更高。
  • 避免使用3D纹理-由于复杂,从体积纹理中获取数据非常昂贵,需要执行过滤以计算结果值。
  • 限制从着色器采样的纹理数量-单个使用四个采样器,着色器是可以接受的,但是在一个着色器阶段访问更多纹理可能会导致
    性能瓶颈。
  • 压缩所有纹理-可以更好地利用内存,从而减少了纹理在渲染管道中停顿。
  • 考虑使用mipmaps-Mipmaps可帮助合并纹理提取并有助于改进性能以增加内存使用为代价

纹理过滤可以影响纹理采样的速度。滤波器的性能取决于体系结构/芯片,在某些体系结构中,开发人员可能会发现使用双线性或最接近的滤波优于三线性或各向异性的滤波效果。 Mipmap钳位可以减少使用三线性过滤的成本,因此在实际情况下,平均成本可能较低。添加各向异性过滤乘以各向异性程度;这意味着16倍各向异性查询的速度可能比常规的各向同性查询慢16倍。但是,由于各向异性过滤是自适应的,因此仅对需要进行各向异性过滤的片段执行此匹配。总共可能只有几个片段。实际情况的经验法则是,各向异性过滤的平均成本不到各向同性的成本的两倍;立方体贴图纹理和投影纹理查找不会产生任何额外成本,而基于dFdx和dFdy的特定于着色器的渐变功能,需要额外付费。这些特定于着色器的渐变不能跨查询存储。如果在相同的采样器中使用相同的梯度再次执行纹理查找,则会再次产生成本

飞行/动态分支中的线程

分支对于着色器的性能至关重要。每当分支遇到分歧时,或线程的某些元素以一种方式分支而另一些元素又以另一分支分支时,两个分支都将使用谓词,而对于不采用给定分支的元素则使用NULL out操作。仅当数据以符合这些条件的方式对齐(片段着色器很少见这种情况)时,这才是正确的。共有三种类型的分支,按从AdrenoGPU上的最佳性能到最差的顺序列出:

  • 在已知的常数上进行分支在编译时
  • 在统一变量上分支
  • 在着色器内部修改的变量上分支在常量上分支可能会产生可接受的性能

Pack着色器插值器

着色器插值或变量需要GPR(通用寄存器)来保存馈入片段着色器的数据。因此,请尽量减少使用。在值统一的地方使用常量。打包值一起使用,因为所有变量都有四个组成部分,无论是否使用它们。将两个vec2纹理坐标放入单个vec4值是一种常见做法,但其他策略则采用了更具创意的打包和动态数据压缩

避免在着色器常数上进行数学运算

几乎所有已发布的游戏,因为着色器的问世花费了大量的指令对着色器常数进行不必要的数学运算。在着色器中识别这些指令,然后将这些计算移至CPU。在后编译的微代码中标识着色器常数的数学运算可能会更容易。

中断绘图调用

如果着色器处理GPR过多和/或处理纹理缓存需求过多,则通过将绘图调用拆分为多个遍可提高性能。结果是否会是很难预测的,因此两种方式同时使用实际测量值是确定的最佳方法。理想情况下,两次通过绘制调用将其结果与简单的alpha混合结合在一起,由于图形内存(GMEM),这在Adreno GPU上并不繁重。某些开发人员可能会考虑使用真正的延迟渲染算法,但是这种方法有很多缺点,例如,必须解析GMEM,才能将先前的通行证用作后续通行证的输入。由于解析不是免费的,因此必须在算法中的其他地方补偿性能成本。理想情况下,使用Vulkan的RenderPass将有助于最大程度地减少GMEM解析,因此重组渲染算法以使用尽可能多的子遍将是最佳方法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值