好好編程-物流項目19【客戶管理-更新客戶】
776
2022-05-30
在使用經典的圖形API(比如Direct3D11)時,一個典型的場景渲染過程可以用偽代碼描述如下:
Map Constant Buffer For View? //For example, View Transform, Projection Transform
for each Mesh
{
Map_Write_Discard Call For [Constant Buffer For Per Mesh Data] //For example, Model Transform
...... //For example, CPU Write to It
Unmap Call For It
Draw Call For Mesh
}
盡管應用層繪制了很多個Mesh,但是應用層只創建了一個Constant Buffer。
那么問題來了!當我們在繪制第2個Mesh時,該Constant Buffer中存放著第1個Mesh的相關數據,很可能正在被GPU讀取;但是,我們仍可以用CPU將第2個Mesh的相關數據寫入到該Constant Buffer中,并不會與GPU的讀取發生沖突,這是為什么呢?
注:雖然下文中的討論是針對Direct3D的Map_Write_Discard,但是,在使用OpenGL時,應用層時也是在只創建一個UniformBuffer的情況下繪制多個Mesh;這意味著OpenGL中的DRAW_DYNAMIC的實現也是如此;雖然按照OpenGL規范,DRAW_DYNAMIC只是應用層的Hint,并不保證驅動實現,但是應用層的用法已經假定了驅動的實現(否則應用層在繪制時需要分配和Mesh個數一樣多的Uniform Buffer了(滑稽臉))。
MSDN / Direct3D11 / How to: Use dynamic resources
https://docs.microsoft.com/en-us/windows/desktop/direct3d11/how-to--use-dynamic-resources
MSDN上的Direct3D11文檔中對Map_Write-_Discard的實現方式進行了說明:當應用層以Write_Discard的方式Map一個Buffer時,驅動會返回一塊新的內存區域給應用層,從而避免了CPU與GPU之間的讀寫沖突。
Holger Gruen. "Constant Buffers without Constant Pain". NVIDIA GameWorks Blog 2015.
http://developer.nvidia.com/content/constant-buffers-without-constant-pain-0
NVIDIA GameWorks Blog上的一篇文章對Map_Write_Discard的驅動實現進行了說明:驅動根據某個配額(目前是128MB)預先分配一大塊內存,當應用層調用Map_Write_Discard時,驅動以類似于線性分配器的方式不斷將指針后移,并將新的內存區域返回給應用層。
同時該文章中指出:驅動將應用層對UpdateSubresource的調用轉發到Map_Write_Discard,UpdateSubresource和Map_Write_Discard在本質上是等價的。
//分界線---------------------------------------------------------------------------------------------------------------------------
MSDN / Direct3D12 / Fence-Based Resource Management / Ring Buffer
https://docs.microsoft.com/en-us/windows/desktop/direct3d12/fence-based-resource-management
在使用次世代的圖形API(比如Direct3D12)時,Map_Write_Discard不再被API支持,需要在應用層實現相關的語義,MSDN上的Direct3D12文檔中給出了一種基于RingBuffer的實現方式(本質上即模仿驅動實現Map_Write_Discard的方式,只不過配額(即上文中的128MB)可以根據應用層自身的實際情況進行定制)。
本文轉載自異步社區
軟件開發 軟件開發
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。