You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用D3d Shared Texture实现高性能游戏实时截图

D3D Shared Texture 游戏捕获核心原理

BitBlt、PrintWindow、旧版桌面复制这类方案帧率低、拖慢游戏的核心原因是:所有方案都需要把GPU渲染完成的帧数据做一次GPU显存到系统内存的CPU拷贝,过程中要锁GPU帧缓冲、频繁切换内核态/用户态,CPU开销极高,碰到吃满CPU负载的游戏自然会互相抢占资源,帧率难以上30FPS。
D3D共享纹理是目前Windows平台游戏捕获性能最高的应用层方案,核心逻辑和OBS游戏捕获完全一致:

  • 基于D3D/DXGI的跨进程GPU资源共享能力,全程不需要把帧数据拷贝到CPU内存,捕获程序直接在GPU侧访问游戏渲染完成的帧纹理,额外开销可以压到1%以内,1080P/2K分辨率下跑满游戏原生144/240帧率都不会拖慢游戏运行。
  • 主流实现用D3D11/D3D12的NT类型共享句柄,支持跨D3D版本共享:不管游戏是用D3D9、D3D11还是D3D12渲染,捕获端只要用同一块物理GPU创建D3D11设备,就能直接打开共享句柄拿到纹理,不需要额外做格式转换。
  • 捕获时机完全对齐游戏渲染节奏:通过Hook游戏交换链的Present方法,在游戏每帧渲染完成、准备提交到显示器的时候触发捕获,不会打断游戏本身的渲染管线,也不存在轮询带来的延迟和性能浪费。
代码实现步骤(对接OpenCV实时展示)

前置准备:安装Windows 10/11 SDK,编译时链接d3d11.lib dxgi.lib,OpenCV需要编译时开启WITH_D3D11选项,才能直接对接D3D纹理做GPU侧处理,避免不必要的CPU拷贝。

  • 第一步:在捕获主程序里初始化D3D11设备
    注意设备必须和游戏运行在同一块物理GPU上,双显卡笔记本要提前在系统显卡设置里指定两个程序都用独立显卡,否则共享句柄会打开失败。
    #include <d3d11.h>
    #include <dxgi1_2.h>
    #include <opencv2/opencv.hpp>
    #include <opencv2/core/directx.hpp>
    
    ID3D11Device* dev = nullptr;
    ID3D11DeviceContext* ctx = nullptr;
    
    HRESULT hr = D3D11CreateDevice(
        nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
        nullptr, 0, D3D11_SDK_VERSION,
        &dev, nullptr, &ctx
    );
    if (FAILED(hr)) { /* 处理设备创建失败逻辑 */ }
    
  • 第二步:Hook游戏交换链的Present方法
    用MinHook这类轻量Inline Hook库,注入游戏进程后Hook IDXGISwapChain::Present 虚函数,每次游戏调用Present提交帧的时候,拿到当前交换链的后备缓冲纹理:
    // 游戏进程内的Hook逻辑
    ID3D11Texture2D* backbuf = nullptr;
    pSwapChain->GetBuffer(0, IID_PPV_ARGS(&backbuf));
    
    static HANDLE shared_tex_handle = nullptr;
    // 仅首次获取后备缓冲、或游戏重建交换链(切分辨率/切全屏)时创建共享句柄
    if (!shared_tex_handle) {
        IDXGIResource1* res = nullptr;
        backbuf->QueryInterface(__uuidof(IDXGIResource1), (void**)&res);
        res->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, &shared_tex_handle);
        // 用命名管道/内存映射文件把shared_tex_handle传递给捕获主程序
        res->Release();
    }
    backbuf->Release();
    
  • 第三步:捕获端拿到共享句柄后读取纹理,对接OpenCV处理展示
    这一步全程在GPU侧完成,不需要CPU拷贝,性能和OBS捕获一致:
    ID3D11Texture2D* shared_tex = nullptr;
    dev->OpenSharedResource(shared_tex_handle, IID_PPV_ARGS(&shared_tex));
    
    cv::UMat gpu_frame;
    // 直接把D3D11纹理转成OpenCV的GPU矩阵
    cv::directx::convertFromD3D11Texture2D(shared_tex, gpu_frame);
    
    // 此处编写OpenCV画面编辑逻辑,所有操作均在GPU执行
    cv::cvtColor(gpu_frame, gpu_frame, cv::COLOR_BGRA2BGR);
    cv::GaussianBlur(gpu_frame, gpu_frame, cv::Size(5,5), 0);
    // 可自行添加边缘检测、绘制UI元素等处理逻辑
    
    // 实时展示,imshow原生支持UMat直接显示,无额外拷贝开销
    cv::imshow("Game Capture", gpu_frame);
    cv::waitKey(1);
    
    shared_tex->Release();
    
常见避坑点
  • 绝对不要调用Map或者GetDC方法把GPU纹理锁存到系统内存,这一步拷贝会直接让性能掉回30FPS水平,所有画面处理尽量用OpenCV的UMat走GPU加速,只有需要本地存帧的时候再把UMat拷贝到CPU端的Mat即可。
  • 共享句柄不要每帧重复创建,句柄可长期复用,只有检测到游戏交换链重建(切分辨率、切全屏/窗口模式)的时候,才需要释放旧句柄、重新获取新的后备缓冲创建共享句柄。
  • 带内核级反作弊的游戏会检测应用层Hook,该方案和OBS游戏捕获逻辑完全一致,正常走反作弊软件签名白名单流程即可,不要用这套逻辑做违规外挂功能,否则会触发账号封禁。
  • 如果不想自己实现进程注入逻辑,Win10 1903以上版本也可以直接用Windows Graphics Capture API,本质也是基于共享纹理实现,不需要手动写Hook,但对部分老独占全屏游戏的兼容性不如手动Hook Present的方案。

内容的提问来源于stack exchange,提问作者user541396

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:30:49