Metal框架詳細解析(四十) —— Metal編程指南之函數和庫(五)

版本記錄

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

前言

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

Functions and Libraries - 函數和庫

本章介紹如何創建MTLFunction對象作為Metal著色器或計算函數的引用,以及如何使用MTLLibrary對象組織和訪問函數。


MTLFunction Represents a Shader or Compute Function - MTLFunction表示著色器或計算函數

MTLFunction對象表示以Metal著色語言編寫并在GPU上作為圖形或計算管道的一部分執行的單個函數。有關Metal shading language的詳細信息,請參閱Metal Shading Language Guide

要在Metal運行時和使用Metal著色語言編寫的圖形或計算函數之間傳遞數據或狀態,可以為紋理,緩沖區和采樣器分配參數索引。參數索引標識Metal運行時和Metal著色代碼正在引用哪個紋理,緩沖區或采樣器。

對于渲染過程,您可以指定MTLFunction對象以用作MTLRenderPipelineDescriptor對象中的頂點或片段著色器,如 Creating a Render Pipeline State中所述。對于計算傳遞,在為目標設備創建MTLComputePipelineState對象時指定MTLFunction對象,如Specify a Compute State and Resources for a Compute Command Encoder中所述。


A Library Is a Repository of Functions - 庫是函數的倉庫

MTLLibrary對象表示一個或多個MTLFunction對象的存儲庫。 單個MTLFunction對象表示使用著色語言編寫的一個Metal函數。 在Metal著色語言源代碼中,任何使用Metal函數限定符(vertex, fragment, or kernel)的函數都可以由庫中的MTLFunction對象表示。 沒有這些函數限定符之一的Metal函數不能由MTLFunction對象直接表示,盡管它可以由著色器中的另一個函數調用。

可以從以下任一來源創建庫中的MTLFunction對象:

  • 在應用程序構建過程中編譯為二進制庫格式的Metal著色語言代碼。
  • 包含Metal著色語言源代碼的文本字符串,由應用程序在運行時編譯。

1. Creating a Library from Compiled Code - 從編譯代碼創建庫

為了獲得最佳性能,請在Xcode的應用程序構建過程中將Metal著色語言源代碼編譯到庫文件中,這樣可以避免在應用程序運行時編譯函數源的成本。 要從庫二進制文件創建MTLLibrary對象,請調用以下MTLDevice方法之一:

  • newDefaultLibrary檢索為主包構建的庫,該庫包含應用程序Xcode項目中的所有著色器和計算函數。
  • newLibraryWithFile:error:獲取庫文件的路徑并返回包含存儲在該庫文件中的所有函數的MTLLibrary對象。
  • newLibraryWithData:error:獲取包含庫中函數代碼的二進制blob,并返回MTLLibrary對象。

有關在構建過程中編譯Metal著色語言源代碼的更多信息,請參閱Creating Libraries During the App Build Process

2. Creating a Library from Source Code - 從源代碼創建庫

要從可能包含多個函數的Metal著色語言源代碼字符串創建MTLLibrary,請調用以下MTLDevice方法之一。 這些方法在創建庫時編譯源代碼。 要指定要使用的編譯器選項,請在MTLCompileOptions對象中設置屬性。

3. Getting a Function from a Library - 從庫中獲取函數

MTLLibrarynewFunctionWithName:方法返回具有所請求名稱的MTLFunction對象。 如果在庫中找不到使用Metal著色語言函數限定符的函數的名稱,則newFunctionWithName:返回nil

Listing 4-1使用MTLDevicenewLibraryWithFile:error:方法通過其完整路徑名定位庫文件,并使用其內容創建具有一個或多個MTLFunction對象的MTLLibrary對象。 加載文件時的任何錯誤都會返回error。 然后MTLLibrarynewFunctionWithName:方法創建一個MTLFunction對象,該對象表示源代碼中名為my_func的函數。 返回的函數對象myFunc現在可以在應用程序中使用

Listing 4-1  Accessing a Function from a Library

NSError *errors;
id <MTLLibrary> library = [device newLibraryWithFile:@"myarchive.metallib"
                          error:&errors];
id <MTLFunction> myFunc = [library newFunctionWithName:@"my_func"];

Determining Function Details at Runtime - 在運行時確定函數詳細信息

