新版 DirectX 12 不應在執行期間切換 Swap Chain 的多重取樣設定。較穩定的做法是建立獨立的多樣本 Render Target 與 Depth Stencil,使用相同 Sample Count 的 Pipeline State,完成繪製後再把結果 Resolve 到一般的 Back Buffer。

  1. 建立 SampleDesc.Count = 4 的 MSAA Color Resource 與 RTV
  2. 建立相同 Sample Count 的 Depth Resource 與 TEXTURE2DMS DSV
  3. 建立 MSAA 專用 PSO,RTV/DSV Format 必須與資源一致
  4. 繪製前把 MSAA Color Resource 轉成 RENDER_TARGET
  5. 繪製後轉成 RESOLVE_SOURCE,把 Back Buffer 轉成 RESOLVE_DEST,呼叫 ResolveSubresource()
  6. 把 Back Buffer 轉回 PRESENT 後顯示

所有資源狀態、Format、Sample Count 與 Sample Quality 都必須配對;硬體支援的 Quality 應先透過 API 查詢。

新版 DirectX 12 不应在运行时切换 Swap Chain 的多重采样设置。更稳定的做法是创建独立的多采样 Render Target 和 Depth Stencil,使用相同 Sample Count 的 Pipeline State,绘制完成后再把结果 Resolve 到普通 Back Buffer。

  1. 创建 SampleDesc.Count = 4 的 MSAA Color Resource 与 RTV
  2. 创建相同 Sample Count 的 Depth Resource 与 TEXTURE2DMS DSV
  3. 创建 MSAA 专用 PSO,RTV/DSV Format 必须与资源一致
  4. 绘制前把 Color Resource 转换为 RENDER_TARGET
  5. 绘制后转换为 RESOLVE_SOURCE,把 Back Buffer 转换为 RESOLVE_DEST,调用 ResolveSubresource()
  6. 把 Back Buffer 转回 PRESENT 后显示

资源状态、Format、Sample Count 和 Sample Quality 必须完全匹配;Quality 应先通过 API 查询硬件支持情况。

Modern DirectX 12 code should not toggle multisampling on the Swap Chain at runtime. Instead, render into separate multisampled Color and Depth resources with a matching Pipeline State, then resolve the result into the normal Back Buffer.

  1. Create an MSAA Color Resource and RTV with SampleDesc.Count = 4
  2. Create a Depth Resource and TEXTURE2DMS DSV with the same sample count
  3. Create a matching MSAA PSO; the RTV and DSV formats must match the resources
  4. Transition the Color Resource to RENDER_TARGET and draw
  5. Transition it to RESOLVE_SOURCE, transition the Back Buffer to RESOLVE_DEST, and call ResolveSubresource()
  6. Transition the Back Buffer to PRESENT and display it

Resource states, formats, sample counts, and sample quality must agree. Query the supported quality level before creating the resources.

現在の DirectX 12 では、実行中に Swap Chain のマルチサンプル設定を切り替えるべきではありません。代わりに、同じ Sample Count を持つ Color/Depth Resource と Pipeline State を用意し、描画後に通常の Back Buffer へ Resolve します。

  1. SampleDesc.Count = 4 の MSAA Color Resource と RTV を作成します
  2. 同じ Sample Count の Depth Resource と TEXTURE2DMS DSV を作成します
  3. Format が Resource と一致する MSAA 用 PSO を作成します
  4. Color Resource を RENDER_TARGET へ遷移して描画します
  5. RESOLVE_SOURCE へ遷移し、Back Buffer を RESOLVE_DEST にして ResolveSubresource() を呼びます
  6. Back Buffer を PRESENT に戻して表示します

Resource State、Format、Sample Count、Sample Quality はすべて一致させ、Quality は事前に API で対応状況を確認します。

1
2
3
4
5
6
7
8
9
// 繪製到多重取樣 Render Target
Transition(msaaColor, D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
DrawScene();

// Resolve 到 Swap Chain 的 Back Buffer
Transition(msaaColor, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
Transition(backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST);
commandList->ResolveSubresource(backBuffer, 0, msaaColor, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
Transition(backBuffer, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT);
原始畫面 4x MSAA
原始畫面 MSAA 畫面
1
2
3
4
5
6
7
8
9
// 绘制到多采样 Render Target
Transition(msaaColor, D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
DrawScene();

// Resolve 到 Swap Chain 的 Back Buffer
Transition(msaaColor, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
Transition(backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST);
commandList->ResolveSubresource(backBuffer, 0, msaaColor, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
Transition(backBuffer, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT);
原始画面 4x MSAA
原始画面 MSAA 画面
1
2
3
4
5
6
7
8
9
// Draw into the multisampled render target
Transition(msaaColor, D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
DrawScene();

// Resolve into the swap-chain back buffer
Transition(msaaColor, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
Transition(backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST);
commandList->ResolveSubresource(backBuffer, 0, msaaColor, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
Transition(backBuffer, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT);
Original 4x MSAA
Original MSAA
1
2
3
4
5
6
7
8
9
// マルチサンプル Render Target へ描画する
Transition(msaaColor, D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
DrawScene();

// Swap Chain の Back Buffer へ Resolve する
Transition(msaaColor, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
Transition(backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST);
commandList->ResolveSubresource(backBuffer, 0, msaaColor, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
Transition(backBuffer, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT);
元画像 4x MSAA
元画像 MSAA 画像