【问题标题】:Direct3D11: Flipping ID3D11Texture2DDirect3D11:翻转 ID3D11Texture2D
【发布时间】:2017-10-19 07:00:16
【问题描述】:

我执行 Direct3D 后台缓冲区的捕获。当我下载像素时,图像帧沿其垂直轴翻转。复制资源或创建目标ID3D11Texture2D 时是否可以“告诉”D3D 翻转帧?

这是我的做法:

我复制帧缓冲区的纹理是这样创建的:

    D3D11_TEXTURE2D_DESC description =
    {
        desc.BufferDesc.Width, desc.BufferDesc.Height, 1, 1,
        DXGI_FORMAT_R8G8B8A8_UNORM,
        { 1, 0 }, // DXGI_SAMPLE_DESC
        D3D11_USAGE_STAGING,//transder from GPU to CPU
        0, D3D11_CPU_ACCESS_READ, 0
    };
    D3D11_SUBRESOURCE_DATA data = { buffer, desc.BufferDesc.Width * PIXEL_SIZE, 0 };
     device->CreateTexture2D(&description, &data, &pNewTexture);

然后在我做的每一帧上:

     pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast< void** >(&pSurface));
     pContext->CopyResource(pNewTexture, pSurface);
     D3D11_MAPPED_SUBRESOURCE resource; 
     pContext->Map(pNewTexture, 0, D3D11_MAP_READ , 0, &resource);
     //reading from resource.pData
     //...

PS:我无法控制渲染管道。我用这段代码挂钩了一个外部应用程序。 另外,我不想弄乱 CPU 上的像素缓冲区,比如循环中的反向复制等。复制的低延迟是高优先级。

更新:

我也试过这个:

    D3D11_BOX box;
    box.left = 0;
    box.right = desc.BufferDesc.Width;
    box.top = desc.BufferDesc.Height;
    box.bottom = 0;
    box.front = 0;
    box.back = 1;
    pContext->CopySubresourceRegion(pNewTexture, 0, 0, 0, 0, pSurface, 0, &box);

这会导致框架的内容为空。

【问题讨论】:

  • 不要忘记检查那些返回非void 的函数的HRESULT 值。您目前假设它始终有效。使用SUCCEEDEDFAILED 或类似ThrowIfFailed
  • @ChuckWalbourn 实际上一直在做。为简单起见,此处已删除。
  • 一个基于多钩子的旧项目示例:github.com/headmax/Cplus/blob/master/Projet4/Main.cpp不知道如果真的对你有帮助...
  • 你想对图像数据做什么,你如何意识到它被翻转了?您是否将图像数据复制到 hbitmap 中? HBitmap 自下而上存储图像数据。如果您要复制图像数据以显示它,那么以 Y 的相反顺序复制它不会花费太多。
  • @MichaelIV 关于您的更新部分,ID3D11DeviceContext::CopySubresourceRegion() 的 MSDN 文档声明“空框导致无操作。如果顶部值大于或等于底部,则框为空值,或 [...]"。

标签: directx direct3d direct3d11


【解决方案1】:

使用 D3D11_USAGE_DEAFULT 创建纹理,CPUAccessFlags=0 和 BindFlags=D3D11_BIND_SHADER_RESOURCE。 CopyResource 交换链的后备缓冲区给它。使用 D3D11_BIND_RENDER_TARGET 创建另一个纹理。将其设置为渲染目标,设置像素着色器并使用第一个纹理绘制一个翻转的四边形。现在您应该能够将第二个纹理复制资源到您现在使用的暂存纹理。这应该比使用 CPU 复制翻转的图像数据更快。但是,此解决方案将占用 GPU 上的更多资源,并且可能难以在挂钩中进行设置。

【讨论】:

  • 如果后备缓冲区有 D3D11_BIND_SHADER_RESOURCE 标志,则可以省略第一个副本。
【解决方案2】:

所有 Direct3D 映射资源都应逐个扫描线处理,因此只需反转副本:

auto ptr = reinterpret_cast<const uint8_t>(resource.pData)
           + (desc.BufferDesc.Height - 1) * resource.RowPitch;

for(unsigned int y = 0; y < desc.BufferDesc.Height; ++y )
{
    // do something with the data in ptr
    // which is desc.BufferDesc.Width * BytesPerPixel(desc.Format) bytes
    // i.e. DXGI_FORMAT_R8G8B8A8_UNORM would be desc.BufferDesc.Width * 4
    ptr -= resource.RowPitch;
}

有关使用 Direct3D 资源的大量示例,请参阅DirectXTex

【讨论】:

  • 不是一个选项。我需要非常快的副本。我寻求一种在驱动程序或 GPU 端进行翻转的方法。我将在我的问题中强调它。
猜你喜欢
  • 2016-06-25
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
相关资源
最近更新 更多