CPU GPU设计工作原理《转》

我知道这非常长,可是,我坚持看完了.希望有幸看到这文章并对图形方面有兴趣的朋友,也能坚持看完.一定大有收获.毕竟知道它们究竟是怎么"私下勾搭"的.会有利于我们用程序来指挥它们....(这是我加上去的)

原文从这里開始:

要说到设计的复杂程度,那还是CPU了!这个不用讨论,非常easy的道理你看看显卡芯片的更新速度和CPU的更新速度就可见一斑了。还是简单说说他们的设计原理吧。

CPU:

      可是,如今我要问一句:“什么是CPU?”我相信大多数人并不知道什么是CPU。当然,你可以回答CPU是中央处理器,或者来一句英文: Central Processing Unit。是的,没错。

但,RISC和CISC是什么?什么是“9路超标量设计”、“20级流水线”?什么是“解 码”,为什么Athlon和PIII的解码过程须要的时钟周期大大大于其它的RISC处理器?

这些都不是一句“中央处理器”所可以回答的。

一、 指令系统

要讲CPU,就必须先讲一下指令系统。

指令系统指的是一个CPU所可以处理的所有指令的集合。是一个CPU的根本属性。

比方我们如今所用的CPU都是 採用x86指令集的。他们都是同一类型的CPU,无论是PIII、Athlon或Joshua。我们也知道。世界上还有比PIII和Athlon快得多的 CPU。比方Alpha。但它们不是用x86指令集,不能使用数量庞大的基于x86指令集的程序,如Windows98。之所以说指令系统是一个CPU的 根本属性。是由于指令系统决定了一个CPU可以执行什么样的程序。所有採用高级语言编出的程序。都须要翻译(编译或解释)成为机器语言后才干执行。这些机 器语言中所包括的就是一条条的指令。

1、 指令的格式

一条指令一般包含两个部分:操作码和地址码。操作码事实上就是指令序列号,用来告诉CPU须要运行的是那一条指令。地址码则复杂一些,主要包含源操作数地址、目的地址和下一条指令的地址。在某些指令中,地址码能够部分或所有省略。比方一条空指令就仅仅有操作码而没有地址码。

举个样例吧,某个指令系统的指令长度为32位。操作码长度为8位,地址长度也为8位,且第一条指令是加,第二条指令是减。

当它收到一个 “00000010000001000000000100000110”的指令时,先取出它的前8位操作码,即00000010,分析得出这是一个减法操 作。有3个地址,各自是两个源操作数地址和一个目的地址。于是。CPU就到内存地址00000100处取出被减数,到00000001处取出减数,送到 ALU中进行减法运算,然后把结果送到00000110处。

这仅仅是一个相当简单化的样例。实际情况要复杂的多。

2、 指令的分类与寻址方式

一般说来,如今的指令系统有下面几种类型的指令:

(1)算术逻辑运算指令

算术逻辑运算指令包含加减乘除等算术运算指令,以及与或非异或等逻辑运算指令。如今的指令系统还增加了一些十进制运算指令以及字符串运算指令等。

(2)浮点运算指令

用于对浮点数进行运算。浮点运算要大大复杂于整数运算,所以CPU中一般还会有专门负责浮点运算的浮点运算单元。如今的浮点指令中一般还增加了向量指令,用于直接对矩阵进行运算,对于如今的多媒体和3D处理非常实用。

(3)位操作指令

学过C的人应该都知道C语言中有一组位操作语句,相相应的,指令系统中也有一组位操作指令,如左移一位右移一位等。

对于计算机内部以二进制不码表示的数据来说,这样的操作是很easy快捷的。

(4)其它指令

上面三种都是运算型指令,除此之外还有很多非运算的其它指令。这些指令包含:数据传送指令、堆栈操作指令、转移类指令、输入输出指令和一些比較特殊的指令。如特权指令、多处理器控制指令和等待、停机、空操作等指令。

对于指令中的地址码。也会有很多不同的寻址(编址)方式,主要有直接寻址,间接寻址,寄存器寻址。基址寻址。变址寻址等,某些复杂的指令系统会有几十种甚至很多其它的寻址方式。

3、 CISC与RISC

CISC。Complex Instruction Set Computer,复杂指令系统计算机。RISC, Reduced Instruction Set Computer,精简指令系统计算机。尽管这两个名词是针对计算机的。但下文我们仍然仅仅对指令集进行 研究。

(1)CISC的产生、发展和现状

一開始,计算机的指令系统仅仅有非常少一些基本指令。而其它的复杂指令全靠软件编译时通过简单指令的组合来实现。

举个最简单的样例。一个a乘以b的操作就 能够转换为a个b相加来做。这样就用不着乘法指令了。

当然,最早的指令系统就已经有乘法指令了,这是为什么呢?由于用硬件实现乘法比加法组合来得快得多。

因为那时的计算机部件相当昂贵,并且速度非常慢,为了提快速度,越来越多的复杂指令被增加了指令系统中。可是。非常快又有一个问题:一个指令系统的指令数是受指令操作码的位数所限制的,假设操作码为8位,那么指令数最多为256条(2的8次方)。

那么怎么办呢?指令的宽度是非常难添加的,聪明的设计师们又想出了一种方案:操作码扩展。

