Metal框架詳細解析(四十七) —— Metal編程指南之資源堆(十二)

版本記錄

版本號 時間
V1.0 2018.11.11 星期日

前言

很多做視頻和圖像的,相信對這個框架都不是很陌生,它渲染高級3D圖形丁屎,并使用GPU執(zhí)行數(shù)據(jù)并行計算。接下來的幾篇我們就詳細的解析這個框架旱眯。感興趣的看下面幾篇文章晨川。
1. Metal框架詳細解析(一)—— 基本概覽
2. Metal框架詳細解析(二) —— 器件和命令(一)
3. Metal框架詳細解析(三) —— 渲染簡單的2D三角形(一)
4. Metal框架詳細解析(四) —— 關(guān)于GPU Family 4(一)
5. Metal框架詳細解析(五) —— 關(guān)于GPU Family 4之關(guān)于Imageblocks(二)
6. Metal框架詳細解析(六) —— 關(guān)于GPU Family 4之關(guān)于Tile Shading(三)
7. Metal框架詳細解析(七) —— 關(guān)于GPU Family 4之關(guān)于光柵順序組(四)
8. Metal框架詳細解析(八) —— 關(guān)于GPU Family 4之關(guān)于增強的MSAA和Imageblock采樣覆蓋控制(五)
9. Metal框架詳細解析(九) —— 關(guān)于GPU Family 4之關(guān)于線程組共享(六)
10. Metal框架詳細解析(十) —— 基本組件(一)
11. Metal框架詳細解析(十一) —— 基本組件之器件選擇 - 圖形渲染的器件選擇(二)
12. Metal框架詳細解析(十二) —— 基本組件之器件選擇 - 計算處理的設(shè)備選擇(三)
13. Metal框架詳細解析(十三) —— 計算處理(一)
14. Metal框架詳細解析(十四) —— 計算處理之你好,計算(二)
15. Metal框架詳細解析(十五) —— 計算處理之關(guān)于線程和線程組(三)
16. Metal框架詳細解析(十六) —— 計算處理之計算線程組和網(wǎng)格大猩静颉(四)
17. Metal框架詳細解析(十七) —— 工具共虑、分析和調(diào)試(一)
18. Metal框架詳細解析(十八) —— 工具、分析和調(diào)試之Metal GPU Capture(二)
19. Metal框架詳細解析(十九) —— 工具呀页、分析和調(diào)試之GPU活動監(jiān)視器(三)
20. Metal框架詳細解析(二十) —— 工具妈拌、分析和調(diào)試之關(guān)于Metal著色語言文件名擴展名、使用Metal的命令行工具構(gòu)建庫和標(biāo)記Metal對象和命令(四)
21. Metal框架詳細解析(二十一) —— 基本課程之基本緩沖區(qū)(一)
22. Metal框架詳細解析(二十二) —— 基本課程之基本紋理(二)
23. Metal框架詳細解析(二十三) —— 基本課程之CPU和GPU同步(三)
24. Metal框架詳細解析(二十四) —— 基本課程之參數(shù)緩沖 - 基本參數(shù)緩沖(四)
25. Metal框架詳細解析(二十五) —— 基本課程之參數(shù)緩沖 - 帶有數(shù)組和資源堆的參數(shù)緩沖區(qū)(五)
26. Metal框架詳細解析(二十六) —— 基本課程之參數(shù)緩沖 - 具有GPU編碼的參數(shù)緩沖區(qū)(六)
27. Metal框架詳細解析(二十七) —— 高級技術(shù)之圖層選擇的反射(一)
28. Metal框架詳細解析(二十八) —— 高級技術(shù)之使用專用函數(shù)的LOD(一)
29. Metal框架詳細解析(二十九) —— 高級技術(shù)之具有參數(shù)緩沖區(qū)的動態(tài)地形(一)
30. Metal框架詳細解析(三十) —— 延遲照明(一)
31. Metal框架詳細解析(三十一) —— 在視圖中混合Metal和OpenGL渲染(一)
32. Metal框架詳細解析(三十二) —— Metal渲染管道教程(一)
33. Metal框架詳細解析(三十三) —— Metal渲染管道教程(二)
34. Metal框架詳細解析(三十四) —— Hello Metal蓬蝶! 一個簡單的三角形的實現(xiàn)(一)
35. Metal框架詳細解析(三十五) —— Hello Metal尘分! 一個簡單的三角形的實現(xiàn)(二)
36. Metal框架詳細解析(三十六) —— Metal編程指南之概覽(一)
37. Metal框架詳細解析(三十七) —— Metal編程指南之基本Metal概念(二)
38. Metal框架詳細解析(三十八) —— Metal編程指南之命令組織和執(zhí)行模型(三)
39. Metal框架詳細解析(三十九) —— Metal編程指南之資源對象:緩沖區(qū)和紋理(四)
40. Metal框架詳細解析(四十) —— Metal編程指南之函數(shù)和庫(五)
41. Metal框架詳細解析(四十一) —— Metal編程指南之圖形渲染:渲染命令編碼器之Part 1(六)
42. Metal框架詳細解析(四十二) —— Metal編程指南之圖形渲染:渲染命令編碼器之Part 2(七)
43. Metal框架詳細解析(四十三) —— Metal編程指南之?dāng)?shù)據(jù)并行計算處理:計算命令編碼器(八)
44. Metal框架詳細解析(四十四) —— Metal編程指南之緩沖和紋理操作:Blit命令編碼器(九)
45. Metal框架詳細解析(四十五) —— Metal編程指南之Metal工具(十)
46. Metal框架詳細解析(四十六) —— Metal編程指南之Tessellation(十一)

