`
v5qqcom
  • 浏览: 1282267 次
文章分类
社区版块
存档分类
最新评论

Realtime Rendering 3rd笔记 3

 
阅读更多

3.2 The Programmable Shader Stage

现代的shader stages(即支持Shader Model4.0, DirectX 10以及更高)使用common-shader core。即vertex, pixel和geometry shaders共享同一种编程模型。common-shader core是对应用程序员而言的API,相应的在GPU架构上则为unified shaders。早期的GPU在vertex和pixel shaders上缺少共通性,并且可能没有geometry shaders。然而,这种shader model的多数设计元素是老GPU也有的,只是一些设计元素简化或丢失,没有太大的不同。因此,本书中将关注Shader Model 4.0,并在后面讨论老的GPU的shader models。

shaders由c-like shading languages编写,例如HLSL,Cg,GLSL.他们被编译成独立于机器的汇编语言,也称作中间语言(IL)。以前的shader models允许直接用汇编语言编写shader,到了DirectX10,汇编代码只能在debug output中看到。这种汇编语言的代码在一个独立的步骤中(通常在驱动中)被转换成真正的机器语言。这种安排允许在不同硬件实现上保持兼容性。这种汇编语言可以被看做定义了一个虚拟机,这个虚拟机是shading语言编译器的目标平台。

该虚拟机是一个具有多种类型寄存器和数据源的处理器,使用一个指令集编程。因为很多图形操作是在short vectors之上进行(长度最多为4),处理器具有4-way SIMD能力。每个寄存器容纳4个独立的值。32位单精度浮点标量和vector是基本的数据类型,对32位整数的支持也已经加上。浮点向量一般存储位置(xyzw),法线,矩阵行,颜色(rgba),纹理坐标(uvwq)等数据;整数常用来表示计数器、索引或bit mask。结构,数组,矩阵之类的复合数据类型也支持。并且还支持swizzling和masking。

一次draw call触发了图形API绘制一组图元,因此引起图形流水线的执行。每个可编程shader阶段具有两种类型的input:
uniform inputs: with values that remain constant throughout a draw call (but can be changed between draw calls) 对一次draw call来说是常量。
varying inputs: are different for each vertex or pixel processed by the shader.
texture是一种特殊类型的uniform input,texture曾经总是color image,现在可以被当做任意类型的数据数组。


shader和通用CPU上的程序一个最大的不同是尽管shader有很多种输入,但是输出非常有限。底层的虚拟机为不同的输入和输出提供特殊的寄存器。uniform inputs通过只读的常量寄存器或者常量buffer访问,所谓常量就是在一次draw call中不变。可用的常量寄存器的数量比varying input或output使用的寄存器数量多得多。这是因为varying inputs和outputs需要为每个vertex或者pixel存储,而uniform inputs只在一次draw call中存储一次并为所有的顶点和像素复用。虚拟机还具有一般目的的临时寄存器,用作scratch space。所有类型的寄存器可以使用临时寄存器中的整形值作为数组索引访问。

图形计算方面常用的一些操作在现代GPU上都被高效的执行了,最快的操作是标量和矢量乘法,加法,乘法加法混合操作如乘加和点积。另外一些操作,如倒数,平方根,sine,cosine,指数,对数等稍微多费一些但也是相当快的。纹理操作是高效的,但是性能受到取得访问结果所等待的时间的影响。shading语言通过操作符暴露了大多数常用的操作,例如*,+。剩下的通过固有函数暴露出来,如atan(),dot(),log()等。固有函数也存在一些更复杂的操作,如向量归一化、反射和叉积,矩阵转置和求行列式等。
术语flow control指if,else以及各种循环语句。Shaders支持两种类型的flow control。静态flow control是基于uniform inputs的值。这意味着代码流向在整个draw call上是恒定的。static flow control的主要好处是允许同一个shader在各种不同的情形下使用(如不同数目的灯光)。动态flow control是基于varying inputs的值,因此比静态的更强大但也更费,特别是当code flow在shader调用中不规律的改变时。shader同时在很多个顶点或像素上计算。如果对于某些元素走if分支,另外的一些走else分支,那么两个分支对于所有的元素都要计算(然后每个元素不使用的分支将被丢弃)。
shader程序可以在程序载入前离线编译或者在运行时编译。像任意的编译器那样,可以有优化选项来生成不同的优化级别的输出文件,编译好的shader作为一个文本字符串存储并且通过驱动传递给GPU。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics