Unity中Shader指令优化

文章目录

  • 前言
  • 解析一下不同运算、条件、函数所需的指令数
    • 1、常数基本运算
    • 2、变量基本运算
    • 3、条件语句、循环 和 函数


前言

上一篇文章中,我们解析了Shader解析后的代码。我们在这篇文章中来看怎么实现Shader指令优化

  • Unity中Shader指令优化(编译后指令解析)

解析一下不同运算、条件、函数所需的指令数

1、常数基本运算

在DirectX平台,常数运算是不占指令数的。但是,稳妥起见我们最好自己计算好常数计算的结果。防止其他平台认为常数运算需要占指令。

  • Shader片元着色器中:

fixed4 frag (v2f i) : SV_Target
{
//常数基本计算
return 2 * 3;
}

  • 编译后只有一个赋值给输出结果的指令:

ps_4_0
dcl_output o0.xyzw
0: mov o0.xyzw, l(6.000000,6.000000,6.000000,6.000000)
1: ret

定义临时存储变量,也是不消耗指令数的,对性能没有影响

  • Shader片元着色器中:

fixed4 frag (v2f i) : SV_Target
{
//常数基本计算
fixed4 c = 0.2 * 3 / sin(4);
fixed4 c1 = c;
return c1;
}

  • 编译后同样只有一个赋值给输出结果的指令:

ps_4_0
dcl_output o0.xyzw
0: mov o0.xyzw, l(-0.792809,-0.792809,-0.792809,-0.792809)
1: ret

2、变量基本运算

变量的基本运算,是会使用GPU计算指令的。因为变量在计算前是未知的,会预留计算指令

  • Shader中:
  1. 属性面板定义一个四维向量

_Value(“Value”,Vector) = (0,0,0,0)

  1. 片元着色器中,使用该变量进行 加法 计算

fixed4 frag (v2f i) : SV_Target
{
//2、变量基本运算
float a = _Value.x;
float b = _Value.y;
float c = _Value.z;
float d = _Value.w;
float e = 1 + a;
return e;
}

  • 编译后(使用了加指令):

ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: add o0.xyzw, cb0[2].xxxx, l(1.000000, 1.000000, 1.000000, 1.000000)
1: ret

  1. 变量进行减法运算

e = 1 - a;

  • 编译后(使用了加指令):

ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: add o0.xyzw, -cb0[2].xxxx, l(1.000000, 1.000000, 1.000000, 1.000000)
1: ret

  1. 变量进行乘法运算(这里测试乘法,别使用 1 或 2,会自动转化为加法)

e = 3 * a

  • 编译后(使用了乘指令):

ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: mul o0.xyzw, cb0[2].xxxx, l(3.000000, 3.000000, 3.000000, 3.000000)
1: ret

  1. 变量进行除法运算

e = 3 / a

  • 编译后(使用了除法指令):

ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: div o0.xyzw, l(3.000000, 3.000000, 3.000000, 3.000000), cb0[2].xxxx
1: ret

  1. 变量进行多个相同运算

e = 3 * a * b;

  • 编译后:

ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
dcl_temps 1
0: mul r0.x, cb0[2].x, cb0[2].y
1: mul o0.xyzw, r0.xxxx, l(3.000000, 3.000000, 3.000000, 3.000000)
2: ret

  1. 变量进行乘加运算,对性能优化特别重要(特殊)

e = 3 * a + b;

  • 编译后,会使用乘加指令(把乘法和加法合并成一个指令)

ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: mad o0.xyzw, cb0[2].xxxx, l(3.000000, 3.000000, 3.000000, 3.000000), cb0[2].yyyy
1: ret

3、条件语句、循环 和 函数

  1. 条件语句

if(i.uv.x < 0.5)
{
i.uv.x = 1;
}
else
{
i.uv.x = 0;
}
return i.uv.x;

在这里插入图片描述

  • 编译后:

在这里插入图片描述
这里我们可以使用 step 函数来替代 该 条件语句
替代后,虽然编译结果一样的。但是,这是因为 条件语句 的程序体太简单
如果遇到比较复杂的 条件语句,我们可以使用 结合 step 和 算法的方法 把条件语句剔除

使用 step 函数后:

return step(0.5,i.uv.x);

  • 编译后
    在这里插入图片描述
  1. 循环语句

float e = 0;
for(int i = 0;i < 5;i++)
{
e += 0.1;
}
return e;

  • 编译后:

在这里插入图片描述

  1. mad指令优化:

优化前:

float e = (a + b) * (a - b);
return e;

  • 编译后:

在这里插入图片描述
优化后:

float e = a * a * (-b * b);
return e;

  • 编译后:

在这里插入图片描述

  1. 透过编译后的代码来直观的看出函数的内部执行(这里使用 normalize 来测试)

一维向量(常数):

float e = normalize(a);
return e;

  • 编译后:

在这里插入图片描述
多维向量归一化(编译后会使用点乘)

float e = normalize(_Value);
return e;

  • 编译后:

在这里插入图片描述

  1. abs(如果abs传入的是单一参数,就不会多用指令。但是传入式子,会多用指令)

传入式子:

float e = abs(a * b);
return e;

  • 编译后:

在这里插入图片描述
传入单一参数:

float e = abs(a) * abs(b);
return e;

  • 编译后:

在这里插入图片描述

  1. 负号可以适当的移到变量中

移动前:

float e = -dot(a,a);
return e;

  • 编译后:

在这里插入图片描述

移动后:

float e = dot(-a,a);
return e;

  • 编译后:

在这里插入图片描述

  1. 尽量把同一维度的向量进行结合运算

结合前:

float3 e = _Value.xyz * a * b * _Value.yzw * c * d;
return fixed4(e,1);

  • 编译后:

在这里插入图片描述

结合后:

float3 e = (_Value.xyz * _Value.yzw) * (a * b * c * d);
return fixed4(e,1);

  • 编译后:

在这里插入图片描述

  1. asin / atan / acos开销很大,尽量不要使用 (这里使用asin测试)

float e = asin(a);
return e;

  • 编译后
    在这里插入图片描述

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

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

相关文章

什么是事务?事务的特性是什么?

一、概念 事务是并发控制的单位&#xff0c;是用户定义的一个操作序列。 二、特性 事务具有四大特性&#xff1a;原子性、一致性、隔离性、持久性 原则性&#xff1a;事务是数据库的逻辑工作单位&#xff0c;事务中包括的诸操作要么全做&#xff0c;要么全不做。 一致性&a…

【深度学习实验】图像处理(四):PIL——自定义图像数据增强操作(图像合成;图像融合(高斯掩码))

文章目录 一、实验介绍二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 导入必要的库1. PIL基础操作2~4. 随机遮挡、随机擦除、线性混合5. 图像合成5.1 原理5.2 实现5.3 效果展示 6. 图像融合6.1 原理6.2 实现6.3 效果展示 一、实验介绍 在深度学习任务中&#xff0c…

csapp-linklab

超详细csapp-linklab之第一阶段“输出学号”实验报告-CSDN博客 csapp-linklab之第二阶段“输出学号”实验报告-CSDN博客 csapp-linklab之第3阶段“输出学号”实验报告&#xff08;强弱符号&#xff09;-CSDN博客 csapp-linklab之第4阶段“输出学号”实验报告&#xff08;swi…

wordpress主题的后台Settings API 和 Theme Customizer API开发部分

先看两个概念Settings API和Theme Customizer API Settings API和Theme Customizer API是WordPress提供的用于处理主题和插件设置的工具。它们分别用于不同的场景和目的&#xff0c;但都旨在简化在WordPress仪表板中添加设置和选项的过程。 Settings API Settings API主要用…

java_基础——ArrayList

1.ArrayList构造方法和添加方法 方法名说明public ArrayList创建一个空的集合对象public boolean add(E e)将指定的元素追加到此集合的末尾public void add(int index,E element)在此集合的指定位置插入指定的元素 import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_O…

MySQL进阶_EXPLAIN重点字段解析

文章目录 第一节.准备1.1 版本信息1.2 准备 第二节.type2.1 system2.2 const2.3 eq_ref2.4 ref2.5 ref_or_null2.6 index_merge2.7 unique_subquery2.8 range2.9 index2.10 all 第三节. Extra3.1 No tables used3.2 No tables used3.3 Using where3.4 No matching min/max row3…

【数据结构高阶】AVL树

上期博客我们讲解了set/multiset/map/multimap的使用&#xff0c;下面我们来深入到底层&#xff0c;讲解其内部结构&#xff1a; 目录 一、AVL树的概念 二、AVL树的实现 2.1 节点的定义 2.2 数据的插入 2.2.1 平衡因子的调整 2.2.1.1 调整平衡因子的规律 2.2.2 子树的旋…

JavaEE 多线程

JavaEE 多线程 文章目录 JavaEE 多线程引子多线程1. 特性2. Thread类2.1 概念2.2 Thread的常见构造方法2.3 Thread的几个常见属性2.4 启动一个线程2.5 中断一个线程2.6 等待一个线程2.7 获取当前线程引用2.8 休眠当前线程 3. 线程状态 引子 当进入多线程这一块内容时&#xff…

2023-12-03 LeetCode每日一题(可获得的最大点数)

