【unity】shader优化总结-转载

news2024/11/26 20:28:59

分为三个部分:Unity官方文档,GDC,个人经验。

Unity Manual

1.计算量优化。着色器进行的计算和处理越多,对性能的影响越大。针对不影响最终效果但依然进行计算的无效代码,进行移除操作。计算的频率也会影响游戏的性能。通常,像素着色器比顶点着色器的执行次数要多。在可能的情况下,将计算从像素着色器移动到顶点着色器,或将它们完全在着色器移除,在脚本中计算并传递给着色器。

2.表面着色器优化。Unity提供的表面着色器非常适合编写与光照交互的着色器。针对特定情况设置关键字以使着色器效率更高或减小体积:

  • approxview使用逐顶点而不是逐像素的规范化观察向量。虽然是近似值,通常足够使用。
  • 镜面反射着色器类型使用halfasview更快。计算半角向量并逐顶点进行规范化,并且光照函数使用半角向量而不是观察向量作为参数。
  • noforwardadd着色器仅完全支持前向渲染中的一个定向光源。其余的光源仍然可以有逐顶点光照或球谐的效果。减少了着色器大小,即使存在多个灯光始终只渲染一次。
  • noambient禁用着色器的环境光和球谐光照。

3.计算精度优化。当使用CG / HLSL编写着色器时,存在三种基本的数字类型:float(32bits)half(16bits)fixed(11bits)

  • 对于世界空间位置和纹理坐标,使用float精度。
  • 对于其他一切(矢量,HDR颜色等),首先使用half精度,必要时增加精度。
  • 对于纹理数据的非常简单的操作,使用fixed精度。

实际上,应该使用哪种数据精度取决于平台和GPU。一般来说:

  • 所有现代桌面级GPU总是以完全float精度进行计算,float/half/fixed在底层是完全相同的。因此在Unity编辑器中(即使切换为移动平台),难以确定半/固定精度是否足够,因此请始终在目标设备上测试着色器以获得准确的结果。
  • 移动GPU具有实际half精度支持。通常更快,并且使用更少的功率来进行计算。
  • Fixed精度通常仅对较旧的移动GPU有效。大多数现代GPU(支持OpenGL ES 3.0或Metal)内部处理fixedhalf精度完全相同。

4.Alpha Testing优化。固定函数AlphaTest - 或其可编程等价函数clip()- 在不同平台上具有不同的性能表现:

  • 通常,在大多数平台上使用它来移除的完全透明像素时,有些许性能优势。
  • 但是,在iOS和某些使用PowerVR GPU的Android设备上,alpha testing是资源密集型的。不要试图在这些平台上使用它进行性能优化,会导致游戏运行速度比平常慢。

5.Color Mask优化。在某些平台上(主要是iOS和Android设备中的移动GPU),使用ColorMask忽略某些通道(例如ColorMask RGB)可能是资源密集型的,因此请在必要时才使用。

GDC

GDC2013和GDC2014上介绍了DX10和DX11上PC和Console上的底层着色语言优化,将优化放在减少着色器指令数量上面。

GDC2013:http://www.humus.name/Articles/Persson_LowLevelThinking.pdf

GDC2014:http://www.humus.name/Articles/Persson_LowlevelShaderOptimization.pdf

个人认为,在PC和Console平台上对于指令数量的优化意义并不大。但是在移动平台,指令数量的优化还是有必要。虽然SM3.0指令数量已经基本不会对着色器编写复杂度进行限制,但是如果要求支持SM2.0,96条指令数量要求十分严苛。

由于着色器指令的优化与硬件(HW)关系密切,因此我们需要根据硬件厂商提供的相关文档进行优化。移动平台的三大GPU品牌,分别是PowerVR,Mali,Adreno。PowerVR有专门的GLSL优化文档,Mali和Adreno也有相关文档提到这部分内容。

 但这样做,必然会增加着色器变体数量,因为我们要使用关键字来选择执行不同的代码,这会生成不同的着色器变体。

