Metal 4 精要:全新核心 API 究竟改變了什麼
Metal 4 並非重寫。Apple 將其作為與原本 Metal 類型並存的平行 API 介面推出,新類型加上 MTL4 前綴,因此應用程式可以漸進地採用新核心 API,而無需重寫現有的渲染程式碼。1 這個定位很重要:Metal 框架本身已長期推出;在 WWDC25 真正改變的是 Metal 4 核心 API。
新核心 API 為應用程式開發者實際改變的三件事:
- 多執行緒命令緩衝區編碼成為一等模式。
- 運算編碼器將 blit 和加速結構編碼器吸收為單一統一介面。
- 機器學習作為一等 pass 類型與渲染、運算並列執行,在 GPU 時間軸上執行 Core ML 模型,無需往返 CPU。
下列章節將逐一說明這三項變更在實務中的樣貌、開發者所需採用的新類型,以及 Apple 文件對其形式提出的理由。
TL;DR
MTL4CommandQueue、MTL4CommandBuffer、MTL4RenderCommandEncoder、MTL4ComputeCommandEncoder、MTL4MachineLearningCommandEncoder是新類型。1 原本MTL前綴的類型仍保留。您透過混合兩者進行漸進採用。- 命令緩衝區從獨立的
MTL4CommandAllocator取得其工作記憶體,這讓多個執行緒能平行對多個緩衝區進行編碼。單次commit:count:呼叫便可將整批送交至佇列。1 MTL4ComputeCommandEncoder取代了三個先前的編碼器:MTLBlitCommandEncoder、MTLComputeCommandEncoder和MTLAccelerationStructureCommandEncoder。1 一個編碼器,三項工作。MTL4MachineLearningCommandEncoder在 Metal 命令緩衝區內執行 Core ML 模型。2 系統會為每個模型挑選 GPU 或 Apple Neural Engine。張量承載輸入與輸出;同一個命令緩衝區可混合 ML 推論、渲染與運算工作。- 資源繫結改用引數表(
MTL4ArgumentTable),取代每個編碼器的繫結方法。所有資源皆未追蹤;您需透過明確的屏障進行同步。1
為何採用平行 API 介面
Apple 對於平行類型抉擇的定位,原文摘自文件:「Metal 4 引入多個帶 MTL4 前綴的類型,這些類型完全獨立於它們所取代的原本 MTL 類型,例如 MTL4CommandQueue 對比 MTLCommandQueue。其他類型則為所有 Metal 版本所共用。」1
執行階段判斷很簡單:應用程式偵測系統是否支援 Metal 4,若支援則建立 MTL4CommandQueue,否則退回至 MTLCommandQueue。應用程式建立的佇列類型決定了渲染程式碼其餘部分使用哪一系列類型。1
設計的另一半讓兩個系列得以互通。MTLEvent 與 MTLSharedEvent 可在 MTLCommandQueue 與 MTL4CommandQueue 實例之間同步。1 一個搭載大量 Metal 1 程式碼的應用程式,可以將單一子系統切換至 Metal 4,而不破壞應用程式其餘部分依賴的同步模式。
這回答了應用程式開發者自 WWDC25 以來不斷詢問的問題:我需要重寫我的 Metal 程式碼嗎?不需要。API 的形態鼓勵以子系統為單位進行漸進採用。
多執行緒命令緩衝區編碼
最重要的執行階段改進:命令緩衝區記憶體來自一個搭配類型 MTL4CommandAllocator,而非來自佇列。每個執行緒可使用自己的配置器,將工作編碼至自己的命令緩衝區,佇列再以批次方式提交緩衝區。
Apple 的 API 形態:1
let device: MTLDevice = ...
let commandQueue: MTL4CommandQueue = device.makeMTL4CommandQueue()
var commandAllocators: [MTL4CommandAllocator] = ...
let commandBuffer: MTL4CommandBuffer = device.makeCommandBuffer()
// Per frame:
let frameAllocator = commandAllocators[frameNumber % kMaxFramesInFlight]
frameAllocator.reset()
commandBuffer.beginCommandBuffer(allocator: frameAllocator)
// ...encode commands to commandBuffer...
commandBuffer.endCommandBuffer()
commandQueue.commit(commandBuffer, count: 1)
相對於原本 API 的兩項操作改變:
命令緩衝區可重複使用。 Apple 的文件:「您可以無限次地重複使用與重新運用每一個命令緩衝區,方法是重新開始、編碼新命令並再次提交,而非分配新緩衝區。」1 早期 Metal 要求每次提交都使用全新的暫態緩衝區。
沒有自動資源保留。 「每個 MTL4CommandBuffer 實例不會建立對資源的強參照。」1 此行為類似於舊 API 的 makeCommandBufferWithUnretainedReferences()。應用程式需明確管理資源生命週期,使資源在 GPU 完成工作之前持續存活。
Apple 在範例程式碼中所提供的 frame-allocator 模式,每個運行中的影格使用一個配置器(範例使用三個),並在影格依序經歷編碼 → 渲染 → 顯示生命週期時輪替使用。1 在每個影格開始時對配置器呼叫 reset(),會將其記憶體歸還至池中以供重複使用。
統一的運算編碼器
MTL4ComputeCommandEncoder 是「一個結合其三個前身功能的新類型:MTLBlitCommandEncoder、MTLComputeCommandEncoder、MTLAccelerationStructureCommandEncoder。」1
舊有的 API 要求應用程式根據工作形態切換編碼器類型:blit 用於資源複製與紋理傳輸、compute 用於核心派發、acceleration-structure 用於光線追蹤場景管理。Metal 4 將這三者合併為單一介面。一個應用程式編碼某個影格——建立加速結構、派發降噪核心,並將紋理複製到呈現緩衝區——現在可透過單一編碼器類型完成這三件事。
渲染編碼器也獲得了一項行為變化。MTL4RenderCommandEncoder 支援跨命令緩衝區編碼渲染 pass,方法是在某個渲染編碼器結束時暫停工作,並在序列中下一個渲染編碼器開始之後繼續。1 Apple 的定位:「此技術在概念上取代了 MTLParallelRenderCommandEncoder 協定,並簡化了以多執行緒平行編碼渲染 pass 的工作,因為每個執行緒都能擁有自己的渲染編碼器,而不必將所有執行緒繫結至單一渲染編碼器。」1
模式一致:平行編碼成為自然的形態,API 不再要求單一協調器類型。
引數表取代每個編碼器的資源繫結
原本的 Metal 編碼器 API 在每個編碼器上提供 setVertexBuffer(_:offset:index:) 與 setFragmentTexture(_:index:) 等方法,並在編碼器內部維護獨立的每階段繫結表。1 Metal 4 以明確的 MTL4ArgumentTable 實例取代此模式。
Apple 對該設計優勢的定位:「Metal 4 編碼器不需要為每個資源類型、每個階段儲存繫結表的記憶體。每個表只消耗其儲存資源繫結所需的記憶體。」1
流程:1
let descriptor = MTL4ArgumentTableDescriptor()
descriptor.maxBufferBindCount = ...
descriptor.maxTextureBindCount = ...
let argumentTable = device.makeArgumentTable(descriptor: descriptor)
argumentTable.setResource(buffer, bufferIndex: 0)
argumentTable.setSamplerState(sampler, index: 0)
renderEncoder.setArgumentTable(argumentTable, stages: [.vertex, .fragment])
單一引數表可服務多個編碼器,包括不同命令緩衝區上的編碼器,只要其繫結的資源適用於所有編碼器即可。Apple 文件指出:「您的編碼器共用的每項資源、以及您每次將引數表指派給新編碼器,記憶體與執行階段的節省都會累積。」1
但這當中存在一項取捨。早期 Metal 版本支援透過 MTLTextureDescriptor.hazardTrackingMode 或 MTLHeapDescriptor.hazardTrackingMode 啟用紋理與堆積的危害追蹤。1 在 Metal 4 中,「框架將所有資源視為未追蹤。如果這些管線中的任何著色器會修改某項資源,您必須同步可同時存取該資源的管線階段。」1 應用程式需加入明確的屏障以延遲某個階段,直到前一個階段完成。這比舊有的選擇性追蹤需要更多程式碼,但換來的是可預測的效能與更低的執行階段開銷。
機器學習作為一等 Pass
MTL4MachineLearningCommandEncoder 是架構意義上最重要的新增功能。Apple 的定位:2
「Metal 4 引入從 Metal 工作流程內部高效執行 CoreML 模型的能力。這對需要在 Metal 環境中應用模型輸出的應用程式(例如渲染場景或執行運算派發)相當實用。」
兩件事同時發生。首先,ML 推論在 GPU 時間軸上執行,與渲染和運算工作位於同一個命令緩衝區。應用程式不會在模型推論與消耗其輸出的渲染 pass 之間往返 CPU。其次,系統選擇推論引擎:「系統會自動為每個機器學習模型選擇推論引擎,例如裝置的 GPU 或 Apple Neural Engine(ANE)。當系統選擇在 ANE 上執行模型時,GPU 可以同時執行額外、獨立的渲染或運算工作。」2
開發工作流程:2
- 使用 Xcode 26 隨附工具中的
metal-package-builder,將 Core ML 模型轉換為 Metal ML 套件。 - 將 Metal ML 套件加入 Xcode 專案。Xcode 會在建置時將其編譯為 Metal 程式庫。
- 在執行階段,應用程式從該程式庫建立
MTL4MachineLearningPipelineState。 - 編碼器會接收管線狀態、用於暫存記憶體的
MTLHeap,以及作為輸入與輸出的MTLTensor實例。
MTLTensor 是用於多維資料陣列的新資源類型。2 Apple 文件指出此類型可搭配常見的 ML 權重類型運作,例如 int8 與 fp16。張量負責將輸入帶入模型並將輸出帶出;對於推論呼叫之間的暫態資料,Metal Shading Language 新增了直接存在於 GPU 上的張量類型:2
tensor_handle:對 CPU 上建立的MTLTensor的控制代碼tensor_inline:在 GPU 上定義的張量,作為對某個張量或緩衝區的視圖cooperative_tensor:在處理該張量的執行緒之間分配其元素的張量
cooperative_tensor 類型是延遲敏感的情境:「協作張量為暫態張量提供臨時記憶體,方法是在處理該張量的執行緒之間平均分配其資料。此記憶體分配透過從執行緒私有或執行緒群組私有位址空間配置記憶體來降低記憶體頻寬,這對於延遲關鍵的機器學習演算法相當重要。」2
MSL 也獲得了直接在著色器程式碼中運作的張量運算子:卷積、矩陣乘法、約簡。2 需要在推論 pass 之間操作權重的應用程式可直接執行此操作,無需將張量複製回 CPU 記憶體或執行另一個運算 pass;這些運算子可融入一般的 MSL 核心。
有一個邊界值得引述:「機器學習編碼器執行 Core ML 模型,但無法建構新網路或修改現有網路的層與輸入;對於那些任務,請參閱 Core ML 與 Metal Performance Shaders Graph。」2 Metal 4 的 ML 編碼器專為提供推論而設計,並非用於訓練或模型建構。
Metal 4 對 Apple 技術堆疊的意義
對於規劃採用 Metal 4 的應用程式開發者,三項要點:
- 依子系統漸進採用。 平行的
MTL4前綴類型以及與原本 API 基於事件的互通,正是為部分遷移而設計。挑選一個具有明顯效能壓力的子系統(渲染路徑、運算管線、模型推論迴圈),先進行遷移。1 - 多執行緒編碼成為新常態。 每執行緒一個配置器的模式、
commit:count:批次提交,以及暫停/繼續的渲染 pass 機制,皆預設平行編碼是高效應用程式將採用的形態。單執行緒編碼仍可運作,但框架的執行階段優勢會隨多執行緒採用而累加。1 - ML 與其他工作位於同一個命令緩衝區。 對於結合裝置端模型推論與渲染或運算的應用程式(透過 Core ML 模型過濾的影像處理管線、依賴分類器輸出的即時效果、其渲染依賴每影格推論結果的 AR 體驗),能將 ML 推論編碼至消耗其輸出的同一個命令緩衝區,正是質的轉變。2
Metal Shading Language 的新增功能值得另闢專文討論。著色器程式碼中的張量類型與運算子,加上自訂運算的運算描述符,改變了 Metal 核心所能表達的內容。那是另一篇文章。
完整的 Apple 生態系列:Foundation Models 裝置端 LLM介紹在此堆疊之上運行的框架;自訂介面卡生命週期介紹開發者管理的特化;Core ML 裝置端推論介紹 Metal 4 如今可內嵌執行其模型的 ML 框架。中樞位於 Apple 生態系列文章。
FAQ
Metal 4 是與 Metal 分離的框架嗎?
不是。框架仍是 Metal。Apple 文件將 Metal 4 描述為「Metal 4 核心 API」:一組帶 MTL4 前綴的新類型,與原本 MTL 類型並存於同一個框架中。1 應用程式透過在執行階段偵測 Metal 4 支援並建立合適的佇列類型,以漸進方式採用新類型。
我需要 iOS 26 才能使用 Metal 4 嗎?
Metal 框架支援 iOS 8+,但 Metal 4 核心 API 是 Apple 在 WWDC25 引入的版本。請執行執行階段偵測,並根據裝置支援情況建立 MTL4CommandQueue 或 MTLCommandQueue。1
Metal 4 ML pass 與 Foundation Models 之間的關係是什麼?
它們在不同堆疊上運行。MTL4MachineLearningCommandEncoder 執行轉換為 Metal ML 套件的 Core ML 模型,與渲染、運算工作位於同一個命令緩衝區。2 Foundation Models 是另一個獨立框架,使用其自己的 session API 執行 Apple 的裝置端系統語言模型,於 Foundation Models 裝置端 LLM 文章中介紹。兩者互補:應用程式可以使用 Foundation Models 進行文字生成,並在其渲染迴圈內使用 Metal 4 ML pass 進行視覺或音訊模型推論。
為什麼運算編碼器現在統一了?
Apple 文件將 MTLBlitCommandEncoder、MTLComputeCommandEncoder 與 MTLAccelerationStructureCommandEncoder 合併為 MTL4ComputeCommandEncoder。1 理由偏向操作面而非僅效能面:單一編碼器類型負責 compute、blit 與 acceleration-structure 工作,簡化了管線管理,並降低交錯使用三者的應用程式中的編碼器切換負擔。
Metal 4 中還有 store-action 選項嗎?
對於 MTL4RenderCommandEncoder沒有了。Apple 文件指出:「Store-action 選項(請參閱 MTLStoreActionOptions)並未提供,因為它們不適用於 Apple silicon GPU。」1 此架構決策反映了 Apple 對於 Metal 4 核心 API 僅鎖定 GPU 的目標。
我必須使用引數表嗎?
在 Metal 4 中,是的。編碼器協定不再提供每個資源的繫結方法。您需在 MTL4ArgumentTable 上設定資源繫結,並將該表指派給一個或多個編碼器階段。1 執行階段優勢在於,該表只為實際使用的繫結配置記憶體,而非為每個編碼器配置固定大小的每階段表。
References
-
Apple Developer, “Understanding the Metal 4 core API”. 類型階層比較(
MTL4對比MTL)、命令佇列與緩衝區行為、命令配置器模式、編碼器統合、引數表、危害追蹤、暫停/繼續渲染 pass。擷取於 2026-05-04。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple Developer, “Machine learning passes”.
MTL4MachineLearningCommandEncoder、MTLTensor、MSL 張量類型(tensor_handle、tensor_inline、cooperative_tensor)、metal-package-builder、系統推論引擎選擇(GPU/ANE)、MSL 張量運算子。擷取於 2026-05-04。 ↩↩↩↩↩↩↩↩↩↩↩