去年,KlayGE就已经有了Windows Store的版本和Windows Phone的版本。随着Win10的推出,UWP成了统一两者的平台。CMake 3.4加入了UWP的支持之后,KlayGE也很顺利地增加了UWP的支持。
UWP的用法
在CMake 3.4中用UWP非常简单,和原先用Windows Store的完全一样,只是系统版本号改成10,仅此而已(-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0)。所以代码其实都没改,只需要增加一个UWP的manifest。为了方便起见,在代码和CMake里定义了KLAYGE_PLATFORM_WINDOWS_UWP,用来表明是UWP的build。
另一个细节需要注意,在UWP应用里,小图标的大小是44x44,而不是30x30。
ARM的桌面
UWP讲究一份代码各种架构。但在编译ARM ...
自从Win8引入WinRT以来,主流开发者的说法一直是,C++/CX可以方便地把现有C++代码移植到WinRT。一般来说确实如此,绝大部分原有C++代码可以的保留,只需要写UI的部分就可以了。但因为C++/CX的引入,还是会带来一些副作用,不完全都是好处。本篇将以KlayGE为例,讲解如何在不用C++/CX的情况下完成WinRT应用(包括UWP)。
C++/CX的功与过
C++/CX使用起来挺方便,语法和原先的C++/CLR极其相似,但是native的,没有虚拟机执行开销。任何懂C++的人都可以很快上手,把程序移植到WinRT。同时,WinRT背后一大套COM机制都被隐藏掉了,可以直接用普通的类一样使用COM对象。
但是,仔细观察就能发现,在C++项目中加入C++/CX有几个缺点。
C++/CX ...
本系列前面的五篇已经让引擎可以在D3D12下跑通所有的例子。但这并不代表功能已经齐全。其中很多例子能跑通的原因,是因为例子本身有fall back的代码,允许在没有各种高级功能的情况下运行。Compute shader就是其中的一个。本篇将会讲解如何加入compute shader,以及在此过程中遇到的一个大坑。
计算引擎
和以前的API不同的是,D3D12是个多引擎的API,可以让硬件的不同的独立部分异步执行,以提高效率。D3D12里的引擎有,渲染引擎、计算引擎和拷贝引擎。这三个引擎有不同的指令队列,可以在程序的控制下并行执行和互相同步。所以,在D3D12里,推荐的做法是,渲染和计算分开,放到不同引擎执行。所以虽然compute shader也可以在渲染引擎执行 ...
Universal DX SDK的第二阶段也完成了。新加了一个批处理文件,用于从系统的.dll生成.lib或者.a。
这个脚本支持vc7-vc14,以及mingw。只要装了这些中的任意一个,执行脚本的时候,它就会从System32或SysWOW64中挑选需要的dll,从中生成vc所有用的导入库lib,或者mingw所用的导入库.a,放到Lib下。如此一来,非动态载入的情况也可以使用Universal DX SDK。
目前我的实验是,在KlayGE里用Universal DX SDK,在VS2013下开发D3D12的东西,包括桌面应用和WinRT应用。目前为止一切正常,程序可以编译链接运行。
前两天刚宣布了一个新的开源项目,Universal DX SDK,现在以完成了第一阶段。
在现在的master分支里,头文件已经被更新到Win10 SDK 10.0.10240.0,并作出一些修改:
注掉了winapifamily.h相关的代码,以适用于VS2010及以前的vc,和MinGW/Clang。
在MinGW下编译不会出现warning。
这么一来,如果用LoadLibrary进行动态载入,只需要头文件的话,在各种编译器下都能使用Universal DX SDK,支持D3D 9-12、DXGI 1.1-1.4、DInput、DSound、D2D 1.1-1.3、DWrite 1.1-1.3、XAudio等,并支持古老的XNAMath、D3DX 9-11等。基本可以满足各种对DX的需求。
经过KlayGE的实验,用了Universal DX SDK之后,大部分根据SDK版本进行的#ifdef都可 ...
从Windows 8开始,DirectX SDK就被合并到Windows SDK里了。June 2010成了最后一次独立发布的DX SDK。大部分情况下,这么做挺方便,VS装好之后就能用了,不再需要单独装DX SDK、设置路径等。但有的时候,这样也会带来些麻烦。
用Windows SDK的不便之处
Visual Studio的用户基本上都使用VS自带的Windows SDK,很少有单独装的。这带来的问题就是,如果VS不升级,SDK就不升级,两者变成一对一的关系了。所以如果你想用VS2012开发D3D11.2,或者VS2013开发D3D12的东西,就没法弄。
另一方面,在Windows上也可以用MinGW和Clang来编译。但它们所带的DX SDK比较古老,而且不全。用June 2010的话,因为sal的关系,编译中会有很多错误。即便绕开了 ...
经过前面的练习,实现query已经没什么难的了。
Query heap
在D3D12里,query也是放在heap中。但和其他heap不同的是,query heap与其说是heap,不如说是array。它并不需要设置给设备,而是相当于一次可以提交多个query。Query heap的数量不限,所以为了简单实现,可以给每个query建立一个query heap。
D3D12_QUERY_HEAP_DESC query_heap_desc;
query_heap_desc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION;
query_heap_desc.Count = 1;
query_heap_desc.NodeMask = 0;
ID3D12QueryHeap* query_heap;
TIF(device->CreateQueryHeap(&query_heap_desc, IID_ID3D12QueryHeap,
reinterpret_cast<void**>(&query_heap))); ...
据我上一次写D3D11 feature一晃已经4年了。相信这么多年来大部分开发者不再像当年那样无知了。现在Win10和D3D12已经发布,图形驱动模型也有不少发展。现在在Win10里的图形栈经过了较大规模的重构。虽然在上层很难察觉,但底层已经很不一样。
老的兼容方式
当年D3D9刚出来的时候,大部分显卡和驱动还是D3D8的。当时的兼容方式是,让D3D9的runtime跑在D3D8的驱动上。D3D9和D3D10之间出现了个短暂的断层,互相不兼容。不久之后D3D10.1又可以通过feature level的方式在老显卡上跑。这个东西叫做10level9,意思是10的runtime在9的硬件上。后来出了11,也一直是用这样的方式。
总的来说,老的兼容方式就是,硬件厂商提供一个或多个驱动,runti ...
上一篇把完成了一个最基本的D3D12程序,画一个三角形。同时我也说了,没有回头路。本篇将开始从11on12转向纯D3D12。
上一篇我们的假设假设是最基本的系统,关掉所有post process、UI、文字,就渲染一个三角形。这样的系统至少需要一个vertex buffer、一个rtv、一个vs、一个ps、一次clear、一次draw call。进一步的发展需要一个稍微复杂的系统,有文字和UI。也就是还需要一个index buffer、一个cbv、一个srv、一个sampler。Index buffer和vertex buffer的构建没区别,所以就是cbv、srv和sampler的事情。
在此之前,需要先介绍两个D3D12的概念,heap和root signature。因为CBV/SRV/UAV/Sampler都需要依赖于这两个。
Heap
Heap是D3D12新 ...
从八月初开始正式做D3D12插件以来,经过5个星期、每天平均一小时的开发,终于达成了第一阶段的目标:在渲染层接口不变的情况下,用纯D3D12渲染所有例子。
其实还不是所有特性都实现了。在例子中,遇到这种情况会退回到另一条code path。原先这些code path是为了在较弱的硬件上也能达到同样的效果,同样也可以用于开发新插件的中间产品。还没实现的特性有:
Stream output(退回到render to texture)
Compute shader(退回到用pixel shader实现)
UAVs
No overwrite(退回到discard)
Query(总是返回0)
Indirect draw
Depth stencil和压缩纹理的mipmap生成(退回到在CPU上生成)
下一个阶段会进一步实现这些特性,做 ...