根据PowerVR Low Level GLSL Optimisation,我这里列举一些优化的方式。至于Mali和Adreno的优化,需要参考其开发文档进行。

通常来讲,在PowerVR上的Shader性能取决于执行Shader的周期次数。PowerVR Rogue架构提供了多种选择用于在USC ALU管线中的单一周期执行多个指令。

从下图可以看到,在一个周期内,可以执行最多三个Phase。为了高效的利用ALU,按照下面的规则,重新排列我们的GLSL代码是明智的。

指令优化

1.MAD

上图可以知道,MAD和MUL/ADD均占用一个Phase,但是MAD却执行了a*b+c的计算,这想当于一个Phase执行了一次乘法和加法。将表达式是改为MAD形式,会减少50%的周期消耗。

2.Division

将除法写为乘以除数的倒数(rcp)的形式,对优化有帮助。同样的,简化表达式也会获得额外的性能增加。

3.Sign

sign(x)的计算是这样的:返回 -1 if x<0; 0 if x =0;1 if x >0.

如果不需要x=0的情况,那么最好的方式是自己实现。

4.Rcp/Rsqrt/Sqrt

在PowerVR Rogue架构中,倒数操作是直接一条指令支持的。

rsqrt()也同样是硬件支持的。

sqrt()在另一方面是以1/(1/sqrt(x))的方式实现的,因此它占用两个循环。

一般来说用替代的实现x*1/sqrt(x)实现sqrt的功能。

同样是两个周期,使用替代实现更好的唯一情形是结果会被测试。在这种情况下,测试指令刚好放入第二条指令中。

5.Abs/Neg/Saturate

在PowerVR架构中,修饰符如abs(),neg()和clamp(…,0.0,1.0)(相当于saturate())的优势是很重要的,因为在特定的情况下,他们没有消耗。abs()和neg()如果用于操作的输入,是无消耗的。在这种情况下,他们被编译器转换成无消耗的修饰。saturate()相反,当用于操作的输出的时候,被转换为无消耗的修饰。

但是对于复杂的或者采样/插值指令却不符合这个规则。换句话说,对于纹理采样输出,或者复杂的指令输出,saturate()并不是无消耗的。当这些函数没有使用时,它们可能会引入额外的mov指令,这些指令可能会影响着色器的循环计数。

使用clamp(…,0.0,1.0)而不是min(…,1.0)和max(…,0.0)也有利于优化。这令原有的测试指令变为saturate修饰符。

之后,对于复杂函数,他们被译为多个操作并且因此在这个情形下,修饰符的位置就十分重要。比如,规范化函数normalize(),它的实现。

正如所看到的,在这种情况下,最好是对最终乘法的一个输入取负,而不是所有情况下的都对输入取负,或者创建一个临时的负值输入:

6.Exp/Log

在PowerVR Rogue架构,2^n操作是一条指令支持的操作。

Log2()同样。

Exp()与Exp2()的实现不同,占用两个循环。

Pow(x,y)的实现如下,需要三个周期。

7.Sin/Cos/Sinh/Cosh

Sin,Cos,Sinh,Cosh在PowerVR架构上有适度的四个周期的低消耗。它们被分解为fred*2+fsinc+一个条件。

8.Asin/Acos/Atan/Degrees/Radians

如果实现了数学表达式的简化,之后的这些函数通常不会被用到。因此,它们并不会精确的映射到硬件。这意味着这些函数有者非常高的消耗,并且在任何时候都应该避免使用。

Asin()耗费多达67个周期。

Acos()耗费多达79个周期。

Atan()依然比较耗,但是如果需要的话还是可以使用的。

虽然degrees和radians只有一个周期,但如果只使用弧度进行计算,通常是可以避免的。

9.Vector*Matrix

Vector*Matrix有一个相对比较合理的开销,不管需要发生的计算数量。优化例如会知道w=1的优势,但并不会降低开销。

10.Mixed Scalar/Vector math

Normalize()/length()/distance()/reflect()等函数内部通常会包含许多的函数调用例如dot()。知道这些函数是如何实现的是一个优势。

例如,如果我们知道两个操作有共享的子表达式,我们可以减少周期数量。然而,这只在如果输入顺序允许的情况下发生。

手动的展开这些复杂的函数有时可以帮助编译器优化代码。

同样的,在展开形式组合向量和标量指令也可能得到优化。

下面列举一些复杂指令的展开形式。

cross()可以扩展为:

distance()可以扩展为:

dot()可以扩展为:

faceforward()可以扩展为:

length()可以扩展为:

normalize()可以扩展为:

reflect()可以扩展为:

refract()可以扩展为:

11.Operation grouping

将标量和向量操作分别组合是有利于优化的。这样编译器可以将更多的操作打包到单一的周期中。

FP16概述

1.FP16精度和转化

当简化的精度满足的时候,FP16的管线工作的不错。然而,依然建议经常检查优化后的结果会不会出现精度瑕疵。当16位的浮点精度硬件可用,并且着色器使用中精度的时候,16位与32位的转化使用修饰符是无开销的,因为被USC ALU管线包含了它。

然而,当着色器不使用16位指令或者例如早期的Rogue硬件硬件不包含16位浮点管线,指令只会在常规的32位管线执行并且因此也不会有转化发生。

2.FP6 SOP/MAD operation

FP16 SOP/MAD管线是PowerVR ALU管线最强大的地方之一。如果使用得当。它允许开发者打包更多到操作到单一周期中。这可以提高性能并降低功率消耗。

单一周期的FP16 SOP/MAD操作可以被以下的伪代码描述:

输入应用各种修饰符(abs(),negete(),oneminus())和输出应用clamp()也是合适的。下一小节介绍如何完全的利用FP16 SOP/MAD管线。

3.利用FP16 SOP/MAD管线

PowerVR Rogue架构有一个强大的为常规图形操作优化的FP16管线。这节描述了如何利用FP16管线。注意转换输入到FP16之后转换输出到FP32是零开销很重要。

对SOP/MAD你有许多的选择。在一个周期中,你可以执行2个SOP操作或2个MAD操作或1个MAD+1个SOP操作。二选一的,你可以在单一周期执行4个FP16 MAD操作。

在单一周期执行4个MAD:

SOP表示乘法的结果之间选择一个操作的点积之和:

这里OP可以是一个加法,减法,min()或者max():

你也可以对输入应用取负,abs()或者clamp()(saturate)中的任一:

最后,你也可以对最终结果应用clamp()(saturate):

在应用完所有的知识之后,我们可以通过使用单一周期的任何事情来炫耀我们的管线功率:

经验

1.将一些计算烘焙到纹理

具体来讲,就是使用纹理读取的方式减轻运算量。在一般硬件,采样操作占用一个周期。如果将BRDF的D/F/G等计算烘焙到一张RGBA的四个通道中,我们只需要计算输入的几个点积结果以及粗糙度等参数,通过采样纹理得到计算结果(或者是中间结果)。这部分的操作比较灵活。在不追求计算精确的情况下,以空间换时间。

2.计算转移的思考

由Unity的官方手册优化建议第一条,我们可以知道,在Shader编写中,我们可以知道有些计算,在不影响表现的情况下,是可以放到三个部分中的,顶点着色器,片段着色器以及脚本中。顶点着色器和片段着色器,分别是逐顶点和逐像素来进行计算的。而脚本中,是每一帧计算的(Update函数)。
那把计算放到哪里更能优化性能?Unity的官方文档给出的建议的脚本优于顶点着色器优于像素着色器。

在不考虑剔除的情况下:

