转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=3403

据我上一次写D3D11 feature一晃已经4年了。相信这么多年来大部分开发者不再像当年那样无知了。现在Win10和D3D12已经发布,图形驱动模型也有不少发展。现在在Win10里的图形栈经过了较大规模的重构。虽然在上层很难察觉,但底层已经很不一样。

老的兼容方式

当年D3D9刚出来的时候,大部分显卡和驱动还是D3D8的。当时的兼容方式是,让D3D9的runtime跑在D3D8的驱动上。D3D9和D3D10之间出现了个短暂的断层,互相不兼容。不久之后D3D10.1又可以通过feature level的方式在老显卡上跑。这个东西叫做10level9,意思是10的runtime在9的硬件上。后来出了11,也一直是用这样的方式。

总的来说,老的兼容方式就是,硬件厂商提供一个或多个驱动,runtime提供多个下层接口。这样能快速达到兼容的目的,但开发成本和运行开销都不小。

新的兼容方式

在Win10上,这个情况终于有所改变,采用了一个新的相反的兼容方式。一个API runtime和驱动之间被插了一层,可以从一个API的runtime接口重定向到另一个API的驱动接口。或者说,用一个API实现了另一个API。这么一来,硬件厂商只要提供一个驱动,runtime也只要一个下层,但有多个中间层可以替换。原先N对N的组合,变成N+2的分层策略。一来开发和测试变简单了,二来性能有所保证,因为新的驱动性能高于老的。

各种层

那么究竟有哪些兼容层呢?这里就来试着列举一下。

10level9

这个前面有提到,其实不是兼容层,为了完整起见也列在这里。10level9的意思是10+的runtime跑在9的硬件上。

11on12

我上半年的一篇文章有提到过11on12。它把11的runtime接到12的API上,以达到快速从11移植到12,或者两者交互操作的目的。其实原先warp和ref设备就是通过这种方式实现的,插在runtime底层。

12on11

别闹,怎么反过来了?嗯,这个是12on11,正式名字是D3D 11.3。意思是把12新增的硬件功能暴露给11的API。它也不是个兼容层,而是API的改变。

9on11

这是Win10新增的。9的runtime可以接到11的驱动上,实现反向兼容。原先9和11走的不同的驱动,现在可以统一了。

对开发者来说,9on11和以前的方式,有一点点细微区别。原先在feature level 9.x上,IDXGIAdapter1::GetDesc1返回的设备名是Software Adapter,其他属性都是0。IDXGIAdapter2::GetDesc2才能返回正确的设备信息。而在9on11上,GetDesc1也能返回正确信息,因为它终归会被重定向到11上,和其他feature level的没本质区别。

总结

其实对开发者来说,11on12和12on11需要写代码才能用上。其他两个是透明的层,平常几乎察觉不到。

另一个有意思的是,如果你在Win10上运行一个D3D11 feature level 9.x的程序,而你的硬件只支持D3D9,那么就会出现9on11->10level9,转了一圈。但好在这么做性能并没有损失,因为厂商现在都能提供11的驱动,更何况桌面平台已经基本找不到D3D9的硬件了。