热点推荐

曝你不知道的DX11 解析GPU通用计算妙用


分页浏览|全文浏览    【中关村在线 原创】 作者:顾杰 | 责编:林光楠     评论
产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

为通用计算买单很不合算?

  ● 为通用计算买单很不合算? 

  DirectX 10是一个里程碑式的API。在DirectX 10当中,微软第一次将底层的ALU开放给了程序员,这种直接面向底层运算器的开放不仅带来了花样百出的shader类型和应用,还将GPU本身所蕴藏的巨大的理论运算能力摆在了世人面前。大量针对GPU运算的非传统图形领域开发的想法几乎在第一时间就遍地开花。可以说从 DirectX 10开始,GPU通用计算时代正式开始。


图形计算破界者 compute shader深入分析
NVIDIA CUDA通用计算架构

打破图形界限 compute shader深入分析
ATI Stream通用计算架构

  与其前身流计算不同,通用计算更加贴近真实的数学要求,只要代码能够最终被转化成几何关联形式,支持DX10的硬件就可以将运算能力用于非图形领域。也正是因为这种特点,能够执行通用计算的硬件在结构上必须要应对更加真实的数学需要,比如跳转,分支,并行处理等能力。这些能力对运算单元的周边资源以及构架设计的并行度和灵活度都有着极高的要求。因此,通常情况下在通用计算领域能够表现出纯吞吐以外的灵活和效率的硬件,在面对灵活的shader的过程中也会保持很高的效率。

打破图形界限 compute shader深入分析
通用计算在医学领域的应用

图形计算破界者 Compute Shader深入分析
通用计算在流体力学方面的应用

  传统的通用计算应用大体上还只是对构架运算能力的单纯数学分支开发,应用的领域大多集中在纯数学以及与数学相关的模拟和运算领域。受限于多种原因,构架的通用计算领域应用还不能直接被用来为3D图形渲染提供帮助。因此,尽管能够执行通用计算的构架也能够更好的执行渲染过程,但是大多数人依旧认为通用计算与图形计算是没有任何关联的两个过程,这两者之间存在着明确的界限,谁都无法逾越界限进入到另一个领域,因此图形构架为通用计算买单是一件没有意义的事情。

  暂且不评价这句话是对是错,起码现在情况改变了,图形构架为通用计算买单肯定不是一件没有意义的事情,因为Compute Shader来了。


顾杰所写过的其他相关文章:《谁是微软忠实随从 A/N统一构架历史回顾

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

DirectX 11“破界者”

  ● DirectX 11“破界者”

  我们知道,DirectX 11相对于DirectX 10最重要的两个更新就是并行kernel和Compute Shader,immediate Context和Deferred Context为数据的并行管理以及并行过程中的数据交换提供了前提条件,解决了并行度的问题之后,Compute Shader的出现就顺理成章了。


打破图形界限 compute shader深入分析

更加强调并行度的DirectX 11

  Compute Shader与传统shader最大的不同在于几何关联性的问题。传统shader必须对应某种几何过程,比如Vertex、Texture或者Z-buffer,这样做的好处在于可以在图形过程中将shader自动对应到操作上,但坏处也是显而易见的——所有程序员,不管你是搞理论物理的眼镜轮椅男还是写算数函数的图形门外汉,要想利用DirectX 10硬件的通用计算性能都必须要掌握GLSL和HLSL,了解图形处理过程以及整个图形流水线的特点,甚至还可能要跑去学点fortran什么的。即便后来出现了类似CUDA这类C++型的对象式编译接口,指令的图形关联还是一个必不可少的过程,对硬件的使用依旧不是很方便。于是在DirectX 11中,微软彻底取消了Compute Shader与几何过程的关联。

打破图形界限 compute shader深入分析
传统结构的通用计算指令结构示例

  取消了几何关联的Compute Shader是史上第一个完全开放的数学指令型shader,Compute Shader可以透过并行管理方便的实现数据共享,可以透过树结构和延迟操作快速执行任意过程,虽然丧失了几何关联所带来的各种自动功能让Compute Shader看上去与大多数图形过程绝缘了,但事实却恰恰相反。Compute Shader的出现,不仅没有进一步的将通用计算和图形计算割裂开,反倒直接打破了传统的界限和束缚,将图形和通用计算彻底联系在了一起。有了它,显卡的通用计算能力将最大限度的成为图形计算能力。

