MCPLive > 杂志文章 > N/A之战新领地 DirectX 12初窥解析

N/A之战新领地 DirectX 12初窥解析

2015-12-09《微型计算机》评测室《微型计算机》2015年12月上

DirectX 12的核心变化——全新的底层渲染改进

说起“底层渲染”,就不得不提到一个问题—多线程化。

目前的CPU都是多核心的,支持多线程运作。在DirectX中,GPU接受CPU传输过来的数据,在计算后再将这些数据返还给CPU,这个过程可看做一个“黑盒”:用户从盒子的一端输入数据,API帮用户处理完成后从盒子的另一端输出数据,至于中间发生了什么,那只有API自己知道—因为这个过程只受API本身控制,图形程序、游戏引擎都无法染指。看起来这个过程比较简单明了,但关键之处来了:这个“黑盒”过程多线程化目前来看非常糟糕,由于存在相关性等问题,程序无法判断哪些应用在前,哪些应用无关,哪些可以并行化,因此绝大部分情况下都只能以单线程的方式运作。在之前DirectX 9甚至DirectX 10时代还好,因为CPU的性能依旧处于快速增长中,无论是频率还是单核心性能。但是随着技术发展,并行化的GPU的性能增长速度远远超过了串行化的CPU单核心性能的增长速度,这就导致很多情况下GPU受制于单线程的CPU,性能无法全部发挥。

这样一来,我们看到GPU性能在快速增长,但是其接受到的从CPU端发出的Draw Call绘制指令却一直没有爆发性、突破性的增长。只是慢吞吞的随着每代CPU增长一部分。这种情况对一些重GPU负载的游戏来说,还不算太难受,因为重GPU负载的游戏大量的时间都耗费在GPU的各个部分中,还算可以接受。但是对重CPU负载的游戏来说,就变得非常难平衡—大量的负载压在CPU上,多核心的CPU只有单线程在和GPU沟通,整个CPU-GPU沟通开销非常大,典型的例子就是《魔兽世界》这样的网游,在人和物体太多的场景下,CPU根本无法做到多核心满载,庞大的计算量使得CPU少数几个线程的压力暴增,终帧数跌落至甚至只有20fps。

现在问题很清楚了,DirectX目前在CPU-GPU体系的计算开销方面出现了问题,“黑盒”模式是主要原因。这个时候就需要底层渲染出场了。

什么是底层渲染呢?这个时候需要拿出游戏主机来举例。很多玩家看到游戏机就会想到,虽然主流游戏机价格只有不到3000元,配置也只是两三前的电脑配置,为何其画面质量和效果都和当期的PC游戏持平?这里面存在两个原因,其中一个原因是游戏机可以在画面上做很多“取巧”的手段,使得画面“看起来”很精美,另外,游戏机所使用的底层渲染方式,使得游戏机不太存在CPU-GPU的计算开销。游戏主机往往使用不一样的API来沟通CPU和GPU,程序开发人员需要在更接近硬件底层的层面来调配CPU和GPU,这里程序自动处理的部分就会少很多。这样就很明确了—所谓底层渲染,就是将“黑盒”模式放弃,将这个过程开放给程序员,使得程序员来判断任务应该如何执行,同时CPU多线程就能被很好地运作起来。比如在大量单位的场景中,不同分组的单位之间不存在交互的话,那么这些不同的分组可以被分派在不同的CPU上,大幅度提高GPU的处理速度和效率。

底层渲染的出现,使得程序员能够更为接近CPU和GPU本身,能够更为彻底地释放CPU和GPU的潜能。在目前的很多测试中,底层渲染的都带来了CPU-GPU系统绘制执行几倍甚至数十倍的提升。虽然,这样的提升终不太可能反映在游戏中,只能是纸面上的数据,但是这也从一个侧面说明DirectX 12对资源的利用效率更高了。

微软在很早之前就演示过,在使用了DirectX 12的底层渲染后,CPU的负载更为平衡,整体响应时间更为快速。
微软在很早之前就演示过,在使用了DirectX 12的底层渲染后,CPU的负载更为平衡,整体响应时间更为快

AMD解释异步计算的两张幻灯片,非常形象地说明了这项功能的作用。

AMD解释异步计算的两张幻灯片,非常形象地说明了这项功能的作用。
AMD解释异步计算的两张幻灯片,非常形象地说明了这项功能的作用。

DirectX 12的计算改进—异步计算的出现

相比之前比较难以理解的底层渲染而言,异步计算(Async Compute)算是一个比较方便理解的概念。

提起异步计算,那么肯定有所谓的“同步计算”。在之前的DirectX中,当数据或者指令进入GPU时,GPU或者驱动程序需要先为这些任务分类,比如分成“数据组1”和“指令组1”等其他什么名称,然后根据先来后到将一样类型的任务排在一组队列中,不同的任务组成不同的队列,再进行“抢占式”的处理—抢到了就先处理,抢不到就后面等着吧。

之所以将数据类型或者指令类型的任务排在一起处理,是因为GPU在不同的任务模式下需要切换,切换过程需要耗费一定的时间。如果所有的任务不加以排序和处理,GPU不断地切换过来切换过去,效率会大幅度下降。

“同步计算”解决了GPU计算不同任务时的效率问题,不过也带来了任务的互相等待问题。因为要对不同的任务进行排序、抢占,那么一些紧急却数量较少的任务有可能难以抢到GPU资源,不得不被迫等待,降低了系统效率。在这种情况下,异步计算就做得很好。异步计算不需要排队也不需要等待,数据或者指令来了直接根据先来后到处理就好,核心原因是GPU不再需要切换数据状态或者指令状态。既然不需要切换,那么来了就处理就变得理所应当。

分享到:

用户评论

用户名:

密码: