首页 > 解决方案 > 复制 D3D11 子资源数据

问题描述

我有一个关于 Direct3D 11 的快速问题。我已经实现了 D3D DrawIndexed 挂钩,它将当前顶点缓冲区从 GPU 复制到 CPU,修改了一些数据并将其复制回 GPU。

也许我忘记了什么,但即使我不修改任何数据,只是将数据复制到 CPU 并返回,结果是完全损坏的渲染。

代码片段是:

m_pDeviceContext->IAGetIndexBuffer(&indexBuffer, &format, &offset);

// copy current region of the index buffer from GPU to CPU
D3D11_BOX box;
box.left = offset + StartIndexLocation * sizeof(unsigned __int16);
box.right = offset + (StartIndexLocation + IndexCount) * sizeof(unsigned __int16);
box.top = box.front = 0;
box.bottom = box.back = 1;
m_pDeviceContext->CopySubresourceRegion(cpuBuffer, 0, 0, 0, 0, indexBuffer, 0, &box);

D3D11_MAPPED_SUBRESOURCE mappedResource = { 0 };
hRes = m_pDeviceContext->Map(cpuBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
if (hRes == S_OK) {
    // now read all indexes and find the min and max index
    std::vector<unsigned __int16> indexes((unsigned __int16*)mappedResource.pData, (unsigned __int16*)mappedResource.pData + IndexCount);
    auto minmax = std::minmax_element(indexes.begin(), indexes.end());
    m_pDeviceContext->Unmap(cpuBuffer, 0);

    // get the vertex buffer
    UINT stride, offset;
    CComPtr<ID3D11Buffer> vertexBuffer;
    m_pDeviceContext->IAGetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);

    // copy the region where the min index and max index points to
    box.left = BaseVertexLocation + *minmax.first * stride;
    box.right = BaseVertexLocation + *minmax.second * stride + stride;
    m_pDeviceContext->CopySubresourceRegion(cpuBuffer, 0, 0, 0, 0, vertexBuffer, 0, &box);

    // now I am able to Map/Unmap cpuBuffer and access the data in memory - the data are correct
    // ...

    // copy data back to GPU vertex buffer
    // it results in corrupted rendering - it seems that data are copied to wrong location
    box.right = box.right - box.left;
    box.left = 0;
    m_pDeviceContext->CopySubresourceRegion(vertexBuffer, 0, BaseVertexLocation + *minmax.first * stride, 0, 0, cpuBuffer, 0, &box);

为什么最后一个 CopySubResourceRegion 会复制到错误的位置并因此破坏原始顶点缓冲区?

我假设顶点是按它们的索引排序的,这就是我在 min 和 max 之间复制区域的原因。

编辑:我测试了以下简单的代码片段,甚至只是从 GPU 复制到 CPU 并返回到 GPU 会导致渲染损坏,尽管顶点缓冲区未修改。我启用了 D3D 调试层,并且在操作过程中没有记录任何错误。

box.left = 0;
box.right = desc.ByteWidth;
m_pDeviceContext->CopySubresourceRegion(cpuBuffer, 0, 0, 0, 0, vertexBuffer, 0, &box);
m_pDeviceContext->CopySubresourceRegion(vertexBuffer, 0, 0, 0, 0, cpuBuffer, 0, &box);

标签: c++hookdirect3d11

解决方案


推荐阅读