【Siggraph 2015】GPU-Driven Rendering Pipelines

本文是育碧的兩個(gè)工程師在Siggraph2015上的陳述旺聚,是《刺客信條Unity》(以下簡稱ACU脐区,Montreal工作室)開發(fā)過程中所使用的GPU驅(qū)動(dòng)的渲染管線以及RedLynx工作室的GPU驅(qū)動(dòng)渲染管線實(shí)施方案的介紹。

整個(gè)陳述分成如下幾個(gè)部分谋旦,第一個(gè)部分是GPU驅(qū)動(dòng)渲染管線的背景與動(dòng)機(jī)享言;第二個(gè)部分是GPU/CPU渲染管線都會(huì)用到的mesh cluster rendering方法的簡介;第三個(gè)部分會(huì)對ACU的GPU驅(qū)動(dòng)渲染管線做一個(gè)詳細(xì)的介紹愕撰;第四個(gè)部分則是對Occlusion Depth數(shù)據(jù)的生成算法的介紹,最后給出所有成果的實(shí)施效果醋寝。

GPU驅(qū)動(dòng)渲染管線是什么意思搞挣?總的來說,就是將此前由CPU完成的物件渲染前剔除處理以及渲染輸出的target viewport的指定工作移交給GPU來完成音羞,物件渲染的整個(gè)過程不需要CPU對資源數(shù)據(jù)進(jìn)行干涉以避免對GPU流程的阻塞囱桨。

之所以要這樣做,是因?yàn)殡S著算法復(fù)雜度的增加以及場景復(fù)雜度的提升嗅绰,相對于串行處理運(yùn)算器CPU而言舍肠,并行處理運(yùn)算器GPU的消耗會(huì)更低,計(jì)算效率更高窘面,且物體可見性使用時(shí)延基本可以忽略翠语。

育碧RedLynx工作室(以下簡稱R工作室)產(chǎn)出的游戲,對于UGC(user generated content)依賴較高:

  1. 包括背景在內(nèi)财边,場景大多是由小塊數(shù)據(jù)拼接而成肌括;
  2. 場景渲染范圍通常也比較廣(深度大);
  3. 場景數(shù)據(jù)需要從服務(wù)器下載得到酣难,而由于場景是由小塊組成的谍夭,因此離線光照烘焙基本用不了。如果再考慮到陰影的渲染管線的話憨募,整個(gè)渲染管線的負(fù)擔(dān)進(jìn)一步加重紧索;
  4. 物理模擬以及邏輯腳本系統(tǒng)會(huì)占用較多的CPU時(shí)間。

背景介紹:

R工作室很早就在Xbox 360上試驗(yàn)GPU驅(qū)動(dòng)渲染管線的可行性了馋嗜,最早是嘗試通過可編程頂點(diǎn)fetch以及memexport方案來實(shí)現(xiàn)齐板,不過由于硬件限制,當(dāng)時(shí)的性能表現(xiàn)并不能達(dá)到要求葛菇。

之后Persson在Siggraph 2012上給出的Merge-Instancing技術(shù)方案(詳情參考此前的這篇文章)進(jìn)入了R工作室的視線甘磨,這個(gè)技術(shù)使用了Xbox 360的可編程頂點(diǎn)fetch技術(shù)在運(yùn)行時(shí)通過vs對mesh數(shù)據(jù)進(jìn)行合并處理。這個(gè)技術(shù)實(shí)現(xiàn)過程中不需要通過在內(nèi)存中進(jìn)行頂點(diǎn)或者索引數(shù)據(jù)的的拷貝來實(shí)現(xiàn)不同mesh的一次性繪制眯停,而是通過在VS中模擬index buffer的工作流程來強(qiáng)制對每個(gè)三角面片執(zhí)行三遍VS邏輯的方式實(shí)現(xiàn)的济舆。在這個(gè)過程中不需要用到Post Vertex Cache(即post-transform cache ,指的是那些使用帶索引的渲染API在執(zhí)行的時(shí)候莺债,會(huì)將一小批近期用到的頂點(diǎn)數(shù)據(jù)存儲(chǔ)到cache中滋觉,從而提升后續(xù)渲染時(shí)訪問數(shù)據(jù)的速度),因此性能上有一個(gè)非常大的提升齐邦。

ACU是第一代為新一代硬件而設(shè)計(jì)的《刺客信條》游戲椎侠,在這個(gè)游戲中,美術(shù)同學(xué)添加了大量的幾何物件以實(shí)現(xiàn)對真實(shí)巴黎的模擬措拇。

同時(shí)我纪,ACU也是第一次嘗試實(shí)現(xiàn)模型內(nèi)部空間的無縫銜接(seamless interior spaces這個(gè)是啥,目的何在丐吓?推測是指內(nèi)部面片結(jié)構(gòu)無縫銜接浅悉,以達(dá)到高真實(shí)度的表現(xiàn)效果,通常會(huì)需要使用較多的面片來對細(xì)節(jié)進(jìn)行填充)的游戲券犁,這種做法使得需要處理的幾何數(shù)據(jù)進(jìn)一步上升术健。

此外,還有眾多的角色模型粘衬,進(jìn)一步加劇了渲染管線的壓力荞估。

為了能夠創(chuàng)建一個(gè)如此巨大的游戲場景,巴黎場景的第一輪構(gòu)建是通過半自動(dòng)的方式實(shí)現(xiàn)的稚新,整個(gè)過程使用了數(shù)百個(gè)可以復(fù)用的模型來創(chuàng)建大量的房屋模塊(house blocks)泼舱。如果按照傳統(tǒng)的一個(gè)模型占用一個(gè)DP的渲染方式,將會(huì)導(dǎo)致DP數(shù)超過五萬枷莉,而即使使用實(shí)例化渲染技術(shù)娇昙,最終的DP也會(huì)高于一萬五。

即使在主機(jī)上笤妙,CPU也是非常寶貴的資源冒掌,為了避免CPU稱為渲染管線的瓶頸,這里給出的做法是為使用更為激進(jìn)的合批策略蹲盘,同時(shí)采用更為高效的剔除手段股毫。而Mesh cluster rendering正好符合這個(gè)標(biāo)準(zhǔn)。

Mesh Cluster Rendering可以在加大剔除粒度的前提下同時(shí)得到更為激進(jìn)的合批策略(召衔?铃诬?沒看出這兩者有什么矛盾)。由于在GPU中無法通過可編程方式獲得頂點(diǎn)的索引數(shù)據(jù),因此想要通過單個(gè)帶實(shí)例的DP實(shí)現(xiàn)多個(gè)不同物件的渲染趣席,就需要強(qiáng)制多個(gè)物體使用相同的拓?fù)浣Y(jié)果(為什么使用相同的拓?fù)浣Y(jié)構(gòu)兵志,就能實(shí)現(xiàn)單DP,多Mesh渲染宣肚?當(dāng)每個(gè)instance的頂點(diǎn)數(shù)固定時(shí)想罕,通過instance_id就能夠拿到當(dāng)前instance在VB中的起始地址,從而可以一次性取出所有頂點(diǎn)進(jìn)行VS處理霉涨?)按价。ACU選擇的是“Vertex Strip”拓?fù)浣Y(jié)構(gòu):將所有的mesh數(shù)據(jù)分割成64個(gè)vertex strips組成的clusters(由于每個(gè)mesh的頂點(diǎn)數(shù)不同,組成這個(gè)mesh的clusters數(shù)目也有所區(qū)別笙瑟,相同的是cluster的尺寸是恒定的)楼镐,也就是62個(gè)三角形組成一個(gè)cluster。

