GPU编程入门-- 1

先从HLSL开始

 

HLSL中的基本概念

 

 *什么是HLSL

 

 

 

 

 

使用HLSL进行图形绘制,将更多的依赖于计算机图形硬件的支持。而计算机图形硬件的发展又是极快的,这主要是因为以下3个原因:

1)半导体技术一般每18个月就可以使一块微芯片上集成的晶体管数量增加一倍。计算机所使用的芯片同样如此。历史上也称这个规律为“摩尔定律”。这个晶体管数量的翻倍和制作工艺的提升,意味着计算速度的成倍提升、发热量的降低及存储效率的提高;

2)计算机图形技术一直是站在虚拟者的位置来对真实的世界进行模拟的。因此,计算机模拟的效果不管如何真实,在目前来说都还只是处在简单模拟的阶段。现实的世界实在是太复杂了,要进行模拟,依靠的不仅仅只是硬件的进步。不少的图形学专家们都能站起来用当前的计算机技术来挑战真实的世界,这是一种非常大的勇气,也是这种勇气在促使着软硬件技术飞速提升。

3)人们对于视觉效果的追求使计算机软硬件技术都飞速的发展着。

实际上,从第一块真正意义上的图形硬件(即可以在硬件级别对3D世界进行渲染的硬件)开始发展以来到现在,图形硬件的发展并没有经历太长的时间,至少比CPU的发展时间要短。但是现在的图形硬件的核心部分,即GPUGraphics Process Unit,图形处理单元)内所集成的晶体管的数量,已经超过了CPUCenter Process Unit)。如Intel Pentium 4 2.4GHzCPU中封装了5500万个晶体管,但是nNIDIAGeForceFX显卡的GPU中就封装了超过1.25亿个晶体管。

目前,图形硬件工业普遍认同的图形硬件发展有以下7个时期:

1)前图形处理加速器。

该时期属于图形处理器技术启蒙期,这个时期,图形处理器刚刚出现,还不具备很强大的图形处理能力;;

2)第一代图形处理器。

第一代图形处理器时期,到1998年结束。该时期的主要代表作是NvidiaTNT2ATI公司的Rage以及3D Fax公司的Voodoo3。这些图形处理器能够光栅化变换的三角形和使用一或两个纹理,它们还实现了DirectX6的大部分特征。这些图形处理器已经能将CPU从大量三角形的运算中解脱出来了。不过,这些硬件仍然有一些计算只能由CPU来完成,因此其GPU并不是完全独立的,如顶点变换就仍然是放在CPU中进行的;

3)第二代图形处理器。

第二代图形处理器时期从1999年开始到大约2000年底结束。代表作品是Nvidia公司的GeForce 1GeForce 2ATI公司的Radeon 7500以及S3公司的Savage 3D。这些图形处理器已经将第一代处理器仍然放在CPU中进行的工作搬到GPU中来了,并能较好地支持DirectX 7。这一代的图形处理器已经具备之前高端图形工作站的图形硬件处理能力。但它们仍然不能算是真正意义上的图形处理器——因为他们不能够被人们自由地编程控制;

4)第三代图形处理器。

第三代图形处理器只存在了大约一年的时间,代表作品是nNIDIA公司的GeForce 3GeForce 4ATI8500等。这一代图形处理器已经拥有了管线可编程的能力。这比起提供更多的设置来说更有价值。不过,这一代的处理器仍然不被认为是真正可编程的,因为他们只能支持顶点级别的编程,缺少对像素级别编程的支持,同时顶点级别的编程能力还很差,使用了可编程方式之后的图形渲染效率也没有固定管线方式的高。所以这一代的产品基本上只能算是过渡的产品;

5)第四代图形处理器。

nNIDIAGeForce FXATIRadeon 9700。这些硬件提供了完整的顶点级别和像素级别的图形管线编程能力,并且用可编程管线完全替代了固定管线。这一代的图形处理器就是完全意义上的图形处理器了,因为它不再需要对CPU的依靠便可独立地完成所有工作。

6)第五代图形处理器。

Geforce 67Radeon X1900系列显卡。更强的可编程能力,支持Shader Model3.0,完全兼容DirectX 9c

7)现在的图形处理器。

nNIDIAGeForce 8***系列和ATIHD 2***系列。支持Shader Model4.0,完全兼容DirectX 10。这一代的显卡改变了原来显卡中固定的顶点处理管线和像素处理管线,也就是说能处理顶点的管线只能处理顶点,处理像素的只能处理像素。现在采用的是统一渲染管线,即可以处理顶点也可以处理像素。并引入了Geometry shader,也就是几何渲染。增加了纹理阵列,绘制断言,数据流输出等新特性。

