版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.11.10 星期六 |
前言
很多做視頻和圖像的,相信對這個框架都不是很陌生,它渲染高級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編程指南之資源對象:緩沖區和紋理(四)
40. Metal框架詳細解析(四十) —— Metal編程指南之函數和庫(五)
41. Metal框架詳細解析(四十一) —— Metal編程指南之圖形渲染:渲染命令編碼器之Part 1(六)
42. Metal框架詳細解析(四十二) —— Metal編程指南之圖形渲染:渲染命令編碼器之Part 2(七)
Data-Parallel Compute Processing: Compute Command Encoder - 數據并行計算處理:計算命令編碼器
本章介紹如何創建和使用MTLComputeCommandEncoder對象來編碼數據并行計算處理狀態和命令,并提交它們以便在設備上執行。
要執行數據并行計算,請遵循以下主要步驟:
- 1) 使用MTLDevice方法創建包含來自MTLFunction對象的已編譯代碼的計算狀態(MTLComputePipelineState),如Creating a Compute State中所述。
MTLFunction
對象表示使用Metal著色語言編寫的計算函數,如Functions and Libraries中所述。 - 2) 指定計算命令編碼器要使用的MTLComputePipelineState對象,如Specifying a Compute State and Resources for a Compute Command Encoder中所述。
- 3) 指定可能包含要由計算狀態處理和返回的數據的資源和相關對象(MTLBuffer,MTLTexture和可能的MTLSamplerState),如Specifying a Compute State and Resources for a Compute Command Encoder中所述。還要設置它們的參數表索引,以便Metal框架代碼可以在著色器代碼中找到相應的資源。在任何給定時刻,MTLComputeCommandEncoder都可以與許多資源對象相關聯。
- 4) 按照 Executing a Compute Command中的說明,將計算函數分配指定的次數。
Creating a Compute Pipeline State - 創建計算管道狀態
MTLFunction對象表示可由MTLComputePipelineState對象執行的數據并行代碼。 MTLComputeCommandEncoder對象對用于設置參數和執行計算功能的命令進行編碼。由于創建計算管道狀態可能需要昂貴的Metal著色語言代碼編譯,因此您可以使用阻塞或異步方法以最適合應用程序設計的方式安排此類工作。
- 要同步創建計算管道狀態對象,請調用MTLDevice的方法newComputePipelineStateWithFunction:error:或newComputePipelineStateWithFunction:options:reflection:error:。這些方法阻塞當前線程,而Metal編譯著色器代碼以創建管道狀態對象。
- 要異步創建計算管道狀態對象,請調用MTLDevice的方法newComputePipelineStateWithFunction:completionHandler:或newComputePipelineStateWithFunction:options:completionHandler:。這些方法立即返回 - Metal異步編譯著色器代碼以創建管道狀態對象,然后調用完成處理程序以提供新的MTLComputePipelineState對象。
創建MTLComputePipelineState對象時,還可以選擇創建反映數據,以顯示計算函數及其參數的詳細信息。 newComputePipelineStateWithFunction:options:reflection:error:和newComputePipelineStateWithFunction:options:completionHandler:方法提供此數據。如果不使用反射數據,請避免獲取反射數據。有關如何分析反射數據的更多信息,請參閱Determining Function Details at Runtime。
Specifying a Compute State and Resources for a Compute Command Encoder - 為計算命令編碼器指定計算狀態和資源
MTLComputeCommandEncoder對象的setComputePipelineState:方法指定用于數據并行計算通道的狀態,包括已編譯的計算著色器函數。 在任何給定時刻,計算命令編碼器可以僅與一個計算函數相關聯。
以下MTLComputeCommandEncoder方法指定一個資源(即緩沖區,紋理,采樣器狀態或線程組內存),該資源用作MTLComputePipelineState對象表示的計算函數的參數。
- setBuffer:offset:atIndex:
- setBuffers:offsets:withRange:
- setTexture:atIndex:
- setTextures:withRange:
- setSamplerState:atIndex:
- setSamplerState:lodMinClamp:lodMaxClamp:atIndex:
- setSamplerStates:withRange:
- setSamplerStates:lodMinClamps:lodMaxClamps:withRange:
- setThreadgroupMemoryLength:atIndex:
每個方法都將一個或多個資源分配給相應的參數,如圖6-1所示。
Implementation Limits表中列出了緩沖區,紋理或采樣器狀態參數表中最大條目數的限制。
Implementation Limits表中還列出了最大總線程組內存分配的限制。
Executing a Compute Command - 執行計算命令
要編碼執行計算函數的命令,請調用MTLComputeCommandEncoder的dispatchThreadgroups:threadsPerThreadgroup:方法,并指定線程組維度和線程組數。您可以查詢MTLComputePipelineState的threadExecutionWidth和maxTotalThreadsPerThreadgroup屬性,以優化此設備上計算函數的執行。
線程組中的線程總數是threadsPerThreadgroup
組件的產品:threadsPerThreadgroup.width * threadsPerThreadgroup.height * threadsPerThreadgroup.depth
。 maxTotalThreadsPerThreadgroup屬性指定在單個線程組中可以在設備上執行此計算函數的最大線程數。
計算命令按照它們編碼到命令緩沖區的順序執行。當與命令關聯的所有線程組完成執行并且所有結果都寫入內存時,計算命令完成執行。由于這種排序,計算命令的結果可用于在命令緩沖區中編碼的任何命令。
要結束計算命令編碼器的編碼命令,請調用MTLComputeCommandEncoder的endEncoding方法。在結束上一個命令編碼器之后,您可以創建任何類型的新命令編碼器,以將其他命令編碼到命令緩沖區中。
Code Example: Executing Data-Parallel Functions - 代碼示例:執行數據并行函數
Listing 6-1顯示了一個示例,該示例創建并使用MTLComputeCommandEncoder對象來執行對指定數據的圖像轉換的并行計算。 (此示例未顯示如何創建和初始化設備,庫,命令隊列和資源對象。)該示例創建命令緩沖區,然后使用它創建MTLComputeCommandEncoder對象。接下來,創建一個MTLFunction對象,表示從MTLLibrary對象加載的入口點filter_main
,如Listing 6-2所示。然后,函數對象用于創建名為filterState
的MTLComputePipelineState對象。
計算函數對inputImage
圖像執行圖像變換和過濾操作,并在outputImage
中返回結果。首先,setTexture:atIndex:和setBuffer:offset:atIndex:方法將紋理和緩沖區對象分配給指定參數表中的索引。 paramsBuffer
指定用于執行圖像轉換的值,inputTableData
指定過濾器權重。計算功能作為每個維度中尺寸為16 x 16
像素的2D線程組執行。 dispatchThreadgroups:threadsPerThreadgroup:方法將命令排入隊列以分派執行計算函數的線程,endEncoding方法終止MTLComputeCommandEncoder。最后,MTLCommandBuffer的commit方法會導致命令盡快執行。
// Listing 6-1 Specifying and Running a Function in a Compute State
id <MTLDevice> device;
id <MTLLibrary> library;
id <MTLCommandQueue> commandQueue;
id <MTLTexture> inputImage;
id <MTLTexture> outputImage;
id <MTLTexture> inputTableData;
id <MTLBuffer> paramsBuffer;
// ... Create and initialize device, library, queue, resources
// Obtain a new command buffer
id <MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
// Create a compute command encoder
id <MTLComputeCommandEncoder> computeCE = [commandBuffer computeCommandEncoder];
NSError *errors;
id <MTLFunction> func = [library newFunctionWithName:@"filter_main"];
id <MTLComputePipelineState> filterState
= [device newComputePipelineStateWithFunction:func error:&errors];
[computeCE setComputePipelineState:filterState];
[computeCE setTexture:inputImage atIndex:0];
[computeCE setTexture:outputImage atIndex:1];
[computeCE setTexture:inputTableData atIndex:2];
[computeCE setBuffer:paramsBuffer offset:0 atIndex:0];
MTLSize threadsPerGroup = {16, 16, 1};
MTLSize numThreadgroups = {inputImage.width/threadsPerGroup.width,
inputImage.height/threadsPerGroup.height, 1};
[computeCE dispatchThreadgroups:numThreadgroups
threadsPerThreadgroup:threadsPerGroup];
[computeCE endEncoding];
// Commit the command buffer
[commandBuffer commit];
Listing 6-2
顯示了前面示例的相應著色器代碼。 (函數read_and_transform
和filter_table
是用戶定義代碼的占位符)。
Listing 6-2 Shading Language Compute Function Declaration
kernel void filter_main(
texture2d<float,access::read> inputImage [[ texture(0) ]],
texture2d<float,access::write> outputImage [[ texture(1) ]],
uint2 gid [[ thread_position_in_grid ]],
texture2d<float,access::sample> table [[ texture(2) ]],
constant Parameters* params [[ buffer(0) ]]
)
{
float2 p0 = static_cast<float2>(gid);
float3x3 transform = params->transform;
float4 dims = params->dims;
float4 v0 = read_and_transform(inputImage, p0, transform);
float4 v1 = filter_table(v0,table, dims);
outputImage.write(v1,gid);
}
后記
本篇主要講述了數據并行計算處理:計算命令編碼器,感興趣的給個贊后者關注~~~