4

Microsoft の HelloWorld の例では、ほとんどの場合、単一の CommandAllocator を使用してから、前のフレームが完全に完了するまで待機します。ただし、彼らは(すべて大文字で)それがどのように行われるべきではないとも言っています。

したがって、私の考えは、スワップチェーンでフレームごとに Allocator を作成し、循環バッファーで待機するフェンス値を保持することです。

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

これは健全なアプローチですか?それとももっと良い方法がありますか?

4

1 に答える 1

3

すでに答えを見つけているかもしれませんが、念のため答えておきます。GPU がコマンド アロケーターに関連付けられたメモリに格納されているコマンド リストを実行している可能性がある場合、コマンド アロケーターをリセットすることはできません。そのため、アプローチは正しいです。フレーム バッファーごとに個別のコマンド アロケーターが必要になります。

一方、コマンド リストは、ExecuteCommandLists() を呼び出した直後にリセットできます。つまり、フレームごとにコマンド アロケータが必要ですが、「スレッド」ごとに必要なコマンド リストは 1 つだけです。

コマンド リストは、一度に 1 つのスレッドでのみ入力できます。つまり、コマンド リストを入力するスレッドごとに 1 つのコマンド リストが必要です。

したがって、numFrames*numThreads コマンド アロケーターと numThreads コマンド リストが必要です。

于 2016-05-10T01:59:12.177 に答える