前面说过。操作码的后面跟的是地址码,而有些指令是用不着地址码或仅仅用少量的地址码的。

那么。就能够把操作码扩展到这些位置。

举个简单的样例。假设一个指令系统的操作码为2位,那么能够有00、01、10、11四条不同的指令。如今把11作为保留,把操作码扩展到4位,那么 就能够有00、01、10、1100、1101、1110、1111七条指令。

当中1100、1101、1110、1111这四条指令的地址码必须少两 位。

然后,为了达到操作码扩展的先决条件:降低地址码,设计师们又动足了脑筋,发明了各种各样的寻址方式。如基址寻址、相对寻址等,用以最大限度的压缩地址码长度,为操作码留出空间。

就这样。慢慢地。CISC指令系统就形成了。大量的复杂指令、可变的指令长度、多种的寻址方式是CISC的特点,也是CISC的缺点:由于这些都大大 添加了解码的难度。而在如今的快速硬件发展下。复杂指令所带来的速度提升早已不及在解码上浪费点的时间。除了个人PC市场还在用x86指令集外,server以 及更大的系统都早已不用CISC了。x86仍然存在的唯一理由就是为了兼容大量的x86平台上的软件。

(2)RISC的产生、发展和现状

1975年。IBM的设计师John Cocke研究了当时的IBM370CISC系统,发现当中占总指令数仅20%的简单指令却在程序调用中占了80%,而占指令数80%的复杂指令却仅仅有20%的机会用到。由此。他提出了RISC的概念。

事实证明,RISC是成功的。80年代末,各公司的RISC CPU如雨后春笋般大量出现。占领了大量的市场。到了90年代。x86的CPU如pentium和k5也開始使用先进的RISC核心。

RISC的最大特点是指令长度固定。指令格式种类少,寻址方式种类少,大多数是简单指令且都能在一个时钟周期内完毕,易于设计超标量与流水线,寄存器 数量多,大量操作在寄存器之间进行。因为下文所讲的CPU核心大部分是讲RISC核心。所以这里就不多介绍了,对于RISC核心的设计以下会具体谈到。

RISC眼下正如日中天,Intel的Itanium也将终于抛弃x86而转向RISC结构。

二、CPU内核结构

好吧。以下来看看CPU。CPU内核主要分为两部分:运算器和控制器。

(一) 运算器

1、 算术逻辑运算单元ALU(Arithmetic and Logic Unit)

ALU主要完毕对二进制数据的定点算术运算(加减乘除)、逻辑运算(与或非异或)以及移位操作。在某些CPU中还有专门用于处理移位操作的移位器。

通常ALU由两个输入端和一个输出端。整数单元有时也称为IEU(Integer Execution Unit)。

我们通常所说的“CPU是XX位的”就是指ALU所能处理的数据的位数。

2、 浮点运算单元FPU(Floating Point Unit)

FPU主要负责浮点运算和高精度整数运算。

有些FPU还具有向量运算的功能,另外一些则有专门的向量处理单元。

3、通用寄存器组

通用寄存器组是一组最快的存储器,用来保存參加运算的操作数和中间结果。

在通用寄存器的设计上。RISC与CISC有着非常大的不同。

CISC的寄存器通常非常少,主要是受了当时硬件成本所限。

比方x86指令集仅仅有8个通用寄存 器。

所以。CISC的CPU运行是大多数时间是在訪问存储器中的数据,而不是寄存器中的。这就拖慢了整个系统的速度。而RISC系统往往具有非常多的通用 寄存器,并採用了重叠寄存器窗体和寄存器堆等技术使寄存器资源得到充分的利用。

对于x86指令集仅仅支持8个通用寄存器的缺点,Intel和AMD的最新CPU都採用了一种叫做“寄存器重命名”的技术,这样的技术使x86CPU的寄 存器能够突破8个的限制,达到32个甚至很多其它。只是。相对于RISC来说。这样的技术的寄存器操作要多出一个时钟周期,用来对寄存器进行重命名。

4、 专用寄存器

专用寄存器一般是一些状态寄存器。不能通过程序改变,由CPU自己控制,表明某种状态。

(二) 控制器

运算器仅仅能完毕运算,而控制器用于控制着整个CPU的工作。

1、 指令控制器

指令控制器是控制器中相当重要的部分,它要完毕取指令、分析指令等操作,然后交给运行单元(ALU或FPU)来运行,同一时候还要形成下一条指令的地址。

2、 时序控制器

时序控制器的作用是为每条指令按时间顺序提供控制信号。

时序控制器包含时钟发生器和倍频定义单元,当中时钟发生器由石英晶体振荡器发出很稳定的脉冲信号。就是CPU的主频;而倍频定义单元则定义了CPU主频是存储器频率(总线频率)的几倍。

3、 总线控制器

总线控制器主要用于控制CPU的内外部总线,包含地址总线、数据总线、控制总线等等。

4、中断控制器

中断控制器用于控制各种各样的中断请求,并依据优先级的高低对中断请求进行排队,逐个交给CPU处理。

(三) CPU核心的设计

CPU的性能是由什么决定的呢?单纯的一个ALU速度在一个CPU中并不起决定性作用。由于ALU的速度都差点儿相同。而一个CPU的性能表现的决定性因素就在于CPU内核的设计。