打破图形界限 compute shader深入分析
Compute Shader在图形过程中的地位

  这是怎么回事?史上第一个彻底与几何过程划清界限的通用计算专用形式的shader应用怎么可能成了图形和通用计算两个领域之间的“破界者”呢?这一切都要从一个古老但却又非常先进的技术——Deferred shading说起。

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

上帝说,像素要有光

  ● 上帝说,像素要有光

  要方便的了解Deferred shading(延迟着色)技术以及他跟Compute Shader的关系,我们首先要回顾一些关于像素和光线的基本知识。

  构成我们所看到的场景的最基本元素是顶点和像素,其中顶点负责几何构造的形状以及一些特定参数的表达和搭载,比如重力或者高度,而像素则负责最终图像的颜色表现问题。不管是怎样的场景,要达到真实的感觉,像素表达出正确的符合物理规律的颜色是重中之重。


打破图形界限 compute shader深入分析

正确的颜色才能产生真实感

  所谓正确的符合物理规则的颜色,指的就是物体固有的颜色与光线交互作用之后的结果。任何物体处在自然环境之中都要与周遭的光线发生关系,最基本的包括反射,折射,漫反/散射等。如果剔除了这些光线关系,物体的立体感不仅会丢失,整体上给人的感觉也会极为不真实。而如果使用了错误的光线关系,日常生活中的经验也会让我们敏锐的产生各种不真实感。所以,要表达趋近于真实的视觉效果,正确的符合光学规律的像素是必要的要素。

打破图形界限 compute shader深入分析
调整光线关系之后的图形表现

  让像素表达正确的颜色有两个途径——开发者可以在预制阶段事先烘焙好含有正确颜色表现的材质,再结合光照材质和预先设定的颜色信息来完成场景效果的光影关系。或者在编程阶段为程序添加含有正确光线关系的代码,让程序在运行过程中实时计算像素应该具备的正确颜色,然后通过fillrate过程将正确的像素填进纹理。

  预制纹理的方式对硬件没有多少运算能力的要求,只需要进行单纯的材质操作即可完成场景的表达,对硬件来说操作效率很高。但因为所有效果全部需要预先烘焙而成,在游戏过程这种讲究高自由度高互动性的场合,开发者不可能把所有可能性都考虑进去——玩家总能在最意想不到的地方做出最意想不到的事情,靠对行为的猜测来构筑的场景最终总能被好奇心爆棚的玩家用各种方式找出破绽,所以单纯依赖这种操作方式必定会导致很多错误的或者说不真实的效果表达。

打破图形界限 compute shader深入分析
预制纹理无法达到正确表达光线效果的作用

  如果在程序运行过程中根据场景的互动需要实时的进行计算,然后将计算好的正确结果填充进纹理,就可以在过程中顺应实时变化的要求,使用正确的像素来表达正确的效果了。Pixel Shader的出现就是对应了这种要求。只不过这种操作方式需要专门的运算单元来处理关于颜色相关信息的计算和操作,对硬件的速度和效率有极高的要求,在实际应用中必须考虑硬件执行环境的能力以及其对最终图形过程的影响。为了平衡效率和对硬件的要求,现代的图形应用如游戏的特效都是大量采用Pixel Shader结合烘焙纹理和光照贴图的综合手段来的完成的。

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

上帝说,光要延迟才是好的

  ● 上帝说,光要延迟才是好的

  既然像素的正确与否取决于物体固有颜色与光线的交互关系,那么对于像素以及最终效果来说,光照的过程就成了关键。

  在实际的应用中,对光照的操作有很多种方式,传统的方式大多是将光照信息直接对应到Pixel Shader指令的执行过程,比如multi-pass render及multi-light single pass render等。在Pixel Shader2.0中,这些方式被用于处理不同场景的光源对物体的影响。如multi-pass render pipeline会为每个光源创建一个单独的过程用来执行,多用于室内环境处理,而multi-light single pass render能够在一个过程中同时处理3至4个光源,可被用于室外大范围表现的环境。每种方式各有利弊也都有自己的应用场合,但大家都要求像素在完成光源关系的处理之后才继续执行流水线的其他部分操作。


