如何从Direct3d11中的顶点缓冲区读取顶点

时间:2013-07-01 22:09:40

标签: directx buffer direct3d vertex

我对顶点缓冲区有疑问。如何从D3D11中的顶点缓冲区读取顶点?我想得到一个特定的顶点位置进行计算,如果这种方法错了,怎么会这样做呢?以下代码(显然)不起作用。

VERTEX* vert;
D3D11_MAPPED_SUBRESOURCE ms;
devcon->Map(pVBufferSphere, NULL, D3D11_MAP_READ, NULL, &ms);
vert = (VERTEX*) ms.pData;
devcon->Unmap(pVBufferSphere, NULL);  

感谢。

3 个答案:

答案 0 :(得分:6)

代码错误的地方:

  • 您要求GPU为其内存提供一个地址(Map()),
  • 存储此地址(operator=()),
  • 然后说:"谢谢,我再也不需要它" (Unmap())。

取消映射后,您无法真正说出指针指向的位置。它可以指向已经分配了另一个东西的内存位置或者在你女朋友的笔记本电脑的记忆中(只是开玩笑=))。 您必须复制数据(全部或部分),而不是Map() Unmap()之间的指针:使用memcopy,for循环,任何东西。把它放在数组,std::vector,BST,一切。

新手可以在这里犯下的典型错误:

  1. 不要从ID3D11DeviceContext::Map方法检查HRESULT返回值。如果map失败,它可以返回它喜欢的任何指针。取消引用此类指针会导致未定义的行为。因此,最好检查任何DirectX函数的返回值。
  2. 不检查D3D11调试输出。它可以清楚地说出什么是错的,用简单的英语做什么(显然比我的英语更好=))。所以,你几乎可以立即修复bug。
  3. 如果ID3D11Buffer created带有D3D11_CPU_ACCESS_READ CPU访问标记,则只能从D3D11_USAGE_STAGING开始阅读,这意味着您还必须设置ID3D11DeviceContext::CopyResource()使用时间。
  4. 我们如何通常从缓冲区读取

    • 我们不使用暂存缓冲区进行渲染/计算:速度很慢。
    • 相反,我们从主缓冲区(非暂存和CPU不可读)复制到暂存(ID3D11DeviceContext::CopySubresourceRegion()或{{3}}),然后将数据复制到系统内存(memcopy() )。
    • 我们在发布版本中不会做太多,这会损害性能。
    • 暂存缓冲区有两个主要的实际用法:调试(查看缓冲区是否包含错误的数据并修复算法中的一些错误)并读取最终的非像素数据(例如,如果您在Compute着色器中计算科学数据)。
    • 在大多数情况下,您可以通过精心设计代码来避免暂存缓冲区。认为好像CPU< - > GPU仅以一种方式连接:CPU-> GPU。

答案 1 :(得分:2)

以下代码仅获取映射资源的地址,在Unmap之前没有读取任何内容。

vert = (VERTEX*) ms.pData;

如果你想从映射资源中读取数据,首先分配足够的内存,然后使用memcpy复制数据,我不知道你的VERTEX结构,所以我认为vert是void *,你可以自己转换< / p>

vert = new BYTE[ms.DepthPitch];
memcpy(vert, ms.pData, ms.DepthPitch];

答案 2 :(得分:1)

Drop的回答很有帮助。我认为我之所以无法读取缓冲区的原因是因为我之前没有将CPU_ACCESS_FLAG设置为D3D11_CPU_ACCESS_READ。这里

D3D11_BUFFER_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
bufferDesc.ByteWidth = iNumElements * sizeof(T);
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
bufferDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE ;
bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
bufferDesc.StructureByteStride = sizeof(T);

然后读取我做的数据

    const ID3D11Device& device = *DXUTGetD3D11Device();
    ID3D11DeviceContext& deviceContext = *DXUTGetD3D11DeviceContext();
    D3D11_MAPPED_SUBRESOURCE ms;
    HRESULT hr = deviceContext.Map(g_pParticles, 0, D3D11_MAP_READ, 0, &ms);    

    Particle* p = (Particle*)malloc(sizeof(Particle*) * g_iNumParticles);
    ZeroMemory(p, sizeof(Particle*) * g_iNumParticles);
    memccpy(p, ms.pData, 0, sizeof(ms.pData));
    deviceContext.Unmap(g_pParticles, 0);

    delete[] p;

我同意它的性能下降,我想这样做,只是为了能够调试价值!

非常感谢! =)