2013-07-01 134 views
3

我有一个关于顶点缓冲区的问题。如何从D3D11的顶点缓冲区读取顶点?我想获得一个特定的顶点位置进行计算,如果这种方法是错误的,将如何做呢?下面的代码不(显然)工作。如何在Direct3d11中从顶点缓冲区中读取顶点

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

谢谢。

回答

2

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

vert = (VERTEX*) ms.pData; 

如果你想从映射资源读取数据时,先分配足够的内存,然后使用memcpy复制数据,我不知道你的顶点结构,所以我想VERT为void *,你可以自己进行转换

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

感谢您的解释! –

5

当你的代码是错误的:

  • 你问GPU给你一个地址到内存(Map()),
  • 存储此地址(operator=()),
  • 然后说:“谢谢,我不再需要它了”(Unmap())。

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

典型错误:

  1. 不从ID3D11DeviceContext::Map方法检查HRESULT返回值。如果map失败,它可以返回它喜欢的任何指针。解引用这样的指针会导致未定义的行为。所以,最好检查一下DirectX函数的返回值。
  2. 不检查D3D11调试输出。它可以清楚地说出什么是错的,以及如何用简单的英语来做(显然比我的英语=))。所以,你几乎可以立即修复bug。
  3. 您只能从ID3D11Buffer中读取,如果它是createdD3D11_CPU_ACCESS_READ CPU访问标志,这意味着您还必须设置D3D11_USAGE_STAGING使用fag。

我们如何usualy从缓冲区中读取:

  • 我们不使用分段缓存渲染/计算:它的速度慢。
  • 取而代之,我们从主缓冲区(非分段和CPU不可读取)复制到一个(ID3D11DeviceContext::CopyResource()ID3D11DeviceContext::CopySubresourceRegion()),然后将数据复制到系统内存(memcopy())。
  • 我们不这样做太多的发布版本,它会影响性能。
  • 有分期缓冲区的两个主要的现实生活用法:调试(看是否缓冲区包含错误的数据,并修复了一些bug的算法)和阅读最终非像素数据(例如,如果你在计算着色器计算的科学数据)。
  • 你可以通过良好的设计代码避免缓冲区暂存在所有大多数情况下。认为CPU < - > GPU只连接一种方式:CPU-> GPU。
+0

感谢您的解释。作为directx中的新手,我没有意识到我可以将最终变换矩阵与顶点相乘,以获得它在C++代码中的位置,即在着色器之外。这就是我想要的,所以使用来自管道的输出流是严重的矫枉过正。 –

1

下降的答案是有帮助的。我发现我之所以无法读取缓冲区是因为我之前没有将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; 

我认为这是一只业绩下滑,我想这样做,只是为了能够调试值!

还是要谢谢你! =)