除了這種拓?fù)浣Y(jié)構(gòu)之外往枷,其他的比如32四邊形(quad)等固定索引buffer的拓?fù)浣Y(jié)構(gòu)也是可用的框产。不管選擇哪種拓?fù)浣Y(jié)構(gòu),都是需要在其中添加退化三角形實(shí)現(xiàn)多個(gè)mesh part之間的連接师溅,以及在每個(gè)mesh末尾添加退化三角形來補(bǔ)足最后一個(gè)cluster茅信。

這個(gè)過程是在mesh編輯完成后進(jìn)行的,可以看成mesh編輯后處理:從mesh數(shù)據(jù)構(gòu)建出triangle strips墓臭,之后使用一個(gè)貪心算法構(gòu)建一個(gè)局部clusters蘸鲸。由于在渲染的時(shí)候需要獲取一個(gè)cluster的不同頂點(diǎn)數(shù)據(jù),因此這里不能直接使用硬件自帶的vertex fetch函數(shù)窿锉,而是需要通過vertex id & instance id手動(dòng)讀取全量數(shù)據(jù)酌摇。按照這種方式,我們可以通過一個(gè)DrawInstancedIndirect(在D3D11中嗡载,這個(gè)函數(shù)可以看成是DrawInstanced函數(shù)的重載版本窑多,其作用是將某個(gè)instance繪制多遍,其中指定了起始vertex在VB中的Offset跟instance的Offset洼滚,如果這個(gè)接口真的能夠完成對多個(gè)不同mesh的一次性繪制埂息,那么即使每個(gè)instance使用不同尺寸的VB應(yīng)該也是可以的吧?DrawInstancedIndirect有兩個(gè)參數(shù)遥巴,一個(gè)是參數(shù)列表指針千康,第二個(gè)是參數(shù)偏移,通過調(diào)整參數(shù)偏移铲掐,可以實(shí)現(xiàn)對不同instance的繪制拾弃,因此在設(shè)置好VB之后,多次調(diào)用這個(gè)接口就能夠?qū)崿F(xiàn)不同mesh的instance繪制摆霉,不過這樣就是多個(gè)DP了豪椿,跟描述貌似不太符合奔坟?這個(gè)接口應(yīng)該是將多個(gè)不同mesh的數(shù)據(jù)統(tǒng)一到一個(gè)VB中,并且將這些帶有instance的數(shù)據(jù)塞入到instance buffer中搭盾,之后調(diào)用一個(gè)DrawInstancedIndirect接口咳秉,在VS中完成對不同mesh cluster數(shù)據(jù)的讀取與訪問,實(shí)現(xiàn)多個(gè)mesh的一次性繪制) DP完成任意數(shù)目的mesh的繪制增蹭,DP參數(shù)以及cluster stream數(shù)據(jù)會(huì)通過GPU計(jì)算得到滴某,計(jì)算過程會(huì)對每個(gè)cluster啟用一次culling計(jì)算磅摹。


對于stripped渲染拓?fù)浣Y(jié)構(gòu)滋迈,每個(gè)strip cut(相當(dāng)于告訴硬件當(dāng)前strip已經(jīng)結(jié)束,下面進(jìn)入下一個(gè)strip)都會(huì)導(dǎo)致4個(gè)額外的冗余頂點(diǎn)與4個(gè)冗余面片户誓,對內(nèi)存占用饼灿,VS渲染消耗以及最大多邊形吞吐量有影響。

ACU中將mesh數(shù)據(jù)分割成固定64個(gè)頂點(diǎn)的實(shí)例數(shù)據(jù)(每個(gè)cluster可以看成一個(gè)instance)帝美,這個(gè)過程通過貪心clustering算法完成碍彭,這種渲染架構(gòu)對于頂點(diǎn)數(shù)據(jù)與instance數(shù)據(jù)獲取的時(shí)間復(fù)雜度為O(1)。

算法Bonus:DX11的DrawInstancedIndirect接口會(huì)在每個(gè)instance結(jié)束的時(shí)候自動(dòng)添加一個(gè)strip cut(這個(gè)是什么悼潭?可以堪稱是一個(gè)用于結(jié)束繪制的overhead)庇忌,這個(gè)過程是免費(fèi)的。

在PC可編程管線中舰褪,無法通過vertex fetch獲得頂點(diǎn)數(shù)據(jù)皆疹。ACU是通過SRV(Shader Resource View)來對頂點(diǎn)數(shù)據(jù)進(jìn)行讀取的:頂點(diǎn)數(shù)據(jù)按照SoA(Structure of Array,由多個(gè)數(shù)組作為成員組成的結(jié)構(gòu)體占拍,對應(yīng)到VB上略就,就是將頂點(diǎn)的每個(gè)屬性都單獨(dú)抽取出來組成一個(gè)個(gè)的屬性數(shù)組;與之相對應(yīng)的是AoS晃酒,Array of Structure表牢,由相同結(jié)構(gòu)體組成的結(jié)構(gòu)體數(shù)組,對應(yīng)到VB上贝次,就是將每個(gè)頂點(diǎn)的多個(gè)屬性組成一個(gè)結(jié)構(gòu)體崔兴,之后用這種結(jié)構(gòu)體數(shù)組表示VB)方式排布。這種做法可以降低GPU延遲(為啥蛔翅?對于不同頂點(diǎn)的同一個(gè)屬性的讀取敲茄,其速度更快)在GCN(這個(gè)是啥?Graphics Core Next搁宾,是AMD為其GPU所開發(fā)的微結(jié)構(gòu)microarchitecture的代號(hào)折汞,也指與之對應(yīng)的指令集)上比硬件Vertex Buffer讀取數(shù)據(jù)表現(xiàn)更好。

這些特點(diǎn)不但可以用于實(shí)現(xiàn)更為激進(jìn)的合批方案盖腿,而且還可以用于對GPU Frustum/Occlusion Bulling效果進(jìn)行精細(xì)調(diào)整爽待。

這里不會(huì)對GPU Occlusion Culling的實(shí)現(xiàn)細(xì)節(jié)進(jìn)行深入介紹损同,不過會(huì)給出一些參考文獻(xiàn)供大家查閱。

另外鸟款,culling方案調(diào)整程度越精細(xì)膏燃,不但可以剔除更多的頂點(diǎn)數(shù)據(jù),而且還能進(jìn)一步降低overdraw(如右圖所示)何什,此外對于美術(shù)同學(xué)的工作也有所幫助:他們不再需要對于物件尺寸做精心規(guī)劃以得到更為有效的裁剪結(jié)果组哩。

