DX12-Befehlswarteschlange und Zaun
Synchronisieren Sie CPU und GPU zum richtigen Zeitpunkt
Die in diesem Blog verfassten Artikel wurden mit dem Ziel erstellt, zu unterrichten. Außerdem können die Informationen im Artikel falsch sein, also seien Sie bitte vorsichtig.
In DirectX 12 zeichnet die CPU die Befehlsliste auf und die GPU führt sie später aus. Da sich die beiden Geräte gleichzeitig bewegen, müssen sie synchronisiert werden, damit die CPU nicht die von der GPU noch genutzten Ressourcen überschreibt.
Befehlswarteschlange und Befehlsliste
Die Befehlsliste ist eine Liste, die Zeichenbefehle aufzeichnet, und die Befehlswarteschlange übermittelt die vollständige Liste an die GPU.
CPU
CommandAllocator-Initialisierung
Befehlslistenverlauf
CommandList Close
↓
Befehlswarteschlange senden
↓
GPU-Ausführung
CommandAllocator verwaltet den für die Aufzeichnung erforderlichen Speicher. Derselbe Allocator sollte nicht zurückgesetzt werden, während die GPU noch Anweisungen aus dem vorherigen Frame liest.
Überprüfen Sie die Fertigstellungszeit mit Fence
void WaitForGPU()
{
const UINT64 SignalValue = ++FenceValue;
CommandQueue->Signal(Fence, SignalValue);
if (Fence->GetCompletedValue() < SignalValue)
{
Fence->SetEventOnCompletion(SignalValue, FenceEvent);
WaitForSingleObject(FenceEvent, INFINITE);
}
}
Wenn ein Signalwert in die Warteschlange eingegeben wird, verarbeitet die GPU alle vorherigen Befehle und aktualisiert dann den Fence-Wert. Die CPU wartet nur dann auf ein Ereignis, wenn der Abschlusswert kleiner als der Zielwert ist.
Es ist langsam, wenn Sie auf jedes Bild warten.
Um es im Dreiecksbeispiel leichter verständlich zu machen,WaitForGPU()aufgerufen werden kann. Wenn Sie dies tun, können CPU und GPU jedoch nicht zusammenarbeiten und nicht jeden Frame seriell ausführen.
In der Praxis gibt es so viele Frame-Ressourcen wie BackBuffers und der Fence-Wert jedes Frames wird separat aufgezeichnet.
struct FrameContext
{
ComPtr<ID3D12CommandAllocator> Allocator;
UINT64 FenceValue = 0;
};
Es wartet nur auf den Fence der aktuell genutzten Frame-Ressource und ermöglicht der GPU, mit der Verarbeitung anderer Frames fortzufahren.
Aktivieren Sie die Debug-Ebene
In DX12 sind Entwickler direkt für falsche Zustandsübergänge oder die Verwendung von Deskriptoren verantwortlich. Wenn Sie die Debug-Ebene vor der Initialisierung aktivieren, können Sie viel schneller herausfinden, welcher Ressourcenstatus und welche Befehlsreihenfolge falsch sind.
Der Zweck der DX12-Synchronisation besteht nicht darin, bedingungslos zu warten. Dadurch können CPU und GPU so viel wie möglich gleichzeitig arbeiten, während sie genau darauf warten, wieder dieselben Ressourcen zu nutzen.