Resource Heaps - 資源堆

可用于:iOS_GPUFamily1_v3猜惋,iOS_GPUFamily2_v3,iOS_GPUFamily3_v2培愁,tvOS_GPUFamily1_v2

資源堆允許Metal資源由相同的內(nèi)存分配支持著摔。這些資源是從稱為堆的內(nèi)存池創(chuàng)建的,它們由捕獲和管理GPU工作依賴關(guān)系的fence進行跟蹤竭钝。資源堆可幫助您的應(yīng)用降低以下成本:

  • Resource creation - 資源創(chuàng)造梨撞。資源創(chuàng)建可能涉及分配新內(nèi)存,將其映射到您的進程香罐,并將其填充為零卧波。通過從較大的堆或由堆支持的可循環(huán)資源內(nèi)存創(chuàng)建資源,可以降低此成本庇茫。
  • Fixed memory budget - 固定內(nèi)存預(yù)算港粱。如果您的某些資源在一段時間內(nèi)未使用,則虛擬內(nèi)存可能會壓縮資源內(nèi)存以節(jié)省空間旦签。這可能會導(dǎo)致額外的時間花費在再次使用此資源內(nèi)存以供下次使用查坪。通過使用少量堆,您可以將分配保持在給定的內(nèi)存預(yù)算內(nèi)宁炫,并確保這些資源不斷使用(這有助于提供更一致的性能)偿曙。
  • Transient resources - 瞬態(tài)資源。為每個幀生成和消耗瞬態(tài)資源羔巢,但并非所有這些資源同時一起使用望忆。為了減少內(nèi)存消耗,未一起使用的瞬態(tài)資源可以共享由堆支持的相同內(nèi)存竿秆。

Heaps - 堆

MTLHeap對象是表示抽象內(nèi)存池的Metal資源启摄。從此堆創(chuàng)建的資源定義為可別的或不可別的(aliasable or non-aliasable)。當(dāng)子分配的資源與另一個別名資源共享相同的堆內(nèi)存部分時幽钢,它們會被別名化歉备。

1. Creating a Heap - 創(chuàng)建堆

通過調(diào)用MTLDevice對象的newHeapWithDescriptor:方法來創(chuàng)建MTLHeap對象。 MTLHeapDescriptor對象描述堆的存儲模式匪燕,CPU緩存模式和字節(jié)大小蕾羊。從同一堆子分配的所有資源共享相同的存儲模式和CPU緩存模式。堆的字節(jié)大小必須足夠大谎懦,以便為其資源分配足夠的內(nèi)存肚豺。

通過調(diào)用setPurgeableState:方法創(chuàng)建堆后,可以使堆可以清除界拦。堆清除狀態(tài)指的是其整個后備內(nèi)存,并影響堆中的所有資源梗劫。堆是可以清除的享甸,但它們的資源不是截碴;子分配的資源僅反映堆的可清除狀態(tài)◎韧可清除性對于僅存儲渲染目標(biāo)的堆可能是有用的日丹。

2. Sub-Allocating Heap Resources - 子分配堆資源

MTLBufferMTLTexture對象都可以從堆中進行子分配。為此蚯嫌,請調(diào)用MTLHeap對象的以下兩種方法之一:

默認情況下哲虾,每個子分配的資源都被定義為不可別名的,這可以防止將來的子分配資源使用其內(nèi)存择示。要使子分配的資源可以別名束凑,請調(diào)用makeAliasable方法;這允許未來的子分配資源重用其內(nèi)存栅盲。

別名不會破壞可分配的子分配資源汪诉,命令編碼器仍可使用它們。這些資源擁有對其堆的強引用谈秫,只有在資源本身被銷毀時才釋放扒寄,而不是在它變?yōu)榭蓜e名的時候釋放。只有在引用它們的所有命令緩沖區(qū)都已完成執(zhí)行后拟烫,才能銷毀子分配的資源该编。

注意:堆是線程安全的,但您可能仍需要在應(yīng)用級別同步堆硕淑,以確保按預(yù)期設(shè)置別名课竣。子分配資源之間的命令依賴關(guān)系不是自動的;必須通過Fences部分中描述的MTLFence API顯式聲明和管理手動跟蹤喜颁。

Listing 13-1顯示了使用堆進行簡單的資源子分配

Listing 13-1  Simple heap creation and resource sub-allocation

// Calculate the size and alignment of each resource
MTLSizeAndAlign albedoSizeAndAlign = [_device heapTextureSizeAndAlignWithTextureDescriptor:_albedoDescriptor];
MTLSizeAndAlign normalSizeAndAlign = [_device heapTextureSizeAndAlignWithTextureDescriptor:_normalDescriptor];
MTLSizeAndAlign glossSizeAndAlign  = [_device heapTextureSizeAndAlignWithTextureDescriptor:_glossDescriptor];
 
// Calculate a heap size that satisfies the size requirements of all three resources
NSUInteger heapSize = albedoSizeAndAlign.size + normalSizeAndAlign.size + glossSizeAndAlign.size;
 
// Create a heap descriptor
MTLHeapDescriptor* heapDescriptor = [MTLHeapDescriptor new];
heapDescriptor.cpuCacheMode = MTLCPUCacheModeDefaultCache;
heapDescriptor.storageMode = MTLStorageModePrivate;
heapDescriptor.size = heapSize;
 
// Create a heap
id <MTLHeap> heap = [_device newHeapWithDescriptor:heapDescriptor];
 
// Create sub-allocated resources from the heap
id <MTLTexture> albedoTexture = [_heap newTextureWithDescriptor:_albedoDescriptor];
id <MTLTexture> normalTexture = [_heap newTextureWithDescriptor:_normalDescriptor];
id <MTLTexture> glossTexture  = [_heap newTextureWithDescriptor:_glossDescriptor];

Fences

MTLFence對象用于跨命令編碼器跟蹤和管理子分配的資源依賴性稠氮。資源依賴性隨著資源由不同命令生成和使用而出現(xiàn),無論這些命令是編碼到同一隊列還是不同隊列半开。fence捕獲GPU工作到特定時間點隔披;當(dāng)GPU遇到fence時,它必須等到所有捕獲的工作完成后再繼續(xù)執(zhí)行寂拆。

1. Creating a Fence - 創(chuàng)建一個柵欄

通過調(diào)用MTLDevice對象的newFence方法創(chuàng)建MTLFence對象奢米。fence主要用于跟蹤目的,僅支持GPU內(nèi)部跟蹤纠永,而不支持CPU和GPU之間的跟蹤鬓长。 MTLFence協(xié)議不提供任何方法或完成處理程序,您只能修改label屬性尝江。

注意:Fences可以重復(fù)更新涉波,硬件管理fence更新以防止死鎖。

2. Tracking Fences Across Blit and Compute Command Encoders - 跟蹤Blit和計算命令編碼器的Fences

可以使用fence跟蹤MTLBlitCommandEncoderMTLComputeCommandEncoder對象。要更新fence啤覆,請分別為每個命令編碼器調(diào)用updateFence:updateFence:方法苍日。要等待fence,請分別為每個命令編碼器調(diào)用waitForFence:waitForFence:方法窗声。

當(dāng)命令緩沖區(qū)實際提交給硬件時相恃,會更新或評估fence。這可以維護全局秩序并防止死鎖笨觅。