測試顯示,手動(dòng)vertex fetch功能比自動(dòng)vertex fetch功能還要快一點(diǎn)处渣,此外伶贰,這種方法還可以用于對cluster depth進(jìn)行排序,從而起到類似depth pre-pass一樣的降低overdraw的作用罐栈。

Stripped triangle instance渲染方法+mesh clustering 渲染方法在所有平臺(tái)上的表現(xiàn)都還不錯(cuò)黍衙。不過ACU在上線之前還是選擇切換到另一種渲染方法,原因是為了降低由于退化三角形導(dǎo)致的內(nèi)存消耗以及修復(fù)由于無法調(diào)整cluster的渲染順序(non-deterministic cluster order)而導(dǎo)致的深度競爭問題(這些問題通常是由于building模塊對齊關(guān)系處理得不夠好導(dǎo)致)荠诬。

使用比如手動(dòng)index buffer數(shù)據(jù)獲取或者cluster depth排序方法可以解決這些問題琅翻,不過ACU選擇的是一個(gè)類似的mesh cluster渲染方法,即使用多個(gè)DrawIndexedInstancedIndirect接口來完成繪制(這個(gè)接口跟之前的DrawInstancedIndirect接口大同小異柑贞,區(qū)別在于不再使用strip拓?fù)浣Y(jié)構(gòu)方椎,加上了索引數(shù)據(jù)來降低頂點(diǎn)數(shù)據(jù)的空間占用)。在這種方法中钧嘶,會(huì)借助傳統(tǒng)的頂點(diǎn)緩存優(yōu)化策略來對mesh數(shù)據(jù)進(jìn)行優(yōu)化棠众,之后將mesh分割成統(tǒng)一的64個(gè)triangle的cluster(如果使用索引方法,就沒有辦法通過instance_id + vertex_id來得到頂點(diǎn)在vertex buffer中的位置康辑,反之亦然摄欲,此時(shí)還有必要保證每個(gè)cluster的triangle數(shù)目恒定在64上有什么意義呢?難道僅僅是為了指定一個(gè)恒定的cluster尺寸嗎疮薇?方便實(shí)現(xiàn)cluster的拆分與深度排序)胸墙。

這是整個(gè)渲染管線的概覽,在CPU側(cè)按咒,依然需要進(jìn)行粗糙的frustum culling迟隅,之后將所有未被剔除的物件按照材質(zhì)進(jìn)行合批處理。在GPU側(cè)励七,對每個(gè)instance進(jìn)行frustum/occlusion culling處理智袭。在對cluster按照frustum/occlusion depth進(jìn)行cull之前還需要進(jìn)行一個(gè)cluster expansion處理(干了啥,目的何在掠抬?)吼野。部分backfacing面片在index buffer compaction過程中會(huì)被剔除掉。完成所有可見性測試之后的輸出數(shù)據(jù)被用作multi-drawcall處理階段的輸入两波。此外瞳步,可形變物體不需要經(jīng)過上述管線的cluster相關(guān)步驟闷哆,直接跳過即可。

正如之前所說单起,在CPU上抱怔,需要進(jìn)行簡單的quad tree culling。之后對每個(gè)動(dòng)態(tài)實(shí)例物件進(jìn)行數(shù)據(jù)更新嘀倒,如transform等數(shù)據(jù)的更新屈留,更新過程在GPU Ring Buffer(Ring buffer是GPU Command的索引buffer,存儲(chǔ)了每個(gè)GPU Command在Command buffer中的位置與長度)進(jìn)行测蘑,并為所有無法通過GPU Instancing繪制的物體構(gòu)建一個(gè)hash值灌危,之后基于此hash值對DP進(jìn)行合并處理,并為GPU渲染構(gòu)建所需要的instance stream帮寻。


四叉樹中物體的粒度會(huì)隨著數(shù)據(jù)而變化:

1.房屋

2.大型物件

3.部分特別的物體

4.部分細(xì)小的動(dòng)態(tài)物件(比如角色)

DP會(huì)在合并之前按照距離進(jìn)行排序乍狐。雖然通過通過boundingbox來進(jìn)行排序得到的并不是完美的深度順序結(jié)果赠摇,但是相對于合并后排序固逗,其效果已經(jīng)好很多了。

由于傳統(tǒng)技術(shù)的限制藕帜,ACU的渲染管線距離完美的CPU目標(biāo)還有很長的距離烫罩。在CPU上依然需要對物件(即使是靜態(tài)的)進(jìn)行處理,且只能對使用相同材質(zhì)的物件進(jìn)行實(shí)例繪制洽故。

Instance stream包含了各個(gè)instance在GPU-buffer中的offset列表贝攒,從而使得GPU獲取如transform,instance bounds等數(shù)據(jù)时甚。

GPU會(huì)使用這些數(shù)據(jù)進(jìn)行instance層面的frustum/Occlusion culling隘弊。對于所有通過culling test的instance,會(huì)生成一個(gè)cluster chunks列表荒适。

這里ACU使用中間過程的cluster chunk expansion(這個(gè)是啥意思梨熙?將mesh數(shù)據(jù)拆分成多個(gè)cluster嗎?)而非直接的cluster expansion刀诬,這是因?yàn)槊總€(gè)mesh的clusters數(shù)目是可變的(1~1000)咽扇。直接的cluster export在同一個(gè)wavefront的不同GPU線程中可能會(huì)非常的不平衡(會(huì)有什么結(jié)果呢?GPU算力浪費(fèi))陕壹。而每個(gè)cluster chunk卻最多對應(yīng)于64個(gè)clusters质欲。

之后的cluster culling過程會(huì)使用instance transform&bounds數(shù)據(jù)來對cluster進(jìn)行frustum/occlusion culling處理。對于每個(gè)cluster糠馆,ACU還會(huì)獲取一個(gè)View Dependent Triangle Mask用于進(jìn)行烘焙前的backface culling嘶伟。通過culling的clusters會(huì)輸出一個(gè)index compaction job,用于構(gòu)建繪制所需要的index buffer又碌。index compaction job輸出數(shù)據(jù)包含了triangle mask以及索引讀寫offsets九昧。這些offsets可以通過相關(guān)的instance面片數(shù)目計(jì)算得到盛霎。

對所有通過剔除測試的cluster進(jìn)行index compaction處理,并將結(jié)果寫入到一個(gè)動(dòng)態(tài)index buffer中耽装。

這個(gè)index buffer是在CPU上分配的愤炸,因此需要為每個(gè)instance mesh按照全量的未被剔除前的索引數(shù)據(jù)分配所需要的空間。由于index buffer尺寸比較械粞佟(8mb规个,為什么比較小,8mb怎么得到的姓建?)诞仓,因此一個(gè)render pass的數(shù)據(jù)可能無法全部塞入到buffer中,而需要分成多個(gè)render passes速兔,因此索引buffer compaction與multi-draw rendering操作會(huì)交叉進(jìn)行墅拭。

