【Direct3D篇】为什么游戏总要编译着色器?
省流:

















































我超,原
































































































这里可以发现,早期的GPU的渲染管线Shader是分离的状态,即GPU内部有GPU clock和shader clock两种频率。

比如GT240,它并没有整合shader,这和现代GPU还是有明显区别的

顺带说下这种分离的设计直到DX11时代依然存在,比如费米,比如S3的集显
















这里的例子感觉并不算特别贴切,实践中原神卡一下通常发生在联机过程中加人时、以及非N卡CPU优化列表的CPU(比如E5)搭配N卡运行的时候就会时常顿卡,画面定住CPU占用冲高,但是过一会儿又恢复正常,然后又卡,如此循环往复。
原的优化其实还可以,至少我在实践中没看到画面上出现新物体就会卡的情况除了多人联机的时候进人就没了,但是我觉得这也不是pipeline而是游戏联机机制的问题。
























黑神话是有DX11的,所以真正意义上的编译着色器也不是不可能






























和微软关系不好?
理论上摩尔线程之类的购买了IMG GPU IP的显卡由于原设计是针对手机平板等ARM端移动GPU,所以对OGL的支持比DX更好。比如MTT S80的原生架构IMG BXT的DX只有D3D9支持是原生的,但是D3D11其实是基于驱动转译的,因此效率很低。至今3060规模的GPU在D3D11的表现都只有1650水平。这点MTT S30和同样购买IMG BXT架构的风华二号也是一样的。
但是这类GPU如果运行OGL或者D3D9游戏的话水平就很高,遗憾的是市面上几乎没有用这些API同时还对GPU性能有高需求的游戏,作为参考,圣安地列斯就是D3D9时代的游戏,这个游戏原生的性能需求最多只有GT240水平(1080P)
不过理论上这种显卡搭配ARM处理器跑AOSP或者其他移动端系统就可以实现类似POWERVR的水平,毕竟原生API支持还是偏向移动端的。








是不是有点太理想了,DX12推出了这么多年了DX11依然是主流,而且未来说不准还有VULKAN之类的API会直接打破DX的平台限制








