交換組和交換屏障是分別在同一系統和分布式系統上的不同窗口之間同步緩沖區交換的眾所周知的方法。最初是為 OpenGL 引入的,后來通過公共 NvAPI 接口進行擴展,并在 DirectX 9 到 12 中得到支持。
NVIDIA 現在引入了當前障礙的概念。它們結合了交換組和交換障礙,并提供了一種在系統內和系統之間設置同步當前調用的簡單方法。
當應用程序請求加入當前障礙時,驅動程序會根據當前系統配置嘗試設置交換組或交換組與交換障礙的組合。這些函數再次通過公共 NvAPI 接口提供。
目前的障礙只有在應用程序處于全屏狀態,沒有窗口邊框,也沒有桌面縮放或任務欄組合時才有效。如果這些要求中至少有一項未得到滿足,則當前的安全柵將斷開并恢復到掛起狀態,直到所有要求都得到滿足。當當前屏障處于掛起狀態時,顯示器之間不會發生同步。
類似地,只有當顯示器連接到相同的 GPU 并設置為相同的定時時,當前屏障才能正常工作。顯示器也可以與 Quadro Sync 卡或 NVLink 連接器同步。
顯示同步通過以下兩種方式之一進行:
顯示器已配置為使用 Quadro sync 插件板形成同步組或同步到外部同步源,或兩者兼而有之。
通過創建跨越顯示器的馬賽克顯示表面,實現了顯示器的同步。
當通過其中一種方法同步顯示定時時,則可以使用 DX12 顯示屏障。
NvAPI 接口
要通過 NvAPI 中的 present barrier 擴展設置同步 present 調用,應用程序必須確保完全支持 present barrier 。如果是這種情況,它必須創建一個當前 barrier 客戶端,注冊所需的 DirectX 資源,并加入當前 barrier 。
查詢當前屏障支持
在嘗試同步當前調用之前,應用程序應首先檢查當前操作系統、驅動程序和硬件配置是否支持當前屏障同步。這是通過使用所需的 D3D12 設備作為參數調用相應的函數來實現的。
ID3D12Device* device; ... // initialize the device bool supported; assert(NvAPI_D3D12_QueryPresentBarrierSupport(device, &supported) == NVAPI_OK); if(supported) { LOG("D3D12 present barrier is supported on this system."); ... }
創建當前屏障客戶端句柄
如果系統提供當前屏障支持,應用程序可以通過提供 D3D12 設備和 DXGI 交換鏈來創建當前屏障客戶端。句柄用于注冊所需的資源、加入或離開當前障礙以及查詢幀統計信息。
IDXGISwapChain swapChain; ... // initialize the swap chain NvPresentBarrierClientHandle pbClientHandle = nullptr; assert(NvAPI_D3D12_CreatePresentBarrierClient(device, swapChain, &pbClientHandle) == NVAPI_OK);
注冊現有障礙資源
創建客戶端后,當前障礙需要訪問交換鏈的緩沖區資源和圍欄對象,以實現適當的幀同步。圍欄值由每幀的當前屏障增加,應用程序不得更改。然而,應用程序可以使用它來同步主機和設備之間的命令分配器使用。每當交換鏈的緩沖區發生變化時,必須再次調用該函數。
ID3D12Fence pbFence; // the app may wait on the fence but must not signal it assert(SUCCEEDED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pbFence)))); ID3D12Resource** backBuffers; unsigned int backBufferCount; ... // query buffers from swap chain assert(NvAPI_D3D12_RegisterPresentBarrierResources(pbClientHandle, pbFence, backBuffers, backBufferCount) == NVAPI_OK);
加入當前的障礙
創建當前屏障客戶端句柄并注冊掃描資源后,應用程序可以加入當前屏障同步。然后,未來 – 現在的呼叫與其他客戶端同步。
NV_JOIN_PRESENT_BARRIER_PARAMS params = {}; params.dwVersion = NV_JOIN_PRESENT_BARRIER_PARAMS_VER1; assert(NvAPI_JoinPresentBarrier(pbClientHandle, ¶ms) == NVAPI_OK);
離開目前的障礙
存在一個類似的函數來保持當前的勢壘同步。客戶端保持不變,這樣應用程序就可以輕松地再次加入。
assert(NvAPI_LeavePresentBarrier(pbClientHandle));
應用程序的主循環
當一切都設置好后,應用程序可以執行其主循環,而無需任何更改,包括當前調用。目前的障礙自行處理同步。雖然應用程序可以選擇使用提供給當前屏障的圍欄進行主機和設備同步,但也可以使用自己的專用圍欄。
查詢統計信息
當客戶端注冊到當前屏障時,應用程序可以隨時查詢幀和同步統計信息,以確保一切按預期工作。
NV_PRESENT_BARRIER_FRAME_STATISTICS stats = {}; stats.dwVersion = NV_PRESENT_BARRIER_FRAME_STATICS_VER1; assert(NvAPI_QueryPresentBarrierFrameStatistics(pbClientHandle, &stats) == NVAPI_OK);
由函數調用填充的當前障礙統計對象提供了幾個有用的值。
SyncMode:上次當前調用中客戶端的當前障礙模式。可能值:
PRESENT_BARRIER_NOT_JOINED:客戶尚未加入當前的障礙。
PRESENT_BARRIER_SYNC_CLIENT:客戶端加入了當前障礙,但未與任何其他客戶端同步。
PRESENT_BARRIER_SYNC_SYSTEM:客戶端加入了當前屏障,并與系統內的其他客戶端同步。
PRESENT_BARRIER_SYNC_CLUSTER:客戶端加入了當前的障礙,并與系統內和跨系統的其他客戶端同步。
PresentCount:幀成功加入當前障礙后從客戶端顯示的總次數。
PresentInSyncCount:自返回SyncMode以來,從客戶端顯示幀的總次數是PRESENT_BARRIER_SYNC_SYSTEM或PRESENT_BARRIER_SYNC_CLUSTER。如果SyncMode偏離這些值,它將重置為 0 。
FlipInSyncCount:自返回SyncMode以來,客戶端的翻轉總數為PRESENT_BARRIER_SYNC_SYSTEM或PRESENT_BARRIER_SYNC_CLUSTER。如果SyncMode偏離這些值,它將重置為 0 。
RefreshCount:自客戶端返回SyncMode以來的 v 空格總數為PRESENT_BARRIER_SYNC_SYSTEM或PRESENT_BARRIER_SYNC_CLUSTER。如果SyncMode偏離這些值,它將重置為 0 。
示例應用程序
NVIDIA DesignWorks Samples GitHub repo 中提供了一個專用的示例應用程序。它具有可調整和移動的彩色條和列模式,以直觀地檢查同步質量(圖 1 )。該應用程序還支持多 GPU 設置上的交替幀渲染和立體渲染。在運行期間,它可以加入或離開當前的障礙同步。
圖 1.具有移動條線和實時統計信息的示例應用程序。
結論
Present barrier 同步是一種簡單、高級的方法,可以在單個系統和多個分布式系統場景中在多個顯示器上實現同步 Present 調用。該界面完全包含在 NvAPI 庫中,僅包含六個設置函數,而復雜的管理概念對面向用戶的代碼隱藏。
關于作者
Nico Marniok 是 NVIDIA 專業可視化部門的高級開發技術工程師,他與獨立軟件供應商合作,利用計算機圖形軟件和硬件的最新技術。他專攻光線追蹤算法。 ISV 應用范圍從專業圖形設計到數字孿生可視化和模擬。在加入 NVIDIA 之前,Nico 畢業于奧斯納布呂克大學并獲得碩士學位,并在 3D 重建領域進行了研究,首先是計算機層析成像,后來是深度相機。
審核編輯:郭婷
-
顯示器
+關注
關注
21文章
4989瀏覽量
140135 -
NVIDIA
+關注
關注
14文章
5024瀏覽量
103264
發布評論請先 登錄
相關推薦
評論