2016-01-25 5 views
4

The HelloWorld examples from Microsoft в основном используют один CommandAllocator, а затем дождитесь завершения предыдущего кадра. Однако они также говорят (во всех случаях), что это не то, как это должно быть сделано.Имеет ли смысл создавать распределитель на renderTarget в swapchain?

Так что моя идея заключается в том, чтобы создать Allocator для каждого кадра в swapchain и держать который забор значение ждать в кольцевом буфере:

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(); 
} 

Это разумный подход? Или есть лучший способ?

+0

это разумный подход, и я бы сказал, что рекомендуемый способ, но вы должны включать в себя список команд тоже, так как вы не можете вызовите Сброс, пока список команд не будет полностью использован. Я создаю обычно backbufferCount + N с N в распределителях [1..4] и по крайней мере один основной список команд на распределитель. N - это позволить каскадам очереди ожидания, если они хотят поглощать пузырьки gpu. – galop1n

+0

@ galop1n на самом деле неверно: [В отличие от ID3D12CommandAllocator :: Reset, вы можете вызвать \ [ID3D12GraphicsCommandList :: \] Сброс, пока список команд все еще выполняется.] (Https://msdn.microsoft.com/en-us /library/windows/desktop/dn903895%28v=vs.85%29.aspx) –

ответ

3

Возможно, вы уже нашли ответ, но я отвечу на всякий случай. Вы не можете сбросить распределитель команд, в то время как графический процессор может выполнять список команд, хранящийся в памяти, связанной с распределителем команд, поэтому ваш подход правильный, вам нужно будет иметь отдельный распределитель команд для каждого кадра-буфера.

Списки команд, с другой стороны, могут быть сброшены сразу же после вызова ExecuteCommandLists(). Это означает, что, хотя у вас должен быть распределитель команд на каждый кадр, вам нужен только один список команд на «поток».

Списки команд могут заполняться только одним потоком за раз, что означает, что вам нужно иметь один список команд для каждого потока, который заполняет список команд.

Итак, вам нужно иметь numFrames * Команда numThreads распределители и numThreads списки команд