打破图形界限 compute shader深入分析

使用multi-light single pass的farcry

  我们不难发现,传统的处理方式与流水线的结合度很好,他可以在“正确的时间”为流水线提供正确的像素。但也正因为这种良好的结合度,传统的光照操作导致了大量的无效操作。因为后面的流水线过程中还有一步很关键的动作——Z Occlusion Culling(Z遮蔽消除)。

打破图形界限 compute shader深入分析
Z Occlusion Culling(Z遮蔽消除)

  现实3D游戏中的物体存在大量的视觉遮蔽现象,前面的物体如果挡住了后面的物体,那么渲染这些从摄像机(玩家)角度无法被看到的物体显然是在浪费时间。这种情况下,为了减轻不可见渲染造成的浪费,流水线会进行Z Occlusion Culling操作,根据对Z轴数据也就是景深数据的对比判定来去掉那些不可见的像素。在early-z culling之类的技术出现之前,流水线对像素可见性的判定都在Pixel Shader过程完成之后,显而易见的,这导致了大量本来不可见的像素被执行了复杂的光照操作。

  为了应对这种局面,提高流水线的执行效率,微软将一个当时新兴的技术引入了DirectX 9.0C,这就是延迟渲染。

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

延迟渲染之Deferred shading

  ● 延迟渲染之Deferred shading

  最初的延迟渲染主要集中在Deferred shading,为了提高流水线的效率,Deferred shading通过延迟处理的思路,将光照操作的步骤从传统的Pixel Shader前段直接转移到整个流水线后端的MRT(多目标渲染)里。

  这简单的一个步骤移动,直接导致了所有像素在统一完成其他一切步骤并实现Z Occlusion Culling之后再集合在一起统一进行关于光照的运算和操作,从而避免了大量的无效光照计算。场景的复杂度越高,Deferred shading所能够带来的效率提升也就越明显。


打破图形界限 compute shader深入分析

killzone2中使用的Deferred shading过程

  初期的Deferred shading使用幁缓存,将整个光照过程当做一个2D过程来进行处理。虽然Deferred shading的最初形态在今天看来非常原始,而且由于DX9.0C的MRT还不支持MSAA采样导致所有Deferred shading之后的图形都无法支持常规抗锯齿,但在没有early-z culling的当时,Deferred shading是效率最高的光照处理手段,同时他所提出的延迟的处理概念也在很大程度上影响了未来图形界的发展方向。

打破图形界限 compute shader深入分析
Deferred shading处理完毕的画面

  延迟渲染模式从出现至今已经7年了,这7年里Deferred shading技术有了极大的进步。结合DX10之后越来越明确的并行度设计,Deferred shading透过延迟操作可以完成几乎全部涉及光照的操作,比如全局亮度调节,高动态范围(HDR)调节,复杂多光源漫散射,甚至已经开始尝试处理原来无法涉及的半透明等极为复杂光线关系。

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

只有延迟还远远不够

  ● 只有延迟还远远不够

  经过多年的发展,支持Deferred shading的引擎和游戏也越来越多,寒霜1.X和寒霜2、X-ray、UE3、CE2甚至CE3,使命召唤系列、彩虹6号:维加斯、极品飞车系列、战地系列、Bioshock系列、战争机器、crysis、crysis2,甚至是家用机平台上的killzone系列……太多的优秀引擎和游戏大作上都活跃着Deferred shading的身影。


打破图形界限 compute shader深入分析

使用CE2引擎的crysis

打破图形界限 compute shader深入分析
使用X-ray引擎的潜行者

打破图形界限 compute shader深入分析
使用寒霜2引擎的BattleField 3

打破图形界限 compute shader深入分析
使用UE3引擎的战争机器

  随着应用和研究的深入,人们越来越多的在各种场合使用着Deferred shading,随着图形需求的不断增长,Deferred shading也越来越多的暴露出了对纯运算能力方面的需求。

  光线的关系,其实本质上就是数学的关系。每一种光照最终都可以演变成简单但却又暴力的乘法,连加以及半角H计算。既然是常规数学操作,就需要大量的通用运算资源和缓冲用于操作。于是,问题来了——传统的图形代码所能够使用的buffer和操作模式不足以应付Deferred shading日益增长的需求,我们迫切的需要强大的运算能力来帮助程序实现场景中所需要的各种数学运算。

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

