junfanbl
junfanbl

Reputation: 461

Read Back Vertex Buffers from GPU in DirectX 11 (and get vertices)

Im trying to gain access to my applications Vertex Buffers (and there vertices) using the below method:

//access vertex buffers
UINT* Stride = new UINT[32];
UINT* veBufferOffset = new UINT[32];
ID3D11Buffer** veBuffer = new ID3D11Buffer * [32];
pContext->IAGetVertexBuffers(0, 32, veBuffer, Stride, veBufferOffset);

std::ostream& operator<<(std::ostream & out, const ID3D11Buffer& buff); // my attempt at overloading...
for (int i = 0; i < 32; i++)
{
    ID3D11Buffer* buff = veBuffer[i];
    for (int e = 0; e < 50; e++) {
        out << buff[e] << std::endl;
        return out;
    }   
}

I can loop through veBuffer no problem, however I haven't had any success in gaining access to the vertices (buff[e]). I have done quite a bit of reading on this, and I'm still not entirely sure where to go from here.

I'm also aware of what can be done using the Stream Output stage: https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-stream-stage?redirectedfrom=MSDN

Where it states that you can get vertex Buffers from the Geometry Shader. From what I understand though, the Geometry Shader is fed one primitive (triangle or a line) at a time. Where I'm looking to get buffers per model.

I found this article on reading back data from the GPU: https://learn.microsoft.com/en-us/windows/win32/direct3d12/readback-data-using-heaps

Unfortunatley for me, it's for DirectX 12. Is there an equivalent DirectX 11 method?

Upvotes: 1

Views: 1751

Answers (1)

Soonts
Soonts

Reputation: 21956

Here’s one way to do that.

  1. Get the ID3D11Buffer pointer like you’re doing. Ideally use something like std::vector<CComPtr<ID3D11Buffer>> instead of new/delete but that’s not too important, at least not for small projects.

  2. Call ID3D11Buffer::GetDesc to get size and other parameters of the buffer you wanna read.

  3. Adjust the description of the buffer, set usage to D3D11_USAGE_STAGING, bind flags to zero, and CPU access flags to D3D11_CPU_ACCESS_READ.

  4. Create another temporary buffer using the modified description, by calling ID3D11Device::CreateBuffer. Don’t specify initial data, pass nullptr there.

  5. Copy the source buffer into the newly created temporary one, by calling ID3D11DeviceContext::CopyResource

  6. Now you can use ID3D11DeviceContext::Map/Unmap to read vertex data from the temporary buffer you created on step 4.

P.S. If you wanna read back index buffer, or any other resource type really, the workflow is the same: create a temporary staging resource, copy, and read from the staging resource.

Upvotes: 3

Related Questions