Swap Chains

Swap chains control the back buffer rotation, forming the basis of graphics animation.

Overview

The programming model for swap chains in Direct3D 12 is not identical to that in earlier versions of D3D. The programming convenience, for example, of supporting automatic resource rotation that was present in D3D10 and D3D11 is no longer supported. Automatic resource rotation enabled apps to render the same API object while the actual surface being rendered changes each frame. The behavior of swap chains is changed with Direct3D 12 to enable other features of Direct3D 12 to have low CPU overhead. Automatic color key and multisampling are not supported, although notably stretching and rotation still are.

Buffer lifetime

Apps are allowed to store pre-created descriptors which reference back buffers This is enabled by ensuring that the set of buffers owned by a swap chain never changes for the lifetime of the swap chain. The set of buffers returned by IDXGISwapChain::GetBuffer doesn't change until certain APIs are called:

The order of buffers returned by GetBuffer never changes.

IDXGISwapChain3::GetCurrentBackBufferIndex returns the index of the current back buffer to the app.

Swap effects

The only supported swap effects are DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD, which requires the buffer count to be greater than one.

Transitioning between windowed and full-screen modes

Direct3D 12 doesn't support full-screen exclusive mode (FSE). Instead, when a game is the only visible application on-screen, the OS uses a strategy called full-screen optimisations (FSO) to achieve a similar effect to FSE without the performance drawbacks. For more info about FSO, see Demystifying Fullscreen Optimisations.

Direct3D 12 maintains the restriction that applications must call ResizeBuffers after transitioning between windowed and full-screen modes (D3D11 flip-model swap chains have the same restrictions).

The IDXGISwapChain::SetFullscreenState transitions do not change the set of app-visible buffers in the swap chain. Only the ResizeBuffers and ResizeTarget calls create or destroy app-visible buffers. However, in Direct3D 12 IDXGISwapChain::SetFullscreenState doesn't enter full-screen exclusive mode, and simply changes resolutions and refresh rates to allow full-screen optimisations. These changes can be made by an app without the use of this method

When or IDXGISwapChain::Present or IDXGISwapChain1::Present is called, the back buffer to be presented must be in the D3D12_RESOURCE_STATE_PRESENT state. Present will fail with DXGI_ERROR_INVALID_CALL if this is not the case.

Full-screen swap chains continue to have the restriction that SetFullscreenState(FALSE, NULL) must be called before the final release of the swap chain. SetFullscreenState(FALSE) succeeds on swap chains running on Direct3D 12 devices.

Present operations occur on the 3D queue provided at swapchain creation, and apps are free to concurrently present multiple swap chains, and record and execute command lists.

When the final part of the graphics work (for example, frame postprocessing) is done on a compute queue, or doesn't involve the device's graphics queue, creating a second 3D queue to present on can be beneficial and prevent the latency of presentation delaying the start of the next frame.

Example

The following example code would be present in the main rendering loop:

void Present()
{
    m_swapChain->Present(0, m_presentFlags);
    m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount;
}

Creating swap chains

When using the CreateSwapChainForHwnd, CreateSwapChainForCoreWindow, or CreateSwapChainForComposition calls, note that the pDevice parameter actually requires a pointer to a direct command queue in Direct3D 12, and not a device.

Presenting on Windows 7

When targeting Direct3D 12 on Windows 7, the necessary DXGI types for Direct3D 12 are not present, so you must use the D3D12On7-provided ID3D12CommandQueueDownLevel (queried off of the direct command queue) to present.

You provide an open command list to the Windows 7 present method, which will then be used, closed, and automatically submitted to the device for you. You must provide a back buffer which must be app-created, must be a committed resource, must be single-sampled, and must be one of the following formats.

  • DXGI_FORMAT_R16G16B16A16_FLOAT
  • DXGI_FORMAT_R10G10B10A2_UNORM
  • DXGI_FORMAT_R8G8B8A8_UNORM
  • DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
  • DXGI_FORMAT_B8G8R8X8_UNORM
  • DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
  • DXGI_FORMAT_B8G8R8A8_UNORM
  • DXGI_FORMAT_B8G8R8A8_UNORM_SRGB