AI字幕:三界四洲无所求
你玩黑神话了吗
编译着色器编译了多久
反正我是卡了半天
那么为什么黑神话要变异这么久的着色器呢
之前我就出过一期编译着色器的视频
不过那期视频主要讲的是手机平台
这期视频我们就来聊一下
PC平台上的着色器编译
首先什么是着色器
着色器英语里边叫做SHADER
其实就是一段程序
一段代码
这段代码会跑到显卡上面去
游戏开发者可以通过编写SHADER代码
来指挥显卡进行相应的运算
所谓GPU可编程管线就是指可以写SHADER
手机平台上搭载的open gl和windows平台上搭载的direct
3D都是可以写SHADER的
但是两者对于SHADER的处理方式却很不一样
SHADDER的源代码是无法直接运行的
必须把源代码编译成二进制机器码
显卡才能够运行
那么open gl是怎么编译SHADER的呢
首先我们需要看一下open gl所扮演的角色
假设市面上有五款不同的显卡
open gl的责任
就是为这些显卡提供一套统一的接口
游戏开发者不需要考虑具体的硬件
他们只需要接入open g2就可以了
而硬件生产厂商只需要在自家的硬件上面实现
open gl的内容
不用针对具体的软件做适配
那open gl实际上就是起到一个桥梁的作用
在面对SHADER的问题的时候
open jail只规定了SHADER源代码的格式
也就是只规定了游戏开发者应该如何写SHADER
具体这个SHADER源代码到了GPU上面如何去编译
如何去运行
open gl说了
我不管你们各家硬件厂商自己去做
我只负责把这个SHADDER的源代码传递给显卡
在这种策略的指导下
不同品牌的不同型号的
他们的SHADER编译器都是不相同的
编译出来的产物也是不相同的
所以早期基于open gl的游戏里边
都是每次运行都要编一次SHADER
后来open gl推出了
可以把SHADER编译后的产物取回的接口
不过这个取回来的编译产物
只能在同一台机器上面运行
所以现在很多基于open gl的手机游戏
都是在游戏安装包里边内置SHADDER的源代码
第一次运行的时候把SHADER编译一遍
然后把编译产物拿到之后再运行
就用第一次的编译产物就不用再去编译了
这就是基于open gl的手游
第一次进入要进行着色器编译的原因
那么windows电脑上运行的游戏
也和基于open gl的手游是一样的吗
还是有一些区别的
首先windows上的端游普遍使用的不是open gl
而是d direct3D啊
当然除了这个玩意儿
DERRX3D和open gl的作用一样
也是作为一个桥梁
不过d direct3D和open gl不同的是
DX3D除了规定SHADER源代码的语法之外
它还推出了一种预编译格式
叫做DXBC
Dx bc
是介于人写的源代码
和最后运行的机器码之间的一种格式
游戏开发者可以选择将SHADDER的源代码
在开发阶段就先编译成DXBC
当年微软推出DXBC的时候
想法其实也比较简单
人写的SHADER源代码编译成显卡运行的机器码
这个过程不是比较耗时吗
那我微软就推出一种
尽可能贴近硬件的中间格式
这样游戏开发者就可以预先把源代码
转换成这种中间格式
然后放到游戏安装包里边
游戏运行的时候
d direct3D会把DXBC格式的SHADER传递给显卡
当然具体显卡怎么执行
DIRX3D也就管不着了
对于显卡来说
因为DXBC对机器更加友好
所以相较于直接处理人写的SHADER源代码
处理DXBC会快非常多
上面介绍的是d direct3D11
以及之前的处理方式
2014年
微软提出了新一代迪尔X3D标准
Drx 3d12
DRX3D12的SHADER处理方式改变了非常多
首先微软推出了一种新的SHADER中间格式
DEXIL用于取代略显成就的DXBC
此外还有一项更重要的改进
要介绍这一项改进
我们需要先介绍一些前置知识
首先先举个例子
假如我们想要使用显卡来绘制这个傻浮浮
那么显卡内部应该怎么做呢
首先我们需要明白
任何复杂的模型都是由三角形组成的
而三角形则是由这些顶点组成的
这个傻浮浮也不例外
所以第一步
我们就是要把傻福福的原始顶点数据
传输给显卡
显卡在拿到这些原始的顶点数据之后
第一步就是要对这些顶点数据做一些变换
当然也可以做一些复杂的
比如跳个舞什么的
大丘丘病了
二丘丘
瞧
三丘丘
采药
四丘丘熬
因为这些变换比较复杂
而且要求必须十分灵活
所以显卡会允许游戏开发者
在这里插入一段程序
来对顶点进行自定义的操作
那么这段程序其实就是SHADDER
因为它是用来处理顶点的
所以就叫做what tex shader
顶点着色器在经过顶点着色器的加工变换之后
这些顶点就有了新的位置
那么接下来显卡要做的事情
就是把这些点连接成几何体
这个过程又被称之为图源
装配在一些较为高级的显卡里边
还可以在这个阶段插入几何着色器
细分曲面着色器等等
因为电脑屏幕其实并不能直接显示
这些几何信息
你必须要把这些几何体变成像素点信息
才可以显示
那么下一步显卡就要进行这个转换
这个过程被称之为光栅化
光栅化之后
这些几何数据就变成了像素点
那么接下来就是要给这些像素点进行上色
给像素点上色其实也是一个非常复杂的过程
你要考虑颜色
光照反射等非常多的因素
所以显卡也允许你在这里插入一个SHADER
这就是pixel shader
像素着色器有些地方也叫做片源着色器
在这之后显卡还要进行透明度测试
深度测试等一些后期处理
最后图像才能被渲染和显示出来
这整个过程就像是一条流水线
所以我们一般管这个流程叫做render pipeline
渲染管线
你想要渲染一个物体
你就需要构建一条这样的渲染管线
这条渲染管线里边的自定义数据除了SHADER之外
其实还包括很多的状态需要设置
比如你要不要启用细分着色器
要不要启用几何着色器
要不要做透明度混合
混合方式又是什么
这些状态都需要进行设置
在direct3D12之前
渲染管线都是在运行的时候实时构建的
有时候你需要进行几十次的调用
才能完成这个构建
并且每次调用GPU
都要对你的操作进行大量的校验工作
防止非法操作
把系统给干崩溃
这个过程是比较耗时的
所以在一些老游戏里边
当画面上出现一个新的物体的时候
就会卡一下
这个卡一下就是在构建这个新物体的PAPI
DERDIRECT3D12则改进了这一点
在DERRX3D12里边
你可以在第一次运行游戏的时候
构建一个PAPI
把pipeline里边用到的SHADER
各种状态的设置都做了
显卡也会对你的操作进行校验来防止出错
然后显卡会把你的这个pop line生成一段
直接可以跑在显卡上面的机器码
显卡会允许游戏开发者
把这段机器码给缓存下来
等到下次运行的时候
游戏也可以直接将这段机器码塞给显卡
就不用废弃巴咧的再去构建一个pop i显卡
拿到之后直接就可以运行起来
这个过程被叫做PSO catch
渲染管线状态对象的缓存
所以现在很多DEREK3D开发的游戏
表面上写的是正在编译着色器
实际上是在做PSO的缓存
这个p so缓存和硬件是强绑定的
不同的显卡
甚至不同版本的显卡驱动
生成的PRS缓存也是不能通用的
所以当你更新了显卡驱动之后
你大概率还需要再经历一次正在编译着色器
不过这个创建PSO缓存的过程
是不是有点太长了
创建PRO缓存确实是一个相对耗时的操作
但是PS用到的SHADER
不是已经预编译成DXIL了吗
去设置一堆状态
然后做一堆验证
真的需要让用户等待十几分钟吗
其实是不需要的
之所以要等这么久
是因为很多游戏内置的SHADER
仍然是SHADDER的源代码
而不是DXLL的中间格式
所以这里边的编译着色器
是把源代码先编译成DXIL或者DXBC
然后再去构建PS缓存
而这一部分则占用了大部分的时间
可是为什么要这样做呀
微软不是推出了预编译的中间格式吗
为什么不用呢
第一是体积问题
DXBC和DXIL
会比源代码的体积要大不少
直接内置源代码可以缩小游戏安装包的体积呃
不过这个可能不是主要原因
第二我们知道DX3D11用的预编译格式是
DXBCDRX3D12里边放弃了DXBC
推出了一种新的格式
D x i l
DXBC和DXIL是互不相通的
也就是说如果你游戏里边放的是DXBC
那你就只能跑DX3D11
你放的是DXIL
那你就只能跑DX3D12
而有一部分用户的老电脑
是不支持DX3D12的
总不能放弃这部分用户吧
所以很多游戏仍然会选择
直接内置SHADDER的源代码
在运行的时候是用户电脑的支持情况
分别编译成DXLL和DXBC
然后再分别运行到DRX3D11和
DRX3D12上面去
那么随着用户电脑的迭代以后
不支持DX3D12的电脑会越来越少
这正在编译着色器的问题也会越来越好
在黑神话这个游戏中
你会发现它的场景非常的细节
面数都非常多
做过功课的朋友也许知道
黑神话使用了UE5里边的NANNET技术
那么NANNET到底是怎么一回事呢
正好我最近自己实现了一套NANNET的demo
那么下期视频
我们就和大家来一起研究一下NANNET
别忘了一键三连加关注哦
我们下期再见
作者声明本文无利益相关,欢迎值友理性交流,和谐讨论~