1、超标量(Superscalar)

既然无法大幅提高ALU的速度,有什么替代的方法呢?并行处理的方法重新产生了强大的作用。所谓的超标量CPU。就是仅仅集成了多个ALU、多个FPU、多个译码器和多条流水线的CPU。以并行处理的方式来提高性能。

超标量技术应该是非常easy理解的,只是有一点须要注意。就是不要去管“超标量”之前的那个数字。比方“9路超标量”,不同的厂商对于这个数字有着不同的定义,很多其它的这仅仅是一种商业上的宣传手段。

2、流水线(Pipeline)

流水线是现代RISC核心的一个重要设计,它极大地提高了性能。

对于一条详细的指令运行过程,通常能够分为五个部分:取指令,指令译码。取操作数。运算(ALU)。写结果。当中前三步一般由指令控制器完毕,后两步 则由运算器完毕。依照传统的方式,全部指令顺序运行,那么先是指令控制器工作,完毕第一条指令的前三步,然后运算器工作。完毕后两步。在指令控制器工作。 完毕第二条指令的前三步。在是运算器。完毕第二条指令的后两部……非常明显。当指令控制器工作是运算器基本上在歇息,而当运算器在工作时指令控制器却在休 息。造成了相当大的资源浪费。解决方法非常easy想到。当指令控制器完毕了第一条指令的前三步后,直接開始第二条指令的操作,运算单元也是。这样就形成了流水 线系统,这是一条2级流水线。

如果是一个超标量系统,如果有三个指令控制单元和两个运算单元,那么就能够在完毕了第一条指令的取址工作后直接開始第二条指令的取址,这时第一条指令 在进行译码,然后第三条指令取址。第二条指令译码,第一条指令取操作数……这样就是一个5级流水线。非常显然,5级流水线的平均理论速度是不用流水线的4 倍。

流水线系统最大限度地利用了CPU资源,使每一个部件在每一个时钟周期都工作,大大提高了效率。

可是。流水线有两个很大的问题:相关和转移。

在一个流水线系统中,假设第二条指令须要用到第一条指令的结果,这样的情况叫做相关。以上面哪个5级流水线为例,当第二条指令须要取操作数时,第一条指 令的运算还没有完毕,假设这时第二条指令就去取操作数,就会得到错误的结果。所以,这时整条流水线不得不停顿下来,等待第一条指令的完毕。这是非常讨厌的问 题,特别是对于比較长的流水线,比方20级,这样的停顿通常要损失十几个时钟周期。眼下解决问题的方法是乱序运行。

乱序运行的原理是在两条相关指令中插 入不相关的指令。使整条流水线顺畅。比方上面的样例中,開始运行第一条指令后直接開始运行第三条指令(假设第三条指令不相关),然后才開始运行第二条指 令。这样当第二条指令须要取操作数时第一条指令刚好完毕。并且第三条指令也快要完毕了,整条流水线不会停顿。当然。流水线的堵塞现象还是不能全然避免的, 尤其是当相关指令许多的时候。

还有一个大问题是条件转移。在上面的样例中,假设第一条指令是一个条件转移指令,那么系统就会不清楚以下应该运行那一条指令?这时就必须等第一条指令的 推断结果出来才干运行第二条指令。

条件转移所造成的流水线停顿甚至比相关还要严重的多。所以,如今採用分支预測技术来处理转移问题。尽管我们的程序中充满 着分支,并且哪一条分支都是有可能的。但大多数情况下总是选择某一分支。

比方一个循环的末尾是一个分支,除了最后一次我们须要跳出循环外,其它的时候我们 总是选择继续循环这条分支。依据这些原理,分支预測技术可以在没有得到结果之前预測下一条指令是什么,并运行它。如今的分支预測技术可以达到90%以上的 正确率,可是。一旦预測错误。CPU仍然不得不清理整条流水线并回到分支点。

这将损失大量的时钟周期。所以。进一步提高分支预測的准确率也是正在研究的一 个课题。

越是长的流水线,相关和转移两大问题也越严重。所以。流水线并非越长越好,超标量也不是越多越好,找到一个速度与效率的平衡点才是最重要的。

三、CPU的外核

1、解码器(Decode Unit)

这是x86CPU才有的东西,它的作用是把长度不定的x86指令转换为长度固定的类似于RISC的指令,并交给RISC内核。解码分为硬件解码和微解 码,对于简单的x86指令仅仅要硬件解码就可以,速度较快,而遇到复杂的x86指令则须要进行微解码,并把它分成若干条简单指令,速度较慢且非常复杂。好在这些 复杂指令非常少会用到。

Athlon也好,PIII也好,老式的CISC的x86指令集严重制约了他们的性能表现。

2、一级缓存和二级缓存(Cache)

以及缓存和二级缓存是为了缓解较快的CPU与较慢的存储器之间的矛盾而产生的,以及缓存通常集成在CPU内核。而二级缓存则是以OnDie或OnBoard的方式以较快于存储器的速度执行。对于一些大数据交换量的工作,CPU的Cache显得尤为重要。

GPU:

     Graphic Processing Unit简称GPU距离那场革命已经5年了还记得最早由伟大的nVIDIA在1999年8月31日提出

一,GPU