传统的DirectX在多张纹理中进行切换的操作是一个很消耗CPU的操作,因为每切换一次,都要调用一次DirectXAPI函数。而每绘制一个使用新纹理的物体,就要进行一次这样的切换操作;有时为了实现特殊的材质特效,绘制一个物体时可能就要切换好几次纹理,开销很大。

所以,以前游戏美工们经常索性将大量的小纹理拼合到一张大的纹理中,通过给不同的三维物体分配这张大纹理的不同局部以期减少纹理切换,提高游戏运行效率。然而,这件事做起来会非常麻烦,而且DirectX 9中对纹理的尺寸的限制是4048×4048像素,也就是说,如果要容下更多的小纹理块,可能就得开辟很多张这样的大纹理。

DirectX 10引入的新的纹理阵列机构,将允许在一个由显卡维护的阵列中容纳512张单独的纹理,而且,在shader程序中可以使用一条新的指令来获取这个阵列中的任意一张纹理。而这种shader指令是运行在GPU中的;这样,就把原来要消耗很多CPU时间的纹理切换工作轻松地转给了GPU。由于纹理一般是直接放在显存中的,所以这件事由同显存一起放在显卡上的GPU来完成真是天经地义。现在,在应用程序的层面,只要一开始设置好纹理阵列中的纹理,然后每次绘制一个物体时为它指定一个纹理的索引号,并同物体三维数据一起传递到shader中,就可以放心的让GPU来给物体选纹理了。

在一般的三维场景里,很多物体都是完全被别的物体挡在后面的。这时候如果要显卡绘制这些物体就是白费力气。尽管高级的GPU可以通过硬件算法将场景画面中被挡住的像素(注意是像素)预先剔除,但是仍然会有一些处理消耗。例如,一个完全被挡住的复杂的角色模型,它的身上可能有几千个顶点,需要做复杂的骨骼皮肤动画处理、顶点光照运算等等——然而,GPU是在处理完这些顶点之后,并要把这个角色模型一个像素一个像素地画到画面中时,才开始判断每个像素是否需要画——当所有的像素都被剔除了时,之前做的顶点处理也就全白费了。于是,游戏开发者们想出了一个方法来解决这个问题,这就是绘制断言。

简言之就是用一个可以代表某个复杂物体的简单物体来判断这个物体是否被全部挡住了——例如用一个可以罩住刚才那个角色的包围盒,当绘制这个盒子时,如果所有的像素都被剔除掉了,也就说明这个盒子肯定完全看不见,更不用说里边的角色了,也就不用做什么骨骼皮肤运算之类的操作了。一个盒子有八个顶点,相比处理几千个顶点,开销小得多。但是,以前这步中有些部分也是要在CPU中完成的。现在,在DirectX 10中,已经彻彻低低的交由GPU来做了。

数据流输出。这是一个DirectX 10中的非常重要的特性,它允许GPU上的Vertex shaderGeometry shader向显存中添加数据!这看上去也许没什么特别的,然而在以往的vertex shader中是史无前例的。以前的DirectX中,vertex shader只能读取显存中已有的顶点数据;而DirectX 10中引入的新的Geometry shader,不但能读取显存中的顶点数据、几何(点、线段、三角形)数据,还可以生成新的几何数据放回显存。

可以发现,计算机图形硬件的发展是从能够渲染3D图形,不过离不开CPU,到可以离开CPU独立地渲染3D图形,再到不但可以渲染3D图形,还可以像CPU一样的执行着色程序这样一个过程来发展的。最终的发展目标就是强大的可编程渲染能力,当然也少不了大容量快速度的基本特点。

未来的图形硬件将是可编程图形硬件的天下,而HLSL语言就是这种编程语言,学习好HLSL就是对图形硬件进行编程操作迈出的第一大步。

 

1*VSPS

VertexShader被翻译为“顶点着色器”或“顶点渲染”简写为VS。顶点着色器的功能就是对进入管线的每一个顶点进行着色处理。实际上可以这样说:顶点着色器的功能就是对进入管线的每一个顶点用事先写好的程序进行处理。

PixelShader则被翻译为“像素着色器”或“像素渲染”简写为PS。像素着色器的功能就是对进入管线的每一个像素顶点进行着色处理。与此类似:像素着色器的功能就是对进入管线的每一个像素用事先写好的程序进行处理。