此時(shí)index compaction會(huì)將被cluster culling & backface culling的triangle移除掉。在每個(gè)index compaction計(jì)算任務(wù)中涣狗,每個(gè)wavefront會(huì)處理一個(gè)cluster谍婉,各個(gè)wavefront之間相互獨(dú)立,每個(gè)線程處理一個(gè)triangle镀钓,且線程之間也是相互獨(dú)立的穗熬。基于cluster culling輸出input/output offsets以及triangle mask數(shù)據(jù)丁溅,每個(gè)線程會(huì)獨(dú)立計(jì)算輸出數(shù)據(jù)在動(dòng)態(tài)index buffer的位置(write position)并拷貝3個(gè)triangle 索引(每個(gè)triangle包含三個(gè)頂點(diǎn)唤蔗,對應(yīng)三個(gè)index)。這一步需要占據(jù)5%~10%的渲染時(shí)間窟赏。

之后對每個(gè)批次調(diào)用MultiDrawIndexInstancedIndirect 接口來進(jìn)行g(shù)roup rendering妓柜,group rendering的DP則是在cluster culling階段通過原子操作生成的。

前面說過涯穷,在cluster culling時(shí)棍掐,會(huì)需要取到一個(gè)view dependent的面片mask用于計(jì)算每個(gè)cluster內(nèi)部的可見面片數(shù)目。這里是通過將cluster內(nèi)部面片的可見性數(shù)據(jù)烘焙到一張cubemap中求豫,cubemap的每個(gè)像素?cái)?shù)值對應(yīng)于一個(gè)相機(jī)位置的可見性結(jié)果塌衰。比如相機(jī)處于圖中黃色像素所對應(yīng)的frustum區(qū)域內(nèi),那么綠色面片的可見性就可以根據(jù)相機(jī)與cluster的相對位置直接從預(yù)計(jì)算cubemap中讀取出來蝠嘉,用這種做法可以一次性拿到cluster中所有64個(gè)面片的可見性結(jié)果最疆,這個(gè)結(jié)果是一個(gè)bit mask,之后根據(jù)面片索引就能得到對應(yīng)面片的可見性結(jié)果蚤告。

換個(gè)視角來解釋這個(gè)方法努酸,這個(gè)box是cluster的boundingbox,box中帶有箭頭的線段表示的是cluster中的面片與朝向杜恰。右邊包裹住相機(jī)的綠色區(qū)域表示的是黃色像素對應(yīng)的frustum。每個(gè)面片是否可見可以簡單的轉(zhuǎn)換為面片的正向半空間(half space)跟當(dāng)前像素對應(yīng)的frustum是否存在交集。如果相機(jī)本身位于box內(nèi)部哗总,那么這個(gè)時(shí)候會(huì)直接將所有面片的可見性設(shè)置為可見。

ACU出于對內(nèi)存的考慮笼踩,只使用了六個(gè)像素來表示cubemap,即每個(gè)face只用一個(gè)像素表示亡嫌,這種做法會(huì)導(dǎo)致culling精度有所下降嚎于,雖然通過增加像素frustum深度范圍可以對提升一點(diǎn)精度,但是提升非常有限挟冠,且還可能會(huì)導(dǎo)致一些不正確的剔除結(jié)果(比如本來是不可見的面片隨著frustum深度范圍的增加變成了可見(如上賬圖片中下面的面片一樣))于购。總的來說知染,這種做法可以剔除10%~30%的面片肋僧。

要想實(shí)現(xiàn)高效的GPU遮擋剔除,就需要一個(gè)較好的遮擋深度數(shù)據(jù)(occlusion depth)控淡。這是ACU中的一個(gè)經(jīng)典場景嫌吠,下面將以此為例給出ACU是如何生成不同類型的遮擋深度的。

ACU給出的第一種遮擋深度生成算法逸寓,是使用前n個(gè)最佳遮擋物(面積夠大居兆,距離夠近)完成一個(gè)深度渲染pass(depth pre-pass)。depth渲染結(jié)果不但可以用作GPU culling竹伸,還可以作為early-z用于實(shí)際的normal渲染pass。這種做法可以降低由于合批或者排序問題導(dǎo)致的overdraw簇宽。這里生成的depth會(huì)被下采樣到512x256分辨率勋篓,并與上一幀normal渲染pass輸出的depth buffer經(jīng)過reprojection映射到本幀位置的結(jié)果相結(jié)合來給出最終的depth輸出。

最佳遮擋物的選擇是基于bounding volume以及美術(shù)同學(xué)預(yù)先設(shè)置的標(biāo)記來進(jìn)行的魏割。在這些符合條件的遮擋物中譬嚣,距離相機(jī)最近的300個(gè)遮擋物會(huì)被選擇用于進(jìn)行depth繪制,(也可以考慮面片數(shù)少的钞它,以及覆蓋屏幕范圍大的)拜银。

ACU這邊嘗試了多種選擇策略(比如考慮屏幕空間投影面積等),最終考慮到時(shí)間消耗遭垛,選擇了最為簡單的距離判定方法尼桶。

在這個(gè)pass中,不會(huì)進(jìn)行遮擋剔除锯仪,雖然確實(shí)可以使用上一幀depth buffer reprojection后的結(jié)果來進(jìn)行遮擋篩選泵督。

這里給出一種填充此前Occlusion depth pre-pass中輸出的depth貼圖中的孔洞的簡易方法∈玻孔洞的產(chǎn)生可能是由于物件不符合作為遮擋物的條件小腊,也可以是選擇的遮擋物效果比較差救鲤,也可能是由于alpha test物體導(dǎo)致。

當(dāng)相機(jī)靜止不動(dòng)時(shí)秩冈,使用上一幀的depth buffer結(jié)果可以很好的填充這些孔洞本缠。但當(dāng)相機(jī)向著屏幕邊緣移動(dòng)時(shí)或者由于視差原因(相機(jī)旋轉(zhuǎn)導(dǎo)致),孔洞的填充就比較難辦了入问。

如果是大型的動(dòng)態(tài)物體搓茬,上一幀的深度數(shù)據(jù)也會(huì)被污染,為了避開這種錯(cuò)誤的depth數(shù)據(jù)队他,ACU這邊會(huì)在處理reprojection時(shí)拒絕掉那些距離相機(jī)過近的物體(近才會(huì)導(dǎo)致在depth buffer中占據(jù)足夠多的像素卷仑,錯(cuò)誤就會(huì)很明顯?)麸折。

此外锡凝,ACU還為每級Shadow Map生成了一個(gè)64x64的低分辨率遮擋深度貼圖。

第一步垢啼,通過reprojection操作窜锯,將上一幀的depth buffer數(shù)據(jù)投射到光源空間,來得到由陰影接收者組成的occlusion depth數(shù)據(jù)芭析,后面會(huì)給出更詳細(xì)的介紹锚扎。

這個(gè)occlusion depth結(jié)果接下來會(huì)跟上一幀生成的shadow map經(jīng)過reprojection后的數(shù)據(jù)結(jié)合起來,同樣的馁启,這個(gè)過程會(huì)由于大型的可移動(dòng)物體而導(dǎo)致錯(cuò)誤的occlusion數(shù)據(jù)驾孔。

