View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Vidéos

Ouvrir le menu Fermer le menu
  • Collections
  • Toutes les vidéos
  • À propos

Plus de vidéos

  • À propos
  • Code
  • Bring your game to Mac, Part 3: Render with Metal

    Discover how you can support Metal in your rendering code as we close out our three-part series on bringing your game to Mac. Once you've evaluated your existing Windows binary with the game porting toolkit and brought your HLSL shaders over to Metal, learn how you can optimally implement the features that high-end, modern games require. We'll show you how to manage GPU resource bindings, residency, and synchronization. Find out how to optimize GPU commands submission, render rich visuals with MetalFX Upscaling, and more.

    To get the most out of this session, we recommend first watching “Bring your game to Mac, Part 1: Make a game plan” and “Bring your game to Mac, Part 2: Compile your shaders" from WWDC23.

    Chapitres

    • 0:00 - Intro
    • 1:58 - Manage GPU resources
    • 9:08 - Optimize rendering commands
    • 18:00 - Handle indirect rendering
    • 22:41 - Upscale with MetalFX
    • 25:31 - Wrap-Up

    Ressources

    • Applying temporal antialiasing and upscaling using MetalFX
    • MetalFX
    • Modern rendering with Metal
    • Metal
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC23

    • Bring your game to Mac, Part 1: Make a game plan
    • Bring your game to Mac, Part 2: Compile your shaders

    Tech Talks

    • Bring your high-end game to iPhone 15 Pro

    WWDC22

    • Boost performance with MetalFX Upscaling

    WWDC21

    • Discover Metal debugging, profiling, and asset creation tools

    WWDC20

    • Bring your Metal app to Apple silicon Macs
    • Gain insights into your Metal app with Xcode 12
    • Harness Apple GPUs with Metal
    • Optimize Metal Performance for Apple silicon Macs
  • Rechercher dans cette vidéo…
    • 3:55 - Encode the texture tables.

      // Encode the texture tables outside of the rendering loop.
      
      
      id<MTLBuffer> textureTable  = [device newBufferWithLength:sizeof(MTLResourceID) * texturesCount
                                                        options:MTLResourceStorageModeShared];
      
      
      MTLResourceID* textureTableCPUPtr = (MTLResourceID*)textureTable.contents;
      for (uint32_t i = 0; i < texturesCount; ++i)
      {
          // create the textures.
          id<MTLTexture> texture = [device newTextureWithDescriptor:textureDesc[i]];
      
          // encode texture in argument buffer
          textureTableCPUPtr[i] = texture.gpuResourceID;
      }
    • 4:33 - Encode the sampler tables.

      // Encode the sampler tables outside of the rendering loop.
      
      
      id<MTLBuffer> samplerTable  = [device newBufferWithLength:sizeof(MTLResourceID) * samplersCount
                                                        options:MTLResourceStorageModeShared];
      
      MTLResourceID* samplerTableCPUPtr = (MTLResourceID*)samplerTable.contents;
      for (uint32_t i = 0; i < samplersCount; ++i)
      {
          // create sampler descriptor
          MTLSamplerDescriptor* desc  = [MTLSamplerDescriptor new];
          desc.supportArgumentBuffers = YES;
          . . .
      
          // create a sampler
          id<MTLSamplerState> sampler = [device newSamplerStateWithDescriptor:desc];
      
          // encode the sampler in argument buffer
          samplerTableCPUPtr[i] = sampler.gpuResourceID;
      }
    • 5:05 - Encode the top level argument buffer.

      // Encode the top level argument buffer.
      
      
      struct TopLevelAB
      {
          MTLResourceID* textureTable;
          float*         myBuffer;
          uint32_t       myConstant;
          MTLResourceID* samplerTable;
      };
      
      id<MTLBuffer> topAB = [device newBufferWithLength:sizeof(TopLevelAB)
                                                options:MTLResourceStorageModeShared];
      
      
      TopLevelAB* topABCPUPtr     = (TopLevelAB*)topAB.contents;
      topABCPUPtr->textureTable   = (MTLResourceID*)textureTable.gpuAddress;
      topABCPUPtr->myBuffer       = (float*)myBuffer.gpuAddress;
      topABCPUPtr->myConstant     = 128;
      topABCPUPtr->samplerTable   = (MTLResourceID*)samplerTable.gpuAddress;
    • 6:49 - Allocate the read-only resources.

      // Allocate the read-only resources from a heap.
      
      MTLHeapDescriptor* heapDesc = [MTLHeapDescriptor new];
      heapDesc.size               = requiredSize;
      heapDesc.type               = MTLHeapTypeAutomatic;
      
      id<MTLHeap> heap = [device newHeapWithDescriptor:heapDesc];
      
      
      
      // Allocate the textures and the buffers from the heap.
      
      id<MTLTexture> texture = [heap newTextureWithDescriptor:desc];
      id<MTLBuffer>  buffer = [heap newBufferWithLength:length options:options];
      . . .
      
      
      // Make the heap resident once for each encoder that uses it.
      
      [encoder useHeap:heap];
    • 7:34 - Allocate the writable resources.

      // Allocate the writable resources individually.
      
      id<MTLTexture> textureRW = [device newTextureWithDescriptor:desc];
      id<MTLBuffer>  bufferRW  = [device newBufferWithLength:length options:options];
      
      
      
      // Mark these resources resident when they're needed in the current encoder.
      // Specify the resource usage in the encoder using MTLResourceUsage.
      
      [encoder useResource:textureRW usage:MTLResourceUsageWrite stages:stage];
      [encoder useResource:bufferRW  usage:MTLResourceUsageRead  stages:stage];
    • 19:31 - Encode the execute indirect

      // Encode the execute indirect command as a series of indirect draw calls.
      
      for (uint32_t i = 0; i < maxDrawCount; ++i)
      {
          // Encode the current indirect draw call.
          [renderEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
                             				 indexType:MTLIndexTypeUInt16
                                   indexBuffer:indexBuffer
                             indexBufferOffset:indexBufferOffset
                                indirectBuffer:drawArgumentsBuffer
                          indirectBufferOffset:drawArgumentsBufferOffset];
          
          // Advance the draw arguments buffer offset to the next indirect arguments.
          drawArgumentsBufferOffset += sizeof(MTLDrawIndexedPrimitivesIndirectArguments);
      }
    • 21:48 - Translate the indirect draw arguments to ICB.

      // Kernel written in Metal Shading Language to translate the indirect draw arguments to an ICB. 
      
      
      kernel void translateToICB(device const Command* indirectCommands [[ buffer(0) ]],
                                 device const ICBContainerAB* icb [[ buffer(1) ]],
                                 . . .)
      {
          . . .
         
          device const Command* indirectCommand = &indirectCommands[commandIndex];
          device const MTLDrawIndexedPrimitivesIndirectArguments* args =
          &command->mdiBuffer[mdiIndex];
          
          render_command drawCall(icb->buffer, indirectCommand->mdiCmdStart + mdiIndex);
      
          if(args->indexCount > 0 && args->instanceCount > 0) {
              encodeCommand(indirectCommand, args, drawCall);
          }
          else {
              cmd.reset();
          }
      }
      
      // Encode a render command on the GPU.
      void encodeCommand(device const Command* indirectCommand,
                         device const MTLDrawIndexedPrimitivesIndirectArguments* args,
                         thread render_command& drawCall)
      {
          drawCall.set_render_pipeline_state(indirectCommand->pso);
          
          for(ushort i = 0; i < indirectCommand->vertexBuffersCount; ++i) {
              drawCall.set_vertex_buffer(indirectCommand->vertexBuffer[i].buffer,
                                    indirectCommand->vertexBuffer[i].slot);
          }
          
          for(ushort i = 0; i < indirectCommand->fragmentBuffersCount; ++i) {
              drawCall.set_fragment_buffer(indirectCommand->fragmentBuffer[i].buffer,
                                      indirectCommand->fragmentBuffer[i].slot);
          }
      
          drawCall.draw_indexed_primitives(primitive_type::triangle,
                                      args->indexCount,
                                      indirectCommand->indexBuffer + args->indexStart,
                                      args->instanceCount,
                                      args->baseVertex,
                                      args->baseInstance);
      }

Developer Footer

  • Vidéos
  • WWDC23
  • Bring your game to Mac, Part 3: Render with Metal
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & 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
    • Mini Apps Partner 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
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines