-
Explorez les jeux Metal 4
Apprenez à optimiser votre moteur de jeu avec les dernières avancées de Metal 4. Nous verrons comment unifier l'encodage de commandes pour minimiser la surcharge du processeur, faire évoluer la gestion des ressources graphiques pour prendre en charge des scènes massives tout en maximisant votre budget mémoire, et charger rapidement de vastes bibliothèques d'états de pipeline.
Pour tirer le meilleur parti de cette session, regardez d'abord « Découvrez Metal 4 ».Chapitres
- 0:00 - Introduction
- 1:33 - Encoder plus efficacement
- 8:42 - Optimiser la gestion de vos ressources
- 17:24 - Charger rapidement les pipelines
- 31:25 - Étapes suivantes
Ressources
- Metal binary archives
- Reading and writing to sparse textures
- Synchronizing passes with producer barriers
- Synchronizing passes with consumer barriers
- Synchronizing passes with a fence
- Synchronizing stages within a pass
- Resource synchronization
- Drawing a triangle with Metal 4
- Using the Metal 4 compilation API
- Understanding the Metal 4 core API
- Human Interface Guidelines: Designing for games
Vidéos connexes
WWDC25
- Allez plus loin avec les jeux Metal 4
- Combinez l’apprentissage automatique et les graphismes de Metal 4
- Découvrez Metal 4
- Faites passer vos jeux au niveau supérieur
- Nouveautés du rendu Metal pour les apps immersives
Tech Talks
-
Rechercher dans cette vidéo…
-
-
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 - Introduction
Cette séance est la deuxième d’une série en quatre volets consacrée à Metal 4, la nouvelle API graphique d’Apple conçue pour les moteurs de jeu modernes. Metal 4 améliore l’encodage des commandes, la gestion des ressources et le chargement des pipelines. Metal 4 répond aux exigences des jeux actuels et futurs, qui diffusent des gigaoctets de géométrie détaillée et de textures, rendus à l’aide de milliers de shaders, afin de tirer pleinement parti de toute la puissance de calcul offerte par la puce Apple. Regardez également les autres volets de la série pour en savoir plus sur MetalFX, le ray tracing et l’intégration de l’apprentissage automatique.
- 1:33 - Encoder plus efficacement
Metal 4 est conçu pour améliorer l’efficacité du GPU en optimisant l’encodage des commandes. Il introduit deux principales classes d’encodeurs, render et compute, qui peuvent désormais gérer la plupart des opérations courantes dans les jeux. Vous pouvez utiliser Metal 4 pour améliorer l’efficacité de votre encodage en réduisant le nombre de vos encodeurs, en réutilisant votre mémoire de commande et en encodant sur plusieurs threads.
- 8:42 - Optimiser la gestion de vos ressources
Metal 4 propose de nouvelles fonctionnalités pour vous aider à gérer vos ressources à grande échelle. Les tables d’arguments et les jeux de résidence vous permettent d’étendre votre liaison de ressources à des milliers de ressources. Metal 4 vous permet de gérer vos ressources graphiques et vous offre un contrôle sur les dépendances. Les Queue Barriers permettent d’exprimer vos dépendances de ressources à grande échelle. Les pools de vues de texture et les tas clairsemés avec placement vous aident à gérer la mémoire nécessaire aux ressources volumineuses.
- 17:24 - Charger rapidement les pipelines
Les jeux modernes doivent créer des milliers de pipelines pour créer des visuels complexes et dynamiques. Le chargement rapide de nombreux pipelines est essentiel pour éliminer les ralentissements liés au traitement des shaders et réduire le temps de chargement de votre jeu. Pour charger rapidement les pipelines dans Metal 4, réutilisez les compilations de vos pipelines de rendu, compilez les pipelines directement sur l’appareil avec un nouveau niveau de parallélisme, et effectuez des compilations anticipées afin que le temps de chargement des pipelines soit presque nul.
- 31:25 - Étapes suivantes
Les API de Metal 4 sont conçues pour vous permettre de créer la prochaine génération de jeux hautes performances. Pour commencer, vous pouvez consulter la documentation sur le site web des développeurs, essayer les exemples de projets et télécharger la nouvelle version de Xcode.