2013-07-01 131 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; 

我認爲這是一隻業績下滑,我想這樣做,只是爲了能夠調試值!

還是要謝謝你! =)