Windows平台C++实现144Hz高帧率屏幕捕获优化方案咨询
屏幕捕获帧率优化方案
我正在开发将屏幕画面捕获并复制到应用程序中的功能,现有代码如下:
static bool first = false; static IDirect3DSurface9* pSurface; static IDirect3DSurface9* pBackbuffer; HRESULT hr; if (first == false) { hr = m_pD3DDevice9Ex->CreateOffscreenPlainSurface(1920, 1080, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pSurface, NULL); hr = m_pD3DDevice9Ex->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackbuffer); first = true; } if (pSurface != NULL) { hr = m_pD3DDevice9Ex->GetFrontBufferData(0, pSurface); hr = m_pD3DDevice9Ex->UpdateSurface(pSurface, NULL, pBackbuffer, NULL); }
该代码可正常运行,但帧率极低(1920×1080分辨率下仅60-80fps)。我需要实现至少144Hz的屏幕捕获,以下是可行的优化方案:
- 替换低效的
GetFrontBufferData:GetFrontBufferData是同步操作,且强制将GPU显存数据拷贝到系统内存,这是帧率瓶颈的核心原因。改用IDirect3DDevice9Ex::CreateRenderTarget创建GPU显存池(D3DPOOL_DEFAULT)内的渲染目标,配合StretchRect直接在显存内完成拷贝,避免跨内存池的数据传输。 - 调整内存池类型:将
CreateOffscreenPlainSurface的D3DPOOL_SYSTEMMEM改为D3DPOOL_DEFAULT,让捕获表面留在GPU显存中,彻底消除显存到系统内存的拷贝开销——这一步能大幅提升捕获效率。 - 移除冗余的两次拷贝:当前代码先把前缓冲区数据拷到
pSurface,再拷到pBackbuffer,属于重复操作。直接调用StretchRect将前缓冲区数据复制到应用的pBackbuffer,省去中间表面的中转步骤。 - 改用DXGI的屏幕捕获API:Direct3D9的API设计并非针对高刷新率捕获,而DXGI的
IDXGIOutputDuplication是专门为桌面捕获优化的接口,能直接获取桌面的帧数据,支持硬件加速,轻松达到144Hz甚至更高帧率。核心步骤为:初始化DXGI设备、获取目标显示器的输出复制接口、循环调用AcquireNextFrame获取帧、处理后调用ReleaseFrame释放资源。 - 引入异步处理机制:利用Direct3D的异步查询(
IDirect3DQuery9)检测捕获操作是否完成,避免CPU等待GPU,同时维护一个帧队列,让捕获、处理、渲染三个环节并行执行,充分利用CPU和GPU资源。 - 完善错误处理:当前代码未检查
HRESULT的返回值,若资源创建失败会导致后续操作无效。添加SUCCEEDED(hr)或FAILED(hr)的判断,确保资源初始化成功后再执行捕获逻辑。
内容的提问来源于stack exchange,提问作者medq
相关产品推荐
相关产品推荐

