显卡 频道

引爆3D力量:下一代DirectX前瞻

一体化着色器(Shader)模型

  DirectX 9当中引入了版本为2.0/2.X/3.0的Vertex Shader以及Pixel Shader可编程模型。而所有支持DirectX 9的图形处理器都必须至少支持2.0版的Shader模型,2.X版本的Shader模型将在更高级的图形处理器当中获得硬件级的支持,而3.0版的Shader模型则需要全新一代的图形处理器方可实现全面的硬件级支持(有消息指在2004年就可以推出这样的产品)。Pixel Shader 2.0所需要的通用寄存器数量是DirectX 8中所需寄存器数量的6倍,而指令集数量也大大增加,为原指令集数量的平方数,如此多的改进和增强特性使得Pixel Shader的特效实现能力和Vertex Shader持平,在程序上不再受到任何的限制。Pixel Shader的改进使得在Vertex Shader当中查找纹理的操作增多,特别是在应用程序当中,当我们需要对任意一块贴图进行更换的话,这种操作的次数更加是明显增多不少。此外,在3.0版Shader模型当中,同样有这样的问题存在,因此可以说,硬件上将Vertex Shader以及Pixel Shader分开做两个独立的单元是一种相当大的资源冗余。因此,在一代的4.0版Shader模型当中,全部Shader模型都将采用同样的构造,全套的技术特性都是完全一致的,这样在硬件上,设计者就无需为不同的Shader设计不同的执行单元,只要按照所对应的接口以及操作方式全部融为一体,仅设置一种独立的Shader执行单元,这样Shader执行单元的效能提升就可以带来Vertex Shader以及Pixel Shader双方面的效能提升。

  统一Shader模型是一项重要而有意义的工作,比如说,当我们需要处理Vertex特效的时候,但这种特效又需要应用Pixel Shader方面的指令,或者是我们需要处理Pixel上的特效,但却需要Vertex Shader方面的支持,于是常常就出现捉襟见肘的情形,要用什么但是那样东西却不能够立刻拿到手边,于是,将两种Shader模型统一到一起成为一个单独的Shader模型就成为一件非常有意义的工作,这样在创造各种3D特效的时候,我们就可以随意使用Shader制造各种特效而不必受到拘束,这是一个非常好的想法,但随即我们就知道这样的做法目前来看是很不实际的,有一个相当关键的因素我们还没有考虑到,目前图形处理器(GPU)自身的显存控制系统问题……

虚拟显存技术

  目前消费类图形处理芯片内存子系统是以图形计算为核心内容进行设计的,在显存当中存放着纹理、顶点、三角形以及着色器所需要处理的数据。假如你要用某种纹理贴图渲染一个立体几何框架,而相应的纹理贴图数据尚未加载到显存当中,那么GPU芯片基本上就是停工的,GPU只有等到显存里面已经有纹理贴图的数据方可进行渲染操作。虽然这种设计应用广泛,但毫无疑问,这样的设计方案本身还是有很多问题的。首先,这是一种相当浪费资源的做法,对任意一帧来说,我们在很多情况下未必会使用整个纹理对象,比如说mip-maps纹理贴图,而事实上,我们需要最少资源消耗的mip-maps纹理贴图往往却消耗了我们最多的带宽。在一些空旷的游戏场景当中更是如此,远处的景物体积较小我们仅需要非常低分辨率的mip-maps就可以完成贴图工作,用大量的带宽去传接小量的数据,巨大的浪费就产生了。回到原来所讨论显存系统设计方案当中来,GPU要到加载完所有的数据才开始进行渲染工作,当我们仅需要传递非常少的纹理贴图数据的时候,问题还不会显得十分突出,但当我们不断的去传送这些纹理贴图的时候,AGP和系统主内存就开始变得紧张起来。目前,显卡本地显存所提供的带宽是AGP总线带宽的10倍。如果我们需要处理的纹理贴图,着色器等方面所需要的数据超过了显卡上的显存容量,也就是说,GPU芯片要开始等待这些东西加载完了才能够开始新的操作,那么问题就显得很突出了,我们的3D应用程序的帧速就开始变得十分不稳定,并出现大幅度的下降。

  其中一个解决的办法是在分配给AGP控制器所用的内存上传输所有的纹理贴图,这样就可以完全解决显存速度与AGP总线速度不匹配的问题,但问题是并不是全部的帧都要经过相对缓慢的AGP总线,如果我们采取通过AGP控制器传输纹理贴图的办法来解决问题的话,那么结果就只有一个:一切都跟最慢的同步起来了,于是一切都变慢了,这是不可行的方案,因此我们需要一种新的办法来解决这个问题。

  现在图形处理器逐步开始演变成为一种通用型处理单元,而不再是一些专用的处理单元,因此我们可以参考CPU内存系统管理的方式来解决这个问题,而事实上,在通用型处理单元的发展过程中,类似的问题是不可避免的,比如说,我们不可能把所有的程序都放在处理器本身的缓存当中,因为我们不知道程序本身的大小,但直接从外部存储器中执行程序又会变得很慢,而经典的解决办法就是抛开物理内存的限制而使用虚拟内存管理模式。通过虚拟内存管理模式,程序员不再需要知道处理器内部的缓存和外部存储器的大小,取而代之的办法是将所有存储设备都映射成一个整体的虚拟内存空间,虚拟内存被划分为一个个较小的内存页面,而每个内存页面的经典大小值为4K。管理这些页面的策略就很重要了,急需处理的页面就要放置到处理器内部的缓存当中(Cache),次要一些的就暂时放在系统内存当中,而当内存容量不足的时候,我们就需要将这些页面放到硬盘里面。

  将虚拟内存管理的方法推演到图形处理单元上,于是就有虚拟显存技术了,虽说虚拟显存在存储器管理的策略上是承袭原来的那一套,但我们仍需要关心虚拟显存技术采用之后图形处理系统的表现是否依旧流畅。假设,我们按照经典方法将纹理贴图、着色器等需要处理的数据划分为4KB大小(按照虚拟内存页面经典值设置),一个4KB大小的页面文件等效于32×32×32bit大小的一个子纹理贴图块,我们认为这样一个大小的纹理贴图块是一个比较大的取值,我们不需要传输很多“页”就可以再传输一个大块的纹理贴图了,传输太快就会引起一些抖动的情况出现,前面传完了,后面还没跟上,为了保障速度上的平衡匹配,我们可以将这个页面的值适当调整到一个更小的值上,这样我们就能够以极小的性能损失实现更高效的显存管理。

0
相关文章