VertexShaderPixelShader的不同之处相当明显:一个针对顶点,一个针对像素。因此,要想对顶点进行处理,以控制顶点及顶点相关的数据,就需要使用VertexShader。而想控制实际输出的每一个像素,就需要使用PixelShader,并且PixelShader总是在VertexShader之后执行。如果复习一下以前讲过的Direct3D固定管线的知识,就很容易明白:VertexShader输出后的顶点,会被硬件光栅化为填上了像素的顶点,如果这些顶点还组成一个三角形,那么整个三角形就会被硬件根据三个顶点的属性值插值以填满。这些被填满的每一个像素,都将会经由PixelShader进行处理。因此,VertexShaderPixelShader是分开工作的,可以对一个效果只使用VertexShader,或者只使用PixelShader,或者两者都使用。如图1-1所示是顶点与像素管理图,注意VertexShaderPixelShader所处的位置以及其所代替的处理流程。

 

clip_image004

 

1-1中原本由硬件按预先设定的方式来完成的“变换及光照”功能,如果使用了可编程管线,就会被VertexShader代替掉,而像素管线中的“纹理采样”(包括纹理采样,多重纹理混合,纹理寻址),如果使用了可编程管线,那么就将被PixelShader所代替。很明显,VertexShdaerPixelShader并不是将整个固定管线全部都替换掉了。固定管线中大部分的步骤、顺序和功能仍然被保留着。但是VertexShaderPixelShader替换掉了最重要的顶点管线与像素管线中的环节,那就是顶点变换、光照运算、纹理采样。这种替换也意味着这些原来由硬件来实现的功能在使用了可编程管线之后,全部都需要编程来实现了。

在了解了VertexShaderPixelShader后,那么和HLSL有什么关系呢?在开始的时候就提到了,HLSL只是一个高级着色语言,它的代码实际上是在被编译为目标代码之后才能进行工作的,就像C++一样。如果用一张图来表示VertexShaderPixelShaderHLSL之间的关系,那就是如图1-2所示。

 

1-2中一共有NVertexShaderNPixelShaderVertexShaderPixelShader成对出现,每一组VertexShaderPixelShader组成了一个Pass,这样N对就可以组成NPass。然后Pass又组成了Technique。可以看到,一个Technique可以由任意多个Pass组成,换句话说就是给出NVertexShaderPixelShader之后,可以用任意多个Pass组成任意多个Technique(前提当然是有意义的组合),而这些所有的内容就是一份完整的HLSL

HLSL就是将VertexShaderPixelShader进行组合编程与使用的一个代码的合集。并且在同一时间内只能有一个VertexShaderPixelShader是活动的。这也就是说同一时间内,只能有一个Technique和其所属的一个Pass是被激活的。

关于VertexShaderPixelShader,还有一个需要注意的地方,那就是它们都有版本问题。就像汇编一样,8038680586它们都属于80x86,但是它们的汇编指令集却有一些不同,例如指令数量不一样、寄存器数量、类型不一样等。VertexShaderPixelShader版本的不同导致了在指令、功能、效率、寄存器数量等方面都有一定的差别。表1-1列出了不同版本的VertexShaderPixelShader所能支持的指令数量、最大纹理采样层数以及寄存器的数量等。仅供参考,因为这些东西在使用的时候会被编译器尽可能的优化,如果碰上了编译器告知“太复杂的语法”或者“无法编译时”,就可以考虑是不是VertexShaderPixelShader的版本使用得太低了。

 

1-1 VertexShader各版本差异表

版本

输入寄存器

常量寄存器

临时寄存器

指令数目

vs_1_1

16

>96

12

128

vs_2_0

16

> 256

12

256

vs_2_x

16

>256

12

256

vs_3_0

16

>256

12

>512

vs_4_0

16

16×4096

4096

64K

ps_1_4

2color / 6 tex

8

6

6tex + 8 arithmetic

ps_2_0

2color / 8 tex

32float / 16int

12-32

32tex + 64 arithmetic

ps_2_x

2color / 8 tex

32float / 16int

12-32

>96

ps_3_0

10

224float/16int

32

>512

ps_4_0

32

16×4096

4096

64K

vsps的版本共同构成了shader model的版本。版本的差异决定了HLSL编译出来的汇编代码可以使用的资源数量。还有一个没有在表中指出的指标是2D的纹理尺寸,在shader moder 3.02K×2K像素大小。在shader moder 4.08K×8K像素大小。还有一个shader moder 4.0独有的指标是纹理阵列的数目是512,但这里要说明的是虽然显卡可以保存这么多纹理,但每次渲染时最多只能使用其中的128个,也就是说对一次渲染的顶点数据来说它上面最多能得到的纹理数是128

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值