Direct3D 11对象模型将资源创建和渲染功能分离到一个设备和一个或多个设备上下文中。这种分离旨在促进多线程。
- 设备
- 设备上下文
- 实时设备上下文
- 延迟设备上下文
- 线程问题
设备
设备用于创建资源并枚举显示适配器的功能。在Direct3D 11中,设备用ID3D11Device接口表示。每个应用程序必须至少有一个设备,大多数应用程序只创建一个设备。通过调用D3D11CreateDevice或D3D11CreateDeviceAndSwapChain为机器上安装的硬件驱动程序之一创建一个设备,并使用D3D_DRIVER_TYPE标志指定驱动程序类型。每个设备可以使用一个或多个设备上下文,这取决于所需的功能。
设备上下文
设备上下文包含使用设备的环境和设置。设备上下文用于设置管道状态,并使用设备拥有的资源生成渲染命令。Direct3D11 实现了两种类型的设备上下文,一种是实时设备上下文,一种是延时设备上下文。这两个上下文都用ID3D11DeviceContext接口表示。
实时设备上下文
实时上下文直接渲染给驱动程序。每个设备都有且只有一个可以从GPU获取数据的实时上下文。可以使用实时上下文立即渲染(或回放)命令列表。
有两种方式获取实时上下文:
- 通过调用D3D11CreateDevice 或者 D3D11CreateCreateDeviceAndSwapChain.
- 通过调用ID3D11Device::GetImmediateContext.
延迟设备上下文:
一个延迟设备上下文将GPU命令记录到一个命令队列。一个延迟上下文主要是为了给多线程程序准备的,对单线程序是没有必要的。延迟上下文一般不会在主渲染线程中使用,一般都是在非主渲染线程的工作线程中使用。当你创建一个延迟上下文,它不会从实时上下文中继承任何状态。
通过调用ID3D11Device::CreateDeferredContext函数获取一个延迟上下文。
任何上下文(即时的或延迟的)都可以在任何线程上使用,只要该上下文一次只在一个线程中使用。
线程思考
此表突出显示了Direct3D 11中的线程模型与先前版本的Direct3D的不同之处:
所有ID3D11Device接口方法都是线程安全的,这意味着让多个线程同时调用这些函数是安全的。
- 所有id3d11devichild派生的接口(ID3D11Buffer、ID3D11Query等)都是线程安全的。
- Direct3D 11将资源创建和渲染分成两个接口。Map、Unmap、Begin、End和GetData都是在ID3D11DeviceContext上实现的,因为ID3D11Device严格定义了操作的顺序。ID3D11Resource和ID3D11Asynchronous接口也实现了用于线程安全操作的方法。
- ID3D11DeviceContext方法不是线程安全的,也就是说,它们需要单线程执行。每次只有一个线程可以安全地调用它的任何方法(Draw,Copy,Map等)。
- 通常,线程安全将使用最少的原子操作和最短的调用时间。然而,使用长时间保持同步的应用程序会直接影响应用程序预期实现的并发性。
ID3D10设备接口方法不是设计为线程安全的。ID3D10Device实现了所有的创建和渲染功能(与Direct3D 9中的ID3D9Device一样). Map和Unmap在ID3D10resource派生的接口上实现,Begin、End和GetData在ID3D10Asynchronous异步派生的接口上实现。