2023-12-03每日一题 一、题目编号 1423. 可获得的最大点数二、题目链接 点击跳转到题目位置 三、题目描述 几张卡牌 排成一行&#xff0c;每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。 每次行动&#xff0c;你可以从行的开头或者末尾拿一张卡牌&#x…

【Python/Java/C++三种语言】20天拿下华为OD笔试之【哈希表】2023B-单词接龙【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录 题目描述与示例题目描述输入描述输出描述示例一输入输出说明 示例二输入输出说明 解题思路代码PythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 单词接龙的规则是&#xff1a; 可用于接龙的单词首字母必须要前一个单词的…

虚拟机扩容磁盘/dev/mapper/centos-root

虚拟机扩容磁盘/dev/mapper/centos-root 1. 在虚拟机管理界面增加磁盘大小或添加磁盘 2. 扩容操作 lsblk -l # 下面/dev/sdb 每个人的可能不同&#xff0c;有/dev/sda 或 /dev/sdc&#xff0c;根据实际更改 fdis /dev/sdb m n p 1 回车 回车 wfdisk -l pvdisplay pvcrea…

Vue.js中v-if 和 v-show 的区别

1、v-if: v-if 指令是 Vue.js 中的一个条件渲染指令。 当 v-if 的条件为 false 时&#xff0c;元素及其内容将从 DOM 中完全移除。 适用于你期望大部分时间条件为 false&#xff0c;或者当你希望通过完全移除元素来节省资源时。 2、v-show: v-show 指令同样也是一个条件渲染…

信息流广告行为兴趣定向底层逻辑算法

行为兴趣定向 1: 行为兴趣的背后是计划的数据 行为是用户在平台的动作&#xff1a;点赞、评论、分享、点击、下单、成交等&#xff0c;用户发生过的标签 兴趣不一定发生&#xff0c;我有打高尔夫的兴趣&#xff0c;但是从来没打过&#xff0c;因为穷 系统会根据用户的行为标…

C++STL中的string容器

string 容器基本概念 C 风格字符串 ( 以空字符结尾的字符数组 ) 太过复杂难于掌握&#xff0c;不适合大程序的开发&#xff0c; 所以 C 标准库定义了一种 string 类&#xff0c;定义在头文件。 String 和 c 风格字符串对比&#xff1a; u Char*是一个指针&#xff0c; …

【C++ Primer Plus学习记录】第5章编程练习

1.编写一个要求用户输入两个整数的程序。该程序将计算并输出这两个整数之间&#xff08;包括这两个整数&#xff09;所有整数的和。这里假设先输入较小的整数。例如&#xff0c;如果用户输入的是2和9&#xff0c;则程序将指出2~9之间所有整数的和为44。 //5.9 1 #if 1 #includ…

使用OpenMVS重建模型

1、数据格式转换 首先将生成的稠密点云以及图片信息转换成openmvs支持的.mvs文件。在openmvs_sample中的bin文件内打开终端 作者&#xff1a;舞曲的小水瓶 https://www.bilibili.com/read/cv25019877/ 出处&#xff1a;bilibili interfaceCOLMAP.exe -i D:\desktop\test\toy\…

【Linux服务器Java环境搭建】05 Node JS安装及环境变量配置

【Linux服务器Java环境搭建】01购买云服务器以及在服务器中安装Linux系统 【Linux服务器Java环境搭建】02 通过xftp和xshell远程连接云服务器 【Linux服务器Java环境搭建】03 Git工具安装 【Linux服务器Java环境搭建】04 JDK安装&#xff08;JAVA环境安装&#xff09; 【Linux服…

flink源码分析 - 命令行参数解析-CommandLineParser

flink版本: flink-1.11.2 调用位置: org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint#main 代码位置: flink核心命令行解析器: org.apache.flink.runtime.entrypoint.parser.CommandLineParser /** Licensed to the Apache Software Foundati…

基于OpenAPI工具包以及LSTM的CDN网络流量预测

基于LSTM的CDN网络流量预测 本案例是基于英特尔CDN以及英特尔 OpenAPI Intel Extension for TensorFlow* Intel oneAPIDPC Library 的网络流量预测&#xff0c;CDN是构建在现有网络基础之上的智能虚拟网络&#xff0c;目的是将源站内容分发至最接近用户的节点&#xff0c;使用…

unity学习笔记17

一、动画组件 Animation Animation组件是一种更传统的动画系统&#xff0c;它使用关键帧动画。你可以通过手动录制物体在时间轴上的变换来创建动画。 一些重要的属性&#xff1a; 1. 动画&#xff08;Animation&#xff09;&#xff1a; 类型&#xff1a; Animation组件允许…