Direct3D 11 Backend
The Direct3D 11 backend is a Windows-specific backend implemented using the Direct3D 11 graphics API. A Direct3D 11 GraphicsDevice can be created two ways:
- Using a Win32 window handle. This can be the handle of an embedded frame within a parent window, or simply the handle of an isolated application window.
- Using a UWP SwapChainPanel or SwapChainBackgroundPanel.
API Concept Map
Veldrid Concept | D3D11 Concept | Notes |
---|---|---|
GraphicsDevice | ID3D11Device, and its Immediate Context | Some operations, like mapping or updating resources, use the ID3D11Device's immediate context. |
CommandList | ID3D11DeviceContext | One deferred ID3D11DeviceContext is used per CommandList. When submitted, an ID3D11CommandList is generated, and then the deferred context is reset for further commands to be recorded. |
DeviceBuffer | ID3D11Buffer | |
BufferUsage | D3D11_USAGE, D3D11_BIND_FLAG, D3D11_CPU_ACCESS_FLAG | |
Texture | ID3D11Texture1D, ID3D11Texture2D, ID3D11Texture3D | |
TextureUsage | D3D11_USAGE, D3D11_BIND_FLAG, D3D11_CPU_ACCESS_FLAG | |
TextureView | ID3D11ShaderResourceView, ID3D11UnorderedAccessView | |
Sampler | ID3D11SamplerState | |
Pipeline | Compound (see below) | |
Blend State | ID3D11BlendState | |
Depth Stencil State | ID3D11DepthStencilState | |
Rasterizer State | ID3D11RasterizerState | |
PrimitiveTopology | D3D11_PRIMITIVE_TOPOLOGY | |
Vertex Layouts | ID3D11InputLayout | |
Shader | ID3D11*Shader (Vertex, Pixel, Geometry, Hull, Domain, Compute) | |
ShaderSetDescription | None | D3D11 uses separate shader objects and doesn't combine them into a single state object. The D3D11 backend separately binds the Shader objects contained in a ShaderSetDescription. |
Framebuffer | ID3D11RenderTargetView, ID3D11DepthStencilView | |
ResourceLayout | None | The D3D11 backend uses the information from a ResourceLayout to determine which buffer, texture, sampler, and UAV register slots to bind resources to. |
ResourceSet | None | The D3D11 backend simply uses the individual resources contained in a ResourceSet to bind to particular shader stages. The slots are determined using information from the associated ResourceLayout. |
Swapchain | IDXGISwapchain |
Notes
The D3D11 backend is straightforward and maps easily to Veldrid's abstraction. Much of the complexity is related to translating between D3D11's "individual" pipeline state objects into Veldrid's "monolithic" Pipeline object. Going in this direction ("monolithic" to "separate") is relatively simple, and just means that a D3D11Pipeline object, for example, has several child objects that it manages and binds when necessary.
Veldrid's threading guarantees are easily supported by the relevant concepts in D3D11. An ID3D11Device is thread-safe and can be used to create objects on many threads. Deferred ID3D11DeviceContexts can be created to allow many CommandList instances to be used simultaneously in different threads. Multi-threaded resource mapping (GraphicsDevice.Map) can be slightly slower than other backends because it involves synchronizing access to the ID3D11Device's immediate context, and because D3D11 does not support persistent resource mapping, which would obviate the need to actually map/unmap dynamic resources.
To avoid redundant state changes, the D3D11 backend tracks various pieces of information, and elides state-changing function calls if they are determined to be unnecessary. For example, if a new Pipeline object is bound that has the same Shader objects as the previous Pipeline, then the Shader objects will not be set again. If a new ResourceSet is bound that shares some of the same resources as the previous ResourceSet, then those updates are ignored, and only the resources that have actually changed will be re-bound.
Command execution is done synchronously in D3D11. This means the implementation of some synchronization elements, like Fences, are not interesting. Fences are simply signaled before the SubmitCommands method returns.