由于fog的計(jì)算需要用到下采樣的指數(shù)shadow map,因此上一幀的下采樣陰影貼圖是可以直接拿到的惯疙,不需要額外的計(jì)算翠勉。

通過上一幀的depth buffer reprojection得到的shadow map occlusion,目的是為了剔除那些不會(huì)有陰影接收者的陰影投影物體的繪制霉颠。在這個(gè)示例場景中对碌,院子里的所有處于角色前面(這里指的是靠近光源方向)的陰影投射物體(剔除左側(cè)的大建筑物)都不會(huì)對陰影貼圖的輸出有任何貢獻(xiàn),因?yàn)檎麄€(gè)院子都被前面的建筑物所遮擋住了蒿偎。

這里給出一個(gè)示意圖朽们。

黃色箭頭表示的是太陽光方向。紅色的線段給出的是一級shadow map的覆蓋區(qū)域诉位。

紅色方塊則是找不到接收陰影物體的陰影投射物體(因?yàn)檫@些物件對應(yīng)的陰影接收物體被地表或者其他物件所遮擋骑脱。)

亮黃色區(qū)域標(biāo)出的是foreground物件所創(chuàng)建的地平線以下部分,處于這個(gè)區(qū)域中的物體都是不可見的(即都是不需要用于繪制陰影的)不从,因此這些物體在shadow map渲染中都可以剔除掉惜姐。

黃色區(qū)域上方的紅線在光源空間中的depth數(shù)據(jù)就是我們這里拿來進(jìn)行occlusion culling的數(shù)據(jù)了。

如果對于相機(jī)空間depth buffer中的每個(gè)像素,都在這個(gè)像素對應(yīng)的深度處繪制一個(gè)cube歹袁,之后從近平面向著這個(gè)立方體所在的深度延伸坷衍,就得到了這些cubes。

可以看到条舔,圖中的綠色線條就是這些cube在光源空間中的最大深度對應(yīng)的位置枫耳,而這些位置與前面給出的黃色區(qū)域上方的紅色線條是一致的。很顯然孟抗,如果真的為每個(gè)像素繪制一個(gè)cube迁杨,那么消耗會(huì)非常高,ACU這邊的做法是為每16x16個(gè)像素組成的tile繪制一個(gè)cube凄硼,之后使用每個(gè)tile中的最大深度用作遮擋剔除的depth铅协,這樣做的結(jié)果就是綠線所表示的結(jié)果相對于此前紅線表示的結(jié)果會(huì)更為保守(從位置上來看,綠線會(huì)比紅色更為往下)摊沉。

另外狐史,在將這些cube繪制到光源空間中時(shí),需要注意修正cube的尺寸以保證繪制的結(jié)果不小于一個(gè)shadow map像素说墨,且需要考慮shadow map的最大filter尺寸骏全。

將相機(jī)空間的depth數(shù)據(jù)通過reprojection投影到光源空間。

ACU這里使用的方法跟[Silvennoinen2012]中的方法是非常相似的尼斧,不同的是原文中使用的depth mask姜贡,而ACU使用的是depth buffer,這是因?yàn)锳CU中計(jì)算光源空間frontface的是box tile中的遠(yuǎn)距面而非近距面棺棵,如果使用mask的話楼咳,得到的精度會(huì)低很多。

由于體積霧使用的是exponential shadow map律秃,因此必須要考慮遠(yuǎn)距離陰影投射物體的濾除作用(為什么ESM需要考慮這個(gè)爬橡,標(biāo)準(zhǔn)SM不用嗎?)棒动。ACU在生成exponential shadow map的時(shí)候,會(huì)通過相機(jī)空間的深度經(jīng)過reprojected 后的數(shù)據(jù)來填充由于一些次要的陰影投射物體被culling掉(不能進(jìn)行全量shadow map繪制宾添,成本太高)導(dǎo)致shadow map上的孔洞船惨。之所以要這樣做,是因?yàn)槭褂玫仄骄€來代替光源空間的遠(yuǎn)平面來對陰影投射物體進(jìn)行剔除的效果要好得多缕陕,且光源空間中某個(gè)區(qū)域的陰影投射物體距離光源越遠(yuǎn)粱锐,這個(gè)效果就越好。

這里給出ACU實(shí)施管線的結(jié)果扛邑,基本達(dá)成目標(biāo)怜浅;GPU可能還需要優(yōu)化下異步處理邏輯,增強(qiáng)GPU處理的并行性。

后面會(huì)考慮通過bindless texture進(jìn)一步降低DP(為什么可以降低恶座?)搀暑,這樣做除了可以降低CPU使用率,同時(shí)還有助于降低由于合批mesh在距離上的順序并不嚴(yán)格所導(dǎo)致的GPU overdraw跨琳,當(dāng)DP數(shù)較少的時(shí)候自点,渲染的順序就會(huì)再次接近于按照物體box中心點(diǎn)到相機(jī)的距離來排序時(shí)的表現(xiàn)(推測這里的渲染指的是cluster的渲染),也就是說脉让,當(dāng)DP數(shù)較低的時(shí)候桂敛,可以按照cluster到相機(jī)的距離來排序了(DP數(shù)多的時(shí)候不可以嗎?)

由于DX12&Vulkan極大的降低了DP的消耗溅潜,因此GPU渲染管線(如這里ACU介紹的實(shí)現(xiàn)算法)的優(yōu)勢將被抑制术唬。而這種GPU渲染管線在DX12&Vulkan下是否能夠生效還取決于所用的數(shù)據(jù)結(jié)構(gòu)與算法。后面部分將會(huì)給出一些可能的前進(jìn)方向滚澜。


GPU驅(qū)動(dòng)渲染管線在DX12上的優(yōu)勢:

1.在DX12中粗仓,尤其是PC上,CPU想要獲取到GPU的depth buffer等資源博秫,依然具有較高的延遲-à因此不能根據(jù)可見像素的數(shù)據(jù)來對shadow進(jìn)行剔除

2.CPU在數(shù)目超過100k的sub-object層面的剔除處理效率依然很低

3.GPU驅(qū)動(dòng)的剔除算法更為高效潦牛。

- 參考: Modified Intel DirectX 12 asteroids demo with ExecuteIndirect. Runs faster on Intel GPU and has much lower CPU usage.

在后面加強(qiáng)異步計(jì)算邏輯的控制之后,ACU這邊希望能夠?qū)⒁恍〨PU驅(qū)動(dòng)的管線中的非渲染的部分移動(dòng)到異步計(jì)算邏輯中以移除由于眾多的細(xì)小異步計(jì)算任務(wù)所導(dǎo)致的pipeline bubbles挡育。

下面要介紹的是RedLynx工作室(下面簡稱R工作室)的GPU驅(qū)動(dòng)渲染管線巴碗,核心技術(shù)跟前面介紹過的Montreal的差不多,因此接下來將著重介紹兩者之間的區(qū)別即寒。

首先要介紹的是Virtual Texture(以下簡稱VT)橡淆。這種技術(shù)方案能夠跟GPU驅(qū)動(dòng)的渲染管線完美結(jié)合起來,從而可以極大的降低DP數(shù)目母赵。

