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
相关产品推荐
相关产品推荐

