版本記錄
版本號 | 時(shí)間 |
---|---|
V1.0 | 2018.11.10 星期六 |
前言
很多做視頻和圖像的,相信對這個(gè)框架都不是很陌生动猬,它渲染高級3D圖形啤斗,并使用GPU執(zhí)行數(shù)據(jù)并行計(jì)算。接下來的幾篇我們就詳細(xì)的解析這個(gè)框架赁咙。感興趣的看下面幾篇文章钮莲。
1. Metal框架詳細(xì)解析(一)—— 基本概覽
2. Metal框架詳細(xì)解析(二) —— 器件和命令(一)
3. Metal框架詳細(xì)解析(三) —— 渲染簡單的2D三角形(一)
4. Metal框架詳細(xì)解析(四) —— 關(guān)于GPU Family 4(一)
5. Metal框架詳細(xì)解析(五) —— 關(guān)于GPU Family 4之關(guān)于Imageblocks(二)
6. Metal框架詳細(xì)解析(六) —— 關(guān)于GPU Family 4之關(guān)于Tile Shading(三)
7. Metal框架詳細(xì)解析(七) —— 關(guān)于GPU Family 4之關(guān)于光柵順序組(四)
8. Metal框架詳細(xì)解析(八) —— 關(guān)于GPU Family 4之關(guān)于增強(qiáng)的MSAA和Imageblock采樣覆蓋控制(五)
9. Metal框架詳細(xì)解析(九) —— 關(guān)于GPU Family 4之關(guān)于線程組共享(六)
10. Metal框架詳細(xì)解析(十) —— 基本組件(一)
11. Metal框架詳細(xì)解析(十一) —— 基本組件之器件選擇 - 圖形渲染的器件選擇(二)
12. Metal框架詳細(xì)解析(十二) —— 基本組件之器件選擇 - 計(jì)算處理的設(shè)備選擇(三)
13. Metal框架詳細(xì)解析(十三) —— 計(jì)算處理(一)
14. Metal框架詳細(xì)解析(十四) —— 計(jì)算處理之你好,計(jì)算(二)
15. Metal框架詳細(xì)解析(十五) —— 計(jì)算處理之關(guān)于線程和線程組(三)
16. Metal框架詳細(xì)解析(十六) —— 計(jì)算處理之計(jì)算線程組和網(wǎng)格大斜怂(四)
17. Metal框架詳細(xì)解析(十七) —— 工具崔拥、分析和調(diào)試(一)
18. Metal框架詳細(xì)解析(十八) —— 工具、分析和調(diào)試之Metal GPU Capture(二)
19. Metal框架詳細(xì)解析(十九) —— 工具猿涨、分析和調(diào)試之GPU活動(dòng)監(jiān)視器(三)
20. Metal框架詳細(xì)解析(二十) —— 工具握童、分析和調(diào)試之關(guān)于Metal著色語言文件名擴(kuò)展名、使用Metal的命令行工具構(gòu)建庫和標(biāo)記Metal對象和命令(四)
21. Metal框架詳細(xì)解析(二十一) —— 基本課程之基本緩沖區(qū)(一)
22. Metal框架詳細(xì)解析(二十二) —— 基本課程之基本紋理(二)
23. Metal框架詳細(xì)解析(二十三) —— 基本課程之CPU和GPU同步(三)
24. Metal框架詳細(xì)解析(二十四) —— 基本課程之參數(shù)緩沖 - 基本參數(shù)緩沖(四)
25. Metal框架詳細(xì)解析(二十五) —— 基本課程之參數(shù)緩沖 - 帶有數(shù)組和資源堆的參數(shù)緩沖區(qū)(五)
26. Metal框架詳細(xì)解析(二十六) —— 基本課程之參數(shù)緩沖 - 具有GPU編碼的參數(shù)緩沖區(qū)(六)
27. Metal框架詳細(xì)解析(二十七) —— 高級技術(shù)之圖層選擇的反射(一)
28. Metal框架詳細(xì)解析(二十八) —— 高級技術(shù)之使用專用函數(shù)的LOD(一)
29. Metal框架詳細(xì)解析(二十九) —— 高級技術(shù)之具有參數(shù)緩沖區(qū)的動(dòng)態(tài)地形(一)
30. Metal框架詳細(xì)解析(三十) —— 延遲照明(一)
31. Metal框架詳細(xì)解析(三十一) —— 在視圖中混合Metal和OpenGL渲染(一)
32. Metal框架詳細(xì)解析(三十二) —— Metal渲染管道教程(一)
33. Metal框架詳細(xì)解析(三十三) —— Metal渲染管道教程(二)
34. Metal框架詳細(xì)解析(三十四) —— Hello Metal叛赚! 一個(gè)簡單的三角形的實(shí)現(xiàn)(一)
35. Metal框架詳細(xì)解析(三十五) —— Hello Metal澡绩! 一個(gè)簡單的三角形的實(shí)現(xiàn)(二)
36. Metal框架詳細(xì)解析(三十六) —— Metal編程指南之概覽(一)
37. Metal框架詳細(xì)解析(三十七) —— Metal編程指南之基本Metal概念(二)
38. Metal框架詳細(xì)解析(三十八) —— Metal編程指南之命令組織和執(zhí)行模型(三)
39. Metal框架詳細(xì)解析(三十九) —— Metal編程指南之資源對象:緩沖區(qū)和紋理(四)
40. Metal框架詳細(xì)解析(四十) —— Metal編程指南之函數(shù)和庫(五)
Graphics Rendering: Render Command Encoder - 圖形渲染:渲染命令編碼器
本章介紹如何創(chuàng)建和使用MTLRenderCommandEncoder和MTLParallelRenderCommandEncoder對象,這些對象用于將圖形渲染命令編碼到命令緩沖區(qū)中俺附。 MTLRenderCommandEncoder
命令描述圖形渲染管道肥卡,如圖5-1所示。
MTLRenderCommandEncoder
對象表示單個(gè)渲染命令編碼器事镣。 MTLParallelRenderCommandEncoder
對象允許將單個(gè)呈現(xiàn)過程分解為多個(gè)單獨(dú)的MTLRenderCommandEncoder
對象步鉴,每個(gè)對象可以分配給不同的線程。 然后將來自不同渲染命令編碼器的命令鏈接在一起并以一致,可預(yù)測的順序執(zhí)行氛琢,如 Multiple Threads for a Rendering Pass中所述喊递。
Creating and Using a Render Command Encoder - 創(chuàng)建和使用渲染命令編碼器
要?jiǎng)?chuàng)建,初始化和使用單個(gè)渲染命令編碼器:
- 1) 創(chuàng)建一個(gè)MTLRenderPassDescriptor對象阳似,以定義一組附件骚勘,這些附件用作該呈現(xiàn)過程的命令緩沖區(qū)中圖形命令的渲染目標(biāo)。通常撮奏,您創(chuàng)建一次
MTLRenderPassDescriptor
對象俏讹,并在每次應(yīng)用渲染幀時(shí)重復(fù)使用它。請參閱Creating a Render Pass Descriptor畜吊。 - 2) 通過使用指定的渲染過程描述符調(diào)用MTLCommandBuffer的renderCommandEncoderWithDescriptor:方法來創(chuàng)建
MTLRenderCommandEncoder
對象泽疆。請參閱Using the Render Pass Descriptor to Create a Render Command Encoder。 - 3) 創(chuàng)建一個(gè)MTLRenderPipelineState對象玲献,以定義一個(gè)或多個(gè)繪制調(diào)用的圖形渲染管道的狀態(tài)(包括著色器殉疼,混合,多重采樣和可見性測試)青自。要使用此渲染管道狀態(tài)來繪制基元株依,請調(diào)用
MTLRenderCommandEncoder
的setRenderPipelineState:方法。有關(guān)詳細(xì)信息延窜,請參閱Creating a Render Pipeline State。 - 4) 設(shè)置渲染命令編碼器使用的紋理抹锄,緩沖區(qū)和采樣器逆瑞,如為Specifying Resources for a Render Command Encoder中所述。
- 5) 調(diào)用
MTLRenderCommandEncoder
方法以指定其他固定函數(shù)狀態(tài)伙单,包括深度和模板狀態(tài)获高,如Fixed-Function State Operations中所述。 - 6) 最后吻育,調(diào)用
MTLRenderCommandEncoder
方法繪制圖形基元念秧,如Drawing Geometric Primitives中所述。
1. Creating a Render Pass Descriptor - 創(chuàng)建渲染管道描述符
MTLRenderPassDescriptor對象表示編碼的渲染命令的目標(biāo)布疼,該命令是附件(attachments)
的集合摊趾。渲染通道描述符的屬性可以包括用于顏色像素?cái)?shù)據(jù)的多達(dá)四個(gè)附件的陣列,一個(gè)附件用于深度像素?cái)?shù)據(jù)游两,以及一個(gè)附件用于模板像素?cái)?shù)據(jù)砾层。 renderPassDescriptor便捷方法使用默認(rèn)附件狀態(tài)創(chuàng)建具有顏色,深度和模板附件屬性的MTLRenderPassDescriptor
對象贱案。 visibilityResultBuffer屬性指定設(shè)備可以更新的緩沖區(qū)肛炮,以指示是否有任何樣本通過深度和模板測試 - 有關(guān)詳細(xì)信息,請參閱Fixed-Function State Operations。
每個(gè)單獨(dú)的附件侨糟,包括將要寫入的紋理鞭缭,由附件描述符表示刹衫。對于附件描述符,必須適當(dāng)?shù)剡x擇相關(guān)紋理的像素格式以存儲顏色,深度或模板數(shù)據(jù)墩瞳。對于顏色附件描述符MTLRenderPassColorAttachmentDescriptor,使用顏色可渲染像素格式览妖。對于深度附加描述符MTLRenderPassDepthAttachmentDescriptor瘾杭,使用深度可渲染像素格式,例如MTLPixelFormatDepth32Float汰具。對于模板附件描述符MTLRenderPassStencilAttachmentDescriptor卓鹿,使用模板可渲染像素格式,例如MTLPixelFormatStencil8留荔。
紋理實(shí)際上在設(shè)備上每個(gè)像素使用的內(nèi)存量并不總是與Metal框架代碼中紋理的像素格式的大小相匹配吟孙,因?yàn)樵O(shè)備添加了填充以用于對齊或其他目的。有關(guān)每種像素格式實(shí)際使用的內(nèi)存量以及附件大小和數(shù)量的限制聚蝶,請參閱Metal Feature Set Tables一章杰妓。
Load and Store Actions - 加載和存儲操作
附件描述符的loadAction和storeAction屬性指定在呈現(xiàn)過程的開始或結(jié)束時(shí)執(zhí)行的操作。 (對于MTLParallelRenderCommandEncoder
碘勉,加載和存儲操作發(fā)生在整個(gè)命令的邊界巷挥,而不是每個(gè)MTLRenderCommandEncoder
對象。有關(guān)詳細(xì)信息验靡,請參閱Multiple Threads for a Rendering Pass倍宾。)
可能的loadAction值包括:
- MTLLoadActionClear,它將相同的值寫入指定附件描述符中的每個(gè)像素胜嗓。有關(guān)此操作的更多詳細(xì)信息高职,請參閱 Specifying the Clear Load Action。
- MTLLoadActionLoad辞州,它保留紋理的現(xiàn)有內(nèi)容怔锌。
- MTLLoadActionDontCare,允許附件中的每個(gè)像素在渲染過程開始時(shí)采用任何值变过。
如果您的應(yīng)用程序?qū)⒊尸F(xiàn)給定幀的附件的所有像??素埃元,請使用默認(rèn)加載操作MTLLoadActionDontCare。 MTLLoadActionDontCare
操作允許GPU避免加載紋理的現(xiàn)有內(nèi)容牵啦,從而確保最佳性能亚情。否則,您可以使用MTLLoadActionClear操作清除附件的先前內(nèi)容哈雏,或使用MTLLoadActionLoad操作來保留它們楞件。 MTLLoadActionClear
操作還可以避免加載現(xiàn)有紋理內(nèi)容衫生,但是會(huì)產(chǎn)生使用純色填充目標(biāo)的成本。
可能的storeAction值包括:
- MTLStoreActionStore土浸,它將渲染過程的最終結(jié)果保存到附件中罪针。
-
MTLStoreActionMultisampleResolve將渲染目標(biāo)中的多重采樣數(shù)據(jù)解析為單個(gè)樣本值,將它們存儲在附件屬性
resolveTexture
指定的紋理中黄伊,并使附件的內(nèi)容保持未定義狀態(tài)泪酱。有關(guān)詳細(xì)信息,請參閱示例Example: Creating a Render Pass Descriptor for Multisampled Rendering还最。 - MTLStoreActionDontCare墓阀,在渲染過程完成后將附件保留為未定義狀態(tài)。這可以提高性能拓轻,因?yàn)樗箤?shí)現(xiàn)能夠避免保留渲染結(jié)果所需的任何工作斯撮。
對于顏色附件,MTLStoreActionStore操作是默認(rèn)的存儲操作扶叉,因?yàn)閼?yīng)用程序幾乎總是在渲染過程結(jié)束時(shí)保留附件中的最終顏色值勿锅。對于深度和模板附件,MTLStoreActionDontCare是默認(rèn)的存儲操作枣氧,因?yàn)樵阡秩緜鬟f完成后通常不需要保留這些附件溢十。
Specifying the Clear Load Action - 指定Clear Load Action
如果附件描述符的loadAction屬性設(shè)置為MTLLoadActionClear,則在渲染過程開始時(shí)將清除值寫入指定附件描述符中的每個(gè)像素达吞。清除值屬性取決于附件的類型张弛。
- 對于MTLRenderPassColorAttachmentDescriptor,clearColor包含一個(gè)MTLClearColor值酪劫,該值由四個(gè)雙精度浮點(diǎn)
RGBA
組件組成乌庶,用于清除顏色附件。 MTLClearColorMake函數(shù)從紅色契耿,綠色,藍(lán)色和alpha分量創(chuàng)建清晰的顏色值螃征。默認(rèn)的清晰顏色為(0.0,0.0,0.0,1.0)
或不透明的黑色搪桂。 - 對于MTLRenderPassDepthAttachmentDescriptor,clearDepth包含一個(gè)雙精度浮點(diǎn)清除值盯滚,范圍為
[0.0,1.0]
踢械,用于清除深度附件。默認(rèn)值為1.0魄藕。 - 對于MTLRenderPassStencilAttachmentDescriptor内列,clearStencil包含一個(gè)32位無符號整數(shù),用于清除模板附件背率。默認(rèn)值為0话瞧。
Example: Creating a Render Pass Descriptor with Load and Store Actions - 示例:使用Load and Store Actions創(chuàng)建渲染通道描述符
Listing 5-1
創(chuàng)建了一個(gè)帶有顏色和深度附件的簡單渲染過程描述符嫩与。 首先,創(chuàng)建兩個(gè)紋理對象交排,一個(gè)具有可顏色渲染的像素格式划滋,另一個(gè)具有深度像素格式。 接下來埃篓,MTLRenderPassDescriptor的renderPassDescriptor便捷方法創(chuàng)建默認(rèn)的渲染通道描述符处坪。 然后通過MTLRenderPassDescriptor
的屬性訪問顏色和深度附件。 紋理和動(dòng)作在colorAttachments [0]
中設(shè)置架专,它表示第一個(gè)顏色附件(在數(shù)組中的索引0處)和深度附件同窘。
Listing 5-1 Creating a Render Pass Descriptor with Color and Depth Attachments
MTLTextureDescriptor *colorTexDesc = [MTLTextureDescriptor
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO];
id <MTLTexture> colorTex = [device newTextureWithDescriptor:colorTexDesc];
MTLTextureDescriptor *depthTexDesc = [MTLTextureDescriptor
texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO];
id <MTLTexture> depthTex = [device newTextureWithDescriptor:depthTexDesc];
MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor];
renderPassDesc.colorAttachments[0].texture = colorTex;
renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0,1.0,0.0,1.0);
renderPassDesc.depthAttachment.texture = depthTex;
renderPassDesc.depthAttachment.loadAction = MTLLoadActionClear;
renderPassDesc.depthAttachment.storeAction = MTLStoreActionStore;
renderPassDesc.depthAttachment.clearDepth = 1.0;
Example: Creating a Render Pass Descriptor for Multisampled Rendering - 示例:為多重采樣渲染創(chuàng)建渲染通道描述符
要使用MTLStoreActionMultisampleResolve操作,必須將texture屬性設(shè)置為多重采樣類型紋理部脚,resolveTexture屬性將包含多重采樣解析操作的結(jié)果想邦。 (如果texture
不支持多重采樣,則多重采樣解析操作的結(jié)果未定義睛低。)resolveLevel案狠,resolveSlice和resolveDepthPlane屬性也可用于多重采樣解析操作,以指定多重采樣紋理的mipmap級別钱雷,立方體切片和深度平面骂铁。在大多數(shù)情況下,resolveLevel
罩抗,resolveSlice
和resolveDepthPlane
的默認(rèn)值都是可用的拉庵。 在Listing 5-2
中,最初創(chuàng)建了一個(gè)附件套蒂,然后將其loadAction
钞支,storeAction
,texture
和resolveTexture
屬性設(shè)置為支持多重采樣解析操刀。
Listing 5-2 Setting Properties for an Attachment with Multisample Resolve
MTLTextureDescriptor *colorTexDesc = [MTLTextureDescriptor
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO];
id <MTLTexture> colorTex = [device newTextureWithDescriptor:colorTexDesc];
MTLTextureDescriptor *msaaTexDesc = [MTLTextureDescriptor
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO];
msaaTexDesc.textureType = MTLTextureType2DMultisample;
msaaTexDesc.sampleCount = sampleCount; // must be > 1
id <MTLTexture> msaaTex = [device newTextureWithDescriptor:msaaTexDesc];
MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor];
renderPassDesc.colorAttachments[0].texture = msaaTex;
renderPassDesc.colorAttachments[0].resolveTexture = colorTex;
renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDesc.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;
renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0,1.0,0.0,1.0);
2. Using the Render Pass Descriptor to Create a Render Command Encoder - 使用渲染通道描述符創(chuàng)建渲染命令編碼器
在創(chuàng)建渲染過程描述符并指定其屬性后烁挟,使用MTLCommandBuffer對象的renderCommandEncoderWithDescriptor:方法創(chuàng)建渲染命令編碼器,如Listing 5-3
所示骨坑。
Listing 5-3 Creating a Render Command Encoder with the Render Pass Descriptor
id <MTLRenderCommandEncoder> renderCE = [commandBuffer
renderCommandEncoderWithDescriptor:renderPassDesc];
Displaying Rendered Content with Core Animation - 使用Core Animation顯示渲染內(nèi)容
Core Animation
定義了CAMetalLayer類撼嗓,該類專為使用Metal渲染內(nèi)容的圖層支持視圖的特殊行為而設(shè)計(jì)。 CAMetalLayer
對象表示有關(guān)內(nèi)容幾何(位置和大谢锻佟)且警,其可視屬性(背景顏色,邊框和陰影)的信息礁遣,以及Metal用于在顏色附件中顯示內(nèi)容的資源斑芜。它還封裝了內(nèi)容呈現(xiàn)的時(shí)間,以便內(nèi)容可以在可用時(shí)或在指定時(shí)間顯示祟霍。有關(guān)Core Animation
的更多信息杏头,請參閱Core Animation Programming Guide盈包。
Core Animation
還為可顯示資源的對象定義了CAMetalDrawable協(xié)議。 CAMetalDrawable
協(xié)議擴(kuò)展了MTLDrawable
并提供了符合MTLTexture協(xié)議的對象大州,因此它可以用作渲染命令的目標(biāo)续语。要渲染到CAMetalLayer
對象中,您應(yīng)該為每個(gè)渲染過程獲取一個(gè)新的CAMetalDrawable
對象厦画,獲取它提供的MTLTexture
對象疮茄,并使用該紋理創(chuàng)建顏色附件。與顏色附件(attachment)
不同根暑,深度或模板附件的創(chuàng)建和破壞是昂貴的力试。如果需要深度或模板附件,請創(chuàng)建一次排嫌,然后在每次渲染幀時(shí)重復(fù)使用它們畸裳。
通常,您使用layerClass方法將CAMetalLayer
指定為您自己的自定義UIView子類的支持層類型淳地,如Listing 5-4
所示怖糊。否則,您可以使用其init
方法創(chuàng)建CAMetalLayer
颇象,并將該圖層包含在現(xiàn)有視圖中
Listing 5-4 Using CAMetalLayer as the backing layer for a UIView subclass
+ (id) layerClass {
return [CAMetalLayer class];
}
要顯示圖層中Metal渲染的內(nèi)容伍伤,您必須從CAMetalLayer
對象獲取可顯示資源(CAMetalDrawable對象),然后通過將其附加到MTLRenderPassDescriptor對象來渲染到此資源中的紋理遣钳。為此扰魂,首先設(shè)置描述其提供的可繪制資源的CAMetalLayer
對象的屬性,然后在每次開始渲染新幀時(shí)調(diào)用其nextDrawable方法蕴茴。如果未設(shè)置CAMetalLayer
屬性劝评,則nextDrawable
方法調(diào)用將失敗。以下CAMetalLayer
屬性描述了可繪制對象:
- device屬性聲明從中創(chuàng)建資源的MTLDevice對象倦淀。
- pixelFormat屬性聲明紋理的像素格式蒋畜。支持的值是MTLPixelFormatBGRA8Unorm(默認(rèn)值)和MTLPixelFormatBGRA8Unorm_sRGB。
- drawableSize屬性聲明設(shè)備像素中紋理的尺寸撞叽。要確保您的應(yīng)用以顯示的精確尺寸呈現(xiàn)內(nèi)容(在某些設(shè)備上無需額外的采樣階段)百侧,請?jiān)谟?jì)算圖層所需的大小時(shí)考慮目標(biāo)屏幕的nativeScale或nativeBounds屬性。
-
framebufferOnly屬性聲明紋理是僅可用作附件
(YES)
還是也可用于紋理采樣和像素讀/寫操作(NO)
能扒。如果是YES,則圖層對象可以優(yōu)化紋理以供顯示辫狼。對于大多數(shù)應(yīng)用初斑,建議值為YES。 -
presentsWithTransaction屬性聲明是否使用標(biāo)準(zhǔn)Core Animation事務(wù)機(jī)制
(YES)
更新圖層渲染資源的更改膨处,或者是否異步更新為常規(guī)圖層更新(NO见秤,默認(rèn)值)砂竖。
如果nextDrawable
方法成功,則返回具有以下只讀屬性的CAMetalDrawable
對象:
- texture屬性保存紋理對象鹃答。 在創(chuàng)建渲染管道(MTLRenderPipelineColorAttachmentDescriptor對象)時(shí)乎澄,可以將其用作附件。
-
layer屬性指向負(fù)責(zé)顯示
drawable
的CAMetalLayer
對象测摔。
重要說明:只有一小部分可繪制資源置济,因此長幀渲染時(shí)間可能暫時(shí)耗盡這些資源并導(dǎo)致
nextDrawable
方法調(diào)用阻塞其CPU線程,直到方法完成锋八。為了避免昂貴的CPU停頓浙于,在調(diào)用CAMetalLayer
對象的nextDrawable
方法之前,執(zhí)行所有不需要可繪制資源的每幀操作挟纱。
要在渲染完成后顯示可繪制對象的內(nèi)容羞酗,必須通過調(diào)用drawable
對象的present方法將其提交給Core Animation。要同步drawable
的表示和完成負(fù)責(zé)其呈現(xiàn)的命令緩沖區(qū)紊服,可以在MTLCommandBuffer對象上調(diào)用presentDrawable:或presentDrawable:atTime:便利方法檀轨。這些方法使用調(diào)度處理程序(請參閱Registering Handler Blocks for Command Buffer Execution)來調(diào)用drawable
的present
方法,該方法涵蓋大多數(shù)方案欺嗤。 presentDrawable:atTime:
方法提供了對drawable
何時(shí)呈現(xiàn)的進(jìn)一步控制参萄。
Creating a Render Pipeline State - 創(chuàng)建渲染管道狀態(tài)
要使用MTLRenderCommandEncoder對象對渲染命令進(jìn)行編碼,必須首先指定MTLRenderPipelineState對象以定義任何繪制調(diào)用的圖形狀態(tài)剂府。 渲染管道狀態(tài)對象是一個(gè)長期存在的持久對象拧揽,可以在渲染命令編碼器之外創(chuàng)建,預(yù)先緩存腺占,并在多個(gè)渲染命令編碼器中重用淤袜。 在描述相同的圖形狀態(tài)集時(shí),重用先前創(chuàng)建的渲染管線狀態(tài)對象可以避免重新評估并將指定狀態(tài)轉(zhuǎn)換為GPU命令的昂貴操作衰伯。
渲染管道狀態(tài)是不可變對象铡羡。 要?jiǎng)?chuàng)建渲染管道狀態(tài),首先要?jiǎng)?chuàng)建并配置一個(gè)可變MTLRenderPipelineDescriptor對象意鲸,該對象描述渲染管道狀態(tài)的屬性烦周。 然后,使用描述符創(chuàng)建MTLRenderPipelineState對象怎顾。
1. Creating and Configuring a Render Pipeline Descriptor - 創(chuàng)建和配置渲染管道描述符
要?jiǎng)?chuàng)建渲染管道狀態(tài)读慎,首先要?jiǎng)?chuàng)建一個(gè)MTLRenderPipelineDescriptor對象,該對象具有描述在渲染過程中要使用的圖形渲染管道狀態(tài)的屬性槐雾,如圖5-2所示夭委。 新MTLRenderPipelineDescriptor
對象的colorAttachments屬性包含一個(gè)MTLRenderPipelineColorAttachmentDescriptor對象數(shù)組,每個(gè)描述符表示一個(gè)顏色附加狀態(tài)募强,指定該附件的混合操作和因子株灸,詳見Configuring Blending in a Render Pipeline Attachment Descriptor崇摄。 附件描述符還指定附件的像素格式,該格式必須與渲染管道描述符的紋理的像素格式與相應(yīng)的附件索引匹配慌烧,否則會(huì)發(fā)生錯(cuò)誤逐抑。
除了配置顏色附件外,還要為MTLRenderPipelineDescriptor對象設(shè)置以下屬性:
- 設(shè)置depthAttachmentPixelFormat屬性以匹配MTLRenderPassDescriptor中depthAttachment紋理的像素格式屹蚊。
- 設(shè)置stencilAttachmentPixelFormat屬性以匹配MTLRenderPassDescriptor中stencilAttachment紋理的像素格式厕氨。
- 要在渲染管道狀態(tài)中指定頂點(diǎn)或片段著色器,請分別設(shè)置vertexFunction或fragmentFunction屬性淑翼。將
fragmentFunction
設(shè)置為nil
會(huì)禁用像素光柵化到指定的顏色附件腐巢,該附件通常用于僅深度渲染或用于從頂點(diǎn)著色器將數(shù)據(jù)輸出到緩沖區(qū)對象。 - 如果頂點(diǎn)著色器具有帶有每頂點(diǎn)輸入屬性的參數(shù)玄括,請?jiān)O(shè)置vertexDescriptor屬性以描述該參數(shù)中頂點(diǎn)數(shù)據(jù)的組織冯丙,如Vertex Descriptor for Data Organization中所述。
- 對于大多數(shù)典型的渲染任務(wù)遭京,rasterizationEnabled屬性的默認(rèn)值
YES
是足夠的胃惜。要僅使用圖形管道的頂點(diǎn)階段(例如,要收集在頂點(diǎn)著色器中轉(zhuǎn)換的數(shù)據(jù))哪雕,請將此屬性設(shè)置為NO
船殉。 - 如果附件支持多重采樣(即附件是MTLTextureType2DMultisample類型紋理),則可以為每個(gè)像素創(chuàng)建多個(gè)樣本斯嚎。要確定片段如何組合以提供像素覆蓋利虫,請使用以下
MTLRenderPipelineDescriptor
屬性。-
sampleCount屬性確定每個(gè)像素的樣本數(shù)堡僻。創(chuàng)建MTLRenderCommandEncoder時(shí)糠惫,所有附件的紋理的sampleCount必須與此
sampleCount
屬性匹配。如果附件不支持多重采樣钉疫,則sampleCount
為1硼讽,這也是默認(rèn)值。 - 如果alphaToCoverageEnabled設(shè)置為
YES
牲阁,則讀取colorAttachments [0]
的alpha
通道片段輸出并用于確定coverage
掩碼固阁。 - 如果alphaToOneEnabled設(shè)置為YES,則
colorAttachments [0]
的alpha通道片段值將強(qiáng)制為1.0城菊,這是最大的可表示值备燃。 (其他附件不受影響。)
-
sampleCount屬性確定每個(gè)像素的樣本數(shù)堡僻。創(chuàng)建MTLRenderCommandEncoder時(shí)糠惫,所有附件的紋理的sampleCount必須與此
2. Creating a Render Pipeline State from a Descriptor - 從描述符創(chuàng)建渲染管道狀態(tài)
在創(chuàng)建渲染管道描述符并指定其屬性后凌唬,使用它來創(chuàng)建MTLRenderPipelineState對象赚爵。因?yàn)閯?chuàng)建渲染管道狀態(tài)需要對圖形狀態(tài)進(jìn)行昂貴的評估以及可能編譯指定的圖形著色器,所以您可以使用阻塞或異步方法以最適合您的應(yīng)用程序設(shè)計(jì)的方式調(diào)度此類工作。
- 要同步創(chuàng)建渲染管道狀態(tài)對象冀膝,請調(diào)用MTLDevice對象newRenderPipelineStateWithDescriptor:error:或newRenderPipelineStateWithDescriptor:options:reflection:error:的方法。這些方法阻塞當(dāng)前線程霎挟,而Metal評估描述符的圖形狀態(tài)信息窝剖,并編譯著色器代碼以創(chuàng)建管道狀態(tài)對象。
- 要異步創(chuàng)建渲染管道狀態(tài)對象酥夭,請調(diào)用MTLDevice對象的newRenderPipelineStateWithDescriptor:completionHandler:或newRenderPipelineStateWithDescriptor:options:completionHandler:方法赐纱。這些方法立即返回 - Metal異步評估描述符的圖形狀態(tài)信息,并編譯著色器代碼以創(chuàng)建管道狀態(tài)對象熬北,然后調(diào)用完成處理程序以提供新的MTLRenderPipelineState對象疙描。
創(chuàng)建MTLRenderPipelineState對象時(shí),您還可以選擇創(chuàng)建反射數(shù)據(jù)讶隐,以顯示管道著色器函數(shù)及其參數(shù)的詳細(xì)信息起胰。newRenderPipelineStateWithDescriptor:options:reflection:error:和newRenderPipelineStateWithDescriptor:options:completionHandler:提供此數(shù)據(jù)。 如果不使用反射數(shù)據(jù)巫延,請避免獲取反射數(shù)據(jù)效五。 有關(guān)如何分析反射數(shù)據(jù)的更多信息,請參閱Determining Function Details at Runtime炉峰。
創(chuàng)建MTLRenderPipelineState
對象后畏妖,調(diào)用MTLRenderCommandEncoder
的setRenderPipelineState:方法將渲染管道狀態(tài)與命令編碼器關(guān)聯(lián)以用于渲染。
Listing 5-5
演示了如何創(chuàng)建一個(gè)名為pipeline
的渲染管道狀態(tài)對象疼阔。
Listing 5-5 Creating a Simple Pipeline State
MTLRenderPipelineDescriptor *renderPipelineDesc =
[[MTLRenderPipelineDescriptor alloc] init];
renderPipelineDesc.vertexFunction = vertFunc;
renderPipelineDesc.fragmentFunction = fragFunc;
renderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm;
// Create MTLRenderPipelineState from MTLRenderPipelineDescriptor
NSError *errors = nil;
id <MTLRenderPipelineState> pipeline = [device
newRenderPipelineStateWithDescriptor:renderPipelineDesc error:&errors];
assert(pipeline && !errors);
// Set the pipeline state for MTLRenderCommandEncoder
[renderCE setRenderPipelineState:pipeline];
變量vertFunc
和fragFunc
是著色器函數(shù)戒劫,它們被指定為渲染管道狀態(tài)描述符的屬性,稱為renderPipelineDesc
婆廊。 調(diào)用MTLDevice對象的newRenderPipelineStateWithDescriptor:error:的方法同步使用管道狀態(tài)描述符來創(chuàng)建渲染管道狀態(tài)對象迅细。 調(diào)用MTLRenderCommandEncoder
的setRenderPipelineState:方法指定要與渲染命令編碼器一起使用的MTLRenderPipelineState
對象。
注意:因?yàn)?code>MTLRenderPipelineState對象的創(chuàng)建成本很高否彩,所以只要您想使用相同的圖形狀態(tài)疯攒,就應(yīng)該重復(fù)使用它。
3. Configuring Blending in a Render Pipeline Attachment Descriptor - 在渲染管道附件描述符中配置混合
Blending
使用高度可配置的混合操作將片段函數(shù)(源)返回的輸出與附件(目標(biāo))中的像素值混合列荔【闯撸混合操作確定源和目標(biāo)值如何與混合因子組合。
要配置顏色附件的混合贴浙,請?jiān)O(shè)置以下MTLRenderPipelineColorAttachmentDescriptor屬性:
- 要啟用混合砂吞,請將blendingEnabled設(shè)置為YES。默認(rèn)情況下崎溃,禁用混合蜻直。
-
writeMask標(biāo)識混合了哪些顏色通道。默認(rèn)值
MTLColorWriteMaskAll
允許混合所有顏色通道。 -
rgbBlendOperation和alphaBlendOperation分別使用
MTLBlendOperation
值為RGB和Alpha片段數(shù)據(jù)分配混合操作概而。兩個(gè)屬性的默認(rèn)值是MTLBlendOperationAdd呼巷。 -
sourceRGBBlendFactor, sourceAlphaBlendFactor, destinationRGBBlendFactor
和destinationAlphaBlendFactor分配源和目標(biāo)混合因子。
Understanding Blending Factors and Operations - 了解混合因子和操作
四個(gè)混合因子指的是恒定的混合顏色值:MTLBlendFactorBlendColor
赎瑰,MTLBlendFactorOneMinusBlendColor
王悍,MTLBlendFactorBlendAlpha
和MTLBlendFactorOneMinusBlendAlpha
。 調(diào)用MTLRenderCommandEncoder
的setBlendColorRed:green:blue:alpha:方法餐曼,以指定與這些混合因子一起使用的常量顏色和alpha值压储,如Fixed-Function State Operations中所述。
某些混合操作通過將源值乘以源MTLBlendFactor值(縮寫為SBF
)源譬,將目標(biāo)值乘以目標(biāo)混合因子(DBF)
集惋,并使用MTLBlendOperation值指示的算法組合結(jié)果來組合片段值。 (如果混合操作是MTLBlendOperationMin
或MTLBlendOperationMax
踩娘,則忽略SBF
和DBF
混合因子刮刑。)例如,rgbBlendOperation
和alphaBlendOperation
屬性的MTLBlendOperationAdd
為RGB和Alpha值定義以下額外的混合操作:
RGB = (Source.rgb * sourceRGBBlendFactor) + (Dest.rgb * destinationRGBBlendFactor)
Alpha = (Source.a * sourceAlphaBlendFactor) + (Dest.a * destinationAlphaBlendFactor)
在默認(rèn)的混合行為中霸饲,源完全覆蓋目標(biāo)为朋。 此行為相當(dāng)于將sourceRGBBlendFactor
和sourceAlphaBlendFactor
都設(shè)置為MTLBlendFactorOne
,將destinationRGBBlendFactor
和destinationAlphaBlendFactor
設(shè)置為MTLBlendFactorZero
厚脉。 此行為在數(shù)學(xué)上表示為:
RGB = (Source.rgb * 1.0) + (Dest.rgb * 0.0)
A = (Source.a * 1.0) + (Dest.a * 0.0)
另一種常用的混合操作习寸,其中源alpha定義目標(biāo)顏色的剩余量,可以用數(shù)學(xué)方式表示為:
RGB = (Source.rgb * 1.0) + (Dest.rgb * (1 - Source.a))
A = (Source.a * 1.0) + (Dest.a * (1 - Source.a))
Using a Custom Blending Configuration - 使用自定義混合配置
Listing 5-6
顯示了自定義混合配置的代碼傻工,使用混合操作MTLBlendOperationAdd
霞溪,源混合因子MTLBlendFactorOne
和目標(biāo)混合因子MTLBlendFactorOneMinusSourceAlpha
。 colorAttachments [0]
是一個(gè)MTLRenderPipelineColorAttachmentDescriptor對象中捆,其屬性指定混合配置
Listing 5-6 Specifying a Custom Blending Configuration
MTLRenderPipelineDescriptor *renderPipelineDesc =
[[MTLRenderPipelineDescriptor alloc] init];
renderPipelineDesc.colorAttachments[0].blendingEnabled = YES;
renderPipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
renderPipelineDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
renderPipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
renderPipelineDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
renderPipelineDesc.colorAttachments[0].destinationRGBBlendFactor =
MTLBlendFactorOneMinusSourceAlpha;
renderPipelineDesc.colorAttachments[0].destinationAlphaBlendFactor =
MTLBlendFactorOneMinusSourceAlpha;
NSError *errors = nil;
id <MTLRenderPipelineState> pipeline = [device
newRenderPipelineStateWithDescriptor:renderPipelineDesc error:&errors];
后記
本篇主要講述了圖形渲染:渲染命令編碼器鸯匹,感興趣的給個(gè)贊或者關(guān)注~~~