← SEARCHABLE ARCHIVE
DirectX 12 · 2026-07-11

DX12 指令佇列與柵欄

在正確的時間同步 CPU 和 GPU

INTERACTIVE READING MODE →

該部落格上撰寫的文章是出於教學目的而創建的。 另外,文章中的資訊可能不正確,請謹慎。

在 DirectX 12 中,CPU 記錄命令列表,GPU 稍後執行。 由於兩個裝置同時移動,因此它們必須同步,以便 CPU 不會覆蓋 GPU 仍在使用的資源。

命令隊列和命令列表

Command List是記錄繪圖指令的列表,Command Queue將完成的列表提交給GPU。

CPU
命令分配器初始化
命令列表歷史記錄
CommandList Close
        ↓
提交命令隊列
        ↓
GPU執行

CommandAllocator 管理錄製所需的記憶體。 當 GPU 仍在讀取前一幀的指令時,不應重置同一個分配器。

使用 Fence 檢查完成時間

void WaitForGPU()
{
    const UINT64 SignalValue = ++FenceValue;
    CommandQueue->Signal(Fence, SignalValue);

    if (Fence->GetCompletedValue() < SignalValue)
    {
        Fence->SetEventOnCompletion(SignalValue, FenceEvent);
        WaitForSingleObject(FenceEvent, INFINITE);
    }
}

當訊號值進入佇列時,GPU 會處理先前的所有命令,然後更新 Fence 值。 只有當完成值小於目標時,CPU 才會等待事件。

如果你等待每一幀,那麼速度會很慢。

在三角形的例子中,為了更容易理解,WaitForGPU()可以調用。 但是,如果這樣做,CPU 和 GPU 就無法協同工作並在每一幀串行運行。

在實際應用中,BackBuffer的個數就有多少個Frame Resources,並且單獨記錄每幀的Fence值。

struct FrameContext
{
    ComPtr<ID3D12CommandAllocator> Allocator;
    UINT64 FenceValue = 0;
};

它只等待目前使用的幀資源的柵欄,並允許GPU繼續處理其他幀。

開啟調試層

在 DX12 中,開發人員對錯誤的狀態轉換或描述符的使用負有直接責任。 如果在初始化之前開啟偵錯層,您可以更快找出哪些資源狀態和命令順序錯誤。

DX12同步的目的不是無條件等待。 它允許CPU和GPU盡可能同時工作,同時精確地等待再次使用相同的資源。