GPU全称是Graphic Processing Unit—图形处理器。其最大的作用就是进行各种绘制计算机图形所需的运算。包含顶点设置,光影。像 素操作等。GPU实际上是一组图形函数的集合,而这些函数由硬件实现。主要用于处理3D游戏中物体移动时的坐标转换及光源处理。曾经,这些工作都是由 CPU配合特定的软件来做的。

GPU从某种意义上来讲就是为了代替CPU在图形处理过程中充当主角而出现的,一块标准的GPU主要包含 2D Engine。3D Engine ,Video Processing Engine。FSAA Engine,显存管理单元等等。当中,3D运 算中起决定作用的是3D Engine,这是现代3D显卡的灵魂。也是差别GPU等级的重要标志。

3D Engine在各公司的产品中都是宣传攻势的重点 照应对象,名字叫的一个比一个响。像nVidia的nFinitFX系列,CineFX系列,ATI的SmoothVision系列,一个 3D Engine通常包括着T&L单元。Vertex Processing Engine。Setup Engine, Piexl Shader等

二,API

说到API。或许非常多人不easy理解。

在计算机行业中。全部软件的程序接口,包含3D图形程序接口在内,统称为API (Application Program Interface)—应用程序接口。过去。假设您想让它们发挥最大功效。必须做的一件事,就是记录相关硬件 设备的地址。如今。API已成为软、硬件之间一种连接的桥梁,这道工序就能够省略了。显卡芯片厂商依据标准来设计自己的硬件产品,以达到在API调用硬件 资源时最优化,获得更好的性能。有了这个桥梁。便可实现不同厂家的硬件、软件最大范围兼容。

眼下PC游戏与显卡之间的桥梁主要有两个—DirecX和 OpenGL。可能会有人觉得DriectX是一个专门的图形API,事实上,DirectX并不局限于显示领域。眼下的DirectX中包括有 Direct Graphics(Direct 3D+Direct Draw)、Direct Input、Direct Play、 Direct Sound、Direct Show、Direct Setup、Direct Media Objects等多个组件。它提供了一整套的 多媒体接口方案。当中。Direct Graphics主要负责3D图形部分

初代的DriectX并不成功,技术上也不成熟。这样的情况一直持续DriectX5.0,DirectX 5版本号在D3D上有非常大改善,对D3D的内容做 了彻底改动,除此之外。很多应用程序接口的细节部分也得到了改进。增加了雾化效果、Alpha混合等3D特效。使3D游戏中的空间感和真实感得以增强。因 此,DirectX发展到DirectX 5才真正走向了成熟。而真正显现出DirectX的王者霸气而且的版本号是革命的DirectX7.0

DirectX 7.0增加了硬件几何转换与光源处理,及T&L技术。

尽管OpenGL中已有相关技术,但此前从未在娱乐级显卡中出现。 T&L技术将多边形设置,光影转换等大计量消耗CPU运算能力的工作转移给了GPU内的T&L单元进行,从而在一定程度上将CPU从繁重 的劳力中解放了出来

随后的DirectX 8.0中,T&L被Shader所代替。各种Shader单元的应用带来了图形特效的质的飞跃,DirectX 8.0使 GPU真正成为了可编程的处理器。

而DirectX 9.0则将各种Shader效果带入了FLOAT运算的时代在GPU出现的曾经,显卡和CPU的关系 有点像“主仆”,简单的说这时的显卡就是画笔。依据各种由CPU发出的指令和数据进行着色,材质的填充,渲染。输出等等。所以较早的娱乐用3D显卡又称 “3D加速卡”。因为大部分坐标处理的工作及光影特效须要由CPU亲自来运行,占用了CPU太多的运算时间,从而造成总体画面不能很流畅地表现出来。

随 着时间的推移。CPU进行各种光影运算的速度变的越来越无法满足游戏开发商的要求,很多其它多边形以及特效的应用压榨光了差点儿全部的CPU性能,矛盾产生 了……假设说不堪忍受的游戏速度催生了GPU的话,那么为GPU准备“产床”的则是我们这个世界上唯一的软件帝国:微软—当矛盾接近临界点时。 DriectX7.0来了。接着,1999年8月31日。NV10(就是GeForce)诞生了伴随着DriectX版本号的变化。GPU的发展也经历了3 个阶段:

1、剪除,变形,光照—T&L以及第一代GPU

第一代GPU的最重要的特点就是在硬件级别上实现了T&L运算,其代表有:NV10/15(Geforce256/2GTS/MX),R100 (Radeon256/LE)。Savage2000等,因为这一代GPU的基本工作原理同样,所以这里我们以Geforce2GTS为例。来看看第一代 的GPU是怎样工作的首先。CPU将数据传递给GPU进行处理。数据先进入T&L单元中的Transform Engine,在这里,数据将以顶 点的形式接受视野范围的推断,当处理单元推断某部分顶点处于观察者的视线范围以外时,Transform Engine将把这部分顶点“剪除”以使其不会 干扰兴许的流水线操作, 具个简单的样例:当你在某FPS游戏中突然打开狙击枪的狙击镜,视野变成了一个圆形的空洞。而其他部分则为黑色。这时 Transform Engine将去除这个圆形视野范围以外的全部顶点,只是。这里进行的仅仅是视野范围的推断。Transform Engine去除在 你的视线范围内可是被其他东西挡住了的物体,另外。每个三角形可能被旋转。放大/缩小,上升,下降,左偏。右移等。 这就是多边形转换转换。 Transform Engine依据你的视角,改变了由程序提供的组成3D物体的顶点的坐标。