驅(qū)動程序可能會在命令編碼器的開頭等待fence拦耐,驅(qū)動程序可能會延遲fence更新,直到命令編碼器結(jié)束见剩。因此杀糯,不允許首先更新然后在同一命令編碼器中等待相同的柵欄(但是,您可以先等待然后更新)炮温。生產(chǎn)者 - 消費者關(guān)系必須分散在不同的命令編碼器中火脉。

3. Tracking Fences Across Render Command Encoders - 跟蹤渲染命令編碼器中的Fences

可以使用更精細的粒度跟蹤MTLRenderCommandEncoder對象摘完。 MTLRenderStages枚舉允許您指定更新或等待柵欄的渲染階段斑响,允許頂點和片段命令重疊執(zhí)行。調(diào)用updateFence:afterStages:方法來更新fence并調(diào)用waitForFence:beforeStages:方法來等待fence盟猖。

4. Fence Examples - Fence示例

Listing 13-2顯示了使用fence進行簡單跟蹤担巩。

Listing 13-2  Simple fence tracking

id <MTLFence> fence = [_device newFence];
id <MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
 
// Producer
id <MTLRenderCommandEncoder> renderCommandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:_descriptor];
/* Draw using resources associated with 'fence' */
[renderCommandEncoder updateFence:fence afterStages:MTLRenderStageFragment];
[renderCommandEncoder endEncoding];
 
// Consumer
id <MTLComputeCommandEncoder> computeCommandEncoder = [commandBuffer computeCommandEncoder];
[computeCommandEncoder waitForFence:fence];
/* Dispatch using resources associated with 'fence' */
[computeCommandEncoder endEncoding];
 
[commandBuffer commit];

如果只有后一個命令編碼器更新fence方援,則不能假設(shè)兩個命令編碼器將完成。 消費者命令編碼器必須明確等待將在圍欄上發(fā)生沖突的所有命令編碼器涛癌。 (GPU可能會開始執(zhí)行盡可能多的命令犯戏,除非它遇到圍柵。)Listing 13-3顯示了引入競爭條件的圍欄的錯誤使用拳话。

Listing 13-3  Incorrect fence tracking

id <MTLFence> fence = [_device newFence];
id <MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
 
// Producer 1
id <MTLRenderCommandEncoder> producerCommandEncoder1 = [commandBuffer renderCommandEncoderWithDescriptor:_descriptor];
/* Draw using resources associated with 'fence' */
[producerCommandEncoder1 endEncoding];
 
// Producer 2
id <MTLComputeCommandEncoder> producerCommandEncoder2 = [commandBuffer computeCommandEncoder];
/* Encode */
[producerCommandEncoder2 updateFence:fence];
[producerCommandEncoder2 endEncoding];
 
// Race condition at consumption!
// producerCommandEncoder2 updated the fence and will have completed its work
// producerCommandEncoder1 did not update the fence and therefore there is no guarantee that it will have completed its work
// Consumer
id <MTLComputeCommandEncoder> computeCommandEncoder = [commandBuffer computeCommandEncoder];
[computeCommandEncoder waitForFence:fence];
/* Dispatch using resources associated with 'fence' */
[computeCommandEncoder endEncoding];
 
[commandBuffer commit];

您仍負責(zé)對命令緩沖區(qū)提交隊列進行排序先匪,如Listing 13-4所示。 但是弃衍,fences不允許您控制隊列間命令緩沖區(qū)排序

Listing 13-4  Sequencing fences across command buffer submission queues

id <MTLFence> fence = [_device newFence];
id <MTLCommandBuffer> commandBuffer0 = [_commandQueue0 commandBuffer];
id <MTLCommandBuffer> commandBuffer1 = [_commandQueue1 commandBuffer];
 
// Producer
id <MTLRenderCommandEncoder> renderCommandEncoder = [commandBuffer0 renderCommandEncoderWithDescriptor:_descriptor];
/* Draw using resources associated with 'fence' */
[renderCommandEncoder updateFence:fence afterStages:MTLRenderStageFragment];
[renderCommandEncoder endEncoding];
 
// Consumer
id <MTLComputeCommandEncoder> computeCommandEncoder = [commandBuffer1 computeCommandEncoder];
[computeCommandEncoder waitForFence:fence];
/* Dispatch using resources associated with 'fence' */
[computeCommandEncoder endEncoding];
 