DirectX 10不是救世主

  ● DirectX 10不是救世主

  运算能力?我们不是有现成的运算能力么?DirectX 10硬件的构架可以执行任何类型的shader从而让ALU实现通用计算过程,直接调用这些能力不就好了?

  抱歉,即便抛开各种程序员对数学理解过程的障碍,在DirectX 10环境下的通用计算代码因为与几何过程“优秀”的关联性,实际上是没办法随心所欲的被使用的。


打破图形界限 compute shader深入分析

紧密几何关联性的图形处理过程

  强行插入流水线的通用计算指令会被流水线识别成几何过程,这往往会直接影响正常执行中的图形指令的连续结构,造成不必要的甚至是致命的执行延迟,通用计算代码又没什么办法融入到常规的Pixel shader代码中去,使用通用计算代码得到的效率提升甚至可能远比它所造成的损失低得多。Deferred shading面对体系巨大的通用计算能力却只能望洋兴叹,着实是一种巨大的浪费……

打破图形界限 compute shader深入分析
NVIDIA公司开发的基于CUDA的光线追踪套件

  NVIDIA公司曾经尝试突破这种局面,它利用自己的CUDA接口开发过一系列的针对DirectX和Open GL环境下多光源和延迟渲染甚至是光线追踪的应用,虽然C++的编译环境在一定程度上降低了编程难度同时提高了执行效率,但是由于DirectX 10本身的缺陷,这些应用在效率上距离实用还相去甚远。在CUDA3.0之前我们没有看到有效的针对性应用。这种情况下,人们显然急需一名救世主的出现。

  还好,DirectX 11来了,救世主降临了。

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

Deferred shading与Compute Shader

  ● Deferred shading与Compute Shader

  我们前面已经介绍过了,Compute Shader是一种纯数学形式的代码,它不仅可以结合延迟操作模式和树状结构方便的进行线程间的大并行度管理,实现跨指令的数据共享,快速的实现各种通用计算应用,而且取消了代码形式上对几何过程的强制关联。

  在得知Compute Shader取消了强制几何关联的一瞬间,全世界的程序员眼前都被一道光芒划过了。因为得益于取消关联的改动,Compute Shader面前出现了另外一种应用方式——Compute Shader可以利用自己数学代码的身份,在不干扰图形过程执行的前提下方便而且随意的插入图形处理中任何一个需要数学运算的过程。


打破图形界限 compute shader深入分析

传统代码要求的繁冗的几何关联

  没错,这就是答案,“破界者”由来的答案,不仅是本文而且也是整个图形界所要追寻的答案。因为对于程序员来说,这几乎意味着无限的可能性。   

  既然已经了解了Deferred shading过程,那就让我们从Deferred shading的角度出发,看看程序员究竟是怎样面对“无限的可能性”的。

  在整个过程开始之前,程序员可以很方便的将Compute Shader代码直接插入到常规的载入操作之后,Pixel Shader指令除了多了一段数学代码之外没有任何变化,执行所需的PASS也基本上不变。在处理完前面的G buffer LOAD以及Z/Depth LOAD之后,硬件透过Compute Shader代码直接开始运算场景中每个光源背后所导致的数学运算,甚至连光照模型的二维化都可以通过Compute Shader来进行。完成这些之后再将数值送给output buffer,整个过程以原子操作来进行管理,从外部来看就好像什么都没有改变一样。

打破图形界限 compute shader深入分析
Compute Shader指令的插入极为方便和随意

打破图形界限 compute shader深入分析
完全无需几何关联的代码形式

打破图形界限 compute shader深入分析
以Compute Shader完成的Deferred shading过程

  就这么简单?是的,就这么简单。

  真的什么都没有改变么?不,不仅不是什么都没有改变,而且是改变的惊天动地。