经过Lighting Engine处理后的图象经过推断 处理后的数据将流入T&L单元中的Lighting Engine,依据光源的类型,距离,角度,数目。应用方式等不同參数,每个多边形都会有 不同的光影表现和光影关系。因而须要不同的光线函数予以表征,在Lighting Engine中,处理单元将依据软件提出的光源分布情况为每个顶点计算 出它所具有的光线矢量,以便兴许进行的光线纹理贴图,着色等操作

经过Lighting Engine处理的画面

事实上,经由T&L单元处理过的数据还不过抽象的数据。并非详细的图形,上面两副图不过方便读者进行想象的示意图。

接下来数据将流入Setup Engine,在这里。运算单元将进行三角形的设置工作,这是整个画图过程中最重要的一个步骤。Setup Engine甚 至直接影响着一块GPU的运行效能。

三角形的设置过程是由一个一个的多边形组成的,或者是用更好的三角形取代原来的三角形。在三维图像中可能会有些三角形 被它前面的三角形挡住,可是在这个阶段3D芯片还不知道哪些三角形会被挡住。所以三角形建立单元接收到的是一个个由三个顶点组成的完整三角形。三角形的每 个角(或顶点)都有相应的X轴、Y轴和Z轴坐标值。这些坐标值确定了它们在3D景物中的位置。同一时候,三角形的设置也确定了像素填充的范围

经过Setup Engine处理的画面

终于着色完成的画面

在三角形设置完毕后,T&L单元的所有运算就完毕了。接下来数据将进入NV15独有的NSR像素处理单元进行一定的像素处理。接着流入像素流水线 进行兴许的纹理像素填充等操作,这部分操作在DriectX7.0中的变化并不明显。主要的渲染填充过程与过去的显卡几无二异

T&L尽管再一定程度上缓解了CPU运算能力的不济所带来的瓶颈。使得系统在图形方面的资源得到了再分配和增强,但同一时候,T&L也将新的矛盾转到了GPU上

T&L是一组相对固定的简单的图形函数,所实现的特效受到了函数本身语句的限制。尽管这样的固定的指令集设计能够带来比較高的运行效率。但这样的设置 使得DX7下所能实现的特效受到了指令集的约束。很多逼真的特效无法实现。程序猿的思想也被限定在一个相对狭窄的范围内。

2、我要看到你飘逸的秀发和迷人的微笑—可编程Shader以及第二代GPU

DriectX8.0在传统T&L的基础上增加了两个新的概念—可编程的Vertex Shader和Piexl Shader,相同的,第二代 GPU的标志就是硬件级别的可编程Shader运算。代表产品为NV2X(Geforce3/4Ti),R2XX(Radeon8500)等

可编程Shader的复杂程度远非T&L可比,为了方便大家理解第二代GPU的特点,我们先来认识一下什么是可编程Shader。以及可编程Shader运算单元

可编程Vertex Shader及顶点处理器:

可编程Vertex Shader让程序猿可以对特定物体,甚至整个画面的每个顶点。指定特别的运算程序,却不须要CPU介入。

每个顶点都携带相当多 的信息,比方坐标,重量。法线。颜色,纹理坐标,雾和点大小数据。顶点处理器可以以简短的程序来改变上述这些信息。 这些小程序直接由顶点着色引擎本身执 行,不必劳驾CPU。 典型的T&L引擎将程序猿限制在3D运算的光影转换之前, 在有了顶点处理器的支持之后,游戏设计师对游戏场景里的3D物 体可以为所欲为的操纵变化。并且不须要用到中央处理器。

这导致了一场革新,程序能够改变顶点的坐标。这样基本上改变物体的形状,以达到更接近真实的移动、移动残影、混色、内插(在两种外型间转换)。以及变形, 比方改变角色脸部的骨骼和皮肤一个产生一个适时的微笑。

也可改变顶点上的颜色数据和纹理坐标,物体表面的颜色达到设计师所想要的色彩效果、投影、凹凸贴图 设置(如Blinn Bump mapping)或者其他投射的纹理。光源也能够为程序猿随心所欲的调整。不再像过去那样须要对光源的效果进行笨拙的光线 纹理贴图,而这些在曾经是不可想象的。这一切都归功于可编程Vertex Shader和顶点处理器的出现

Blinn Bump mapping

可编程Piexl Shader以及像素处理器

在NV15中。nVidia以前尝试增加一个叫NSR的像素处理单元。它能够在数据进入像素流水线之前对每一个像素进行一系列运算操作,尽管同为每像素操 作,但NSR与Piexl Shader可不能同日而语。 NSR对于像素的运算仅仅有7种。同T&L一样,它依旧是固定模式的,程序猿依旧要按照 规定好的条条框框写出程序,而Piexl Shader则不同。我们能够用很多不同方式去编程,以实现不同的特效,以下就是一般的像素处理器所具备的特 性:

· 阴影贴图

· 高速纹理加载

· 影像乘法。对称核心

· 支持4096x4096或512x512x512 纹理

· 立方体贴图每边可4096x4096x32-位