// Ensure 'commandBuffer0' is scheduled before 'commandBuffer1'
[commandBuffer0 addScheduledHandler:^(id <MTLCommandBuffer>) {
    [commandBuffer1 commit];
}];
[commandBuffer0 commit];

Best Practices - 最佳實踐

1. Separate Heaps for Render Target Types - 為渲染目標(biāo)類型分配單獨堆

有些設(shè)備不能隨意對子分配資源進行別名呀非;例如,可壓縮深度紋理和MSAA紋理镜盯。您應(yīng)該為每種類型的渲染目標(biāo)創(chuàng)建不同的堆:顏色岸裙,深度,模板和MSAA速缆。

2. Separate Heaps for Aliasable and Non-Aliasable Resources - 為可別名和不可別名的資源分配堆

在使子分配的資源可以別名時降允,必須假定此資源將對所有將來的堆子分配進行別名。如果以后分配不可別名的資源(例如壽命較長的紋理)艺糜,那么這些資源可能會對您的臨時資源進行別名剧董,并且很難正確跟蹤幢尚。

如果保留至少兩個資源堆,則可以非常容易地跟蹤哪些可別名和哪些不可別名:一個用于可別名資源(例如送滞,渲染目標(biāo))侠草,另一個用于非別名資源(例如辱挥,資產(chǎn)紋理或頂點緩沖區(qū)) )犁嗅。

3. Separate Heaps to Reduce Fragmentation - 分開堆以減少碎片

創(chuàng)建或刪除許多不同大小的子分配資源可能會破壞內(nèi)存。碎片整理要求您從碎片堆顯式復(fù)制到另一個堆晤碘」游ⅲ或者,您可以創(chuàng)建專用于類似大小的子分配資源的多個堆园爷。

堆也可以用于棧宠蚂。當(dāng)用作棧時,不會發(fā)生碎片童社。

4. Minimize Fencing - 最小化Fencing

細粒度的柵欄很難管理求厕,它們會降低堆的跟蹤效益。避免為每個子分配資源使用圍欄扰楼;相反呀癣,使用單個圍柵來跟蹤具有相同同步要求的所有子分配資源。

5. Consider Tracking Non-Heap Resources - 考慮跟蹤非堆資源

手動數(shù)據(jù)危險跟蹤擴展到直接從MTLDevice對象創(chuàng)建的資源弦赖。在創(chuàng)建資源時指定新的MTLResourceHazardTrackingModeUntracked資源選項项栏,然后使用fence跟蹤它。手動跟蹤可以減少許多只讀資源的自動跟蹤開銷蹬竖。


Sample Code - 示例代碼

有關(guān)如何使用堆和柵欄的示例沼沈,請參閱MetalHeapsAndFences示例。

后記

本篇主要講述了Metal編程指南之資源堆币厕,感興趣的給個贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末列另,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子旦装,更是在濱河造成了極大的恐慌页衙,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件同辣,死亡現(xiàn)場離奇詭異拷姿,居然都是意外死亡,警方通過查閱死者的電腦和手機旱函,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門响巢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人棒妨,你說我怎么就攤上這事踪古『ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵伏穆,是天一觀的道長拘泞。 經(jīng)常有香客問我,道長枕扫,這世上最難降的妖魔是什么陪腌? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮烟瞧,結(jié)果婚禮上诗鸭,老公的妹妹穿的比我還像新娘。我一直安慰自己参滴,他們只是感情好强岸,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著砾赔,像睡著了一般蝌箍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上暴心,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天妓盲,我揣著相機與錄音,去河邊找鬼酷勺。 笑死本橙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脆诉。 我是一名探鬼主播甚亭,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼击胜!你這毒婦竟也來了亏狰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤偶摔,失蹤者是張志新(化名)和其女友劉穎暇唾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辰斋,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡策州,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了宫仗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片够挂。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖藕夫,靈堂內(nèi)的尸體忽然破棺而出孽糖,到底是詐尸還是另有隱情枯冈,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布办悟,位于F島的核電站尘奏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏病蛉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一铡恕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧探熔,春花似錦烘挫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卤橄。三九已至,卻和暖如春窟扑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嚎货。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工橘霎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人殖属。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓姐叁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親洗显。 傳聞我的和親對象是個殘疾皇子外潜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容