Metal 4 Essentials : ce que la nouvelle API centrale change réellement
Metal 4 n’est pas une réécriture. Apple l’a livré comme une surface API parallèle aux côtés des types Metal d’origine, avec un préfixe MTL4 sur les nouveaux, de sorte qu’une application peut adopter la nouvelle API centrale de manière incrémentale sans réécrire le code de rendu existant.1 Le cadrage importe : le framework Metal lui-même est livré depuis longtemps ; la API centrale de Metal 4 est ce qui a changé à la WWDC25.
Trois choses que la nouvelle API centrale change réellement pour les développeurs d’applications :
- L’encodage multithread des command buffers devient un modèle de première classe.
- L’encodeur de calcul absorbe les encodeurs blit et de structure d’accélération en une seule surface unifiée.
- Le machine learning s’exécute comme un type de passe de première classe aux côtés des passes de rendu et de calcul, en exécutant les modèles Core ML sur la chronologie GPU sans aller-retour vers le CPU.
Les sections ci-dessous parcourent à quoi ressemblent ces trois changements en pratique, les nouveaux types que les développeurs utilisent, et les raisons que la documentation d’Apple donne pour la forme qu’ils ont prise.
TL;DR
MTL4CommandQueue,MTL4CommandBuffer,MTL4RenderCommandEncoder,MTL4ComputeCommandEncoder,MTL4MachineLearningCommandEncodersont les nouveaux types.1 Les types préfixésMTLd’origine subsistent. Vous adoptez progressivement en mélangeant les deux.- Les command buffers obtiennent leur mémoire de travail d’un
MTL4CommandAllocatorséparé, ce qui permet à plusieurs threads d’encoder vers plusieurs buffers en parallèle. Un seul appelcommit:count:soumet le lot à la queue.1 MTL4ComputeCommandEncoderremplace trois encodeurs antérieurs :MTLBlitCommandEncoder,MTLComputeCommandEncoderetMTLAccelerationStructureCommandEncoder.1 Un encodeur, trois travaux.MTL4MachineLearningCommandEncoderexécute les modèles Core ML à l’intérieur d’un command buffer Metal.2 Le système choisit le GPU ou l’Apple Neural Engine pour chaque modèle. Les tenseurs portent les entrées et sorties ; le même command buffer mélange l’inférence ML avec le travail de rendu et de calcul.- La liaison de ressources passe aux tables d’arguments (
MTL4ArgumentTable) au lieu des méthodes de liaison par encodeur. Toutes les ressources sont non suivies ; vous synchronisez avec des barrières explicites.1
Pourquoi une surface API parallèle
Le cadrage d’Apple pour le choix des types parallèles, mot pour mot tiré de la documentation : « Metal 4 introduit plusieurs types avec le préfixe MTL4 qui sont complètement indépendants des types MTL d’origine qu’ils remplacent, comme MTL4CommandQueue versus MTLCommandQueue. D’autres types sont communs à toutes les versions de Metal. »1
La vérification d’exécution est simple : l’application détecte si le système prend en charge Metal 4, crée un MTL4CommandQueue si c’est le cas, sinon revient à MTLCommandQueue. Le type de queue que l’application crée détermine quelle famille de types le reste du code de rendu utilise.1
L’autre moitié de la conception permet aux deux familles d’interopérer. MTLEvent et MTLSharedEvent synchronisent les instances MTLCommandQueue et MTL4CommandQueue à la fois.1 Une application livrant une base de code Metal 1 substantielle peut basculer un sous-système unique vers Metal 4 sans casser les modèles de synchronisation dont dépend le reste de l’application.
Cela répond à une question que les développeurs d’applications se posent depuis la WWDC25 : dois-je réécrire mon code Metal ? Non. La forme de l’API encourage une adoption incrémentale par sous-système.
Encodage multithread des command buffers
L’amélioration phare à l’exécution : la mémoire des command buffers provient d’un type compagnon, MTL4CommandAllocator, plutôt que de la queue. Chaque thread peut encoder le travail vers son propre command buffer en utilisant son propre allocateur, et la queue valide les buffers en lot.
La forme d’API d’Apple :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)
Deux changements opérationnels par rapport à l’API d’origine :
Les command buffers sont réutilisables. La documentation d’Apple : « Vous pouvez réutiliser et réaffecter chaque command buffer indéfiniment en recommençant, en encodant de nouvelles commandes et en le validant à nouveau, au lieu d’allouer un nouveau buffer. »1 Metal antérieur exigeait un nouveau buffer transitoire à chaque validation.
Pas de rétention automatique des ressources. « Chaque instance MTL4CommandBuffer ne crée pas de références fortes vers les ressources. »1 Le comportement est similaire à makeCommandBufferWithUnretainedReferences() de l’ancienne API. Les applications doivent gérer explicitement les durées de vie des ressources de sorte que les ressources restent vivantes jusqu’à ce que le GPU termine le travail.
Le modèle d’allocateur par frame qu’Apple livre dans son code d’exemple utilise un allocateur par frame en vol (l’exemple en utilise trois) et alterne entre eux à mesure que les frames avancent dans le cycle de vie encodage → rendu → affichage.1 Appeler reset() sur l’allocateur au début de chaque frame retourne sa mémoire au pool pour réutilisation.
L’encodeur de calcul unifié
MTL4ComputeCommandEncoder est « un nouveau type qui combine les fonctionnalités de ses trois prédécesseurs : MTLBlitCommandEncoder, MTLComputeCommandEncoder, MTLAccelerationStructureCommandEncoder. »1
L’API antérieure exigeait des applications qu’elles changent de type d’encodeur en fonction de la forme du travail : blit pour les copies de ressources et les transferts de textures, calcul pour les dispatches de noyaux, structure d’accélération pour la gestion de scène en ray tracing. Metal 4 réduit ces trois en une seule surface. Une application qui encode une frame qui construit une structure d’accélération, lance un noyau de débruitage et copie une texture vers un buffer de présentation peut maintenant faire les trois via un seul type d’encodeur.
L’encodeur de rendu a aussi reçu un changement de comportement. MTL4RenderCommandEncoder prend en charge l’encodage d’une passe de rendu à travers les command buffers en suspendant le travail à la fin d’un encodeur de rendu et en le reprenant après le début du suivant dans la séquence.1 Le cadrage d’Apple : « Cette technique remplace conceptuellement le protocole MTLParallelRenderCommandEncoder et simplifie l’encodage d’une passe de rendu en parallèle avec plusieurs threads parce que chaque thread peut avoir son propre encodeur de rendu au lieu de les lier tous à un seul encodeur de rendu. »1
Le modèle tient : l’encodage parallèle devient la forme naturelle, et l’API cesse d’exiger un type coordinateur unique.
Les tables d’arguments remplacent les liaisons de ressources par encodeur
L’API d’encodeur Metal d’origine exposait des méthodes comme setVertexBuffer(_:offset:index:) et setFragmentTexture(_:index:) sur chaque encodeur, avec des tables de liaison séparées par étape internes à l’encodeur.1 Metal 4 remplace ce modèle par une instance explicite MTL4ArgumentTable.
Le cadrage d’Apple sur le bénéfice de la conception : « Les encodeurs Metal 4 ne nécessitent pas de mémoire pour stocker les tables de liaison pour chaque type de ressource, à chaque étape. Chaque table ne consomme que la mémoire dont elle a besoin pour stocker ses liaisons de ressources. »1
Le flux :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])
Une seule table d’arguments peut servir plusieurs encodeurs, y compris des encodeurs sur différents command buffers, tant que les ressources qu’elle lie sont appropriées pour tous. La documentation d’Apple note : « Les économies de mémoire et d’exécution s’additionnent avec chaque ressource commune que vos encodeurs partagent, et chaque fois que vous assignez la table d’arguments à un nouvel encodeur. »1
Il y a un compromis. Les versions antérieures de Metal prenaient en charge le suivi des risques (hazard tracking) pour les textures et les heaps qui s’inscrivaient via MTLTextureDescriptor.hazardTrackingMode ou MTLHeapDescriptor.hazardTrackingMode.1 Dans Metal 4, « le framework considère toutes les ressources comme non suivies. Vous devez synchroniser les étapes de pipeline qui peuvent accéder simultanément à une ressource si l’un des shaders dans ces pipelines la modifie. »1 Les applications ajoutent des barrières explicites pour retarder une étape jusqu’à ce qu’une étape précédente termine. C’est plus de code que le suivi opt-in plus ancien, en échange de performances prévisibles et d’une surcharge d’exécution plus faible.
Le machine learning comme passe de première classe
MTL4MachineLearningCommandEncoder est l’ajout le plus significatif sur le plan architectural. Le cadrage d’Apple :2
« Metal 4 introduit la capacité d’exécuter efficacement des modèles CoreML depuis l’intérieur du flux de travail Metal. Ceci est utile pour les applications qui ont besoin d’appliquer la sortie d’un modèle dans un contexte Metal, comme le rendu d’une scène ou l’exécution d’un dispatch de calcul. »
Deux choses se produisent en même temps. Premièrement, l’inférence ML s’exécute sur la chronologie GPU, dans le même command buffer que le travail de rendu et de calcul. L’application ne fait pas d’aller-retour via le CPU entre l’inférence du modèle et la passe de rendu qui consomme la sortie. Deuxièmement, le système choisit le moteur d’inférence : « Le système choisit automatiquement un moteur d’inférence, comme le GPU d’un appareil ou l’Apple Neural Engine (ANE) pour chaque modèle de machine learning. Le GPU peut exécuter du travail de rendu ou de calcul supplémentaire et indépendant avec le GPU lorsque le système choisit d’exécuter un modèle sur l’ANE. »2
Le flux de travail de développement :2
- Convertissez un modèle Core ML en un package ML Metal en utilisant
metal-package-builder, inclus dans les outils groupés de Xcode 26. - Ajoutez le package ML Metal au projet Xcode. Xcode le compile en une bibliothèque Metal au moment de la construction.
- À l’exécution, l’application crée un
MTL4MachineLearningPipelineStateà partir de cette bibliothèque. - L’encodeur prend l’état du pipeline, un
MTLHeappour la mémoire de travail, et des instancesMTLTensorpour les entrées et les sorties.
MTLTensor est un nouveau type de ressource pour les tableaux de données multidimensionnels.2 La documentation d’Apple note que le type fonctionne avec les types de poids ML courants comme int8 et fp16. Les tenseurs portent les entrées dans le modèle et les sorties hors de celui-ci ; pour les données transitoires entre les invocations d’inférence, Metal Shading Language ajoute des types de tenseurs qui vivent directement sur le GPU :2
tensor_handle: un handle vers unMTLTensorcréé sur le CPUtensor_inline: un tenseur défini sur le GPU comme une vue dans un tenseur ou un buffercooperative_tensor: un tenseur qui distribue ses éléments parmi les threads qui travaillent avec lui
Le type cooperative_tensor est le cas sensible à la latence : « Les tenseurs coopératifs fournissent une mémoire temporaire pour les tenseurs transitoires en distribuant équitablement leurs données parmi les threads qui travaillent avec ce tenseur. Cette distribution mémoire réduit la bande passante mémoire en allouant la mémoire à partir d’espaces d’adresses privés au thread ou au threadgroup, ce qui est important pour les algorithmes de machine learning critiques en latence. »2
MSL a aussi reçu des opérateurs de tenseurs qui fonctionnent directement dans le code de shader : convolution, multiplication matricielle, réduction.2 Les applications qui ont besoin de manipuler les poids entre les passes d’inférence peuvent le faire sans copier les tenseurs vers la mémoire CPU ou exécuter une passe de calcul séparée ; les opérateurs s’intègrent dans les noyaux MSL normaux.
Il y a une frontière qui mérite d’être citée : « Les encodeurs de machine learning exécutent les modèles Core ML mais ils ne peuvent pas construire de nouveaux réseaux ni modifier les couches et entrées de réseaux existants ; pour ces tâches, voir Core ML et Metal Performance Shaders Graph. »2 L’encodeur ML de Metal 4 sert à livrer l’inférence, non à entraîner ou construire des modèles.
Ce que Metal 4 signifie pour la pile Apple
Trois enseignements pour les développeurs d’applications planifiant l’adoption de Metal 4 :
- Adoptez progressivement, par sous-système. Les types parallèles préfixés
MTL4et l’interopérabilité basée sur les événements avec l’API d’origine sont conçus pour une migration partielle. Choisissez un sous-système avec une pression de performance claire (un chemin de rendu, un pipeline de calcul, une boucle d’inférence de modèle) et migrez-le en premier.1 - L’encodage multithread est la nouvelle norme. Le modèle d’allocateur par thread, la soumission par lot
commit:count:et le mécanisme de suspension/reprise des passes de rendu supposent tous l’encodage parallèle comme la forme que les applications performantes utiliseront. L’encodage à thread unique fonctionne toujours, mais les gains à l’exécution du framework s’accumulent avec l’adoption multithread.1 - Le ML s’exécute dans le même command buffer que tout le reste. Pour les applications qui combinent l’inférence de modèle sur l’appareil avec le rendu ou le calcul (pipelines de traitement d’image qui filtrent à travers un modèle Core ML, effets en temps réel qui dépendent de la sortie d’un classificateur, expériences AR dont le rendu dépend d’un résultat d’inférence par frame), la capacité d’encoder l’inférence ML dans le même command buffer que la passe de rendu qui la consomme est le changement qualitatif.2
Les ajouts à Metal Shading Language méritent leur propre traitement. Les types et opérateurs de tenseurs dans le code de shader, plus les descripteurs d’opérations pour les opérations personnalisées, changent ce qu’un noyau Metal peut exprimer. C’est un autre billet.
Le cluster Apple Ecosystem complet : le LLM Foundation Models sur l’appareil pour le framework qui s’exécute au-dessus de cette pile ; le cycle de vie des adaptateurs personnalisés pour la spécialisation gérée par le développeur ; Core ML sur l’inférence sur l’appareil pour le framework ML dont les modèles Metal 4 exécute désormais en ligne. Le hub se trouve à la série Apple Ecosystem.
FAQ
Metal 4 est-il un framework distinct de Metal ?
Non. Le framework reste Metal. La documentation d’Apple décrit Metal 4 comme « la API centrale de Metal 4 » : un ensemble de nouveaux types avec le préfixe MTL4 qui sont livrés aux côtés des types MTL d’origine dans le même framework.1 Les applications adoptent progressivement les nouveaux types en détectant le support de Metal 4 à l’exécution et en créant le type de queue approprié.
Ai-je besoin d’iOS 26 pour utiliser Metal 4 ?
Le framework Metal prend en charge iOS 8+, mais la API centrale de Metal 4 est la version qu’Apple a introduite à la WWDC25. Exécutez une détection à l’exécution et créez soit un MTL4CommandQueue, soit un MTLCommandQueue selon ce que l’appareil prend en charge.1
Quelle est la relation entre les passes ML de Metal 4 et Foundation Models ?
Ils s’exécutent sur des piles différentes. MTL4MachineLearningCommandEncoder exécute des modèles Core ML convertis en packages ML Metal, dans le même command buffer que le travail de rendu et de calcul.2 Foundation Models est un framework distinct qui exécute le modèle de langage système sur l’appareil d’Apple avec sa propre API de session, couvert dans le billet sur le LLM Foundation Models sur l’appareil. Les deux sont complémentaires : une application peut utiliser Foundation Models pour la génération de texte et les passes ML de Metal 4 pour l’inférence de modèles de vision ou audio à l’intérieur de sa boucle de rendu.
Pourquoi l’encodeur de calcul est-il unifié maintenant ?
La documentation d’Apple combine MTLBlitCommandEncoder, MTLComputeCommandEncoder et MTLAccelerationStructureCommandEncoder en MTL4ComputeCommandEncoder.1 La justification est opérationnelle plutôt qu’uniquement de performance : un type d’encodeur unique pour le calcul, le blit et le travail de structure d’accélération simplifie la gestion du pipeline et réduit le brassage des encodeurs dans les applications qui entrelacent les trois.
Les options d’action de stockage sont-elles toujours disponibles dans Metal 4 ?
Pas pour MTL4RenderCommandEncoder. La documentation d’Apple note : « Les options d’action de stockage (voir MTLStoreActionOptions) ne sont pas disponibles parce qu’elles ne s’appliquent pas aux GPUs Apple silicon. »1 La décision architecturale reflète la cible exclusivement GPU d’Apple pour la API centrale de Metal 4.
Dois-je utiliser les tables d’arguments ?
Dans Metal 4, oui. Les protocoles d’encodeur n’exposent pas de méthodes de liaison par ressource. Vous configurez les liaisons de ressources sur une MTL4ArgumentTable et assignez cette table à une ou plusieurs étapes d’encodeur.1 Le bénéfice à l’exécution est que la table n’alloue de la mémoire que pour les liaisons qu’elle utilise réellement, au lieu de tables par étape de taille fixe sur chaque encodeur.
Références
-
Apple Developer, « Understanding the Metal 4 core API ». Comparaison de la hiérarchie des types (
MTL4vsMTL), comportement des command queues et buffers, modèle d’allocateur de commandes, unification des encodeurs, tables d’arguments, suivi des risques, passes de rendu suspension/reprise. Consulté le 2026-05-04. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple Developer, « Machine learning passes ».
MTL4MachineLearningCommandEncoder,MTLTensor, types de tenseurs MSL (tensor_handle,tensor_inline,cooperative_tensor),metal-package-builder, sélection du moteur d’inférence système (GPU/ANE), opérateurs de tenseurs MSL. Consulté le 2026-05-04. ↩↩↩↩↩↩↩↩↩↩↩