· 支持YUYV的纹理(自己主动转换成RGB三原色)

· 支持全景贴图

能够指向不论什么一个图像,如背景缓冲区(back buffer),而可直接当作纹理使用

· 边缘色彩及边缘纹理

· 硬件同步化读/写

对同一张纹理的读及写同意全流水线操作。

能够对背景缓冲区着色。然后立即能当作纹理使用

· Pass through colors

· 支持DX6规格的环境凹凸/亮度贴图(就是环境凹凸贴图)

· 简单的纹理。S,T 在alpha/红(AB)及蓝/绿 (BG)

· 等向的两方向性反射分布功能光源

· 内积产生色彩贴图或Z坐标

· 真实反射凹凸贴图

这看起来似乎有点抽象。简单的说。可编程Piexl Shader实现了一个很重要的特效—真实的毛发

古老街道上昏暗灯光中的狼人

在3D渲染中,渲染真实的毛发一直是一件非常困难的事情,大量的多边形给多边形生成带来了严峻的考验,而每一根毛发之间复杂多变的即时光影关系更不是几个简单固定的指令所能实现的。

Piexl Shader的可编程性和运算能力非常好的攻克了这个问题

好啦,如今让我们来看看第二代GPU是怎样完整处理一个画面的吧

首先,来自CPU的各种物理參数进入GPU,Vertex Shader将对顶点数据进行主要的推断,假设没有须要处理的Vertex效果,则顶点数据直 接进入Transform&Lighting Unit进行传统的T&L操作以节约时间提高效率,假设须要处理各种Vertex效果,则 Vertex Shader将先对各种Vertex Programs的指令进行运算,一般的Vertex Programs中往往包括了过去转换,剪 切,光照运算等所须要实现的效果,故经由Vertex Shader处理的效果一般不须要再进行Transform&Lighting操作。另 外。当遇到涉及到曲面镶嵌(把曲面,比方弓形转换成为多边形或者三角形)的场合时。CPU能够直接将数据交给Vertex Shader进行处理

另外,在DX8.0的Transform过程中。Vertex Shader能够完毕Z值的剔除。也就是Back Face Culling—阴面隐去。这就意味着除了视野以外的顶点外,视野内被前面顶点遮住的顶点也会被一并剪除。这大大减轻了须要进行操作的顶点数目

接下来,经由Vertex Shader处理完毕的各种数据将流入Setup Engine,在这里一如既往的进行三角形的设置工作,到这里为止,Vertex Shader的工作就完毕了

过去,设置好的三角形本来应该带着各自全部的參数进入像素流水线内进行纹理填充和渲染,但如今则不同,在填充之前我们还须要进行Piexl Shader的操作

事实上Piexl Shader并不是独立存在的。它位于纹理填充单元之后,数据流入像素流水线后先进入纹理填充单元进行纹理填充。然后便是 Piexl Shader单元。经由Piexl Shader单元进行各种处理运算之后再进入像素填充单元进行详细的着色。再经由雾化等操作后。一个完整 的画面就算完毕了

值得注意的是。第二代GPU中普遍引入了独立的显示数据管理机制。他们位于Vertex Shader,Setup Engine以及像素流水线之间,负 责数据的更有效率的传输、组合,各种无效值的剔除。数据的压缩以及寄存器的管理等工作,这个单元的出现对整个GPU的工作效率的保证其到了至管重要的作 用。

HyperZ系列:HyperZ技术本身就是一种类似nVIDIA的“Z-封闭甄别”的技术,可是比nVIDIA还更进一步。

它的主要功能简单说来就是分 析在Z轴上的场景,被遮挡的就会被忽略掉,仅仅渲染我们能看到的部分场景。然后对渲染过的Z轴场景进行压缩处理。数据的压缩可降低他所占用的空间。从而在存 取Z-Buffer数据的时候能够保留很多其它的显存带宽。并且这是一种画面质量没有损害的压缩算法。并不影响画面质量。最后一步就是把经过渲染的场景中的Z -Buffer信息立马清除掉。这样就更加大了显存带宽的利用率。

LMA(光速显存架构)系列:光速显存架构採用的第一个技术是“显存交错控制”技术。 LMA中的显存控制器划分成了4个独立的显存控制单元,每一个单元最 大能够进行32bit图形相关数据的存取工作。而且这4个单元之间以及它们和图形处理单元之间都保持密切的通讯联系,并随时协调平衡各个子单元之间的数据 流量,因此总体来看LMA的显存控制单元还是能够进行128bit数据的存储,可是保证了显存带宽的充分利用。光速显存架构採用的第二个技术是“无损Z压 缩算法”。

传统的图形芯片对于每一个待渲染的图形象素都要进行Z轴数据的读写工作。因此存储这些数据的Z缓存一向是消耗显存带宽的大户。LMA中集成了硬件 “无损Z压缩”单元,採用“无损Z压缩算法”对Z-缓存数据进行4:1的全然无损压缩。 光速显存架构採用的第三个技术是“Z-封闭甄别”。排除了图象中 被遮盖住而不可见的部分,这样GPU就不做隐面模型构建(节省处理器的多边形运算资源),而且渲染管线也不正确隐面进行渲染(无需从帧缓存中读写隐面资料数 据,节省渲染管线的象素和纹理生成资源并全然消灭了隐面资料对显存带宽的占用)。

