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

DXGI Present Hook帧捕获失败:CreateShaderResourceView返回E_INVALIDARGS

DXGI Present Hook捕获帧时CreateShaderResourceView返回E_INVALIDARGS的解决方法

问题场景

  • Hook DXGI Present函数,仅在按下M键时执行一次单帧捕获,目标是调用真实Present函数前抓取当前渲染帧
  • 已验证swapchain、device、devicecontext指针均正确,但创建ShaderResourceView(用于ImGui调试显示)时始终返回E_INVALIDARGS

核心原因

D3D11不允许为D3D11_USAGE_STAGING类型的纹理创建ShaderResourceView,暂存纹理仅用于CPU-GPU之间的数据传输,不支持绑定到着色器资源视图。你的代码直接基于staging纹理创建SRV,这违反了D3D11的资源规则。

修复代码

HRESULT hkDXGIPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags)
{
    // ... 保留你的按键检测逻辑,确保仅触发一次捕获

    ID3D11Texture2D* pBackBuffer = nullptr;
    if (SUCCEEDED(pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer))))
    {
        D3D11_TEXTURE2D_DESC backBufferDesc;
        pBackBuffer->GetDesc(&backBufferDesc);

        // 创建用于生成SRV的默认纹理(支持着色器绑定)
        D3D11_TEXTURE2D_DESC srvTextureDesc = backBufferDesc;
        srvTextureDesc.Usage = D3D11_USAGE_DEFAULT;
        srvTextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
        srvTextureDesc.CPUAccessFlags = 0;
        srvTextureDesc.MiscFlags = 0; // 清除交换链相关的特殊标记

        ID3D11Texture2D* pSRVTexture = nullptr;
        if (SUCCEEDED(pDevice->CreateTexture2D(&srvTextureDesc, nullptr, &pSRVTexture)))
        {
            // 将后台缓冲区内容复制到可绑定SRV的纹理
            pDeviceContext->CopyResource(pSRVTexture, pBackBuffer);

            // 创建ShaderResourceView
            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
            ZeroMemory(&srvDesc, sizeof(srvDesc));
            srvDesc.Format = backBufferDesc.Format;
            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
            srvDesc.Texture2D.MipLevels = backBufferDesc.MipLevels;
            srvDesc.Texture2D.MostDetailedMip = 0;

            if (SUCCEEDED(pDevice->CreateShaderResourceView(pSRVTexture, &srvDesc, &pCapturedSRV)))
            {
                // 此处可正常执行,pCapturedSRV可用于ImGui显示
            }

            // 若需CPU读取帧数据,可额外创建staging纹理复制pSRVTexture数据
            // (可选,根据需求添加)
            // D3D11_TEXTURE2D_DESC stagingDesc = backBufferDesc;
            // stagingDesc.Usage = D3D11_USAGE_STAGING;
            // stagingDesc.BindFlags = 0;
            // stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
            // ID3D11Texture2D* pStagingTexture = nullptr;
            // if (SUCCEEDED(pDevice->CreateTexture2D(&stagingDesc, nullptr, &pStagingTexture)))
            // {
            //     pDeviceContext->CopyResource(pStagingTexture, pSRVTexture);
            //     // 映射纹理读取CPU数据
            //     D3D11_MAPPED_SUBRESOURCE mapped;
            //     pDeviceContext->Map(pStagingTexture, 0, D3D11_MAP_READ, 0, &mapped);
            //     // 处理像素数据...
            //     pDeviceContext->Unmap(pStagingTexture, 0);
            //     pStagingTexture->Release();
            // }

            pSRVTexture->Release();
        }

        pBackBuffer->Release();
    }

    return Hooks::DXGIPresent(pSwapChain, SyncInterval, Flags);
}

关键注意事项

  • 用于创建SRV的纹理必须是D3D11_USAGE_DEFAULT用法,且设置D3D11_BIND_SHADER_RESOURCE绑定标记
  • 若需要CPU访问帧数据,单独创建staging纹理复制默认纹理的数据,不要直接用staging纹理生成SRV
  • 确保pCapturedSRV在ImGui渲染周期内保持有效,避免提前释放导致崩溃
  • 若后台缓冲区是SRGB格式(如DXGI_FORMAT_R8G8B8A8_UNORM_SRGB),SRV格式可直接沿用,ImGui会正确处理颜色空间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:12:34