Deferred Texturing不是一個(gè)新的想法逸爵,不過當(dāng)將之與VT以及GPU驅(qū)動(dòng)的渲染管線相結(jié)合時(shí),將煥發(fā)出新的生機(jī)凹嘲。后面將會(huì)介紹著三種技術(shù)方案結(jié)合的實(shí)施細(xì)節(jié)以及R工作室的G-buffer layout师倔,以及后面稱之為MSAA Trick的優(yōu)化方案。

R工作室的遮擋剔除方案跟AC此前的方案有所不同周蹭,這種新的方案稱之為Unity剔除系統(tǒng)趋艘。需要注意的是,R工作室的核心工作大多跟UGC(user generated content) 有關(guān)凶朗,因此會(huì)需要著重考慮多種不同技術(shù)方案的適配與篩選瓷胧。此外,R工作的陰影貼圖管線也跟前面不一樣棚愤,其主要原理跟VT系統(tǒng)類似搓萧。

R工作室使用VT方案已經(jīng)有5年了,到目前為止已經(jīng)有兩款成功的產(chǎn)品應(yīng)用了這項(xiàng)技術(shù):,Trials Evolution and Trials Fusion

其中的核心思想是指將可見的貼圖數(shù)據(jù)維持在內(nèi)存中,主要通過將貼圖拆分成不同的小塊(tile)來實(shí)現(xiàn)瘸洛,這些小塊稱之為page揍移。

Page ID會(huì)提供Page所需要的精確信息以及每個(gè)像素所需要的mip級別,ID數(shù)據(jù)會(huì)被加載到一個(gè)常數(shù)尺寸的Cache中(按照LRU算法進(jìn)行更新置換)

R工作室的實(shí)現(xiàn)是基于256k^2虛擬地址空間實(shí)現(xiàn)的货矮,所有的貼圖數(shù)據(jù)都會(huì)被適配到這個(gè)atlas中羊精,這個(gè)atlas會(huì)被分割成128x128分辨率的page。

在運(yùn)行時(shí)囚玫,有一張8k的貼圖atlas(7680×4320喧锦?)用于存儲(chǔ)當(dāng)前需要駐守在內(nèi)存中的page數(shù)據(jù)。整個(gè)貼圖cache一共包含了5個(gè)數(shù)組元素(array slice)用于存儲(chǔ)所有需要的材質(zhì)屬性:基色抓督,高光燃少,粗糙度,法線等铃在,貼圖cache采用的是DXT壓縮阵具。

R工作室跟Montreal工作室的GPU驅(qū)動(dòng)渲染管線的最大區(qū)別就在于VT的使用。

VT跟GPU驅(qū)動(dòng)渲染管線能夠?qū)崿F(xiàn)完美契合定铜,可以通過單張貼圖binding來實(shí)現(xiàn)所有的可見貼圖數(shù)據(jù)的訪問阳液。

對于GPU驅(qū)動(dòng)的渲染管線而言,這項(xiàng)特性非常重要揣炕,因?yàn)榭梢灾挥靡粋€(gè)DP就允許GPU從任意張數(shù)的貼圖中讀取數(shù)據(jù)帘皿。也就是說,通過這項(xiàng)技術(shù)畸陡,物件的渲染就不需要進(jìn)行合批了鹰溜。

前面說過,GPU驅(qū)動(dòng)渲染管線會(huì)一次性取得所有的mesh數(shù)據(jù)丁恭,而通過VT技術(shù)曹动,則可以一次性取得所有的貼圖數(shù)據(jù),也就是說牲览,只用一個(gè)DP就可以完成全場景物件的繪制墓陈。

通過shader分支,可以實(shí)現(xiàn)不同的頂點(diǎn)動(dòng)畫效果第献,在現(xiàn)代GPU上跛蛋,shader分支的執(zhí)行效率很高,通過測試痊硕,使用shader分支實(shí)現(xiàn)三種不同的復(fù)雜動(dòng)畫類型(包括蒙皮動(dòng)畫)只有不超過2%的額外消耗。

使用一個(gè)DP繪制所有物體的做法有很多優(yōu)點(diǎn):比如說可以將整個(gè)場景的物件cluster按照深度來排序押框,之后以cluster為基本單元按照從前往后的順序進(jìn)行繪制岔绸。這種做法可以提供類似于early-z(depth prepass)的overdraw優(yōu)化效果,且不需要一個(gè)額外的渲染pass

相對于同類解決方案比如說bindless textures,VT還有一些其他的優(yōu)點(diǎn):

1.可以將復(fù)雜材質(zhì)混合的結(jié)果以及貼花渲染結(jié)果存儲(chǔ)到VT atlas中

2.Atlas Cache可以將高帶寬消耗的操作均攤到多幀完成

(這些優(yōu)點(diǎn)對于場景編輯的同學(xué)來說是非常有幫助的盒揉,可以使用較低的消耗來得到非常豐富的表現(xiàn)效果晋被。)

3.使用VT技術(shù),可以不管實(shí)際上有多少張貼圖刚盈,最終繪制所需要的貼圖在內(nèi)存中的尺寸是恒定不變的:美術(shù)同學(xué)就不需要關(guān)注貼圖內(nèi)存預(yù)算羡洛,將精力專注在效果上。

Deferred Texturing并不是一項(xiàng)新技術(shù)藕漱,最早可以追溯到2007年的一篇論壇文章. 不過在此之前欲侮,貌似并沒有哪款游戲有使用過這項(xiàng)技術(shù),其原因可能是無法實(shí)現(xiàn)高效而魯棒的貼圖像素?cái)?shù)據(jù)的存儲(chǔ)與讀取肋联。

Nathan Reed上一年的博客對此問題給出了一個(gè)解決方案威蕉,不過假設(shè)只考慮一些重要的特性比如說各向異性采樣的話,這個(gè)方案會(huì)將G-Buffer的存儲(chǔ)數(shù)據(jù)量增加到144bits橄仍,成本還是有點(diǎn)高韧涨。

而這里的GPU渲染管線的一項(xiàng)重要特性就是,所有可能可見的貼圖數(shù)據(jù)都被加載到一張8k的貼圖atlas中了侮繁。這張atlas對應(yīng)的UV坐標(biāo)足以實(shí)現(xiàn)對任意可見的像素的讀寫虑粥。這張atlas的dimension尺寸相對于巨大的256k virtual texture而言,可以算是非常小的宪哩,從而可以只使用16+16bit的UV坐標(biāo)就能實(shí)現(xiàn)對任意像素的訪問娩贷,在這個(gè)情況下,texture filtering可以達(dá)到8x8的subpixel精度斋射,而這個(gè)數(shù)值實(shí)際上已經(jīng)可以得到非常不錯(cuò)的顯示質(zhì)量了育勺。

場景的渲染,只有UV以及depth數(shù)據(jù)是不夠的罗岖,還需要考慮各向異性采樣的梯度數(shù)據(jù)以及光照計(jì)算所需要的tangent數(shù)據(jù)