由于MTLFunction對象的實際內容是由可能在創建MTLFunction對象之前編譯的圖形著色器或計算函數定義的,因此其源代碼可能無法直接用于應用程序。您可以在運行時查詢以下MTLFunction屬性:

MTLFunction不提供對函數參數的訪問。可以在創建管道狀態期間獲得顯示著色器或計算函數參數的細節的反射對象(MTLRenderPipelineReflectionMTLComputePipelineReflection,具體取決于命令編碼器的類型)。有關創建管道狀態和反射對象的詳細信息,請參閱Creating a Render Pipeline StateCreating a Compute Pipeline State。如果不使用反射數據,請避免獲取反射數據。

反射對象包含命令編碼器支持的每種函數類型的MTLArgument對象數組。對于MTLComputeCommandEncoderMTLComputePipelineReflectionarguments屬性中有一個MTLArgument對象數組,對應于其計算函數的參數。對于MTLRenderCommandEncoderMTLRenderPipelineReflection有兩個屬性,vertexArgumentsfragmentArguments,它們分別對應于頂點函數參數和片段函數參數。

并非函數的所有參數都存在于反射對象中。反射對象僅包含具有關聯資源的參數,但不包含使用[[stage_in]]限定符或內置[[vertex_id]][[attribute_id]]限定符聲明的參數。

Listing 4-2顯示了如何獲取反射對象(在此示例中為MTLComputePipelineReflection),然后在其arguments屬性中迭代MTLArgument對象。

Listing 4-2  Iteration Through Function Arguments

MTLComputePipelineReflection* reflection;
id <MTLComputePipelineState> computePS = [device
              newComputePipelineStateWithFunction:func
              options:MTLPipelineOptionArgumentInfo
              reflection:&reflection error:&error];
for (MTLArgument *arg in reflection.arguments) {
    //  process each MTLArgument
}

MTLArgument屬性顯示著色語言函數的參數的詳細信息。

  • name屬性只是參數的名稱。
  • active是一個布爾值,指示是否可以忽略該參數。
  • index是其對應參數表中從零開始的位置。例如,對于[[buffer(2)]]index2
  • access描述任何訪問限制,例如,讀取或寫入訪問限定符。
  • type由著色語言限定符指示,例如[[buffer(n)]][[texture(n)]][[sampler(n)]][[threadgroup(n)]]

type確定哪些其他MTLArgument屬性是相關的。

如果buffer參數是結構體(即bufferDataTypeMTLDataTypeStruct),則bufferStructType屬性包含表示結構的MTLStructType,而bufferDataSize包含結構的大小(以字節為單位)。如果buffer參數是一個數組(或指向數組的指針),則bufferDataType指示元素的數據類型,bufferDataSize包含一個數組元素的大小(以字節為單位)。

Listing 4-3深入研究MTLStructType對象,以檢查struct成員的詳細信息,每個結構成員由MTLStructMember對象表示。結構成員可以是簡單類型,數組或嵌套結構。如果成員是嵌套結構,則調用MTLStructMemberstructType方法以獲取表示結構的MTLStructType對象,然后遞歸深入分析以進行分析。如果該成員是數組,請使用MTLStructMemberarrayType方法獲取表示它的MTLArrayType。然后檢查它的MTLArrayTypeelementType屬性。如果elementTypeMTLDataTypeStruct,則調用elementStructType方法以獲取結構并繼續深入查看其成員。如果elementTypeMTLDataTypeArray,則調用elementArrayType方法以獲取子數組并進一步分析它。

Listing 4-3  Processing a Struct Argument

MTLStructType *structObj = [arg.bufferStructType];
for (MTLStructMember *member in structObj.members) {
    //  process each MTLStructMember
    if (member.dataType == MTLDataTypeStruct) {
       MTLStructType *nestedStruct = member.structType;
       // recursively drill down into the nested struct
    }
    else if (member.dataType == MTLDataTypeArray) {
       MTLStructType *memberArray = member.arrayType;
       // examine the elementType and drill down, if necessary
    }
    else {
       // member is neither struct nor array
       // analyze it; no need to drill down further
    }
}

后記

本篇主要講述了Metal編程指南之函數和庫,感興趣的給個贊或者關注~~~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容