最后,LMA还包含了4组快速Cache,对传输数据进行缓冲。

3、梦中的镜花水月—可编程Shader2.0以及第三代GPU

当你第一次看到3Dmark03中的MotherNature时。你有没有感觉到震撼?

更加宽泛的色彩范围可以使得图形的逼真度上升,这就是Shader2.0的由来,Shader2.0的核心实际上就是以扩大指令数目以及FLOAT数据形 式的应用来提高色彩表达的准确度,而第三代GPU的Shader单元也由此而具备了高精度FLOAT色彩数据的运算能力。从一般角度来讲,第三代GPU同 第二代GPU相比在主要的操作控制形式等方面并没有本质的差别,可是因为Shader2.0更大的指令长度和指令个数,以及通用程序+子程序调用的程序形 式等使得第三代GPU在处理高精度的庞大指令时效率上有了明显的提升。同一时候也使得第三代GPU的可编程性跃上了一个新的台阶

让我们来看看第三代GPU究竟有哪些改进吧

Vexter Shader部分

第三代GPU的顶点处理器部分除了一般的操作功能外还具备流程控制能力,包含循环,跳跃以及子程序调用等。这些控制指令以及很多其它向量(或标量)寄存器的应 用使得顶点处理器可以以更高的效率运行Vertex Programs,提高了Vertex的处理速度。同一时候,加大的指令长度和指令数量使得顶点处理器的 功能得到了进一步的强化。

另外,在第三代GPU中,传统的T&L数据将全然交由顶点处理器来运行,Transform& Lighting Unit将彻底被顶点处理器“吞并”。这也是第三代GPU的一个重要特点

Piexl Shader部分

第二代GPU的Piexl Shader仅仅能实现INT数据的运算。这势必会带来终于运算结果的不精确。而数据的不精确导致了颜色表现的不准确,干扰了最 终画面的质量以及效果的表现,第三代GPU的重点改进就是运算单元和寄存器所支持的运算格式。如今Piexl Shader能够进行更高精度的FLOAT 运算和输出。从而使得图形的色彩显示更加精确

暴光正确的图象

数据精度不当而无法实现的特种暴光

另外,第三代GPU的像素处理器每周期所能处理的材质以及指令也分别添加了数倍。这些新特性使得第三代GPU能够处理各种复杂程度的效果,营造一个更为真实的3D画面。比方更加真实的水面效果

INT Piexl Shader所表现的水面效果

FLOAT Piexl Shader所表现的水面效果

传统的INT无法表现宽泛的波浪效果,程序猿害怕数据精度范围狭窄引起的上溢或者下溢的发生而不得不在一个非常小的物理參数范围内控制涟漪水面所需的波长、 波浪的大小、移动速度以及反射和折射效果等。如今,因为数据精度的提升。像素处理器全然能够处理一个非常宽泛的数据精度范围,避免数据的溢出,这就使得更 加真实的水面效果得以被表现。第三代GPU的代表是NV3X系列,R3XX系列等,当中R3XX系列的基本处理方式和顺序与第二代GPU在本质上基本相 同,不过Vertex Shader和Piexl Shader的详细操作细节和运算精度上有些许不同,而NV3X尽管在基本原理上也与之大略同样,但 从流水线的角度来看则与全然不同,应该算是个“异类”。产生过程,仅仅分析一下NV3X

以NV35为例:

首先。他具有8个纹理帖图单元,但8个纹理贴图单元并不在固定分布于每一条Piexl流水线,而是集簇在一起,依据情况来搭配,能够是4*2、8*1。

其次。他具有12条Shader流水线,但没有全盘採用浮点渲染流水线。而仅仅是把12条Shader流水线中的8条做成具备浮点处理能力;只是所有12条Shader流水线都具备Fixed-Point Shader的运行能力。

另外,NV3X将流水线后部的各种渲染单元,如雾化,Alpha混合等大幅削减,使得流水线在一定程度上公用这些单元

NV30的构架组成形式基本上与之相当,仅仅是数目上略有不同

因为这个构架并非传统意义上的4*2或者8*1的固定构架,我们不能象过去那样说NV35“每一个流水线具有2个纹理帖图单元”或者“每条管线具有3个Shader流水线”……我们仅仅能说“NV35单位周期能够完毕8次左右的纹理贴图或者12次Shader操作”

另外。因为NV3X对于Fixed-Point Shader的支持精度是FP16和FP32。同一时候NV3X的Shader流水线的单位Fixed- Point Shader处理精度是16位,所以当遇到32位Fixed-Point Shader数据时,能进行Fixed-Point Shader 数据处理的8条Shader流水线也会依据情况进行搭配来运算32位的Fixed-Point Shader数据

Pixel Programs往往是由多条指令构成的,不同的指令须要不同的运行时间来完毕,每一个像素必须在应用在它“身上”的Pixel Shader 操作完毕后才干由像素流水线写入到帧缓存里。故此。对于应用了Piexl Shader的像素实际上是须要多个以上的周期才干写入到帧缓存里,假设採用8 条完整的渲染流水线的话。 流水线后面的雾化、色彩混合等单元非常多时候都会处在等待阶段。这部分单元须要占用的晶体管数量不在少数,假设这样浪费就怪可惜 的,砍掉后当中的雾化等单元后。对总体的性能尽管有一些影响,可是却能够把节省下来的晶体管用于加强Pixel Shader的功能和性能上来,同一时候能够 保证比較高的多重纹理效率,利大于弊。

