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
  • Discover Metal for immersive apps

    Find out how you can use Metal to render fully immersive experiences for visionOS. We'll show you how to set up a rendering session on the platform and create a basic render loop, and share how you can make your experience interactive by incorporating spatial input.

    Chapitres

    • 0:06 - Intro
    • 1:50 - App Architecture
    • 5:58 - Render configuration
    • 11:29 - Render Loop
    • 13:00 - Render a frame
    • 17:28 - User input
    • 20:22 - Wrap-Up

    Ressources

    • Drawing fully immersive content using Metal
    • Metal
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC23

    • Build great games for spatial computing
    • Go beyond the window with SwiftUI
    • Meet ARKit for spatial computing

    WWDC21

    • Explore HDR rendering with EDR
  • Rechercher dans cette vidéo…
    • 4:45 - App architecture

      @main
      struct MyApp: App {
          var body: some Scene {
              ImmersiveSpace {
                  CompositorLayer { layerRenderer in
                      let engine = my_engine_create(layerRenderer)
                      let renderThread = Thread {
                          my_engine_render_loop(engine)
                      }
                      renderThread.name = "Render Thread"
                      renderThread.start()
                  }
              }
          }
      }
    • 10:32 - CompositorLayer Configuration

      // CompositorLayer configuration
      
      struct MyConfiguration: CompositorLayerConfiguration {
          func makeConfiguration(capabilities: LayerRenderer.Capabilities,
                                 configuration: inout LayerRenderer.Configuration) {
      
              let supportsFoveation = capabilities.supportsFoveation
              let supportedLayouts = capabilities.supportedLayouts(options: supportsFoveation ?
                                                                   [.foveationEnabled] : [])
      
              configuration.layout = supportedLayouts.contains(.layered) ? .layered : .dedicated
      
              configuration.isFoveationEnabled = supportsFoveation
      
              // HDR support
              configuration.colorFormat = .rgba16Float
         }
      }
    • 12:20 - Render loop

      void my_engine_render_loop(my_engine *engine) {
          my_engine_setup_render_pipeline(engine);
      
          bool is_rendering = true;
          while (is_rendering) @autoreleasepool {
              switch (cp_layer_renderer_get_state(engine->layer_renderer)) {
                  case cp_layer_renderer_state_paused:
                      cp_layer_renderer_wait_until_running(engine->layer_renderer);
                      break;
                  case cp_layer_renderer_state_running:
                      my_engine_render_new_frame(engine);
                      break;
                  case cp_layer_renderer_state_invalidated:
                      is_rendering = false;
                      break;
              }
          }
      
          my_engine_invalidate(engine);
      }
    • 15:56 - Render new frame

      void my_engine_render_new_frame(my_engine *engine) {
          
          cp_frame_t frame = cp_layer_renderer_query_next_frame(engine->layer_renderer);
          if (frame == nullptr) { return; }
          
          cp_frame_timing_t timing = cp_frame_predict_timing(frame);
          if (timing == nullptr) { return; }
      
          cp_frame_start_update(frame);
      
          my_input_state input_state = my_engine_gather_inputs(engine, timing);
          my_engine_update_frame(engine, timing, input_state);
      
          cp_frame_end_update(frame);
      
          // Wait until the optimal time for querying the input
          cp_time_wait_until(cp_frame_timing_get_optimal_input_time(timing));
      
          cp_frame_start_submission(frame);
      
          cp_drawable_t drawable = cp_frame_query_drawable(frame);
          if (drawable == nullptr) { return; }
      
          cp_frame_timing_t final_timing = cp_drawable_get_frame_timing(drawable);
          ar_pose_t pose = my_engine_get_ar_pose(engine, final_timing);
          cp_drawable_set_ar_pose(drawable, pose);
      
          my_engine_draw_and_submit_frame(engine, frame, drawable);
      
          cp_frame_end_submission(frame);
      }
    • 18:57 - App architecture + input support

      @main
      struct MyApp: App {
          var body: some Scene {
              ImmersiveSpace {
                  CompositorLayer(configuration: MyConfiguration()) { layerRenderer in
                      let engine = my_engine_create(layerRenderer)
                      let renderThread = Thread {
                          my_engine_render_loop(engine)
                      }
                      renderThread.name = "Render Thread"
                      renderThread.start()
                      layerRenderer.onSpatialEvent = { eventCollection in
                          var events = eventCollection.map { my_spatial_event($0) }
                          my_engine_push_spatial_events(engine, &events, events.count)
                      }
                  }
              }
              .upperLimbVisibility(.hidden)
          }
      }
    • 18:57 - Push spatial events

      void my_engine_push_spatial_events(my_engine *engine,
                                         my_spatial_event *spatial_event_collection,
                                         size_t event_count) {
          os_unfair_lock_lock(&engine->input_event_lock);
          
          // Copy events into an internal queue
          
          os_unfair_lock_unlock(&engine->input_event_lock);
      }
    • 19:57 - Gather inputs

      my_input_state my_engine_gather_inputs(my_engine *engine,
                                             cp_frame_timing_t timing) {
          my_input_state input_state = my_input_state_create();
      
          os_unfair_lock_lock(&engine->input_event_lock);
          input_state.current_pinch_collection = my_engine_pop_spatial_events(engine);
          os_unfair_lock_unlock(&engine->input_event_lock);
      
          ar_hand_tracking_provider_get_latest_anchors(engine->hand_tracking_provider,
                                                       input_state.left_hand,
                                                       input_state.right_hand);
      
          return input_state;
      }

Developer Footer

  • Vidéos
  • WWDC23
  • Discover Metal for immersive apps
  • 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