顶点着色器:逐顶点计算,计算次数等于顶点数。
片段着色器:逐像素计算,计算次数等于像素数。
脚本:逐帧计算,每帧计算一次。
从计算次数上来看效率,脚本>顶点着色器>片段着色器。

然而区别是,顶点着色器和片段着色器是Shader内部的计算,运行在GPU上。计算从片段着色器移动至顶点着色器使得性能得到优化是没有疑问的。而脚本的计算则是运行在CPU上,计算得到的结果传递给GPU也会有性能的开销。
举两个极端的例子:
模型1:超高精度模型,模型顶点数1000W。(Nvidia的技术展示Demo)
模型2:Quad,模型顶点数4。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1492896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

增肌_锻炼

目录 练第一步 有氧运动关节活动度 第二步 脊柱侧弯吃 练 https://www.bilibili.com/video/BV14v4y1G7A3 第一步 有氧运动 有氧运动锻炼心肺 最大心率保持在50% - 60% 关节活动度 髋关节活动 亚足背屈   绕肩&#xff0c;肩环绕肩   第二步 高频的中等强度&#xf…

【QT】菜单栏/工具栏/状态栏的应用

QMainWindow 菜单栏&#xff08;menuBar&#xff09;—只有一个 打开对话框 connect(ui->actionOpen,&QAction::triggered,this,[](){ //打开文件通常有一个返回值 //过滤条件&#xff0c;对打开的文件进行过滤QString…

【三维重建】相移法+格雷码

本篇文章介绍一种稠密点云的获取方式——条纹结构光三维重建算法。 在学习此算法前&#xff0c;我们需要对基于视觉的三维重建算法有一定了解。 需要了解什么是相机模型、相机标定以及三角化的相关知识。 【三维重建】摄像机几何-CSDN博客 【三维重建】摄像机标定&#xff…

AlibabaCloud微服务:Linux 部署 Sentinel 流量控制

目录 一、实验 1.环境 2.Linux 部署 Sentinel 3. 微服务接入Sentinel配置 二、 问题 1.Linux本地启动Sentinel控制台 2.JDBC连接失败 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统软件版本IP备注Linuxopenjdk 1.8.0192.168.204.200 maven3.5.0nac…

【QT】QDialog/ QMessageBox/提示对话框/颜色(文字)------对话框

QDialog—对话框 什么是对话框&#xff0c;如下样式 非模态对话框&#xff0c;即打开以后&#xff0c;我还可以对其他框进行操作。 模态对话框&#xff0c;打开以后&#xff0c;其他框都不能再操作了 模态对话框是阻塞对话框 QDialog dig(this);//显示模态对话框dig.exec();…

数据库-Mysql-读写分离(Atalas,Mysql-Router,Mysql-Proxy)

Atalas 这个是很老的了&#xff0c;了解即可。 wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm rpm -ivh Atlas-2.2.1.el6.x86_64.rpm #安装后的目录 cd /usr/local/mysql-proxy配置 /usr/local/mysql-proxy/bin/encrypt roo…

【Bugs】java: 错误: 不支持发行版本 xx

文章目录 报错场景&#xff1a;报错原因&#xff1a;解决方法&#xff1a; 报错场景&#xff1a; IDEA运行Java项目报错&#xff0c;点击运行之后&#xff0c;IDEA在编译代码的时候就出现报错&#xff1a; 报错类型一&#xff1a;java: 错误: 不支持发行版本 21报错类型二&am…

H12-821_131

131.如图所示&#xff0c;R1、R2、R3和R4运行OSPF&#xff0c;缺省情况下该网络中选举________个DR。&#xff08;请填写阿拉伯数字&#xff09; 答案&#xff1a;3 注释&#xff1a; DR是链路上的概念&#xff0c;使用路由器接口的IP地址表示。链路的网络类型是广播网络类型或…

钉钉h5应用 globalthis is not defined vite client

钉钉h5应用 globalthis is not defined vite client problem 背景 钉钉h5应用使用 vue3 vite 构建的前端工程 问题 h5页面在pc端浏览器和pc端钉钉打开正常h5页面在移动端钉钉打开异常 页面空白 通过调试工具找到报错信息 globalthis is not defined vite client reason …

flutter插件市场,字节大牛耗时八个月又一力作

目录 触摸事件分发机制view渲染机制常用view布局ViewGroup自定义View实战 高级UI晋升 1.android的事件分发机制 2.Android面试题——View篇 3.自定义View面试题&#xff01; 4.布局ViewGroup 5.Android自定义View实战 最后 其实Android开发的知识点就那么多&#xff0c;面试…

低代码:数智化助力新农业发展

随着科技的飞速发展和数字化转型的深入推进&#xff0c;低代码开发平台正逐渐成为软件开发的热门话题。尤其在农业领域&#xff0c;低代码技术为传统农业注入了新的活力&#xff0c;助力新农业实现高效、智能的发展。 低代码开发平台的概念与特点 随着科技的飞速发展&#xff0…

Sublime Text 格式化Json文件 之 Pretty Json

需要使用到 Pretty Json插件。 一、安装方法 sublime 下&#xff0c;按快捷键 Comand control p&#xff0c; 输入install Package,然后回车 等几秒钟&#xff0c;加载启动进程完毕后弹出的页面中输入pretty json, 然后回车 等待几秒钟&#xff0c;可以查看Sublime 最下面的…

《UE5_C++多人TPS完整教程》学习笔记27 ——《P28 项目资产(Assets for The Project)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P28 项目资产&#xff08;Assets for The Project&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译…

如何查询docker镜像的最新版本

查询Docker镜像的最新版本通常有两种方式&#xff1a; 通过Docker CLI在本地查询&#xff1a; 如果你已经拉取过某个镜像并且想要查看本地是否已经有该镜像的最新版本&#xff0c;可以使用docker images命令列出所有本地镜像及其标签&#xff08;即版本&#xff09;。但请注意&…

各中间件性能、优缺点对比

参考资料&#xff1a; Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点&#xff1f;

十三、类的继承、访问级别

类的继承与访问控制 类的继承 使用sealed修饰的类&#xff0c;是私有类&#xff0c;不能作为基类使用C#中一个类&#xff0c;只能有一个父类&#xff0c;但是可以实现多个接口子类的访问级别不能超过父类的访问级别 using System; using System.Collections.Generic; using S…

Mysql实战(1)之环境安装

1&#xff0c;进入&#xff1a;MySQL :: MySQL Downloads 2&#xff0c; 3&#xff0c; 4&#xff0c;

【Linux】磁盘情况、挂载,df -h无法看到的卷

文章目录 解决挂载、解决挂载完重启就消失1、查看linux下的硬盘挂载的空间、使用空间2、查看没有挂载的硬盘是否检测在系统中3、挂载 &#xff08;挂载完&#xff0c;要在/etc/fstab 下面配置挂载信息 要不然重启挂载就消失了&#xff09; 解决挂载、解决挂载完重启就消失 linu…

全局渐变滚动条样式

效果如下&#xff1a; APP.vue<style> /* 整个滚动条 */ ::-webkit-scrollbar {width: 5px;height: 10px; } /* 滚动条上的滚动滑块 */ ::-webkit-scrollbar-thumb {background-color: #49b1f5;/* 关键代码 */background-image: -webkit-linear-gradient(45deg,rgba(255,…

鸿蒙4.0-DevEco Studio界面工程

DevEco Studio界面工程 DevEco Studio 下载与第一个工程新建的第一个工程界面回到Project工程结构来看 DevEco Studio 下载与第一个工程 DevEco Studio 下载地址&#xff1a; https://developer.harmonyos.com/cn/develop/deveco-studio#download 学习课堂以及文档地址&#x…