【问题标题】:DXGI Screen capture distorted imageDXGI 屏幕捕获失真图像
【发布时间】:2018-12-03 08:57:44
【问题描述】:

不仅 fps 从 60 下降到 20-21,而且图像看起来也像这样失真。第二张图应该是这样的

What it looks like What it should look like

if (captureVideo == 1) {
    pNewTexture = NULL;

    // Use the IDXGISwapChain::GetBuffer API to retrieve a swap chain surface ( use the uuid  ID3D11Texture2D for the result type ).
    pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &pSurface ) ); 

    /* The swap chain buffers are not mapable, so I need to copy it to a staging resource. */

    pSurface->GetDesc( &description ); //Use ID3D11Texture2D::GetDesc to retrieve the surface description

    // Patch it with a D3D11_USAGE_STAGING usage and a cpu access flag of D3D11_CPU_ACCESS_READ
    description.BindFlags = 0;
    description.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    description.Usage = D3D11_USAGE_STAGING;

    // Create a temporary surface ID3D11Device::CreateTexture2D
    HRESULT hr = pDevice->CreateTexture2D( &description, NULL, &pNewTexture );
    if( pNewTexture )
    {
        // Copy to the staging surface ID3D11DeviceContext::CopyResource
        pContext->CopyResource( pNewTexture, pSurface );
        // Now I have a ID3D11Texture2D with the content of your swap chain buffer that allow you to use the ID3D11DeviceContext::Map API to read it on the CPU
        D3D11_MAPPED_SUBRESOURCE resource;
        pContext->Map( pNewTexture, D3D11CalcSubresource( 0, 0, 0), D3D11_MAP_READ, 0, &resource );

        const int pitch = w << 2;
        const unsigned char* source = static_cast< const unsigned char* >( resource.pData );
        unsigned char* dest = static_cast< unsigned char* >(m_lpBits);
        for( int i = 0; i < h; ++i )
        {
            memcpy( dest, source, w * 4 );
            source += pitch;
            dest += pitch;
        }

        AppendNewFrame(w, h, m_lpBits,24);

        pContext->Unmap( pNewTexture, 0);
        pNewTexture->Release();
    }
}

【问题讨论】:

  • 您应该在此处查看GetBuffer 调用以及其他调用的结果。注意CreateTexture2D 的结果应该被检查而不是指针值。在你使用完pSurface之后,你似乎也没有释放它。
  • 我认为代码存在几个问题,但最显着的影响是AppendNewFrame 行中的24 左右。而且您没有显示此代码...
  • AppendNewFrame 功能有效,多次测试。它只是创建 mp4 视频文件并添加帧,如果没有,我不会得到任何视频文件来显示输出。我取消映射,释放两者现在纹理并刷新上下文,仍然是同样的问题......
  • 同意 Roman R - 我也认为这个问题更多地与音高有关,你给出的输出是一个赠品,我怀疑你应该先看看这里。附带说明:我还建议您重新安排渲染,以便您不直接渲染到 SwapChain 缓冲区,而是将纹理和解析资源(如果不是 msaa,则复制)到其中。原因是你可以让你的屏幕截图成为渲染管道流程的一部分,而不是附加在上面。这也意味着您可以将代码重用于您可能想要捕获的其他后备缓冲区。
  • 嗨,我不认为它与音高有任何关系,因为如果我删除循环并直接执行 AppendNewFrame(w, h, resource.pData,24);我得到同样的东西。似乎我得到的pData有问题,如果我改变音高,我只是修改这个pData的显示方式,所以问题更早,可能在CreateTexture2D?

标签: c++ directx directx-11 dxgi


【解决方案1】:

代码 sn-p 即使不完整也显示出几个潜在问题:

  1. AppendNewFrame 行中的 24 的数量表明您正在尝试将数据视为 24 位 RGB,而您的数据是 32 位 RGB。这种虐待与所附图像上展示的伪影相匹配;
  2. Pitch/stride 被假定为默认设置,而您在D3D11_MAPPED_SUBRESOURCE 结构中拥有有效使用的一种,您应该使用它。

【讨论】:

  • 查看DirectX Tool Kit 中的ScreenGrab 模块以获得更完整的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 2012-01-20
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
  • 1970-01-01
相关资源
最近更新 更多