Je configure une application DX12 qui efface uniquement le backbuffer à chaque image.DXGI Waitable SwapChain n'attend pas
Il est vraiment barebone: pas PSO, pas de racine ... La seule particularité est qu'il attend sur le swapChain à faire avec le présent() avant de commencer un nouveau cadre (msdn waitable swap chain) (je mets le temps d'attente de trame à 1 aussi bien que sur seulement 2 tampons).
La première trame fonctionne bien mais elle commence immédiatement à dessiner la seconde trame, et bien sûr, l'allocateur de commandes se plaint de la réinitialisation alors que les commandes sont encore en cours d'exécution sur le GPU.
Je pourrais bien sûr installer une clôture pour attendre que l'unité centrale soit exécutée avant de passer à une nouvelle trame, mais je pensais que c'était le travail de l'objet chaîne d'attente attendue.
Voici le rendu de routine:
if (m_command_allocator->Reset() == E_FAIL) { throw; }
HRESULT res = S_OK;
res = m_command_list->Reset(m_command_allocator.Get(), nullptr);
if (res == E_FAIL || res == E_OUTOFMEMORY) { throw; }
m_command_list->ResourceBarrier(1,
&CD3DX12_RESOURCE_BARRIER::Transition(m_render_targets[m_frame_index].Get(),
D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
m_command_list->RSSetViewports(1, &m_screen_viewport);
m_command_list->RSSetScissorRects(1, &m_scissor_rect);
m_command_list->ClearRenderTargetView(get_rtv_handle(),
DirectX::Colors::BlueViolet, 0, nullptr);
m_command_list->OMSetRenderTargets(1, &get_rtv_handle(), true, nullptr);
m_command_list->ResourceBarrier(1,
&CD3DX12_RESOURCE_BARRIER::Transition(m_render_targets[m_frame_index].Get(),
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
tools::throw_if_failed(m_command_list->Close());
ID3D12CommandList* ppCommandLists[] = { m_command_list.Get() };
m_command_queue->ExecuteCommandLists(_countof(ppCommandLists),
ppCommandLists);
if (m_swap_chain->Present(1, 0) != S_OK) { throw; }
m_frame_index = m_swap_chain->GetCurrentBackBufferIndex();
boucle I sur cette routine avec un wich objet waitable je suis arrivé du swapchain:
while (WAIT_OBJECT_0 == WaitForSingleObjectEx(waitable_renderer, INFINITE, TRUE) && m_alive == true)
{
m_graphics.render();
}
et j'initialisés la swapchain avec le waitable indicateur:
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
swap_chain_desc.BufferCount = s_frame_count;
swap_chain_desc.Width = window_width;
swap_chain_desc.Height = window_height;
swap_chain_desc.Format = m_back_buffer_format;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
ComPtr<IDXGISwapChain1> swap_chain;
tools::throw_if_failed(
factory->CreateSwapChainForHwnd(m_command_queue.Get(), window_handle, &swap_chain_desc, nullptr, nullptr, &swap_chain));
J'appelle le SetFrameLatency droit après la création du swapChain:
ComPtr<IDXGISwapChain2> swap_chain2;
tools::throw_if_failed(m_swap_chain.As(&swap_chain2));
tools::throw_if_failed(swap_chain2->SetMaximumFrameLatency(1));
m_waitable_renderer = swap_chain2->GetFrameLatencyWaitableObject();
Et le swapChain redimensionne qui va avec:
tools::throw_if_failed(
m_swap_chain->ResizeBuffers(s_frame_count, window_width, window_height, m_back_buffer_format, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT));
Ma question est: je suis en train de quelque chose de manière incorrecte? ou est-ce la façon dont la chaîne d'attente fonctionne (c'est-à-dire que vous devez également synchroniser avec gpu avec des clôtures avant d'attendre que la chaîne d'échange devienne disponible)?
EDIT: Ajout d'appel SetFrameLatency + C++ coloration
Votre code semble être bien, mais on ne sait pas si vous avez appelé réellement 'GetFrameLatencyWaitableObject 'pour obtenir' waitable_renderer'. – VTT
J'ai modifié ma question en fonction de votre suggestion et de votre commentaire. –