在D3D API 中, Device(设备)是一个核心的概念,Device是对一个图形硬件的抽象,它负责创建和销毁其他的对象,渲染图元等功能。D3D11中,Device对象主要用来管理资源,而DeviceContext对象执行渲染操作。一个对象只能被创建它的Device使用。多个Device可以通过共享资源来共享数据,但这个共享的资源也只能在创建它的Device内使用。(意思就是说多个Device都可以访问共享对象里面的数据,但处了创建Device之外,其他Device不能直接把这个资源连接到渲染管线上使用)
每个Device都由一个ID3D11Device接口来代表,可以通过D3D11CreateDevice或者D3D11CreateDeviceAndSwap
D3D11CreateDevice函数的原型如下:
HRESULT D3D11CreateDevice(IDXGIAdapter *pAdapter,D3D_DRIVER_TYPEDriverType,HMODULESoftware,UINTFlags,CONST D3D_FEATURE_LEVEL *pFeatureLevels,UINTFeatureLevels,UINTSDKVersion,ID3D11Device **ppDevice,D3D_FEATURE_LEVEL *pFeatureLevel,ID3D11DeviceContext **ppImmediateContext);
参数解析:
IDXGIAdapter *pAdapter:显示适配器接口。表示要创建的Device与这个适配器硬件对应。一台电脑上可能安装多个显示适配器(即显卡),可以使用IDXGIFactory::EnumAdapters函数来遍历所有的适配器。传入NULL的话就表示使用默认的适配器(你的电脑上至少应该有一个显卡吧)。
D3D_DRIVER_TYPEDriverType:创建的Device的类型。可能的值有:
- D3D_DRIVER_TYPE_UNKNOWN: 未知类型,创建设备时不能使用
- D3D_DRIVER_TYPE_HARDWARE:硬件设备,指使用硬件来实现D3D的功能。它使用硬件来加速D3D功能,并用软件实现硬件不支持的部分,因此能提供最好的性能。这一种设备类型通常都用一个HAL(Hardware Abstraction Layer,硬件抽象层)来代表。
- D3D_DRIVER_TYPE_REFERENCE:参考设备,即使用软件(CPU上运行)来实现D3D的所有功能。参考设备注重功能的准确性而不保证速度。因此主要用来做功能的测试、演示与调试等。参考设备由DirectXSDK提供(D3D11Ref.dll ?)。这个设备通常叫做REF Device或Reference rasterizer(光栅器)
- D3D_DRIVER_TYPE_NULL:空设备,即不提供D3D渲染功能的设备,它主要用来测试一些非测试的API的功能。它也是由DirectXSDK提供。
- D3D_DRIVER_TYPE_SOFTWARE:
软件渲染器,也是由软件实现D3D的所有功能。这个渲染器必须由用户自己实现,并通过一个DLL提供。 - D3D_DRIVER_TYPE_WARP: Windows Advanced Resterization Platform。一个高性能的软件光栅器。提供特性集9.1到10.1的支持。
HMODULESoftware:软件渲染器DLL,如果不用软件渲染器的话,传入NULL
UINTFlags:创建标记,这写标记主要用来控制创建的Device中的层次,这些标记可以按位与操作。如果不特别指定的话,传入0。
- D3D11_CREATE_DEVICE_SINGLETHREADED = 0x1,
设置Device为单线程使用。D3D11默认是支持多线程使用的,即在每个API的调用中都会进行锁保护。如果确定不会在多线程环境中使用,则设置该标记,则不会进行锁保护,这样可以提高性能。 - D3D11_CREATE_DEVICE_DEBUG = 0x2,
让Device支持调试层 - D3D11_CREATE_DEVICE_SWITCH_TO_REF = 0x4,
同时创建REF和HAL设备,这样就可以在运行时进行切换,以支持调试功能。 - D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS = 0x8,
阻止创建多线程(这个需要深入了解) - D3D11_CREATE_DEVICE_BGRA_SUPPORT = 0x20, 在允许D2D与D3D互操作时设置
CONST D3D_FEATURE_LEVEL *pFeatureLevels, UINTFeatureLevels:指向一组特征集。创建函数会按顺序尝试这些特征集,并选择第一个能支持的特征集。传入NULL的话,则会依次尝试从高到低(SM5->SM2)的所有特征集。
- D3D_FEATURE_LEVEL_9_1 = 0x9100,
SM2 - D3D_FEATURE_LEVEL_9_2 = 0x9200,
SM2 - D3D_FEATURE_LEVEL_9_3 = 0x9300,
SM3 - D3D_FEATURE_LEVEL_10_0 = 0xa000,
SM4 - D3D_FEATURE_LEVEL_10_1 = 0xa100,
SM4 - D3D_FEATURE_LEVEL_11_0 = 0xb000,
SM5
UINTSDKVersion: SDK版本,传入D3D11_SDK_VERSION,这是由SDK设置的一个常数
ID3D11Device **ppDevice,D3D_FEATURE_LEVEL *pFeatureLevel,ID3D11DeviceContext **ppImmediateContext
Device Context 包含了Device的环境或设置。更精确地说,DeviceContext用来设置渲染状态,产生渲染命令,并使用资源。D3D11实现了两种Context,一种是立即渲染(immediate rendering),一种是延迟渲染(deferred rendering)。它们都由ID3D11DeviceContext接口代表。每个线程只能有一个Context,一般主线程拥有立即Context,用于渲染,其他工作线程拥有延迟Context。
一个Device有且只有一个立即Context,它用来直接绘制到硬件,它能够从GPU获取数据,也可以用来立即执行(或回放)一个命令列表。立即Context可以在创建Device时获取,也可以通过ID3D11Device::GetImmediateContext()接口获取。
延迟Context将GPU命令记录到命令列表之中。它主要用来在主线程之外记录渲染命令。创建延迟Context时将不会继承任何的立即Context的状态。延迟Context通过ID3D11Device::CreateDeferredContext()接口创建。
ID3D11Device接口函数都是线程安全的,但ID3D11DeviceContext接口不是线程安全的,即必须只能在一个线程内进行调用。这区别于ID3D10Device接口。