DX12单线程应用Present阶段阻塞问题排查求助
DX12单线程应用Present阶段阻塞排查求助
我正在RTX 4060 Laptop GPU上开发单线程DX12应用,采用单个直接队列处理拷贝、图形与调度任务,帧工作流程如下:
- CPU更新(变换等操作)
- 等待帧围栏以让GPU追赶上(等待最后标记值 - (最大队列帧数 - 1))
- 重置当前帧的命令分配器
- 向命令列表填充GPU命令
- 执行命令列表并标记帧围栏
- Present
我的预期是即使GPU受限,等待也应发生在步骤2,但实际发现Present阶段存在大量等待:通常每帧约2ms,偶尔达7-8ms并导致明显卡顿;而帧围栏从未出现等待(当前GPU比CPU更快,此情况符合预期)。
我已按照NVIDIA《Advanced API Performance: Swap Chains》文档配置交换链:设置最大3帧在处理中,创建5个交换链缓冲区(NVIDIA建议比预期队列帧数多1-2个),并将最大帧延迟设为5个缓冲区,按理解这应避免Present阻塞。
通过PIX时序捕获分析,每帧CPU生成的总工作量约1ms,GPU工作量也约1ms。我尝试过开启/关闭撕裂效果、调整交换链标志、后台缓冲区数量及格式等,但均无效果;启用调试层后DX12和DXGI均无报错信息。
交换链创建代码
DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 5; sd.Format = Config::Graphic::SwapChainFormat; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH | DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING | DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; ComPtr<IDXGISwapChain1> swapChain1; ApiCheck(factory->CreateSwapChainForHwnd( queue, window.GetHandle(), &sd, nullptr, nullptr, &swapChain1)); ApiCheck(swapChain1.As(&m_DXGISwapChain)); // ComPtr<IDXGISwapChain3> m_DXGISwapChain m_DXGISwapChain->SetMaximumFrameLatency(5);
Present代码
enum class PresentMode { UncappedWithTearing = -1, Uncapped = 0, VSync = 1, VSyncHalf = 2, VSyncThird = 3, VSyncQuarter = 4 }; uint32_t presentFlags = 0; uint32_t syncInterval = 0; if (presentMode == PresentMode::UncappedWithTearing) { presentFlags |= DXGI_PRESENT_ALLOW_TEARING; } else { syncInterval = uint32_t(presentMode); } HRESULT hres = m_DXGISwapChain->Present(syncInterval, presentFlags); if (FAILED(hres)) { if (hres == DXGI_ERROR_DEVICE_REMOVED) { ApiCheck(GetDevice()->GetDeviceRemovedReason()); } else { ApiCheck(hres); } }
目前我已无排查思路,恳请提供问题排查方向,谢谢!
内容的提问来源于stack exchange,提问作者whatabouthis
相关产品推荐
相关产品推荐