梯度數(shù)據(jù)會(huì)占用不小的空間涧至,因此這里的做法不存儲(chǔ)這項(xiàng)數(shù)據(jù)。幸運(yùn)的是桑包,由于G-Buffer中包含了UV坐標(biāo)數(shù)據(jù)南蓬,因此可以在屏幕空間中完成對梯度的計(jì)算。對于連續(xù)的表面而言哑了,這種計(jì)算方法得到的效果是沒什么問題的赘方,不過對于那些在深度上不連續(xù)的情況表現(xiàn)就不太好了。為了解決這個(gè)問題弱左,這里給出的方案是窄陡,比較從正負(fù)xy軸上的相鄰像素?cái)?shù)據(jù),并取其中UV坐標(biāo)差異小的一個(gè)作為輸出拆火,在這個(gè)計(jì)算原則上跳夭,相同表面的相鄰像素可以得到較高的優(yōu)先級涂圆。

如果選擇的相鄰像素的UV距離超過了設(shè)定的N像素閾值(其中N指的是各向異性采樣的等級),就認(rèn)為此次搜索失效币叹。在這種情況下润歉,會(huì)將算法回退到雙邊線性濾波。實(shí)際上這種情況在幾何物體比較纖細(xì)的時(shí)候發(fā)生的頻率還挺高的颈抚,不過從實(shí)際表現(xiàn)上來看踩衩,并沒有構(gòu)成很大問題,可能是因?yàn)殡p邊線性濾波導(dǎo)致subpixel異常在濾波的過程中被模糊掉了贩汉。

光照計(jì)算所需的tangent數(shù)據(jù)會(huì)以32位歸一化的四元數(shù)(quaternion)的形式存儲(chǔ)驱富,其中2位的alpha通道用于存儲(chǔ)主軸索引(major axis index)。VT技術(shù)可以免費(fèi)讓我們得到每個(gè)page的屬性數(shù)據(jù)雾鬼,比如mip等級萌朱,材質(zhì)ID以及colorize color,這些數(shù)據(jù)不需要存儲(chǔ)到G-Buffer中策菜。而Page索引可以通過UV除上128來得到晶疼。

總結(jié):

每個(gè)像素64bits,在現(xiàn)代GPU上比如GCN可以得到Full fill rate又憨,不需要使用MRT(multiple RT)

Deferred texturing技術(shù)跟VT技術(shù)可以很好的結(jié)合起來翠霍,UV buffer數(shù)據(jù)可以當(dāng)成page ID來使用。如果部分像素的梯度向量長度低于0.5蠢莺,就表示此時(shí)需要加載更高更清晰的貼圖page了寒匙。

這里是實(shí)施方案的一些截圖,可以看到梯度重建質(zhì)量跟ground truth非常接近了躏将。

這里還為deferred texturing+VT結(jié)合的方案(命名為virtual deferred texturing锄弱,簡稱VDT)做了一些優(yōu)化工作,這些優(yōu)化統(tǒng)稱為MSAA trick祸憋。

這個(gè)trick是基于以下觀察結(jié)果得到的:不管是UV坐標(biāo)会宪,還是tangent數(shù)據(jù),都是可以通過頂點(diǎn)數(shù)據(jù)插值得到蚯窥,且這種插值是無損的掸鹅。因此可以將G-buffer數(shù)據(jù)用一個(gè)低分辨率存儲(chǔ)下來,之后在使用的時(shí)候?qū)θ笔У臄?shù)據(jù)進(jìn)行插值求取即可拦赠。

使用MSAA繪制一個(gè)2x2的低分辨率結(jié)果巍沙,之后使用GCN可編程采樣pattern來構(gòu)建一個(gè)有序的網(wǎng)格,這個(gè)網(wǎng)格正好與高分辨率的結(jié)果貼圖的像素中心相匹配荷鼠。

在進(jìn)行光照計(jì)算的時(shí)候句携,會(huì)通過multisample加載指令加載G-Buffer中任意的MSAA樣本數(shù)據(jù)

在lighting計(jì)算compute shader開始之前,會(huì)構(gòu)建一張1080p的G-buffer貼圖允乐,并使用快速的LDS(這個(gè)是啥务甥?Local Data Store)來存儲(chǔ)這張臨時(shí)貼圖牡辽。

MSAA會(huì)通過硬件完成PS計(jì)算,被多個(gè)三角面片覆蓋的像素敞临,其結(jié)果會(huì)被存儲(chǔ)多次,這種做法是有必要的麸澜,因?yàn)榭梢员WC三角形edge兩邊的sample frequency數(shù)據(jù)是有效的挺尿,從而可以按照屏幕分辨率(native resolution)實(shí)現(xiàn)對edge的重建。

由于MSAA已經(jīng)可以兼顧triangle edge效果了炊邦,這里只需要完成三角形內(nèi)部的插值計(jì)算就可以實(shí)現(xiàn)1080p的UV坐標(biāo)以及tangent數(shù)據(jù)的重建编矾。不過由于插值并不是perspective correct,因此相對于直接按照屏幕分辨率渲染的結(jié)果而言馁害,可能會(huì)有一些輕微的差異窄俏。

Benchmark使用的是128bits/pixel的G-buffer格式,并將四個(gè)2xMSAA像素編碼成一個(gè)8xMSAA像素碘菜,其最終質(zhì)量與2xMSAA比較接近凹蜈。

PS waves的數(shù)量削減達(dá)到一半,而渲染時(shí)間消耗削減達(dá)到30%忍啸,此外DRAM訪問量也有所削減仰坦,這是因?yàn)檫@里給出的算法可以將訪問最多的MSAA subsample plane數(shù)據(jù)遷移到ESRAM中(不太明白是啥意思,硬件改動(dòng)嗎计雌?)悄晃。

接下來介紹下R工作室的遮擋剔除實(shí)現(xiàn)技術(shù),其方案跟ACU的有所不同凿滤。

最大的區(qū)別在于妈橄,R工作室的遮擋剔除方案不需要一個(gè)額外的遮擋物體pass(occlusion geometry pass),這是因?yàn)镽工作室這邊需要逐像素精確的遮擋結(jié)果翁脆,因此粗糙的遮擋剔除結(jié)果并沒有什么意義眷蚓。

R工作室這邊的項(xiàng)目通常沒有比較大的結(jié)構(gòu)性物體,場景中的大物體通常都是玩家用小物體搭建出來的鹃祖,比如說一堵墻可能是由若干個(gè)細(xì)小物體搭建而成溪椎,中間可能會(huì)包括若干孔洞,如果使用一些低模物體來構(gòu)建遮擋幾何體的話恬口,最終的表現(xiàn)可能比較差校读,且玩家也無法理解為什么會(huì)這樣。

因此R工作室的遮擋剔除數(shù)據(jù)是基于G-Buffer的深度數(shù)據(jù)計(jì)算得到的祖能,從深度buffer生成一個(gè)深度金字塔(pyramid)歉秫,按照GCN HTILE min/max深度buffer方式生成,這種做法可以使得金字塔的生成算法比普通的全分辨率遞歸下采樣算法快12倍养铸。

