2016-09-30 111 views
2

我在DirectX 12中遇到了問題。我製作了一個小型3D渲染器。模型在頂點着色器中被轉換爲三維空間,基本世界視圖投影矩陣在恆定緩衝區中。將多個網格繪製到不同的位置(DirectX 12)

要更改我當前正在使用的常量緩衝區的數據,請立即使用memcpy(pMappedConstantBuffer + alignedSize * frame, newConstantBufferData, alignedSize)此命令替換常量緩衝區的數據。


於是問題就來了這裏,繪圖記錄稍後將發送到GPU執行的命令列表。

例子:

/* Now i want to change the constant buffer to change the next draw call's position to (0, 1, 0) */ 
memcpy(/*Parameters*/); 

/* Now i want to record a draw call to the command list */ 
DrawInstanced(/*Parameters*/); 

/* But now i want to draw other mesh to other position so i have to change the constant buffer. After this memcpy() the draw position will be (0, -1, 0) */ 
memcpy(/*Parameters*/); 

/* Now i want to record new draw call to the list */ 
DrawInstanced(/*Parameters*/); 

在此之後我發送的命令列表GPU執行,但quess什麼都網格將在相同的位置,因爲所有的memcpys執行發送,即使命令列表前到GPU。所以基本上最後一個memcpy覆蓋了以前的那個。


所以基本上,問題是我如何繪製網格到不同的位置或如何在命令列表替換常量緩衝區的數據,以便各間不斷變化緩衝區上繪製GPU打電話?

感謝


無需再幫助我自己解決它。我爲每個網格創建了常量緩衝區。

+0

請問你能格式化一下嗎? – manetsus

+0

@manetsus我的問題是,我需要爲每個繪圖調用有不同的常量緩衝區,並且當您使用memcpy時,它會立即發生,不同於記錄的繪圖,後來發送執行示例:memcpy();(更新位置以繪製),DrawInstanced()(這被記錄到列表中),memcpy()(現在我想改變位置爲其他,但現在它覆蓋了前一個),DrawInstanced()(現在我想繪製其他網格,這將被添加到列表中)。 (現在列表將被髮送到GPU,並且它將繪製模型到相同的地方,因爲 – Nopeeananasnas

+0

@manetsu第一個常量緩衝區更新被第二個覆蓋 – Nopeeananasnas

回答

0

關於執行順序,你是完全正確的,你memcpy調用會立即更新緩衝區,但這些命令將不會被處理,直到你將你的命令列表放入隊列中(並且你不會確切地知道什麼時候會發生)。

在Direct3D11中,當您在緩衝區上使用Map時,會爲您處理(如果需要,將分配一些空間以避免此情況)。

所以在Direct3D12中你有幾種選擇,我會考慮你想繪製N個對象,並且你想在你的cbuffer中存儲一個對象的每個對象。

首先是爲每個對象創建一個緩衝區並獨立設置數據。如果你只有幾個,這很容易維護(並且由於資源分配的額外內存佔用將會是好的)

其他選項是創建一個大緩衝區(可以包含N個矩陣),並創建N個常量緩衝區指向每個對象的內存位置的視圖。 (請注意,在這種情況下,您也必須遵守256字節的對齊方式,請參閱CreateConstantBufferView)。

您也可以使用StructuredBuffer並將所有數據複製到其中(在這種情況下,您不需要對齊),並使用頂點着色器中的索引查找正確的矩陣。 (可以在着色器中設置一個uint值,並使用SetGraphicsRoot32BitConstant直接應用它)。