简单的,这个有点诡异的体系节省晶体管的同一时候能确保相对较好的Pixel Shader效能,同一时候还有极高的多重贴图效能

nVidia本指望4条Pixel管线+ 12条Shader流水线的设计可以在如今以及未来较长的一段时间的游戏里提供超过4条甚至8条 Pixel Pipeline显卡的效能。只是,实际情况却与nVidia的初衷有些背道而驰。Shader的完美应用带来的一个结果就是越来越好的非多 纹理光效果,传统的多纹理贴图才干表现的非常好的光效果如今仅仅须要进行一次贴图或者直接使用Shader就行达到。这使得NV3X的设计成为了空架子。实 用意义大大减少。而在单纹理处理过程中因为NV3X的兴许效果单元被削减,它的渲染效能注定没有传统的完整流水线高,另外,因为DX9中的终于FP精度被 定义为FP24。这导致了NV3X的相对低下的FP效能。终于。本来“先进”的NV3X构架落的个总体效能低下的下场

从本质上来讲,图形数据在NV3X中的实际处理过程依旧是沿着顶点处理器—Setup Engine—像素流水线的顺序进行的,这与R3XX以及全部的第二代GPU是同样的

天堂的入口—可编程Shader3.0,DriectX Next以及未来的GPU

在微软刚刚发布的Driect9.0C中。Vertex Shader和Piexl Shader已经具有了差点儿同样的能力。而在nVidia新发布的第 四代GPU—NV40中。我们发现Vertex Shader包括了4个纹理取样器。能够使用texld指令进行查表操作, NV40能够在一个 shader pass里完毕4个纹理的读取,这个对于通用替换贴图而言相当的重要,有了vertex texturing功能后, vertex shader就能读取纹理信息直接映射到顶点上,以实现displacement mapping(位移映射)等等效果,用不同的纹理和较 少的顶点传输时间就能实现外形复杂、平滑的模型,这表明GPU中Vertex Shader的功能正在逐渐接近Piexl Shader。随着GPU的发 展,未来GPU中的Vertex Shader和Piexl Shader终于将被合并成一个统一的处理单元—Intergrated Shader。两 种处理单元将使用全然同样的语法以及指令集。Shader的统一将带来全然不同与如今的数据运行处理方式,GPU的内部结构将发生本质的变化, Intergrated Shader带来了更低晶体管数目的解决方式,以更少的晶体管数目来完毕如今须要数亿晶体管才干完毕的功能。同一时候统一 Shader将引出类似全通用I/O接口的设计以利资源的更合理的传输和分配,同一时候,为了解决越来越庞大的数据量,虚拟显存、无限资源訪问以及帧缓冲操作 等技术的引入也势在必行。

另外,我们在DirectX Next中还发现了整数指令集,处理器等特殊的定义,这些新颖的设计为我们勾勒出了未来GPU的轮 廓

整数指令集

在编程中不必在操心指令限制是一个非常大的进步,只是想使得GPU更为通用还须要很多其它的工作。一个须要提高的主要区域就是整数处理能力。眼下基于在着色器中 处理的全部数据都是浮点,这对于大多数显卡操作而言是没有问题的,只是不适合动态分支预測、非内插式显存搜索(如顶点缓冲的索引)等操作。在眼下的GPU 中。唯一的内存寻址就是纹理查找,使用的也是浮点值。

这种情况对于纹理定位而言没有什么问题,只是对于通用内存寻址而言就不合适了,这里的连续内存块可 以全然彼此没有关联。採用内插式查找没有不论什么意义。微软对于这种情况,在4.0版的Shader模型中引入了全新的、完整的整数指令集。

拓扑处理器实际 上,眼下的显卡能够在某些情况下新生成三角形,比方在用到直线以及点的时候。大多数的娱乐级显卡仅仅具备对三角形进行光栅化处理的能力。这也就意味着全部的 点、线就必须转化为三角形。

点和线在最后都将以2个三角形结束。这样就须要用到2-6个顶点(依据索引方式的不同而变化)。

从本质上来说,这种做法是有 益处的,通过可编程的管线,显示先前应该遮蔽的场景也就无需通过CPU,而能够通过微软的“拓扑处理器”直接完毕。

从逻辑上来说,这个拓扑处理器和镶嵌单 元是相互独立的,这个处理器在两种操作集中均能够使用。由眼下的趋势来看,未来的GPU将向着高运算能力,高精度,高通用性的方向发展,GPU在工作方式 上将越来越接近CPU。因为高通用性等CPU特性的引入,GPU可能在一定程度上替代一部分CPU在非画图领域的工作。或许在未来我们会看到由全GPU组 成的图形工作站。虽然未来GPU须要面对因为这些改进而带来得的诸多问题。尤其是通用性导致的效率低下,比方Intergrated Shader的效率 低下,但随着时间的推移,各种问题都将会得到妥善的解决。

posted on 2017-08-10 18:01  blfbuaa  阅读(944)  评论(0编辑  收藏  举报