而遮擋剔除測試則是使用一個(gè)gather4采樣指令一次性獲得四個(gè)采樣結(jié)果的方法進(jìn)行的雁芙。

整個(gè)culling跟rendering可以分成兩個(gè)階段:

第一個(gè)階段使用上一幀創(chuàng)建的深度金字塔數(shù)據(jù)實(shí)現(xiàn)視椎剔除與遮擋剔除轧膘,這個(gè)階段可以看成是一個(gè)occlusion hint(什么意思?可以看成是一輪預(yù)篩選)兔甘。對于通過這個(gè)檢測的物體谎碍,會(huì)以cluster作為基本粒度進(jìn)行視椎,back-face以及遮擋測試洞焙,并將cluster ids輸出到渲染所需要的buffer中蟆淀。

在第二個(gè)階段,會(huì)先使用最新繪制完成的partial frame(是部分物體深度結(jié)果嗎)對深度金字塔進(jìn)行更新澡匪。對于所有通過其他測試但是沒通過遮擋測試的物體以及cluster熔任,會(huì)再進(jìn)行一次遮擋測試,將那些之前檢測錯(cuò)誤的物體添加到渲染列表中(為啥不一步到位唁情,直接在這里做遮擋檢測呢疑苔?因?yàn)檫@里遮擋檢測的遮擋物來源于當(dāng)前幀已經(jīng)繪制的物體,因此需要先繪制一遍甸鸟,而繪制的數(shù)據(jù)來源于第一階段的檢測結(jié)果)惦费。

如果不使用GPU驅(qū)動(dòng)的渲染管線的話,這種剔除方法是很難做到的哀墓,因?yàn)樾枰谥暗牟襟E中以低時(shí)延拿到GPU生成的數(shù)據(jù)趁餐,如果中間夾雜了CPU的數(shù)據(jù)訪問就會(huì)嚴(yán)重阻塞GPU的工作流。

為了測試剔除效果篮绰,這里做了一個(gè)壓力測試后雷,在整個(gè)場景中渲染了二十五萬個(gè)移動(dòng)物體,對于現(xiàn)存的粗糙遮擋剔除系統(tǒng)而言吠各,這些分散的大量物體絕對是個(gè)噩夢臀突。

這個(gè)Bencmark使用的是DX渲染路徑,每個(gè)cluster使用64個(gè)頂點(diǎn)組成贾漏。對于這么高面片場景而言候学,使用MultiDrawIndirect 接口可能沒什么收益。

在光照shader中纵散,物體的貼圖用VT來實(shí)現(xiàn)梳码,整個(gè)場景的繪制只需要兩個(gè)DP。

從結(jié)果上可以看到伍掀,GPU驅(qū)動(dòng)的剔除以及setup過程消耗很低掰茶,加起來不超過0.5ms。需要注意的是蜜笤,這些時(shí)間并不是損耗了的GPU時(shí)間濒蒋,以cluster為粒度的剔除算法在G-buffer步驟中省下來的時(shí)間足以彌補(bǔ)GPU驅(qū)動(dòng)的管線的所有消耗。

在R工作室此前的游戲比如Trials Fusion中,這里列舉的這些工作會(huì)占據(jù)大概50%的CPU時(shí)間沪伙,而現(xiàn)在只需要單核GPU 0.2ms的時(shí)間就能完成瓮顽,因此用這種方法可以騰出CPU給游戲邏輯,物理仿真围橡,破壞等暖混,以創(chuàng)建更豐富生動(dòng)的游戲表現(xiàn)。

對于陰影渲染某饰,R工作室這邊選取的方法跟此前Montreal給出的方法有所不同儒恋。

2001年的時(shí)候,F(xiàn)ernando給出了一種稱之為Adaptive Shadow Maps的實(shí)現(xiàn)技術(shù)這種技術(shù)將陰影貼圖分割成細(xì)小的tiles黔漂,之后根據(jù)距離的不同為每個(gè)tile選定不同的分辨率

這種技術(shù)的問題在于,需要在渲染的過程中將深度數(shù)據(jù)從GPU傳送到CPU禀酱,在CPU中炬守,會(huì)對深度數(shù)據(jù)進(jìn)行分析,并更新culling structures剂跟,之后據(jù)此進(jìn)行shadow rendering减途,這個(gè)過程會(huì)極大的阻塞工作流。

而如果使用GPU驅(qū)動(dòng)的剔除算法曹洽,就可以借助類似于VT的virtual shadow mapping方法解決這個(gè)問題鳍置,因?yàn)樵谶@個(gè)過程中將不再需要CPU的參與,且能夠移除shadow map tile page邊緣上的頂點(diǎn)處理消耗送淆。DX12允許在VS中訪問RT array index税产,從而可以不使用geometry shader,也可以一次性渲染所有的shadow pages偷崩。

Virtual Shadow Mapping方案輸出的貼圖結(jié)果具有最小數(shù)量的under- & oversampling辟拷,Shadow map的分辨率將在任意區(qū)域都能夠與屏幕分辨率實(shí)現(xiàn)最佳匹配。

最終的性能表現(xiàn)令人非常滿意阐斜,尤其是在復(fù)雜場景中衫冻。在之前給出的25萬面片的超復(fù)雜場景中,測試的結(jié)果顯示相對于SDSM(標(biāo)準(zhǔn)shadow map方法)而言谒出,這種方法具有3.5倍的優(yōu)勢(怎么定義的)隅俘。

至于后面更進(jìn)一步的優(yōu)化,比如XOR hashing頁面的數(shù)據(jù)重用等笤喳,還能夠進(jìn)一步提升此方案的運(yùn)行速度为居。

DX12提供了很多新的特性,而其他的API在PC上也有一些重要的特性莉测,除此之外颜骤,相對于下一代主機(jī),還有一些特性是DX以及其他PC API沒有提供的捣卤,不過在DX 12_3中將會(huì)增加這些特性忍抽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末八孝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鸠项,更是在濱河造成了極大的恐慌干跛,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祟绊,死亡現(xiàn)場離奇詭異楼入,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)牧抽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門嘉熊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扬舒,你說我怎么就攤上這事阐肤。” “怎么了讲坎?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵孕惜,是天一觀的道長。 經(jīng)常有香客問我晨炕,道長衫画,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任瓮栗,我火速辦了婚禮削罩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘遵馆。我一直安慰自己鲸郊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布货邓。 她就那樣靜靜地躺著秆撮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪换况。 梳的紋絲不亂的頭發(fā)上职辨,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音戈二,去河邊找鬼舒裤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛觉吭,可吹牛的內(nèi)容都是我干的腾供。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼伴鳖!你這毒婦竟也來了节值?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤榜聂,失蹤者是張志新(化名)和其女友劉穎搞疗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體须肆,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匿乃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豌汇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幢炸。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拒贱,靈堂內(nèi)的尸體忽然破棺而出阳懂,到底是詐尸還是另有隱情,我是刑警寧澤柜思,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站巷燥,受9級特大地震影響赡盘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缰揪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一陨享、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸耸黑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毫捣。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蔬啡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工镀虐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留箱蟆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓刮便,卻偏偏與公主長得像空猜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353