@@ -317,31 +317,79 @@ impl Instance {
317317 ) -> Result < Surface , CreateSurfaceError > {
318318 profiling:: scope!( "Instance::create_surface_metal" ) ;
319319
320- let instance = unsafe { self . as_hal :: < hal:: api:: Metal > ( ) }
321- . ok_or ( CreateSurfaceError :: BackendNotEnabled ( Backend :: Metal ) ) ?;
320+ let mut errors = HashMap :: default ( ) ;
321+ let mut surface_per_backend: HashMap < Backend , Box < dyn hal:: DynSurface > > =
322+ HashMap :: default ( ) ;
322323
323- let layer = layer. cast ( ) ;
324- // SAFETY: We do this cast and deref. (rather than using `metal` to get the
325- // object we want) to avoid direct coupling on the `metal` crate.
326- //
327- // To wit, this pointer…
328- //
329- // - …is properly aligned.
330- // - …is dereferenceable to a `MetalLayerRef` as an invariant of the `metal`
331- // field.
332- // - …points to an _initialized_ `MetalLayerRef`.
333- // - …is only ever aliased via an immutable reference that lives within this
334- // lexical scope.
335- let layer = unsafe { & * layer } ;
336- let raw_surface: Box < dyn hal:: DynSurface > =
337- Box :: new ( instance. create_surface_from_layer ( layer) ) ;
324+ for ( backend, instance) in & self . instance_per_backend {
325+ match * backend {
326+ #[ cfg( vulkan) ]
327+ Backend :: Vulkan => {
328+ // Downcast to Vulkan instance
329+ let vk_instance = instance
330+ . as_any ( )
331+ . downcast_ref :: < hal:: vulkan:: Instance > ( )
332+ . expect ( "Backend mismatch" ) ;
333+
334+ if let Some ( mut layer) = core:: ptr:: NonNull :: new ( layer) {
335+ unsafe {
336+ match vk_instance. create_surface_from_layer ( layer. as_mut ( ) ) {
337+ Ok ( raw) => {
338+ surface_per_backend. insert ( * backend, Box :: new ( raw) ) ;
339+ }
340+ Err ( err) => {
341+ log:: debug!(
342+ "Instance::create_surface_metal: failed to create Vulkan surface: {err:?}"
343+ ) ;
344+ errors. insert ( * backend, err) ;
345+ }
346+ }
347+ }
348+ }
349+ }
350+ #[ cfg( metal) ]
351+ Backend :: Metal => {
352+ // Downcast to Metal instance
353+ let metal_instance = instance
354+ . as_any ( )
355+ . downcast_ref :: < hal:: metal:: Instance > ( )
356+ . expect ( "Backend mismatch" ) ;
357+
358+ let layer_ref = layer. cast ( ) ;
359+ // SAFETY: We do this cast and deref. (rather than using `metal` to get the
360+ // object we want) to avoid direct coupling on the `metal` crate.
361+ //
362+ // To wit, this pointer…
363+ //
364+ // - …is properly aligned.
365+ // - …is dereferenceable to a `MetalLayerRef` as an invariant of the `metal`
366+ // field.
367+ // - …points to an _initialized_ `MetalLayerRef`.
368+ // - …is only ever aliased via an immutable reference that lives within this
369+ // lexical scope.
370+ let layer_ref = unsafe { & * layer_ref } ;
371+ let raw = metal_instance. create_surface_from_layer ( layer_ref) ;
372+ surface_per_backend. insert ( * backend, Box :: new ( raw) ) ;
373+ }
374+ _ => {
375+ // Other backends don't support Metal layer input
376+ continue ;
377+ }
378+ }
379+ }
338380
339- let surface = Surface {
340- presentation : Mutex :: new ( rank:: SURFACE_PRESENTATION , None ) ,
341- surface_per_backend : core:: iter:: once ( ( Backend :: Metal , raw_surface) ) . collect ( ) ,
342- } ;
381+ if surface_per_backend. is_empty ( ) {
382+ Err ( CreateSurfaceError :: FailedToCreateSurfaceForAnyBackend (
383+ errors,
384+ ) )
385+ } else {
386+ let surface = Surface {
387+ presentation : Mutex :: new ( rank:: SURFACE_PRESENTATION , None ) ,
388+ surface_per_backend,
389+ } ;
343390
344- Ok ( surface)
391+ Ok ( surface)
392+ }
345393 }
346394
347395 #[ cfg( dx12) ]
@@ -955,7 +1003,7 @@ impl Global {
9551003 /// # Safety
9561004 ///
9571005 /// `layer` must be a valid pointer.
958- #[ cfg( metal) ]
1006+ #[ cfg( any ( metal, vulkan ) ) ]
9591007 pub unsafe fn instance_create_surface_metal (
9601008 & self ,
9611009 layer : * mut core:: ffi:: c_void ,
0 commit comments