View in English

  • Global Nav Open Menu Global Nav Close Menu
  • Apple Developer
Search
Cancel
  • Apple Developer
  • News
  • Discover
  • Design
  • Develop
  • Distribute
  • Support
  • Account
Only search within “”

Quick Links

5 Quick Links

Videos

Abrir menú Cerrar menú
  • Colecciones
  • Temas
  • Todos los videos
  • Información

Volver a WWDC25

  • Información
  • Resumen
  • Transcripción
  • Código
  • Explorar juegos de Metal 4

    Aprende a optimizar tu motor de juegos con los últimos avances de Metal 4. Hablaremos de cómo unificar la codificación de comandos para minimizar la sobrecarga de la CPU, ampliar la gestión de recursos gráficos para admitir escenas masivas y maximizar el presupuesto de memoria, y cargar rápidamente grandes bibliotecas de estados de canales. Para aprovechar al máximo esta sesión, primero mira “Descubrir Metal 4”.

    Capítulos

    • 0:00 - Introducción
    • 1:33 - Codificar de forma más eficiente
    • 8:42 - Escalar la gestión de recursos
    • 17:24 - Cargar canales rápidamente
    • 31:25 - Resumen

    Recursos

    • Human Interface Guidelines: Designing for games
    • Metal binary archives
    • Reading and writing to sparse textures
    • Resource synchronization
    • Synchronizing resource accesses between multiple passes with a fence
    • Synchronizing resource accesses with earlier passes with a consumer-based queue barrier
    • Synchronizing resource accesses with subsequent passes with a producer-based queue barrier
    • Synchronizing resource accesses within a single pass with an intrapass barrier
    • Understanding the Metal 4 core API
    • Using a render pipeline to render primitives
    • Using the Metal 4 compilation API
      • Video HD
      • Video SD

    Videos relacionados

    WWDC25

    • Combina el aprendizaje automático y los gráficos de Metal 4
    • Descubrir Metal 4
    • Novedades del renderizado de Metal para apps inmersivas
    • Sube de nivel tus juegos
    • Ve más allá con los juegos de Metal 4

    Tech Talks

    • Tune CPU job scheduling for Apple silicon games
  • Buscar este video…

    Hola, soy Jason. Y yo Yang. Somos ingenieros de controladores de GPU. En este video, presentaremos cómo puedes acelerar tu motor de juego con Metal 4. Esta es la segunda de nuestra serie de cuatro partes para presentar la próxima versión de la API Metal. Antes de explorar los juegos de Metal 4, ve "Descubrir Metal 4" para más información sobre lo que Metal 4 puede ofrecer. Al terminar la sesión, conoce las nuevas e increíbles API Metal FX y Metal Raytracing en "Ve más allá con los juegos de Metal 4". Ve "Aprendizaje automático de Metal 4", una charla dedicada a la integración de ML. Exploremos Metal 4.

    Metal 4 está diseñado para el motor de juego moderno. Juegos como Assassin's Creed Shadows de Ubisoft dibujan personajes y paisajes superdetallados para sumergirnos en mundos de fantasía. Transmiten gigabytes de geometría y texturas detalladas, renderizadas con miles de sombreadores para aprovechar la potencia informática disponible con Apple Chip. Los juegos del futuro serán aún más exigentes y necesitarán una API de gráficos que esté a la altura. Ese es Metal 4.

    Metal 4 contiene algunos avances importantes en Metal para juegos. Como una codificación de comandos eficiente, una gestión de recursos escalada para acelerar tu ruta activa, una carga de procesos más rápida para pasar de las pantallas de carga a los juegos y más. Hoy, profundizaremos sobre cómo usar mejor estas funcionalidades. En cada cuadro, las llamadas de dibujo, envíos de kernel, blits y trabajo de trazado de rayos están en la ruta activa de codificación. La codificación Metal 4 está diseñada para afrontar esto con eficiencia y concurrencia.

    Metal 4 unifica las operaciones más comunes en dos clases de codificadores para hacer más con cada codificador. Un asignador de comando permite administrar explícitamente las asignaciones de memoria de la codificación. Un búfer de comandos permite codificar el trabajo en subprocesos.

    En "Discover Metal 4" se describió cómo dos clases de codificador, render y compute, manejan la codificación de comandos. Para un uso eficiente, sincroniza las dependencias de datos entre las operaciones y usa mapas adjuntos con el fin de reasignar las salidas del sombreador de fragmentos. Las operaciones, envíos de kernel, blits y compilaciones de estructuras de aceleración ya se pueden codificar en un único codificador. Sin sincronización adicional, estos comandos se ejecutan simultáneamente. Esto permite que las cargas de trabajo sin dependencias usen mejor los recursos de la GPU. Si hay comandos que necesitan ejecutarse en serie debido a una dependencia de datos, exprésalo usando una barrera de pase. Esta garantiza que la GPU espere hasta que los blits anteriores se completen para iniciar los envíos de cómputo posteriores. Este ejemplo muestra cómo sincronizar el acceso de un blit a un envío. Primero, el blit copyFromBuffer actualiza buffer1, codificando una barrera. Luego puedes codificar un envío que use los datos en el buffer1. Esto es codificación computacional unificada. Haz tu trabajo en un codificador y usa barreras para expresar dependencias de datos, Metal 4 también actualizó la codificación de renderizado. Controla la relación entre las salidas de color de una renderización y los archivos adjuntos del codificador con la asignación de archivos adjuntos de color. Proporciona estas asignaciones en lugar de vincular procesos a un diseño de destino de renderizado fijo. Luego, cuando configures una nuevo proceso, podrás cambiar la asignación y no los codificadores. Imagina que tienes un proceso de Metal con una función de fragmento que dibuja tres archivos adjuntos. Sin la asignación, crearías un codificador de renderizado con tres archivos adjuntos de color. La función de fragmento arroja tres salidas de color y el codificador dirige esas salidas a los archivos adjuntos correspondientes en la memoria. En la próxima llamada de dibujo, necesitarás un proceso que escriba a un conjunto diferente de salidas. Ya que los archivos son diferentes, necesitarás crear un nuevo codificador de renderizado que coincida con las salidas. Con la asignación de archivos de color, no necesitas un segundo codificador. El codificador de renderizado tiene los archivos de color que necesitan ambos procesos. Luego, el mapa de archivos de color traduce la salida de sombreado a archivos específicos. Para implementarla, configura un descriptor de pase de renderizado que admita la asignación de archivos adjuntos de color. Luego, crea el superconjunto de archivos adjuntos que usará el codificador. Para configurar el archivo que usará el codificador, crea un mapa de archivos de color y establece las entradas de reasignación. En cada entrada, establece un índice lógico que determine la salida del sombreador y un índice físico para el índice de archivos. Crea estos objetos de asignación antes de codificar y reúsalos en cada cuadro. Al configurar un proceso de renderizado, vincula un mapa de archivos de color. Si un proceso dibuja diferentes archivos, puedes cambiar a un mapa de archivos de color diferente. La asignación de archivos de color podría reducir los codificadores de renderizado en tu juego. Esto disminuirá la carga de codificación y mejorará la eficiencia de la GPU al minimizar los pases de renderizado.

    Metal 4 también te da más control sobre las asignaciones de memoria.

    Los asignadores de comandos permiten reusar la memoria del búfer y evitar asignaciones dinámicas en la codificación. La memoria del asignador crece junto con los comandos codificados. Restablece los asignadores cuando los comandos de GPU se hayan ejecutado. Esto permite que la memoria de comando se pueda usar de nuevo en la codificación posterior. Usa varios asignadores para evitar bloquear la codificación al completar el trabajo de la GPU. Cuando codifiques un nuevo asignador de comandos, se repartirá memoria entre los comandos codificados. Esta memoria es el trabajo que se ejecuta en la GPU. Espera a que se complete el trabajo antes de reiniciar. Una vez completado, restablece el asignador de comandos. Esto hace espacio en la memoria para su reutilización. Para continuar codificando mientras se ejecuta la GPU, usa un segundo asignador de comandos. Esto evita el bloqueo de la codificación al finalizar el trabajo de la GPU. Es importante restablecer un asignador de comandos al finalizar el trabajo en la GPU. La memoria del asignador crecerá hasta que se restablezca. Si no planeas codificar más trabajo en un asignador de comandos, libéralo para reducir el consumo de memoria. Usar asignadores diferentes para subprocesos diferentes, ya que no son seguros para subprocesos. Hazlo a medida que paraleles la codificación de tu escena. Los búferes de comando de Metal 4 dividen la codificación en varios subprocesos. En la codificación de un subproceso, codificarías una serie de comandos en uno o más búferes de comandos en secuencia. Aprovecha la avanzada CPU multinúcleo de Apple Chip e inicia múltiples búferes de comandos en varios subprocesos, cada uno con un asignador diferente. Usa la flexibilidad mejorada del codificador de Metal 4 para distribuir de manera uniforme la codificación de blits, envíos y trabajo de estructura de aceleración. Cuando hayas terminado de codificar tus búferes de comandos, envíalos con una única llamada de confirmación. Metal 4 también permite ejecutar varios codificadores de renderizado como un solo pase en la GPU. Supongamos que tienes un pase de renderizado que tarda en codificarse. Por defecto, si divides la codificación entre codificadores de renderizado separados, la GPU los ejecuta como pases separados. Cada pase supone una sobrecarga para almacenar y cargar resultados intermedios.

    Metal 4 ofrece la opción Suspender/Reanudar para fusionar varios codificadores. Solo suspende un codificador de renderizado en un búfer de comandos y reanúdalo en otro. Una vez que termines de codificar los búferes, envíalos secuencialmente en una sola llamada de confirmación. Al enviar los codificadores de renderizado en una sola confirmación, Metal fusiona los pases. Para implementarlo, crea el primer codificador con opciones de suspensión. Metal fusionará este codificador con otros futuros. Usa un búfer de comandos diferente para cada codificador. El codificador central tiene opciones de reanudación y suspensión. Crea el codificador final solo con opciones de reanudación. Confirma los tres búferes de comandos codificados juntos. ¡Eso es todo! Tus pases de renderizado están fusionados. Puedes usar Metal 4 para mejorar la eficiencia de la codificación al reducir los codificadores, reusar tu memoria de comandos y codificar en varios subprocesos. Conoce más sobre la codificación de comandos de Metal 4 en el artículo del sitio Apple Developer. Ya que hablamos de la codificación eficiente, profundicemos en la gestión eficiente de recursos. Metal 4 tiene funcionalidades nuevas e interesantes para administrar recursos a escala. Las tablas de argumentos y los conjuntos de residencia permiten escalar la vinculación de recursos. Metal 4 nos ayuda a administrar los recursos dibujables y nos da control sobre las dependencias. Las barreras de fila ofrecen una forma de expresar las dependencias de recursos a escala. Los grupos de vistas de texturas y pilas dispersas de ubicación ayudan a gestionar la memoria de recursos grandes. Aumentar la complejidad de los sombreadores significa que un modelo sin enlaces sería el más apropiado. Con un único búfer de argumento, tu sombreador puede acceder recursos como búferes, texturas, muestreadores, estados de procesos y más. Pero los puntos de enlace indexados aún se usan para vincular recursos de raíz.

    Vincula recursos por índice con tablas de argumentos. Establece la tabla de argumentos que se usará en el próximo dibujo o envío cuando codifiques. Estos recursos están disponibles como argumentos de funciones indexadas. A la hora de dibujar y enviar, Metal compila los argumentos. Así que es seguro establecer un recurso en un índice de enlace entre llamadas de dibujo. Configura una tabla de argumentos en muchas etapas del codificador.

    Crear estas antes de la codificación permite mover la vinculación de recursos fuera de tu ruta crítica. Puedes adjuntar una tabla de argumentos a varios codificadores. Usa tablas junto con búferes de argumentos para escalar tus necesidades de vinculación. Lo siguiente para acceder a estos recursos en tus sombreadores es mostrarlos en la GPU. Agrega un recurso a un conjunto de residencia para verlo en la GPU. Esto incluye procesos, búferes, texturas y elementos dibujables. Los conjuntos de residencia permiten agrupar recursos y hacerlos visibles al mismo tiempo. Adjúntalos a un búfer de comandos que se está confirmando o a la fila de comandos. Si un conjunto no cambia mucho, es preferible adjuntarlo a la fila de comandos. Si cambia con frecuencia, adjúntalo a los búferes de comando adecuados. Puede llevar tiempo preparar grandes recursos para la GPU. Metal hace que los recursos de un conjunto sean residentes con tiempo. Prefiero tener menos conjuntos con más recursos cada uno. Esto mejora el rendimiento al permitir que Metal procese tus recursos en masa. Para conocer más sobre los conjuntos de residencia, lee el artículo en el sitio Apple Developer, así como la charla "Port advanced games to Apple Platforms". Con Metal 4, tu control sobre la residencia de recursos también se aplica a las superficies dibujables. Para que el contenido renderizado se vea en pantalla, renderízalo en las superficies dibujables en un CAMetalLayer. Cada capa mantiene un conjunto de residencia dinámico. Agrégalo a la fila de comandos para que las texturas en la capa sean residentes. Solo debes agregar el conjunto una vez. CAMetalLayer lo actualizará según sea necesario. En Metal 4, debes sincronizar el renderizado con el elemento dibujable. Con cada cuadro, después de obtener el siguiente elemento dibujable, codifica una espera en la fila de comandos antes de renderizarlo. Después de confirmar el trabajo de renderizado, codifica una señal en este elemento dibujable.

    Llama al contenido para enviarlo de tu marco a la pantalla cuando se complete la renderización. Para reducir la sobrecarga de seguimiento, Metal 4 te permite sincronizar tus recursos. Anteriormente, expliqué cómo usar barreras de pase en codificadores. Las barreras de fila expresan una dependencia de datos entre codificadores en la misma fila.

    Estas se filtran por etapas de Metal. Cada comando de un codificador está asociado con una o más etapas de ejecución. Por ejemplo, las llamadas de dibujo generan etapas de sombreado de vértices y fragmentos. Las GPU de Apple Chip agrupan todo el trabajo de vértices y de sombreado de fragmentos. Los comandos de cálculo corresponden a las etapas de estructura de envío, blit y aceleración. Es importante elegir las etapas apropiadas para evitar la sobresincronización. Aquí, un pase de cómputo realiza una simulación atmosférica en un envío de núcleo. Escribe los resultados en una textura en la memoria. El pase de renderizado dibuja la escena. El sombreado de fragmentos necesita que los resultados de la simulación se combinen con la iluminación, pero el trabajo del vértice debe superponerse con el trabajo de cálculo. Para sincronizar el acceso a los resultados de simulación, codifica una barrera del envío de la fila a la fragmentación del codificador de renderizado. Para implementar este ejemplo, codifica el envío en un codificador de cómputo. Luego, en un codificador de comando de renderizado, agrega una barrera después del envío de la etapa de fila y antes de etapa la de fragmentación. Después de la barrera, puedes codificar llamadas de dibujo. Metal garantiza que los trabajos de la etapa de fragmentación, en el codificador de renderizado actual y futuros, no se ejecuten hasta completar el trabajo de la etapa de envío.

    Para ayudarte a encontrar el mejor lugar para tus barreras, el depurador de Metal te mostrará ubicaciones, codificadores y etapas a las que se aplican. Úsalo para maximizar la simultaneidad y mantener tus dependencias de datos.

    Para conocer más sobre la sincronización de recursos mediante barreras de Metal, lee los artículos completos en el sitio Apple Developer.

    La transmisión de texturas y búfer permite gestionar el consumo de memoria de miles de recursos. Metal 4 permite transmitir búferes y texturas eficientemente. Puedes crear vistas de texturas livianas y gestionar el uso de memoria de tus recursos con Placement Sparse. Los juegos modernos crean cientos de vistas de texturas y búferes de texturas por cuadro. TextureViewPools permite preasignar la memoria necesaria para contener todas tus vistas de textura. Luego puedes crear vistas de texturas livianas en cualquier índice del grupo. Esto no implica ninguna asignación dinámica, así que puedes crearlas mientras codificas. Usa el ID de la vista de textura para vincularla a un búfer de argumentos o una tabla de argumentos. Así es cómo puedes implementarlo. Crea un grupo de vistas de texturas antes de codificar. En este caso, el grupo de vistas de textura tiene memoria para 500 vistas de textura. Al codificar, configura una vista de textura en el índice deseado. Usa MTLResourceID para vincular tu vista de textura a una tabla de argumentos. A veces, los recursos que necesitas vincular ocupan una gran cantidad de memoria. Los recursos dispersos son ideales para recursos de alta fidelidad que quizás no quepan en la memoria. Desvinculan la creación de recursos de tu respaldo de memoria. Con la ubicación dispersa, puedes controlar cómo se asignan tus recursos a las páginas de tu pila. Al actualizar las asignaciones de memoria, las API en la fila de comandos de Metal 4 permiten sincronizar estas actualizaciones con otro trabajo de la GPU. La memoria en una pila de ubicación se organiza por pestañas. Tú controlas la asignación de estas pestañas a tus búferes y texturas dispersas. Asigna rangos de bytes o regiones de pixeles a pestañas dispersas otorgando recursos con memoria.

    Al crear una pila de ubicación, considera los tamaños de página dispersos que necesitarán tus recursos. Los tamaños más grandes tienen beneficios de rendimiento durante el mapeo y la desasignación, pero usarán más memoria en el relleno y la alineación. La pila admitirá todos los tamaños hasta el máximo que especifiques. Este ejemplo elige un tamaño de página máximo de 64 kilobyte. Una vez crees una pila de ubicación, puedes crear los recursos dispersos. Las texturas y búferes de ubicación dispersos se crean desde un dispositivo Metal, al igual que los recursos no dispersos. Para los búferes, alinea su tamaño con múltiplos de un tamaño de pestaña disperso. El dispositivo brinda una consulta para realizar esta conversión. Establece el tamaño al convocar un nuevo búfer con longitud o en un descriptor de textura. Esta propiedad informa al dispositivo Metal que una pila de ubicación dará el respaldo de memoria. Al crear por primera vez un búfer disperso de ubicación, no tiene memoria de respaldo. Asigna pestañas a rangos de búfer con operaciones de mapeo de actualización. Para asignarlas de una pila de ubicación a un búfer, especifica una operación de mapeo de actualización. Proporciona el desplazamiento inicial, la longitud y el desplazamiento en la pila donde se asignará este rango de búfer. Luego envía la operación de mapeo en una fila de comandos de Metal 4.

    Para saber más sobre cómo trabajar con recursos dispersos, consulta el artículo en el sitio Apple Developer. Otro reto para los juegos modernos es gestionar grandes bibliotecas de estados de proceso. Para eso, le cederé la palabra a Yang. Gracias, Jason. Los juegos modernos necesitan crear miles de procesos para crear imágenes complejas y dinámicas. Cargar rápido varios procesos es crucial para eliminar las intermitencias en la finalización del sombreador y reducir el tiempo de carga. Para hacer esto en Metal 4, puedes reusar tus compilaciones de procesos de renderizado. También puedes compilar procesos con un nuevo nivel de paralelismo. Para ir más allá, compilar procesos con anticipación permite reducir el tiempo de carga casi a cero. Comenzaré mostrando cómo reusar compilaciones de procesos de renderizado con estados flexibles. Digamos que estás creando un juego de construcción de ciudades donde se pueden colocar casas en el mapa. Cuando alguien decide dónde colocar una casa, el juego debe representarla en estilo holograma, así que necesita un proceso con un estado de mezcla aditiva. El jugador coloca la casa y la casa comienza a construirse. Para renderizar la casa con transparencia, y mostrar el progreso de la construcción, necesitas otro proceso con un estado de mezcla transparente. Finalmente, cuando la casa termine de construirse, se renderizará mediante un tercer proceso con un estado de mezcla opaca. Puedes compilar estos tres procesos con un estado completo haciendo las configuraciones completas del proceso. Inicia con una función de vértice y la de fragmento, y las configuraciones de color para las casas opacas, transparentes y holográficas. En este caso, la configuración de color significa una parte del descriptor que afecta la escritura de las salidas del sombreador de fragmentos en los archivos de color. Esto incluye el formato de pixeles, las máscaras correctas y los estados de fusión. Crea un descriptor del proceso de renderizado que acuda a la función de vértice, de fragmento y la configuración opaca. Con ese descriptor, crea el proceso opaco que contiene un binario de vértice, un cuerpo binario de fragmento y una parte de salida de fragmento. Al intercambiar la configuración de archivos adjuntos de color en el descriptor, puedes crear procesos transparentes y de holograma similares. La mayoría de los binarios en estos tres procesos son los mismos, solo la salida del fragmento es diferente. Desde una vista de la línea de tiempo de la CPU, puedes compilar el proceso opaco completo, transparente y de holograma. La CPU invierte mucho tiempo recompilando el mismo flujo de trabajo, excepto la salida del fragmento. Con Metal 4, ahora puedes reusar la mayoría de la finalización del proceso creando primero uno no especializado. Luego usa diferentes configuraciones de color para obtener los procesos especializados finales necesarios. Esto te ahorrará tiempo de finalización del proceso de renderizado. Para ahorrar, primero hay que crear un proceso no especializado. Comienza con el mismo descriptor y configura todos los campos como no especializados en lugar de hacer la configuración de color. Para lograrlo, solo configura pixelFormat, writeMask y blendingState en los valores no especializados correspondientes a cada descriptor de archivo de color. El proceso no especializado contiene un binario de vértice, el cuerpo del fragmento binario y la salida del fragmento por defecto. Esta salida funciona en algunos casos, pero la mayoría de las veces será necesario reemplazarla especializando el proceso. Para crear el proceso especializado, inicia por uno no especializado y un nuevo descriptor de proceso de renderizado. Esta vez, establece la configuración de archivos de color en el descriptor con los valores que necesitas. El proceso especializado tiene una salida de fragmento que reemplaza la salida de fragmento por defecto. Esta nueva salida se puede generar rápidamente, por lo que no necesitas volver a hacer todo el proceso de compilación del sombreador. Volveré al ejemplo de la especialización del proceso transparente. Empieza estableciendo las propiedades no especializadas anteriores en el descriptor. Habilita el estado de fusión y establece subestados de fusión. El código aquí configura el proceso para realizar una combinación alfa premultiplicada. Luego, crea una instancia del proceso especializado usando el nuevo descriptor con el proceso no especializado. Seguramente tu juego esté creando miles de procesos de renderizado con control de estado. Para maximizar la reducción del tiempo de carga, crea todos tus procesos no especializados y especialízalos cuando sea necesario. Después de hacerlo, tal vez notes una pequeña sobrecarga en el rendimiento de la GPU. Gran parte de esta puede provenir de trabajo innecesario en el cuerpo del fragmento compartido. Por ejemplo, si un sombreador de fragmentos escribe en cuatro canales de color y el archivo de color solo tiene un canal, el compilador ya no puede optimizar los canales sin usar. También hay una pequeña sobrecarga por saltar del cuerpo binario del fragmento a la parte de salida del fragmento. Esta suele ser pequeña, pero puede ser grande en algunos sombreadores de fragmentos. Identifícalos y compílalos con el estado completo en segundo plano para que el reproductor tenga tiempos de carga cortos y una gran velocidad de imagen. Puedes usar Instruments Metal System Trace para clasificar los sombreadores de fragmentos más caros. En resumen, así se incorporan mejor los estados de proceso de renderizado flexibles. Primero, compila cada proceso de renderizado no especializado y especialízalos según sea necesario. Si el rendimiento cae notable, usa Metal System Trace de Instrument para crear un perfil de tu juego e identificar procesos importantes. Para esos procesos, compila una versión básica en segundo plano y úsala para reemplazar una versión especializada cuando esté lista. Conoce más sobre los estados de los procesos de renderizado flexible en este artículo del sitio Apple Developer.

    Después de reusar compilaciones con estados de procesos de renderizado flexibles, acorta aún más el tiempo de carga deteniendo la compilación de tu propio dispositivo. Algunos juegos pueden usar un solo subproceso para cargar procesos al jugar. Aquí está el subproceso de compilación único que construye los procesos que el juego está por usar. Y aquí hay un subproceso de renderizado que ejecuta el renderizado de cuadros repetidos, como la codificación. Si los procesos necesarios no están listos a tiempo, el juego puede trabarse. Puedes acelerar la carga del proceso agregando otro subproceso de compilación. La compilación del proceso finaliza antes. Pero, si no tienes cuidado con la prioridad del subproceso, el juego puede perder sus intervalos actuales. Después de configurar la prioridad del subproceso de finalización en segundo plano a un valor menor, el problema desaparece. Ahora se puede disfrutar de una experiencia más fluida. Ahora te mostramos cómo agregar finalizaciones multiproceso. Usa las API de finalización de Metal 4. El compilador puede llegar incluso más lejos en Metal 4. Puedes usar Grand Central Dispatch o crear tu propio grupo de subprocesos, dependiendo de qué se adapte mejor a tu arquitectura. Independientemente de cuál elijas, recuerda establecer una prioridad adecuada. Metal respetará la prioridad de tus tareas de compilación. Grand Central Dispatch es la forma más sencilla de emitir tus compilaciones multiproceso. Si deseas que la compilación herede la prioridad del subproceso que convoca, usa grupos de envío con los métodos asíncronos del compilador. Estos son aquellos que tienen un controlador de finalización. Metal ejecutará automáticamente estos métodos simultáneamente. Si deseas personalizar la prioridad de tu compilación, puedes crear una fila de envío simultáneo con una calidad de servicio (QoS) personalizada. Para el precalentamiento y la transmisión del proceso, vuélvelo tu valor por defecto. Para enviar pruebas de finalización a una fila de envío, invoca métodos de sincronización en bloque y envíalos a la fila con dispatch_async. Estos métodos no tienen un controlador de finalización.

    También puedes crear tu propio grupo de subprocesos si esto se adapta mejor a tu arquitectura. Usa una propiedad maximumConcurrentCompletionTestCount en Metal Device como el número de subprocesos para un grupo. Establece el número por defecto de subprocesos en 2, ya que este es el máximo en los SO que no admiten esta propiedad. También es importante establecer una QoS adecuada para los subprocesos de compilación y evitar así dejar sin recursos a otros subprocesos importantes. Establece la QoS por defecto para el precalentamiento y la transmisión de procesos. Eso es todo. Ya puedes enviar tareas de compilación a tu grupo de subprocesos. Para conocer más sobre la mejor forma de paralizar y priorizar la compilación de tu proceso, ve estos artículos en el sitio Apple Developer. La compilación multiproceso en el dispositivo puede reducir el tiempo de compilación. Para reducirlo casi a cero, lo mejor es precompilar los procesos durante su desarrollo. Para compilar procesos con anticipación, los juegos por lo general usan un flujo de trabajo de extremo a extremo. El flujo de trabajo comienza recopilando las configuraciones de proceso usadas en el juego al ejecutarlo con cierta instrumentación. Lo obtenido se introduce en la cadena de herramientas de la GPU para crear binarios. Finalmente, el juego busca los binarios de GPU precompilados para crear procesos rápidamente. Metal 4 hace que sea más fácil que nunca recopilar la configuración de procesos en línea y buscar binarios precompilados en tu juego. En Metal 4, la forma más sencilla de recopilar una configuración de procesos es serializar un script. Un script de procesos es un archivo con formato JSON. Contiene una representación textual de los descriptores de procesos que creas en el dispositivo. Serializar un script es fácil con un serializador de conjuntos de datos de procesos en Metal 4. Una vez que vincules este objeto a tu compilador, registrará los descriptores de los procesos creados. Luego, puedes serializar estos descriptores en un script de proceso. Para crear el serializador del conjunto de datos, comienza con un descriptor. Establece la configuración en CaptureDescriptors. Esto le informa al serializador que solo debe rastrear los descriptores y reduce su uso de memoria. Para crear el serializador del conjunto de datos, usa un descriptor. Luego, adjunta un serializador al descriptor del compilador que usas para crear el compilador. Después de crear el compilador, úsalo para crear procesos como de costumbre. El serializador registrará los descriptores de procesos que uses. Al finalizar la recopilación, usa serializeAsPipelinesScriptWithError para serializar los procesos registrados en un script. El valor de retorno es un NSData. Puedes usar tu método favorito para regresarlo a tu sistema de desarrollo. Aquí solo escribimos en un archivo en el disco. Establece el sufijo del archivo en mtl4-json. Este es el esperado por la cadena de la GPU. Una vez que hayas recopilado las configuraciones de procesos, el siguiente paso es crear los binarios. Surte tu script de configuración de procesos y bibliotecas Metal IR a metal-tt. Generará los binarios de la GPU empaquetados en un archivo Metal. Antes de surtir el script de procesos recopilado a metal-tt, abre el script y modifica la ruta a las bibliotecas de Metal IR para que coincida con la de tu sistema de desarrollo. Para conocer más sobre el formato del script de configuración de procesos, abre la página del manual con este comando. Después, ejecuta el comando metal-tt en la pantalla para crear un archivo para iOS. Ahora que precompilas los binarios, tu juego necesita buscarlos durante la ejecución. Metal 4 hace que sea aún más fácil crear procesos a partir de binarios de GPU en un archivo. Solo usa el mismo descriptor que usarías para compilar en el dispositivo con el fin de recuperar los estados de procesos. Por ejemplo, crea un objeto MTL4Archive proporcionando la URL de tu archivo. Luego, consulta el estado del proceso desde el objeto de archivo con un descriptor de procesos.

    La búsqueda en el archivo puede fallar por varios motivos: falta de procesos coincidentes, un SO o una arquitectura de GPU incompatibles. En Metal 4, tendrás que encargarte de estos fallos. El ejemplo aquí recurre a la compilación en el dispositivo, por lo que el juego aún tiene un estado de procesos requerido en el futuro.

    Esta es la línea de tiempo de la CPU de ejemplo con una finalización multiproceso en el dispositivo. Al adoptar una finalización anticipada, el tiempo de carga del proceso se reduce casi a cero. Para saber cómo finalizar el proceso con anticipación, ve estos artículos en el sitio Apple Developer. He aquí un resumen. Metal 4 ofrece excelentes formas de cargar estados de procesos más rápido que nunca. Puedes reusar los resultados de compilación con la especialización de procesos. Puedes acelerar aún más la compilación con subprocesos múltiples. Para lograr tiempos de carga más bajos, adopta una compilación anticipada con un flujo de trabajo de búsqueda y recopilación optimizado. Nos emocionaba mostrarte muchas formas de usar las API de Metal 4 para crear la próxima generación de juegos de alto rendimiento. Descarga el nuevo Xcode para comenzar a optimizar la codificación, la gestión de recursos y la carga de procesos. Hemos incluido proyectos de muestra y artículos detallados para apoyar tu recorrido. Para continuar explorando lo que Metal 4 tiene para ofrecer, ve los otros videos de esta serie. Gracias por tu atención.

    • 0:01 - Synchronize access to a buffer within an encoder

      // Synchronize access to a buffer within an encoder
      
      id<MTL4ComputeCommandEncoder> encoder = [commandBuffer computeCommandEncoder];
      
      [encoder copyFromBuffer:src sourceOffset:0 toBuffer:buffer1 destinationOffset:0 size:64];
      
      [encoder barrierAfterEncoderStages:MTLStageBlit 
                     beforeEncoderStages:MTLStageDispatch
                       visibilityOptions:MTL4VisibilityOptionDevice];
      
      [encoder setComputePipelineState:pso];
      
      [argTable setAddress:buffer1.gpuAddress atIndex:0];
      [encoder setArgumentTable:argTable];
      [encoder dispatchThreads:threadsPerGrid threadsPerThreadgroup:threadsPerThreadgroup];
      
      [encoder endEncoding];code snippet.
    • 4:29 - Configure superset of color attachments

      // Configure superset of color attachments
      
      MTL4RenderPassDescriptor *desc = [MTLRenderPassDescriptor renderPassDescriptor];
      
      desc.supportColorAttachmentMapping = YES;
      
      desc.colorAttachments[0].texture = colortex0;
      desc.colorAttachments[1].texture = colortex1;
      desc.colorAttachments[2].texture = colortex2;
      desc.colorAttachments[3].texture = colortex3;
      desc.colorAttachments[4].texture = colortex4;
    • 4:38 - Set color attachment map entries

      // Set color attachment map entries
      
      MTLLogicalToPhysicalColorAttachmentMap* myAttachmentRemap = [MTLLogicalToPhysicalColorAttachmentMap new];
      
      [myAttachmentRemap setPhysicalIndex:0 forLogicalIndex:0];
      [myAttachmentRemap setPhysicalIndex:3 forLogicalIndex:1];
      [myAttachmentRemap setPhysicalIndex:4 forLogicalIndex:2];
    • 4:57 - Set a color attachment map per pipeline

      // Set a color attachment map per pipeline
      
      [renderEncoder setRenderPipelineState:myPipeline];
      [renderEncoder setColorAttachmentMap:myAttachmentRemap];
      // Draw with myPipeline
      
      [renderEncoder setRenderPipelineState:myPipeline2];
      [renderEncoder setColorAttachmentMap:myAttachmentRemap2];
      // Draw with myPipeline2
    • 8:03 - Encode a single render pass with 3 render encoders

      // Encode a single render pass with 3 render encoders with suspend/resume options
      
      
      id<MTL4RenderCommandEncoder> enc0 = [cmdbuf0 renderCommandEncoderWithDescriptor:desc options:MTL4RenderEncoderOptionSuspending];
      
      id<MTL4RenderCommandEncoder> enc1 = [cmdbuf1 renderCommandEncoderWithDescriptor:desc options:MTL4RenderEncoderOptionResuming | MTL4RenderEncoderOptionSuspending];
      
      id<MTL4RenderCommandEncoder> enc2 = [cmdbuf2 renderCommandEncoderWithDescriptor:desc options:MTL4RenderEncoderOptionResuming];
      
      
      id<MTL4CommandBuffer> cmdbufs[] = { cmdbuf0, cmdbuf1, cmdbuf2 };
      [commandQueue commit:cmdbufs count:3]
    • 11:48 - Synchronize drawable contents

      // Synchronize drawable contents
      
      id<MTLDrawable> drawable = [metalLayer nextDrawable];
      [queue waitForDrawable:drawable];
      
      // ... encode render commands to commandBuffer ...
      [queue commit:&commandBuffer count:1];
      
      [queue signalDrawable:drawable];
      
      [drawable present];
    • 13:25 - Encode a queue barrier to synchronize data

      // Encode a queue barrier to synchronize data
      
      id<MTL4ComputeCommandEncoder> compute = [commandBuffer computeCommandEncoder];
      
      [compute dispatchThreadgroups:threadGrid threadsPerThreadgroup:threadsPerThreadgroup];
      
      [compute endEncoding];
      
      
      id<MTL4RenderCommandEncoder> render = [commandBuffer renderCommandEncoderWithDescriptor:des];
      
      [render barrierAfterQueueStages:MTLStageDispatch
                         beforeStages:MTLStageFragment
                    visibilityOptions:MTL4VisibilityOptionDevice];
      
      [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle
                               vertexStart:vertexStart
                               vertexCount:vertexCount];
      
      [render endEncoding];
    • 14:57 - Create a texture view pool

      // Create a texture view pool
      
      MTLResourceViewPoolDescriptor *desc = [[MTLResourceViewPoolDescriptor alloc] init]; 
      desc.resourceCount = 500;
       
      id <MTLTextureViewPool> myTextureViewPool =  
          [myDevice newTextureViewPoolWithDescriptor:myTextureViewPoolDescriptor 
                                               error:nullptr];
    • 15:07 - Set a texture view

      // Set a texture view
      
      MTLResourceID myTextureView = [myTextureViewPool setTextureView:myTexture  
                                                           descriptor:myTextureViewDescriptor  
                                                              atIndex:5];
      
      [myArgumentTable setTexture:myTextureView 
                          atIndex:0];
    • 16:01 - Choose appropriate sparse page size

      MTLHeapDescriptor *desc = [MTLHeapDescriptor new];    
      desc.type = MTLHeapTypePlacement;
      desc.storageMode = MTLStorageModePrivate;
      desc.maxCompatiblePlacementSparsePageSize = MTLSparsePageSize64;
      desc.size = alignedHeapSize;
      
      id<MTLHeap> heap = [device newHeapWithDescriptor:desc];
    • 17:05 - Update buffer mappings

      // Update buffer mappings
      
      MTL4UpdateSparseBufferMappingOperation bufferOperation;
      
      bufferOperation.mode = MTLSparseTextureMappingModeMap;  
      bufferOperation.bufferRange.location = bufferOffsetInTiles;
      bufferOperation.bufferRange.length = length;
      bufferOperation.heapOffset = heapOffsetInTiles;
      
      [cmdQueue updateBufferMappings:myBuf heap:myHeap operations:&bufferOperation count:1];
    • 20:41 - Set unspecialized configuration

      // In MTL4RenderPipelineColorAttachmentDescriptor
      // Set unspecialized configuration
      
      pipelineDescriptor.colorAttachments[i].pixelFormat   = MTLPixelFormatUnspecialized;
      pipelineDescriptor.colorAttachments[i].writeMask     = MTLColorWriteMaskUnspecialized;
      pipelineDescriptor.colorAttachments[i].blendingState = MTL4BlendStateUnspecialized;
    • 21:40 - Create a specialized transparent pipeline

      // Create a specialized transparent pipeline
      
      // Set the previously unspecialized properties
      pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
      pipelineDescriptor.colorAttachments[0].writeMask =
          MTLColorWriteMaskRed | MTLColorWriteMaskGreen | MTLColorWriteMaskBlue;
      pipelineDescriptor.colorAttachments[0].blendingState = MTL4BlendStateEnabled;
      
      pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
      pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = 
          MTLBlendFactorOneMinusSourceAlpha;
      pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
      
      id<MTLRenderPipelineState> transparentPipeline = 
          [compiler newRenderPipelineStateBySpecializationWithDescriptor:pipelineDescriptor
                                                                pipeline:unspecializedPipeline
                                                                   error:&error];
      
      // Similarly, create the specialized opaque and hologram pipelines
    • 26:22 - Determine thread count

      // Determine thread count
      NSInteger numThreads = 2;
      if (@available(macOS 13.3, iOS 19, visionOS 3, tvOS 19, *))
      {
          numThreads = [device maximumConcurrentCompilationTaskCount];
      }
    • 26:30 - Set a proper QoS class for your compilation threads

      // Create thread pool
      for (NSInteger i = 0; i < numThreads; ++i)
      {
          // Creating a thread with a QoS class DEFAULT
          pthread_attr_set_qos_class_np(&attr, QOS_CLASS_DEFAULT, 0) ;
          pthread_create(&threadIds[i], &attr, entryPoint, NULL);
          pthread_attr_destroy(&attr);
      }
    • 28:24 - Harvest pipeline configuration scripts

      // Harvest pipeline configuration scripts with the pipeline data set serializer
      
      // Create a pipeline data set serializer that only captures descriptors
      MTL4PipelineDataSetSerializerDescriptor *desc = [MTL4PipelineDataSetSerializerDescriptor new];
      desc.configuration = MTL4PipelineDataSetSerializerConfigurationCaptureDescriptors;
      id<MTL4PipelineDataSetSerializer> serializer =
          [device newPipelineDataSetSerializerWithDescriptor:desc];
      
      // Set the pipeline data set serializer when creating the compiler
      MTL4CompilerDescriptor *compilerDesc = [MTL4CompilerDescriptor new];
      [compilerDesc setPipelineDataSetSerializer:serializer];
      id<MTL4Compiler> compiler = [device newCompilerWithDescriptor:compilerDesc error:nil];
      
      // Create pipelines using the compiler as usual
      
      // Serialize the descriptors as a pipeline script
      NSData *data = [serializer serializeAsPipelinesScriptWithError:&err];
      
      // Write the pipeline script data to disk
      NSString *path = [NSString pathWithComponents:@[folder, @"pipelines.mtl4-json"]];
      BOOL success = [data writeToFile:path options:NSDataWritingAtomic error:&err];
    • 30:28 - Query pipeline state from MTLArchive

      // Query pipeline state from MTLArchive
      
      id<MTL4Archive> archive = [device newArchiveWithURL:archiveURL error:&error];
      
      id<MTLRenderPipelineState> pipeline = 
          [archive newRenderPipelineStateWithDescriptor:descriptor error:&error];
      
      if (pipeline == nil)
      {
          // handle lookup miss
      		pipeline = [compiler newRenderPipelineStateWithDescriptor:descriptor 
                                                compilerTaskOptions:nil 
      }
    • 0:00 - Introducción
    • Esta es la segunda de una serie de cuatro partes sobre Metal 4, la nueva API de gráficos de Apple diseñada para motores de juegos modernos. Metal 4 mejora la codificación de comandos, la administración de recursos y la carga de procesos. Metal 4 satisface las demandas de los juegos actuales y futuros que transmiten gigabytes de geometría y texturas detalladas, renderizadas con miles de sombreadores, para que puedan aprovechar toda la potencia informática disponible con el Apple Chip. Consulta también las otras partes de la serie para conocer más detalles sobre MetalFX, el trazado de rayos y la integración del aprendizaje automático.

    • 1:33 - Codificar de forma más eficiente
    • Metal 4 está diseñado para mejorar la eficiencia del GPU mediante la optimización de la codificación de comandos. Presenta dos clases de codificador principales, render y compute, que ahora pueden procesar las operaciones de juego más comunes. Puedes usar Metal 4 para mejorar la eficiencia de la codificación mediante la reducción de codificadores, la reutilización de la memoria de comandos y la codificación en varios subprocesos.

    • 8:42 - Escalar la gestión de recursos
    • Metal 4 tiene funcionalidades nuevas e interesantes para administrar recursos a escala. Las tablas de argumentos y los conjuntos de residencia permiten escalar la vinculación a miles de recursos. Metal 4 ayuda a administrar los recursos dibujables y ofrece control sobre las dependencias. Las barreras de fila ofrecen una forma de expresar las dependencias de recursos a escala. Los grupos de vistas de texturas y las pilas dispersas de ubicación ayudan a administrar la memoria que requieren recursos grandes.

    • 17:24 - Cargar canales rápidamente
    • Los juegos modernos necesitan crear miles de procesos para crear imágenes complejas y dinámicas. Cargar rápido varios procesos es crucial para eliminar las intermitencias en la compilación de los sombreadores y reducir el tiempo de carga del juego. Para cargar procesos rápidamente en Metal 4, reúsa tus compilaciones de procesos de renderizado, compila procesos en el dispositivo con un nuevo nivel de paralelismo y hazlo con anticipación para que el tiempo de carga se reduzca casi a 0.

    • 31:25 - Resumen
    • Las API de Metal 4 están diseñadas para crear la próxima generación de juegos de alto rendimiento. Puedes consultar la documentación en el sitio web para desarrolladores, probar los proyectos de muestra y descargar el nuevo Xcode para comenzar.

Developer Footer

  • Videos
  • WWDC25
  • Explorar juegos de Metal 4
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • App Store
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Fonts
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Open Source
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Sample Code
    • Tutorials
    • Downloads
    • Forums
    • Videos
    Open Menu Close Menu
    • Support Articles
    • Contact Us
    • Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Get the Apple Developer app.
    Copyright © 2025 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines