@@ -317,31 +317,81 @@ 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+ // HashMap unused in Metal-only path
321+ #[ allow( unused_mut) ]
322+ let mut errors = HashMap :: default ( ) ;
323+ let mut surface_per_backend: HashMap < Backend , Box < dyn hal:: DynSurface > > =
324+ HashMap :: default ( ) ;
322325
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) ) ;
326+ for ( backend, instance) in & self . instance_per_backend {
327+ match * backend {
328+ #[ cfg( vulkan) ]
329+ Backend :: Vulkan => {
330+ // Downcast to Vulkan instance
331+ let vk_instance = instance
332+ . as_any ( )
333+ . downcast_ref :: < hal:: vulkan:: Instance > ( )
334+ . expect ( "Backend mismatch" ) ;
335+
336+ if let Some ( mut layer) = core:: ptr:: NonNull :: new ( layer) {
337+ unsafe {
338+ match vk_instance. create_surface_from_layer ( layer. as_mut ( ) ) {
339+ Ok ( raw) => {
340+ surface_per_backend. insert ( * backend, Box :: new ( raw) ) ;
341+ }
342+ Err ( err) => {
343+ log:: debug!(
344+ "Instance::create_surface_metal: failed to create Vulkan surface: {err:?}"
345+ ) ;
346+ errors. insert ( * backend, err) ;
347+ }
348+ }
349+ }
350+ }
351+ }
352+ #[ cfg( metal) ]
353+ Backend :: Metal => {
354+ // Downcast to Metal instance
355+ let metal_instance = instance
356+ . as_any ( )
357+ . downcast_ref :: < hal:: metal:: Instance > ( )
358+ . expect ( "Backend mismatch" ) ;
359+
360+ let layer_ref = layer. cast ( ) ;
361+ // SAFETY: We do this cast and deref. (rather than using `metal` to get the
362+ // object we want) to avoid direct coupling on the `metal` crate.
363+ //
364+ // To wit, this pointer…
365+ //
366+ // - …is properly aligned.
367+ // - …is dereferenceable to a `MetalLayerRef` as an invariant of the `metal`
368+ // field.
369+ // - …points to an _initialized_ `MetalLayerRef`.
370+ // - …is only ever aliased via an immutable reference that lives within this
371+ // lexical scope.
372+ let layer_ref = unsafe { & * layer_ref } ;
373+ let raw = metal_instance. create_surface_from_layer ( layer_ref) ;
374+ surface_per_backend. insert ( * backend, Box :: new ( raw) ) ;
375+ }
376+ _ => {
377+ // Other backends don't support Metal layer input
378+ continue ;
379+ }
380+ }
381+ }
338382
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- } ;
383+ if surface_per_backend. is_empty ( ) {
384+ Err ( CreateSurfaceError :: FailedToCreateSurfaceForAnyBackend (
385+ errors,
386+ ) )
387+ } else {
388+ let surface = Surface {
389+ presentation : Mutex :: new ( rank:: SURFACE_PRESENTATION , None ) ,
390+ surface_per_backend,
391+ } ;
343392
344- Ok ( surface)
393+ Ok ( surface)
394+ }
345395 }
346396
347397 #[ cfg( dx12) ]
0 commit comments