Примеры HelloWorld от Microsoft в основном используют один CommandAllocator, а затем ждут, когда предыдущий кадр будет полностью завершен. Однако они также говорят (во всех заглавных буквах), что это не так, как это должно быть сделано.
Поэтому моя идея состоит в том, чтобы создать Распределитель на кадр в цепочке обмена и сохранить значение ограждения в кольцевом буфере:
struct frame_resources{
ID3D12Resource* renderTarget;
ID3D12CommandAllocator* allocator;
uint64 fenceValue;
} resources[FRAME_COUNT];uint frameIndex = swapChain->GetCurrentBackBufferIndex();
UINT64 lastFence;
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
if (fence->GetCompletedValue() < resources[frameIndex].fenceValue)
{
fence->SetEventOnCompletion(resources[frameIndex].fenceValue, fenceEvent);
DWORD result = MsgWaitForMultipleObjects(1, &fenceEvent, FALSE, INFINITE, QS_ALLEVENTS);
if(result == WAIT_OBJECT_0 + 1)
continue; //message in the queue
}
resources[frameIndex].allocator->Reset();
commandList->Reset(resources[frameIndex].allocator, 0);
//...
commandList->Close();
commandQueue->ExecuteCommandLists(1, &CommandList);
lastFence++;
resources[frameIndex].fenceValue = lastFence;
commandQueue->Signal(fence, lastFence);
swapChain->Present(0, DXGI_PRESENT_RESTART);
frameIndex = swapChain->GetCurrentBackBufferIndex();
}
Это вменяемый подход? Или есть лучший способ?
Вы, наверное, уже нашли ответ, но я отвечу на всякий случай. Вы не можете сбросить распределитель команд, пока графический процессор выполняет список команд, хранящийся в памяти, связанной с распределителем команд, поэтому ваш подход правильный, вам потребуется отдельный распределитель команд для буфера кадра.
С другой стороны, списки команд могут быть сброшены сразу после вызова ExecuteCommandLists (). Это означает, что, хотя вы должны иметь распределитель команд на кадр, вам нужен только один список команд на «поток».
Списки команд могут заполняться только одним потоком за раз, что означает, что вам нужно иметь один список команд на поток, который заполняет список команд.
Итак, вам нужно иметь распределители команд numFrames * numThreads и списки команд numThreads
Других решений пока нет …