我设置了一个DX12应用程序,它只清除每个帧的后台缓冲区。
它真的是巴里伯恩:没有粒子群,没有根..。唯一的特殊性是,它在启动新帧之前等待使用swapChain ()来完成(msdn可等待交换链 (我也将帧延迟设置为1,并且只有2个缓冲区)。
第一帧工作良好,但它立即开始绘制第二帧,当然,命令分配程序抱怨说,在GPU上仍在执行命令时,正在重置它。
当然,我可以设置一个栅栏,等待gpu在移动到新帧之前完成,但我认为这是等待交换链对象的工作。
以下是呈现例程:
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();我在这个例程上循环了一个从交换链中得到的可等待的对象:
while (WAIT_OBJECT_0 == WaitForSingleObjectEx(waitable_renderer, INFINITE, TRUE) && m_alive == true)
{
m_graphics.render();
}我用可等待的标志初始化了交换链:
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));我在创建SetFrameLatency之后立即调用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();并调整了swapChain的大小:
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));我的问题是:我是不是做错了什么?或者这是等待交换链工作的方式(即在等待交换链可用之前,还需要使用栅栏与gpu同步)?
编辑:添加SetFrameLatency调用+ C++着色
发布于 2017-05-04 16:02:44
可等待交换链与保护d3d12对象的工作无关,当GPU仍在使用时,要对其进行修改或重置。
可等待交换链允许您将等待从当前框架的末尾移动到具有可等待对象的框架的开始。它具有对抗延迟和更多控制排队的优势。
对象上的隔离允许您查询GPU以获得完成。我建议你不要只是祈祷,就像它一天在一个系统上工作一样,它可能在不同的驱动程序或不同的机器下不能工作。
因为您不希望每个帧等待GPU完成,所以必须创建几个命令分配器,通常,创建一个min(maxlatency+1,swapchain buffer count)计数,但为了安全起见,我亲自使用back buffer count + 1..3。稍后您会发现您将创建更多的分配器来处理多线程。
它对您的代码意味着什么:
https://stackoverflow.com/questions/43784340
复制相似问题