Я начинаю изучать Direct3D 12 и испытываю трудности в понимании синхронизации CPU-GPU. Насколько я понимаю, забор (ID3D12Fence) - это не более, чем значение UINT64 (unsigned long long), используемое в качестве счетчика. Но его методы смущают меня. Ниже приведена часть исходного кода из примера D3D12. (https://github.com/d3dcoder/d3d12book)
void D3DApp::FlushCommandQueue()
{
// Advance the fence value to mark commands up to this fence point.
mCurrentFence++;
// Add an instruction to the command queue to set a new fence point. Because we
// are on the GPU timeline, the new fence point won't be set until the GPU finishes
// processing all the commands prior to this Signal().
ThrowIfFailed(mCommandQueue->Signal(mFence.Get(), mCurrentFence));
// Wait until the GPU has completed commands up to this fence point.
if(mFence->GetCompletedValue() < mCurrentFence)
{
HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
// Fire event when GPU hits current fence.
ThrowIfFailed(mFence->SetEventOnCompletion(mCurrentFence, eventHandle));
// Wait until the GPU hits current fence event is fired.
WaitForSingleObject(eventHandle, INFINITE);
CloseHandle(eventHandle);
}
}
Насколько я понимаю, эта часть пытается «очистить» очередь команд, что в основном заставляет процессор ждатьГрафический процессор, пока он не достигнет заданного «значения Fence», чтобы у CPU и GPU было одинаковое значение ограждения.
Q. Если этот Signal () является функцией, которая позволяет GPU обновлять значение ограждения внутри заданного ID3D12FenceЗачем нужно это значение mCurrentFence?
Согласно Microsoft Doc, в нем говорится «Обновляет забор до указанного значения.» Какое указанное значение? Что мне нужно, это «Получить последнее значение списка завершенных команд». , не установлен или не указан. Для чего это заданное значение?
Мне кажется, оно должно быть похоже на
// Suppose mCurrentFence is 1 after submitting 1 command list (Index 0), and the thread reached to here for the FIRST time
ThrowIfFailed(mCommandQueue->Signal(mFence.Get()));
// At this point Fence value inside mFence is updated
if (m_Fence->GetCompletedValue() < mCurrentFence)
{
...
}
, если m_Fence-> GetCompletedValue () равно 0,
если (0 <1) </p>
GPU не управлял списком команд (Index 0), то CPU должен ждать, пока GPU не последует. Тогда имеет смысл вызвать SetEventOnCompletion, WaitForSingleObject и т. Д.
если (1 <1) </p>
Графический процессор завершил список команд (индекс 0), поэтому процессору не нужно ждать.
Увеличить mCurrentFence где-нибудь, где выполняется список команд.
mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
mCurrentFence++;