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