前言:时间总是在不经意间就从指缝中溜走了,一转眼GPU大百科全书的连载已近过半了,感谢诸位在这些日子里的陪伴和坚守。在过去的近3个月里,我们在GPU的流水线中进行着各种各样新奇的游历,我们随着一组又一组的数据,从几何端进入到GPU内部,先是经历了赋予图形灵魂的几何调整过程,接着又面对了收割生命一般的光栅化阶段,然后又在shader单元当中目睹了全新图元生命的诞生。相信这几段风格迥异但目的相同的旅程,已经能够让你对各种对应的图形单元以及整个图形流水线的作业情况有所了解了。在今天的GPU大百科全书中,我们将来到GPU的另一个重要单元——Texture Array面前。 图形流水线是一个in-order的顺序执行过程,所以我们的旅程才可以按照“几何—光栅化—接下来的步骤”这样一步一步的进行下去。但当我们来到光栅化单元之后的部分时,岔路出现了。实际上对于像素的处理以及对于材质的处理是没有绝对的先后次序的,像素单元处理好像素特效,材质单元抓取并完成贴图操作之后,ROP才会将两者混合。因此,本篇GPU大百科全书的阅读过程免不了要跟前一章发生许多联系,希望读者们能够在阅读时建立并适应这种联系。 其实纹理单元,或者说大家见得更多的称呼——TMU单元,其工作内容以及结构相对其他单元来说都不复杂,相信本章的阅读不会给大家带来太多的困惑。那么接下来,就请大家放松心情,一起看看Texture Array的故事吧。在今天的故事中你不仅可以领略TMU单元成长的点滴精彩,更能看到一个泥瓦匠最终成长成数学家的奇闻。 另外,我们将会换一种更加轻松的方式来演绎今天的故事,如果你是一位想提前接触故事核心然后再返回来补充细节的读者,可以考虑直接点击这里。 好了,关于TMU单元的故事,现在开始了。 其实,Texture Array是一个较新出现的词汇,它的目的在于应付材质单元从传统的单一贴图操作转向更加全面应用的需要。在更早的时候,纹理单元其实一直都被称为Texture Mapping Unit,也就是我们熟悉的TMU。 材质操作可以说是整个图形操作中最为古老的部分,由此而生的纹理单元也就成了整个图形硬件中最资深的单元之一。TMU的作用,归根到底就是对材质的贴图和过滤操作。根据程序的需要,在完成几何处理和光栅化之后,TMU单元会从材质库中找出合适的纹理贴在对应的位置上以实现模型的外形完整化,这就是TMU单元的日常工作,这工作从本质上其实和泥瓦匠没什么太大区别。在3D图形出现之初,人们通过贴图来实现几乎全部的特效,对于早期的图形硬件来说,材质性能几乎就意味着一切性能。几乎每一家厂商的硬件都以填充率为金科玉律,如果你的填充率比我多个几M,弄不好我的硬件销量就要下滑好几个百分点。 在那个仿佛已经成为歌谣一般的遥远时代,TMU单元有着怎样境遇呢? ● 年幼无知,它曾经是骗子的帮凶 也许你想象不到,TMU最初干的最多的工作,是欺骗。 我们曾经在ZOL显卡探索与发现频道的诸多文章中回忆过整个图形特效的发展史,整个图形特效的发展史,几乎都是围绕着光与影展开的,而光与影的背后,则几乎就是一个关于欺骗的故事。 由于来自硬件以及图形算法实用化本身的限制,最初的图形特效几乎全部来自TMU。人们将预先设计好的效果烘焙成现成的纹理,而TMU单元则根据程序需求机械地将这些现成的材质搬到对应的多边形上去。虽然这几乎不可避免的让TMU直接的参与到了欺骗眼球大行动的核心中,但TMU没有选择,人们也没有选择。对于光与影这种直接影响空间视觉感受的效果,在当时除了拙劣的光照贴图以及类阴影贴图之外,根本没有其他手段可以实现,而光影效果恰恰又是一切立体感以及特效的基础,甚至是整个图形工业表现效果的基础。于是,TMU就这样背负起了实现几乎所有特效的责任,不得已上了贼船,开始了漫长的骗子生涯。 既然没有其他手段,人们只能勉强的依赖着纹理来实现各种特效,而想要实现更好的效果又需要硬件具备一定的功能和性能,于是改进TMU和材质操作手法就成了唯一的出路。那么究竟怎样才能让欺骗进行的更有效率,甚至达到以假乱真的地步呢?答案就是多重纹理贴图。 由于本身依托固定的预制烘焙材质的先天缺陷,材质贴图很难准确的完成对效果的表达,尤其是传统的单次贴图操作,这种操作不仅导致了过低的填充效率,同时也无法充分满足纹理精细度的要求,于是,基于单周期双重以及多重纹理操作的改进就成了人们迫切的需求。多重纹理贴图与以往最大的不同,在于它能够让TMU以一个周期为单位实现二重至四重,甚至是更多次的材质贴图操作。复合贴图的好处是显而易见的,他可以让多边形表面拥有更好的图案和色彩表现,从而提升物体细节的真实度,同时又不会牺牲太多的操作周期从而降低帧数表现。由于几乎是唯一的可选择对象,多重纹理贴图一经出现便马上获得了业界的广泛支持,得益于这种支持,TMU单元也得到了极其快速的发展。当时支持多重纹理贴图的VOODOO2(部分支持,需SLI)和TNT代表了那个时代最高的性能水准,甚至对多重纹理贴图的支持一度成了界定高端显卡的分水岭。 或者说,界定高端骗子的分水岭…… 应该说,将此时的TMU单元划分进坏人的行列是不公平的,毕竟在迅速增长的图形需求面前,所有人都没得选择,只能使用纯材质操作这种权宜之计来。但当时人们对于材质操作的热情,尤其是多重纹理贴图出现之后对材质应用的过度热衷,以及TMU单元的快速增长,从各种意义上来说都对今后的光栅化渲染过程产生了重大的影响。在此我们暂且按下不表,先来看看TMU接下来的命运转机吧。 ● “好碰友”就是来分担责任的 尽管引入了多重纹理贴图机制,单纯的材质操作依旧无法满足人们对图形特效的需求,随着供求关系链,这种不满最终转化成了程序员无法实现希望实现特效的恼怒。提前烘焙好的材质是不可能将全部场合的效果需求都考虑完全的,面对或多或少都有些不大对劲的材质,程序员非常渴望能够拥有修正他们的力量。于是,能够在流水线中自由操作部分像素的可编程shader出现了。 在上一章GPU大百科全书中我们已经介绍过了,通过可编程shader,程序员们对材质表面特定位置的像素进行“精修”,为其加入适当的光线关系等与颜色相关的处理。经过shader处理的像素可以表现出正确的颜色,而当所有像素的颜色都趋于正确时,整个图像都达到或者起码是接近程序员原本想要表达的效果了。TMU单元只需要贴出能够表达正确物体外貌的材质,剩下的事情交给shader去做就可以了。不难看出,在可编程shader出现之后,TMU的工作就从原来的实现全部特效很自然的过渡到了为各种特效提供基础上。 这么一个不经意的自然过渡,对TMU单元以及为实现特效而工作的人们来说却几乎意味着完全的解放。有了直接操作像素的手段,程序员们不必再为材质的不准确而垂头丧气,他们可以自行调节像素以弥补材质本身的不足。美工们也不需要再绞尽脑汁考虑和准备尽可能多的材质来满足光影效果,他们不用再考虑那根本不可能通过“考虑”来照顾周全的现场需求,只需要准备细节足够精致的材质即可。卸下光影和颜色负担的TMU单元则更是从所有压力的承担者摇身一变成了“高薪低责”的小布尔乔亚,为所有物体提供正确的表面细节让TMU继续扮演着图形渲染过程中不可或缺的重要角色,但同时TMU却又不必再对最终特效负责,起码不用负全部的责任,这种地位无可替代同时又不用担全责的感觉,我想每个人都会羡慕不已吧。 可编程shader单元的出现直接改变了TMU单元的命运,TMU不再是混合操作之前实现特效的唯一选择,这不仅卸下了TMU单元的负担和责任,更为今后更加广阔的材质应用前景,甚至是通用计算领域的发展打下了良好的基础。TMU与可编程shader单元的这种“基础—修饰”的配合很快就成为了程序员们实现特效,或者说近乎完美的欺骗我们眼睛的常规手段,这对好碰友的合作为我们带来了10年得特效高速发展期。 既然卸下包袱轻装上阵,同时角色也从过去的单一特效实现者变成了为特效提供基础的单元,这种无异于人性解放的过程,不仅让TMU理所当然的进入了轻快以及高速的发展状态,而且反而催生出了很多过去想象不到的材质操作特效。
模板阴影贴图存在各种荒唐的错误“好碰友”就是来分担责任的
shader可以实现单纯贴图无法实现的皮肤效果
卸下包袱的TMU单元一直处在高速发展的节奏中,这些发展除了围绕着相对传统的更高材质分辨率、更好的过滤效果以及更好的贴图手段来进行之外,最引人瞩目的地方来自对TMU的多样化使用。TMU单元第一次在操作手法上重要的大发展,来自于DirectX 9.0C。
DirectX 9.0C游戏效果
DirectX 9.0C是一个足以名流计算机图形学发展史册的API版本,虽然它仅仅是DirectX 9.0的一次升级,但这次升级却带来了诸多令人印象极其深刻且意义深远的改进,比如长度达65536、已经近乎于无限长度的指令,分支、跳转以及流控制等指令形式的引入,MRT的首次出现等等。在这一系列重大的改进中,有两样是关于TMU单元的,一个是Shader Modle3.0引入的VTF(Vertex Texture Fetch),另一个则是TA/TF单元的分离。
VTF可以被简单直接的翻译成顶点纹理拾取,尽管这种基于Vertex Shader的技术严格意义上并不属于TMU单元本身的改进,但它对TMU单元的操作以及可实现特效的发展有着深远的意义。VTF允许Vertex Shader单元直接访问材质库,并从中读取含有基本光照信息的材质然后贴在完成处理的几何模型表面。由于Vertex Shader包含全部操作之后的顶点信息,其中的重要的信息之一就是顶点相对于网格平面的高度值,因此VTF最大的意义,便在于可以让TMU以比过去方便快捷许多的方式来实现对高度及视差极其敏感的环境凹凸贴图特效。
物体表面的凹凸感,很大程度上来自凹凸带来的光线明暗度的不同,突出部更亮凹陷部更暗对于我们来说是非常自然的视觉经验。如果采用常规的贴图手段,表现暗部细节需要借助阴影贴图来完成,这样做不仅效率低下,而且过多的表面细节显然会给TMU单元带来沉重。现在好了,结合顶点的高度值,VTF可以直接将材质的所有颜色全部转化成灰度,然后根据高度差对灰度进行重新排序和修改,高度值较大的材质灰度也较大,而高度值较小的材质灰度也较小,最终的效果也就自然的变成了物体表面凸出位置的材质亮度正常或者较高,而凹陷部分的材质亮度则相对较低,这就带来了非常自然的视差凹凸效果。VTF的操作方式对于TMU来说几乎就是革命性的,它的出现不仅让TMU在不付出沉痛代价的前提下实现更好的物体表面细节,甚至成了让TMU进军通用计算领域以及GPGPU出现的发端。
相对于VTF,TA/TF分离的改进不仅目的简单直接,而且操作过程也非常简单。随着纹理技术的发展,Texture Address(纹理定址)以及Texture Filtering(纹理拾取)过程以及这两种操作的比例发生了巨大的变化,传统的TMU单元已经无法满足新的定址及拾取操作的需要,因此从DirectX 9.0C开始,TMU单元正式分割成了TA和TF两个部分,TA单元专门负责材质的定址操作,在完成定址之后,TF单元根据定址结果对材质进行拾取并完成贴图作业。
TA/TF的分离不仅提升了整个纹理单元的操作效率,更为材质单元规模的扩展提供了更加多样化的选择,人们可以通过分析指令中定址及拾取操作的比例,来调节构架中TA/TF的比例,从而达到晶体管利用率最大化的目的。也正是从这里开始,TMU这个沿用了很长时间的名词变得不再能够精确的描述纹理单元了,于是Texture Array这个全新的名词也就应运而生了。
技术的发展在不断的督促着GPU内部各个单元的快速进步,纹理单元也不例外。尽管它已经改名叫Texture Array,而且拥有了TA和TF这两个完全不同的组成部分,但人们还是喜欢叫它最开始的名字——TMU。在DirectX 10/10.1的带动下,TMU单元继续维持着自己的发展,又具备了两个非常好用的改进——纹理阵列以及Gather指令。
使用纹理阵列实现的效果
纹理阵列(Texture Array)的名字乍一看与纹理单元新的名字是一样的,但他们的含义并不相同。作为单元出现时,Texture Array代表着“处理材质操作的纹理单元阵列”,而作为操作手段出现时,其意义则变成了“允许由一条指令完成读取的材质的集合”。
尽管GPU本身已经拥有了极大地独立性,但对于DirectX 10之前的GPU来说,图形处理的基本要素,也就是对图形函数的调用,仍然是由CPU来进行的。当GPU存在操作需求时,CPU会调用对应函数并将之发送给GPU流水线。传统的贴图操作的基本单元是材质本身,TMU单元在进行贴图操作时会以某个材质的需求为起点发起一次函数调用请求,而CPU则会以执行函数调用并将之发放给GPU作为回应。不难发现,每一次TMU对材质的操作都会让CPU进行一次函数调用操作,如果TMU需要在多个材质之间进行切换,就需要发起多次函数调用请求,而CPU则要进行多次的回应,尽管函数调用本身对于CPU来说是一项简单到几乎完全不构成任何负载的工作,但这种切换以及CPU的频繁介入却给材质操作和CPU本身带来了极大地切换延迟负担。
纹理阵列的出现很好的解决了这个问题。DirectX 10允许每512个材质组成一组阵列,该组阵列中的任意一个或者多个材质均可以通过一条TEX_LOAD指令进行读取,与此同时,得益于Unified Shader所带来的指令格式的开放化以及指令长度的无限化,TEX_LOAD本身已经可以很好的融入到shader program中,直接由GPU就近执行,而不再需要想过去那样频繁的向CPU发出请求以及在函数之间进行切换。Texture Array的出现不仅让CPU得到了进一步的解放,更让TMU单元有了更好的执行效率和决断权。过去读取材质需要CPU来喊口号,现在则终于可以由TMU自己做主了。
相比纹理阵列简单直接的对实在纹理操作过程的助益,Gather指令的作用和意义相对复杂一些。Gather指令的作用,在于允许单元从非连续存储器地址中直接读取数据。换句话说,Gather指令并不仅仅是针对纹理单元的改进,它可以让所有需要从buffer/ram中读取数据的单元和操作获益。针对纹理操作,Gather指令的引入带来的改进是非常巨大的,对非连续地址的快速读取不仅可以大幅加快定址和拾取过程,整体提升TMU单元的纹理操作效率,为更加优秀的阴影效果、采样以及SSAO提供帮助,更为纹理单元进入数学应用领域打开了另一扇大门。
应该说截止到DirectX 10为止,对于TMU单元的改进主要还都是基于可见的或者说实在的纹理操作领域的。它们都在以非常直接的方式提升着TMU单元的操作效率。尽管已经出现了Gather指令这种泛用性的甚至是有些抽象的变化,但总体来讲这些改进还都是可见的。当我们的技术进步发展到DirectX 11时,TMU单元的进步就开始变得更加抽象了。
● 反客为主 DirectX 11是一个值得图形业界记住的API版本。在这个版本中,微软第一次彻底打破了图形与运算的界限,最大限度的发动GPU内各种运算资源来为图形过程提供帮助。Compute Shader的出现不仅改变了人们对于显卡为通用计算买单很不划算的偏见,更令许多GPU的传统处理过程直接从数学中获益,TMU就是其中之一。 在DirectX 11中,微软通过取消Compute Shader的几何关联性,让纯数学形式的代码直接进入到指令当中去,这种改进让TMU获得了直接调用数学运算能力的机会。透过Compute Shader,Gather指令的效率得到了近一步的提升,这等效的大幅增强了TMU单元的动作效率,而新引入的粗糙偏导函数更是赋予了TMU直接以数学形式生成简单纹理的恐怖能力。TMU单元在DirectX 11中不仅前所未有的高效,而且在功能端也达到了史无前例的高度。 现在的TMU太过强大了,强大到有些喧宾夺主了。
Gather4指令
实际上从DirectX9.0C末期至DirectX 10初期开始,由于shader的极大发展,程序员更加倾向于使用Pixel Shader效果来改进游戏的特效表现。对于画面光线关系以及光影效果的刻画和描绘,自那时起就一直是画面质量和效果提升的主要手段,这种方向性的趋势直接反应在了指令密度方面,在API进入到DirectX 10时代之后,指令中纹理部分的比例就一直在持续下降中。微软正是顺应了这种趋势,才将整个API的发展思路确定成了以更加灵活和强大的shader能力为主。DirectX 10以及DirectX 11对于shader的诸多改进,尤其是DirectX 11对于纯数学代码及运算能力的开放,实际上都是在为Shader尤其是Pixel Shader效果的进一步发挥创造条件。
但是这种开放不光面向ALU及纯Pixel Shader,其本身也会导致TMU单元的大幅受益。
因为那个被反复强调的原因,我们的游戏界在最近几年一直停顿在以DirectX9.0C类应用为主的状态,程序员们的编程习惯并没有因为API的大幅进步以及编程环境的不断改善而跟着提升到新的高度。不管是出于无奈还是别的什么原因,在经历了一段时间的下降之后,指令中纹理部分的比例再一次提升到了一个新的高度。而恰恰就在此时,TMU单元适时的为大家奉上了改进之后各种强劲的功能和效率。再加上曲面细分等新技术的推动,我们面前的许多所谓DirectX 11大作,实际上已经成了以贴图和各种纹理操作为主,像素特效应用为辅的状态,我们看不到真正意义上的各种新技术的应用,看不到传说中的更高的执行效率,却只看到了几乎停滞不前的画面质量以及满眼的贴图操作。换句话说,图形业界辛辛苦苦十来年,现在又回到了解放前……
导致现在TMU单元喧宾夺主甚至回归复辟的根本原因,并不在单元本身,而在于单元的使用者。虽然画面特效的进步缓慢本身与其数学本质和市场及经济环境等都有极大的关联,但不可否认的是程序员们目前对强大的纹理单元的再次过分依赖,也是导致现状的重要原因之一。
我们无意评价TMU单元自身的功过是非,毕竟它只是一个单元。剑本凡铁,因执者之念而分善恶。既然我们改变不了环境,不如静下心来观察,看看大发展之后的TMU单元,究竟是如何动作的吧。
● 不要小看泥瓦匠的活计 在本文的开始部分我们曾经提到过,TMU单元的操作其实并不复杂,起码相对于前面几个单元来说并不复杂。从本质上讲,TMU单元所做的事情,就是在需要时扫描预先准备好的材质库,从中寻找出合适当前多边形需要的材质,然后把它从库中拷出来,加以适当的缩放调整及其他动作之后再贴到多边形表面上去。而对纹理单元的常规改进,也就是增加纹理操作单元的数量,使用更加先进的压缩算法来缩小纹理在操作期间的体积,加入适当的纹理过滤机制以保证其清晰度,以及为纹理单元配置更好的缓冲机制比如Tex Cache之类的琐事了。 是的,完了,就这么简单。明白了上面这些,你就已经算是明白TMU单元的作用和特点了。
纹理定址及拾取操作
相信从第一期GPU大百科全书开始一直阅读到这里的读者们都不难发现,我们在陈述某个GPU功能单元的作用和动作时,最基本的描述都非常简单明了。比如说几何单元就是根据CPU送出的顶点信息完成顶点设置调整、多边形连接以及基本蒙皮等几何和模型相关的动作;光栅化单元虽然收割了生命,但其作用本质上也不过就是完成了3D模型顶点坐标的平面化坐标变换;而像素处理单元的工作就更加直白了,它干脆就是个玩命跑RGB通道数据的计算器。这些单元的功能看上去是那么的简单,以至于笔者还能有闲心把香草MM也加入到描述当中为大家调节气氛。这种简单本质的描述,其实正是笔者一直以来所追求的效果。能够让每一个人都了解GPU单元各部分的特质,进而得以一窥图形世界的精彩,正是GPU大百科全书系列的初衷。
但是接下来,当我们触及到单元作用和动作的细节时,事情似乎就不再那么简单好玩了。各种由看似简单的基本特征出发引出的特殊功能以及概念,还有每一个单元发展所经历的各种历程,甚至是那些专有名词都让很多读者抓狂不已。其实,这恰恰反映了GPU构架的本质——GPU构架是数学原理最实体化的表现之一,它通过自身的结构,将晦涩难懂的数学体系翻译成了具体同时又绚丽多彩的画面。既然它是数学原理的实体化表现,那符合数学本身的特质也就没什么奇怪的了。数学虽然本身晦涩难解而且看上去深不可测,其最核心的本质实际上是建立相当简单但又牢不可破的几条公理之上的。今天气势恢宏的数学大厦,其基础不过是“1+1=2”和“平面上过两点有且仅有一条直线”这种小孩子都知道的道理而已。看似简单的本质可以推导衍生出近乎于无限复杂又精彩的世界,看似纷繁复扰的体系其本质又能以非常简单直接的方式来描述,这就是数学的魅力,同样也是GPU的魅力。
回到TMU单元上,尽管整个材质操作的本质,也就是TA单元根据需要对材质进行定址,然后交由TF去拾取并完成贴图的过程看上去十分简单,但这看似简单的过程背后同样蕴藏着无数的精彩推论和不平凡的延伸,比如多重纹理贴图,比如VTF的操作过程,比如纹理阵列,比如Gather指令……当然,还有那无限的可能性,比如——怎么看都是纯图形单元的TMU,能不能像ALU那样成为一名数学家呢?
其实,在对VTF过程进行描述时,细心的读者应该已经发现我们留下的引子了——VTF的出现,为GPGPU的出现打开了大门。这是怎么回事?TMU单元不是专干贴图工作的么?这么一个纯粹的图形单元怎么会跟通用计算以及GPGPU发生联系,甚至还为它们的出现“打开了大门”呢? 不要小看我们图形处理单元,扫地僧可能是世外高手,泥瓦匠同样也可以是数学家的。
扫地神僧
VTF操作的本质,实际上在于抽离材质的颜色信息,并将之转化成灰度数据,然后再将其与顶点数值进行对照并辅以相关的操作。“抽离颜色信息”,“转化成灰度数据”,“与顶点数值进行对照”,这不正是对一组数据或者说数组的操作么?
对于纹理的定址和拾取,本质上是对一定像素区域内颜色信息的处理过程,从材质库中拾取的纹理,其实就是一大堆像素数据的集合,所以这个处理过程本身其实也就是对数字的比对和改变。因此TMU单元这个看起来好像最为纯粹的图形操作单元,本质上其实也是在于一大堆的数据缠斗着。而VTF的出现,将这种本质更加彻底的暴露到了人们面前。GPGPU所要求的,正是对数据集合的直接处理,既然纹理可以等同于数据,那只需要将通用计算所要处理的数据关联成纹理模式,辅以对应的指令,不就可以让TMU单元来处理通用计算过程了么?
纹理单元所能够进行的各种通用计算中,用途最广且意义最大的就是傅里叶变换以及空域卷积过程。傅里叶变换在图像处理、波形分析、信号分析甚至金融分析等过程中都有极其重要的作用,而空域卷积过程的应用则更加广泛,其在统计学、概率论、声学研究、以及电子信号处理领域都有广泛的涉及,任何一个存在于世界上受物理学支配的线性系统均包含卷积。对这两种运算的直接加速,让TMU单元的意义不仅限于单纯的图形处理,更扩展到了极其广阔的科学研究及日常通用计算处理领域。
利用纹理与数据的对应关系,TMU单元可以将经过对应几何关联过程之后的材质型数据当做一般的纹理,对其进行正常的定址以及拾取作业,通过设计好顺序的常规的贴图操作或者滤波操作,运算的过程就被转换成了图形操作过程,TMU对这些数据进行过处理之后,结果可以通过几何关联的反向操作来进行释放,整个操作的过程还可以得到来自Gather/Scatter指令的协助。
GPU之所以有今天在通用计算领域的成就,一半的功劳归于ALU及通用API的快速发展,而另外一半,则离不开TMU单元的努力。ALU精于纯数学方法以及直接函数领域的计算与应用,比如矩阵操作、并行规约、离散反余弦变换、快速亮方直方图绘制等等,而对于较为复杂而且偏向图形较多的处理,比如傅里叶变换,空域卷积等则是TMU所擅长的部分。ALU与TMU的精诚合作,让GPU拥有了进入HPC领域协助甚至逐步取代CPU的实力。 谁说通用计算跟图形无关的?谁说图形为通用计算埋单是一件很亏的事情的?TMU的故事告诉我们,图形就是计算,计算就是图形。
接下来的问题就显得有点棘手了。尽管大商人微软在DirectX 10/11中所强调的图形发展方向在于更加灵活的shader以及更多通用的或者说自然的数学方法的介入,但我们也能够明显的感受到活雷锋这次的放话欠缺积极的响应。目前为止人们所能见到的程序员们对于DirectX 11新特性的理解和应用,更多的甚至是几乎全部的集中在了曲面细分以及纹理方面的改进上。
贴图mark11
以3Dmark11为例,这款本来应该是公正且带有前瞻性的反映全新API特性及硬件性能的测试程序,竟然几乎没怎么使用到DirectX 11的特性,它完全没有理会Compute Shader在图形处理过程中的应用,对于使用DC进行辅助计算的测试也仅仅是以体现存在感级别的方式出现在了测试场景的最后,就连曲面细分这种DirectX 11中不怎么重要但却能抓人眼球的改进,3Dmark11也未过多的予以涉及,甚至你在测试选项中将DirectX 11相关的数个选项从满级设定拉到最低设定,测试时的帧数也不会有很明显的变化……整个3Dmark11测试的最核心,几乎可以说就是大材质的操作能力,仿佛整个世界只存在Gather4这一条指令一样,这直接导致了3Dmark11被冠上了一个“贴图mark11”的名号。
游戏程序端的状况更加惨淡。放眼望去,除了使用Compute Shader处理DOF特效的地铁2033之外,真正意义上可能支持DirectX 11新特性的就只剩下还未登场的BattleField3所使用的寒霜2引擎了。我们所能够见到的几乎所有的号称支持DirectX 11级别特效的程序,都只是利用了Shader Modle4.0与Shader Modle5.0之间高度的互通性完成了基本的快速支持而已,甚至某些游戏连Gather指令都懒得用,直接以Shader Modle5.0的路径来执行传统代码了事。就连一直站在图形界前沿,以应用各种全新技术为骄傲的资本的Crytek,在Crysis2 DX11版本中也未对Compute Shader进行必要的支持,而是将几乎全部的精力都投入到了各种贴图应用的革新,甚至Crysis2的DX11版本还附带一个高精度纹理包,好像生怕自己没有用够硬件的TMU单元和显存一样。
对于导致目前这个现状的原因,虽然笔者自己给出过解释,但说实话,我依旧不能平息心中的郁闷——这世界究竟怎么了……
诚然,像素效果和纹理效果代表着图形表现的两个不同方向,拥有更好的像素效果可以让整个环境以及物体表面拥有逼真的光线和色彩表现,而拥有高分辨率的纹理则可以让物体获得贴近真实的外表,这两种特效方向是相辅相成的,忽略了谁最终都无法让用户获得完美的图形体验。事实上像素单元和纹理单元也确实是一组平行的处理过程,拾取的纹理和计算好的像素特效必须经由ROP的混合才能达成最终的效果。微软在每个版本的API更新中也确实尽量做到了一碗水端平,在强调灵活shader应用的同时给予了纹理材质部分充分的照顾。但目前的状况,确实程序员们几乎全部无视了微软在像素端的更新,将几乎全部的精力都投入到了已经十分强大的TMU单元的使用中。
一个摆放在现实世界中缺乏细节而且外表模糊的纸盒子,跟一个画卷中极尽细节刻画之能事、拥有超大材质但却几乎没有什么有效光照效果的纸盒子,究竟哪个更加“真实”和“美丽”呢?这个简单的道理我懂,你懂,程序员懂,所有人都懂,但我们都仅仅是懂,却无力改变些什么……
也许,关于像素和纹理,以及像素单元和纹理单元究竟哪个更重要的争论,只有屏幕前的你才知道答案并可以予以终结吧。
● 大一统的未来? 尽管对目前的TMU单元被畸形利用的现状存在不满,但我们也不能无视和否认TMU单元与像素处理单元之间密不可分的合作关系。图形流水线在此之前和之后都是严格的单线顺序关系,虽然存在回溯等必要操作,但像TMU单元和像素处理单元这样并行同时又不断的彼此发生联系的处理过程,在整个GPU流水线中就仅此一处而已了。
纹理和像素操作在流水线中的地位
既然TMU单元对纹理的操作,归根结底实际上还是对像素的操作,只不过更多的局限于复制粘贴之类动作,而像素处理单元虽然一上来就火力全开进行着各种计算,但实际上也是在处理像素,这两个单元在动作时还会时不时的眉来眼去一下,那有没有一种可能,在未来的某一天出现一个单元,将TMU和ALU阵列统一成一个完整的“效果处理器”呢?
同CPU和GPU的关系类似,实际上TMU和Shader的关系很像是一个“分裂-合并”的过程,最初的表面特效全部由TMU单元来实现,后来出现来自性能和需求端的变化之后,像素处理单元才独立出来进行像素相关的特效处理。如果能够实现完整统一的“效果处理器”,或者类似Direct Pixel Texture那样,以直接生成像素的形式来取代现有的“纹理-像素-混合”机制,那不仅可以让表面的颜色处理过程再次得到统一,回避目前纹理-像素切换操作所造成的延迟,还能让后端的ROP单元得到相当程度的解放。统一之后的像素处理机制将从大幅削减的切换延迟中获益,而节约下来的晶体管也可以用来强化缓冲以及其他单元。另外,统一像素处理还能让图形编程变得更加简单直接,简洁的程序反过来又能够进一步提升图形执行过程的效率,这样的诱惑不可谓不大啊。
其实在之前的GPU大百科全书中我们曾经提过类似的问题,受限于由此激增的,甚至是以数量级为单位激增的运算量的限制,可以说在可见未来内,我们应该还无法看到类似的设计。但我们同时也应该注意到,当今GPU的发展,尤其是ALU运算能力的增长,本身也确实在以超越摩尔定律的方式进行着。也许在不久的将来,我们还真的有可能看到TMU单元和像素单元的再次统一呢。
● 尾声
TMU是一个神奇的单元,它常年被认为是最传统的纯图形操作者,但却又是第一个站出来将GPU引入通用计算时代的先驱;它在卸下实现几乎全部特效的责任和重担之后反而获得了快速的发展和长足的进步,甚至还出现了各种各样以前不敢想象的操作方式和手段,并借此实现了更多过去很难实现的特效;它还在市场的推动下再次冲到了图形舞台的正中,成了人们实现特效最为依赖的对象。
在经过连续两章的处理过程和功能单元的游历之后,我们已经完成了对新生的图元生命表面效果的处理。在这之后我们所要做的事情,就只剩下将这些效果“落实”了。落实表面处理效果的过程,实际上就是将平面化的模型、纹理以及对纹理上不正确像素的修正替代结合在一起的过程,也就是我们通常所说的混合输出,这一步的操作,是由GPU中另一个资历颇老的单元——ROP单元来完成的。
在下一章的GPU大百科全书中,我们将要面对图形处理过程的最终环节以及ROP这一图形流水线上最后的大型单元,这最后的环节和单元里究竟蕴藏着哪些故事,我们又会面对哪些新奇的经历呢?关于这些疑问,就让我们留待下期GPU大百科全书中慢慢揭晓吧。
联系客服