Metal 4 essentials: o que a nova API central realmente muda
Metal 4 não é uma reescrita. A Apple lançou ele como uma superfície de API paralela aos tipos originais do Metal, com o prefixo MTL4 nos novos, para que um app possa adotar a nova API central de forma incremental sem reescrever o código de renderização existente.1 O enquadramento importa: o framework Metal em si está há muito tempo no mercado; o que mudou na WWDC25 foi a API central do Metal 4.
Três coisas que a nova API central realmente muda para quem desenvolve apps:
- A codificação de command buffers multi-thread vira um padrão de primeira classe.
- O encoder de compute absorve os encoders de blit e de acceleration-structure em uma superfície unificada.
- Machine learning roda como um tipo de passe de primeira classe ao lado de render e compute, executando modelos Core ML na timeline da GPU sem precisar voltar para a CPU.
As seções abaixo percorrem como cada uma dessas três mudanças se manifesta na prática, os novos tipos que os desenvolvedores vão usar, e as razões que a documentação da Apple dá para o formato que escolheram.
TL;DR
MTL4CommandQueue,MTL4CommandBuffer,MTL4RenderCommandEncoder,MTL4ComputeCommandEncoder,MTL4MachineLearningCommandEncodersão os novos tipos.1 Os tipos originais com prefixoMTLcontinuam existindo. Você adota incrementalmente misturando os dois.- Os command buffers obtêm sua memória de trabalho de um
MTL4CommandAllocatorseparado, o que permite que múltiplas threads codifiquem para múltiplos buffers em paralelo. Uma única chamadacommit:count:envia o lote para a fila.1 MTL4ComputeCommandEncodersubstitui três encoders anteriores:MTLBlitCommandEncoder,MTLComputeCommandEncodereMTLAccelerationStructureCommandEncoder.1 Um encoder, três funções.MTL4MachineLearningCommandEncoderroda modelos Core ML dentro de um command buffer do Metal.2 O sistema escolhe a GPU ou o Apple Neural Engine para cada modelo. Tensors carregam entradas e saídas; o mesmo command buffer mistura inferência de ML com trabalho de render e compute.- O binding de recursos passa para argument tables (
MTL4ArgumentTable) em vez de métodos de bind por encoder. Todos os recursos são untracked; você sincroniza com barreiras explícitas.1
Por que uma superfície de API paralela
O enquadramento da Apple para a escolha de tipos paralelos, citado literalmente da documentação: “O Metal 4 introduz vários tipos com o prefixo MTL4 que são completamente independentes dos tipos MTL originais que substituem, como MTL4CommandQueue versus MTLCommandQueue. Outros tipos são comuns a todas as versões do Metal.”1
A verificação em runtime é simples: o app detecta se o sistema suporta Metal 4, cria um MTL4CommandQueue se sim, e cai de volta para MTLCommandQueue caso contrário. O tipo de fila que o app cria determina qual família de tipos o resto do código de renderização usa.1
A outra metade do design permite que as duas famílias interoperem. MTLEvent e MTLSharedEvent sincronizam tanto instâncias de MTLCommandQueue quanto de MTL4CommandQueue.1 Um app que ainda mantém uma base substancial de código Metal 1 pode trocar um único subsistema para Metal 4 sem quebrar os padrões de sincronização dos quais o resto do app depende.
Isso responde a uma pergunta que os desenvolvedores de apps estão fazendo desde a WWDC25: preciso reescrever meu código Metal? Não. O formato da API incentiva a adoção incremental por subsistema.
Codificação de command buffers multi-thread
A melhoria de runtime que mais chama atenção: a memória do command buffer vem de um tipo complementar, MTL4CommandAllocator, e não da fila. Cada thread pode codificar trabalho em seu próprio command buffer usando seu próprio allocator, e a fila confirma os buffers em lote.
Formato da API da 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)
Duas mudanças operacionais em relação à API original:
Os command buffers são reutilizáveis. Documentação da Apple: “Você pode reutilizar e reaproveitar cada command buffer indefinidamente começando do zero, codificando novos comandos e confirmando ele de novo, em vez de alocar um novo buffer.”1 O Metal anterior exigia um buffer transitório novo para cada commit.
Sem retenção automática de recursos. “Cada instância de MTL4CommandBuffer não cria referências fortes para recursos.”1 O comportamento é parecido com makeCommandBufferWithUnretainedReferences() da API antiga. Os apps precisam gerenciar o tempo de vida dos recursos explicitamente para que eles continuem vivos até a GPU terminar o trabalho.
O padrão de frame allocator que a Apple usa em seu código de exemplo emprega um allocator por frame em voo (a amostra usa três) e rotaciona entre eles conforme os frames avançam pelo ciclo de codificação → renderização → exibição.1 Chamar reset() no allocator no início de cada frame devolve sua memória ao pool para reutilização.
O encoder de compute unificado
MTL4ComputeCommandEncoder é “um novo tipo que combina a funcionalidade de seus três predecessores: MTLBlitCommandEncoder, MTLComputeCommandEncoder, MTLAccelerationStructureCommandEncoder.”1
A API anterior exigia que os apps trocassem de tipo de encoder conforme o formato do trabalho: blit para cópias de recursos e transferências de textura, compute para dispatches de kernel, acceleration-structure para gerenciamento de cena de ray tracing. O Metal 4 colapsa essas três em uma única superfície. Um app que codifica um frame que constrói uma estrutura de aceleração, dispara um kernel de denoising e copia uma textura para um buffer de apresentação agora pode fazer as três coisas com um único tipo de encoder.
O encoder de render também ganhou uma mudança de comportamento. MTL4RenderCommandEncoder suporta codificar um render pass entre command buffers ao suspender o trabalho no fim de um render encoder e retomá-lo após o início do próximo na sequência.1 Enquadramento da Apple: “Esta técnica conceitualmente substitui o protocolo MTLParallelRenderCommandEncoder e simplifica a codificação de um render pass em paralelo com múltiplas threads, porque cada thread pode ter seu próprio render encoder em vez de amarrar todas elas a um único render encoder.”1
O padrão se mantém: a codificação paralela vira o formato natural, e a API deixa de exigir um único tipo coordenador.
Argument tables substituem o binding de recursos por encoder
A API original do encoder Metal expunha métodos como setVertexBuffer(_:offset:index:) e setFragmentTexture(_:index:) em cada encoder, com tabelas de binding separadas por estágio internas ao encoder.1 O Metal 4 substitui esse padrão por uma instância explícita de MTL4ArgumentTable.
Enquadramento da Apple sobre o ganho do design: “Os encoders do Metal 4 não exigem memória para armazenar as tabelas de binding para todo tipo de recurso, em todo estágio. Cada tabela consome apenas a memória necessária para armazenar seus bindings de recursos.”1
O fluxo: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])
Uma única argument table pode servir múltiplos encoders, incluindo encoders em diferentes command buffers, desde que os recursos que ela vincula sejam apropriados para todos eles. A documentação da Apple observa: “A economia de memória e runtime se acumula com cada recurso comum que seus encoders compartilham, e cada vez que você atribui a argument table a um novo encoder.”1
Há um trade-off. Versões anteriores do Metal suportavam hazard tracking para texturas e heaps que optavam por isso via MTLTextureDescriptor.hazardTrackingMode ou MTLHeapDescriptor.hazardTrackingMode.1 No Metal 4, “o framework considera todos os recursos como untracked. Você precisa sincronizar estágios de pipeline que podem acessar concorrentemente um recurso se algum dos shaders nesses pipelines o modificar.”1 Os apps adicionam barreiras explícitas para atrasar um estágio até um anterior terminar. Isso é mais código do que o tracking opt-in mais antigo, em troca de performance previsível e menor overhead em runtime.
Machine learning como um passe de primeira classe
MTL4MachineLearningCommandEncoder é a adição mais significativa do ponto de vista arquitetural. Enquadramento da Apple:2
“O Metal 4 introduz a capacidade de rodar modelos CoreML de forma eficiente dentro do workflow do Metal. Isso é útil para apps que precisam aplicar a saída de um modelo em um contexto Metal, como renderizar uma cena ou rodar um dispatch de compute.”
Duas coisas estão acontecendo ao mesmo tempo. Primeiro, a inferência de ML roda na timeline da GPU, no mesmo command buffer que o trabalho de render e compute. O app não faz a viagem de ida e volta pela CPU entre a inferência do modelo e o render pass que consome a saída. Segundo, o sistema escolhe o motor de inferência: “O sistema escolhe automaticamente um motor de inferência, como a GPU ou o Apple Neural Engine (ANE) do dispositivo, para cada modelo de machine learning. A GPU pode rodar trabalho adicional e independente de render ou compute na GPU quando o sistema escolhe rodar um modelo na ANE.”2
O fluxo de desenvolvimento:2
- Converta um modelo Core ML em um Metal ML package usando
metal-package-builder, incluído nas ferramentas que vêm com o Xcode 26. - Adicione o Metal ML package ao projeto Xcode. O Xcode compila ele em uma biblioteca Metal no momento do build.
- Em runtime, o app cria um
MTL4MachineLearningPipelineStatea partir dessa biblioteca. - O encoder recebe o pipeline state, um
MTLHeappara memória de scratch e instâncias deMTLTensorpara entradas e saídas.
MTLTensor é um novo tipo de recurso para arrays de dados multidimensionais.2 A documentação da Apple observa que o tipo funciona com tipos comuns de pesos de ML, como int8 e fp16. Os tensors carregam as entradas para o modelo e as saídas dele; para dados transitórios entre invocações de inferência, a Metal Shading Language adiciona tipos de tensor que vivem direto na GPU:2
tensor_handle: um handle para umMTLTensorcriado na CPUtensor_inline: um tensor definido na GPU como uma view para um tensor ou buffercooperative_tensor: um tensor que distribui seus elementos entre as threads que trabalham com ele
O tipo cooperative_tensor é o caso sensível à latência: “Cooperative tensors fornecem memória temporária para tensors transitórios distribuindo igualmente seus dados entre as threads que trabalham com aquele tensor. Essa distribuição de memória reduz a largura de banda de memória ao alocar a memória dos espaços de endereçamento privados de thread ou de threadgroup, o que é importante para algoritmos de machine learning críticos em latência.”2
A MSL também ganhou operadores de tensor que funcionam direto no código de shader: convolução, multiplicação de matrizes, redução.2 Apps que precisam manipular pesos entre passes de inferência podem fazer isso sem copiar tensors de volta para a memória da CPU ou rodar um passe de compute separado; os operadores se encaixam em kernels normais de MSL.
Há um limite que vale citar: “Os encoders de machine learning rodam modelos Core ML, mas eles não podem construir novas redes ou modificar camadas e entradas de redes existentes; para essas tarefas, veja Core ML e Metal Performance Shaders Graph.”2 O encoder de ML do Metal 4 é para entregar inferência em produção, não para treinamento ou construção de modelo.
O que o Metal 4 significa para o stack da Apple
Três pontos para os desenvolvedores de apps que estão planejando a adoção do Metal 4:
- Adote incrementalmente, por subsistema. Os tipos paralelos com prefixo
MTL4e a interoperabilidade baseada em eventos com a API original foram desenhados para migração parcial. Escolha um subsistema com pressão de performance clara (um caminho de render, um pipeline de compute, um loop de inferência de modelo) e migre ele primeiro.1 - Codificação multi-thread é o novo normal. O padrão de allocator por thread, o envio em lote
commit:count:e o mecanismo de suspender/retomar render pass assumem todos a codificação paralela como o formato que os apps performáticos vão usar. A codificação single-thread ainda funciona, mas os ganhos em runtime do framework se acumulam com a adoção multi-thread.1 - ML roda no mesmo command buffer que tudo o mais. Para apps que combinam inferência de modelo on-device com renderização ou compute (pipelines de processamento de imagem que filtram através de um modelo Core ML, efeitos em tempo real que dependem da saída de um classificador, experiências de AR cuja renderização depende de um resultado de inferência por frame), a capacidade de codificar inferência de ML no mesmo command buffer que o render pass que a consome é a mudança qualitativa.2
As adições à Metal Shading Language merecem tratamento próprio. Tipos e operadores de tensor em código de shader, mais descritores de operação para operações customizadas, mudam o que um kernel Metal pode expressar. Esse é um post separado.
O cluster completo do ecossistema Apple: o LLM on-device do Foundation Models para o framework que roda em cima desse stack; o ciclo de vida de adapter customizado para especialização gerenciada pelo desenvolvedor; inferência on-device com Core ML para o framework de ML cujos modelos o Metal 4 agora roda inline. O hub está na Apple Ecosystem Series.
FAQ
O Metal 4 é um framework separado do Metal?
Não. O framework continua sendo o Metal. A documentação da Apple descreve o Metal 4 como “a API central do Metal 4”: um conjunto de novos tipos com o prefixo MTL4 que vêm ao lado dos tipos MTL originais no mesmo framework.1 Os apps adotam os novos tipos incrementalmente detectando o suporte ao Metal 4 em runtime e criando o tipo de fila apropriado.
Preciso de iOS 26 para usar o Metal 4?
O framework Metal suporta iOS 8+, mas a API central do Metal 4 é a versão que a Apple introduziu na WWDC25. Faça uma detecção em runtime e crie um MTL4CommandQueue ou um MTLCommandQueue com base no que o dispositivo suporta.1
Qual é a relação entre os passes de ML do Metal 4 e o Foundation Models?
Eles rodam em stacks diferentes. MTL4MachineLearningCommandEncoder roda modelos Core ML convertidos em Metal ML packages, no mesmo command buffer que o trabalho de render e compute.2 Foundation Models é um framework separado que roda o modelo de linguagem on-device do sistema da Apple com sua própria API de sessão, coberto no post sobre o LLM on-device do Foundation Models. Os dois são complementares: um app pode usar Foundation Models para geração de texto e os passes de ML do Metal 4 para inferência de modelo de visão ou áudio dentro do seu loop de renderização.
Por que o encoder de compute agora é unificado?
A documentação da Apple combina MTLBlitCommandEncoder, MTLComputeCommandEncoder e MTLAccelerationStructureCommandEncoder em MTL4ComputeCommandEncoder.1 A justificativa é operacional, não apenas de performance: um único tipo de encoder para trabalho de compute, blit e acceleration-structure simplifica o gerenciamento de pipeline e reduz a rotatividade de encoders em apps que intercalam os três.
As opções de store-action ainda estão disponíveis no Metal 4?
Não para MTL4RenderCommandEncoder. A documentação da Apple observa: “As opções de store-action (veja MTLStoreActionOptions) não estão disponíveis porque não se aplicam às GPUs do Apple silicon.”1 A decisão arquitetural reflete o foco da Apple em GPU apenas como alvo da API central do Metal 4.
Tenho que usar argument tables?
No Metal 4, sim. Os protocolos do encoder não expõem métodos de bind por recurso. Você configura os bindings de recurso em uma MTL4ArgumentTable e atribui essa tabela a um ou mais estágios do encoder.1 O ganho em runtime é que a tabela só aloca memória para os bindings que ela realmente usa, em vez de tabelas de tamanho fixo por estágio em cada encoder.
Referências
-
Apple Developer, “Understanding the Metal 4 core API”. Comparação da hierarquia de tipos (
MTL4vsMTL), comportamento de command queue e buffer, padrão do command allocator, unificação de encoders, argument tables, hazard tracking, render passes com suspender/retomar. Acessado em 2026-05-04. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple Developer, “Machine learning passes”.
MTL4MachineLearningCommandEncoder,MTLTensor, tipos de tensor da MSL (tensor_handle,tensor_inline,cooperative_tensor),metal-package-builder, seleção do motor de inferência pelo sistema (GPU/ANE), operadores de tensor da MSL. Acessado em 2026-05-04. ↩↩↩↩↩↩↩↩↩↩↩