diff --git a/crates/mobile/src/lib.rs b/crates/mobile/src/lib.rs index 2e4a0859f92268f5ad2961767f0041a2c78f1728..4a35d430df620a5f1de86be3ab5ad761d4e9370c 100644 --- a/crates/mobile/src/lib.rs +++ b/crates/mobile/src/lib.rs @@ -671,6 +671,27 @@ fn view_pixels(size: [f32; 2], scale: f32, limit: u32) -> Result<[u32; 2]> { Ok(pixels.map(|side| side as u32)) } +/// The GPU instance the first view starts. On Android it offers one backend, Vulkan where the +/// device has it, else GL: Android's Vulkan loader connects a window to make its surface, and +/// EGL then can't make one on the same window. +fn instance() -> wgpu::Instance { + let with = |backends| { + wgpu::Instance::new(wgpu::InstanceDescriptor { + backends, + ..wgpu::InstanceDescriptor::new_without_display_handle() + }) + }; + if !cfg!(target_os = "android") { + return with(wgpu::Backends::all()); + } + let vulkan = with(wgpu::Backends::VULKAN); + if pollster::block_on(vulkan.enumerate_adapters(wgpu::Backends::VULKAN)).is_empty() { + with(wgpu::Backends::GL) + } else { + vulkan + } +} + struct Presentation { surface: wgpu::Surface<'static>, /// Field order keeps the acquired window alive until the surface has dropped. @@ -700,7 +721,7 @@ impl Presentation { let mut gpu = gpu(); let instance = match &*gpu { Some(gpu) => gpu.instance.clone(), - None => wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle()), + None => instance(), }; // SAFETY: Android retains its window; the Apple caller keeps its layer alive. let surface = unsafe { instance.create_surface_unsafe(target) }?;