打破图形界限 compute shader深入分析
透过Compute Shader生成的1000光源场景

  透过Compute Shader带来的运算能力的方便调用,整个系统处理Deferred shading的效率暴增至原来的几十甚至数百倍,能够面对的总光源数被快速的放大,这所带来的直接结果就是场景中同时出现光源数量的激增。在效率允许的情况下,支持Compute Shader的硬件可以为程序提供充足的效率换效果的空间,更多的光源意味着更加接近自然光的光线关系表现,也就是更好的图形体验。

  久旱逢甘露,急需的运算和快速处理能力来了,而且来的如此简单直接。透过Compute Shader,通用计算和图形计算终于被彻底的紧密的联系在了一起。

产品:GeForce GTX560Ti nVIDIA 显示芯片 回到顶部阅读

我们需要更多,也能做更多

  ● we need much much more,also we can do much much more

  伴随着DirectX 11的出现,借由Compute Shader完成的图形应用如雨后春笋般涌现了出来。


打破图形界限 compute shader深入分析

Compute Shader引入的A-buffer应用

  人们现在可以通过Compute Shader快速执行Deferred shading,为整个场景计算和设置平均亮度,异常方便的添置更多更真实的光源,让SSAO过程变得实用以及精确,使用Compute Shader提供的A-buffer来进行抗锯齿以及边缘无规则透明度的高速检查,借以实现更加精确和完善的MSAA,还可以透过它生成很多Pixel Shader执行效率很低或者干脆无法实现的高级特效如DOF等。这些应用已经在寒霜2,UE3,CE3以及X-ray等应用广泛支持游戏众多的知名引擎中得到了充分的体现。BattleForge,地铁2033,Dirt2,BFBC2等知名游戏中也有了大量Compute Shader实际应用的身影。

打破图形界限 compute shader深入分析
使用Compute Shader处理DOF特效的Metro2033

打破图形界限 compute shader深入分析
使用Compute Shader处理SSAO的BattleForge

  至于未来,对Compute Shader来说则更加精彩纷呈。Compute Shader可以帮助开发人员将大量常规数学方法直接引入到需要复杂运算能力的几乎任何几何过程中,比如通过快速的亮度直方图绘制来检查场景光照情况,以2维卷积求解为基础的锐化操作,快速矩阵区域求和带来的硬件Deferred Z culling、HiZ以及由此产生的更加逼真和高效的流体计算,快速傅里叶变换带来的更加高效的水面波幅效果,还有视频和像素操作中至关重要的离散反余弦,甚至是光线追踪等等。太多太多绝不是空中楼阁的应用等待着人们去探索和实现,他们中的任何一个都处在已经或者即将出现并改变图形世界的阶段了。

打破图形界限 compute shader深入分析
实现HiZ操作需要插入的Compute Shader代码

打破图形界限 compute shader深入分析
Compute Shader会在未来大量介入光线追踪过程

  当然,作为一名长时间冷眼观察图形业界进步的人来说,屏幕前的您一定敏锐的意识到了世界上并不存在绝对的完美这种东西。没错,即便是目前看来拥有无限可能的Compute Shader,本身实际上也依旧存在着诸多局限性。比如强制要求构架具有32K以上的shared,性能依赖原子操作的效率以及可用缓冲空间的性能和操作方式,受限于运算方式而无法参与和加强alpha混合(alpha blending)之类的操作,跨CPU/GPU运算资源调用的转换延迟还不够低等。相信随着应用深度广度加剧所带来的需求,微软一定会在未来的版本中不断的完善和强化Compute Shader,将“破界者”的威力进一步提升到难以想象的高度。

打破图形界限 compute shader深入分析
Compute Shader在未来的应用

  写在最后: 

  人类上一次将运算能力以特定的形式引入到几何过程中所产生的Vertex shader和Pixel Shader完全改变了人类实现光栅化过程的方式。伴随着Compute Shader打破了通用计算和图形计算的界限,将不受形式限制的数学方法和运算能力引入到几何过程中的每一个角落,图形处理过程发生的变化将更具颠覆性。相信DirectX 11之后的图形世界必将更加绚烂和精彩。


顾杰所写过的其他相关文章:《谁是微软忠实随从 A/N统一构架历史回顾

频道热词:华硕主板  Intel  AMD  
视觉焦点
NVIDIA GeForce GTX560Ti
    显卡评测热点
    排行 文章标题