Option::unwrap in wgpu_hal on nixos
So I'm using nixos and building an iced application. So far so good, everything works, i got all libraries set up. Then I pull in iced_aw and i start getting the error below and can't for the live of me figure out which library it's missing
thread 'main' panicked at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-hal-0.19.5/src/gles/egl.rs:789:88:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
with RUST_BACKTRACE
❯ RUST_BACKTRACE=1 target/debug/chip8-iced
thread 'main' panicked at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-hal-0.19.5/src/gles/egl.rs:789:88:
called `Option::unwrap()` on a `None` value
stack backtrace:
0: rust_begin_unwind
1: core::panicking::panic_fmt
2: core::panicking::panic
3: core::option::unwrap_failed
4: core::option::Option<T>::unwrap
at /build/rustc-1.77.2-src/library/core/src/option.rs:931:21
5: <wgpu_hal::gles::egl::Instance as wgpu_hal::Instance<wgpu_hal::gles::Api>>::init
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-hal-0.19.5/src/gles/egl.rs:789:31
6: wgpu_core::instance::Instance::new::init
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-core-0.19.4/src/instance.rs:86:32
7: wgpu_core::instance::Instance::new
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-core-0.19.4/src/instance.rs:115:17
8: wgpu_core::global::Global<G>::new
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-core-0.19.4/src/global.rs:59:23
9: <wgpu::backend::wgpu_core::ContextWgpuCore as wgpu::context::Context>::init
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.4/src/backend/wgpu_core.rs:513:14
10: wgpu::Instance::new
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.4/src/lib.rs:1833:36
11: iced_wgpu::window::compositor::Compositor::request::{{closure}}
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_wgpu-0.12.1/src/window/compositor.rs:29:24
12: futures_executor::local_pool::block_on::{{closure}}
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:317:23
13: futures_executor::local_pool::run_executor::{{closure}}
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:90:37
14: std::thread::local::LocalKey<T>::try_with
at /build/rustc-1.77.2-src/library/std/src/thread/local.rs:286:16
15: std::thread::local::LocalKey<T>::with
at /build/rustc-1.77.2-src/library/std/src/thread/local.rs:262:9
16: futures_executor::local_pool::run_executor
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:86:5
17: futures_executor::local_pool::block_on
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:317:5
18: iced_wgpu::window::compositor::new
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_wgpu-0.12.1/src/window/compositor.rs:159:22
19: iced_renderer::compositor::Candidate::build
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_renderer-0.12.1/src/compositor.rs:247:34
20: <iced_renderer::compositor::Compositor as iced_graphics::compositor::Compositor>::new
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_renderer-0.12.1/src/compositor.rs:35:19
21: iced_winit::application::run
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_winit-0.12.2/src/application.rs:191:22
22: iced::application::Application::run
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced-0.12.1/src/application.rs:208:12
23: iced::sandbox::Sandbox::run
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced-0.12.1/src/sandbox.rs:153:9
24: chip8_iced::main
at ./chip8-iced/src/main.rs:11:5
25: core::ops::function::FnOnce::call_once
at /build/rustc-1.77.2-src/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
And with full backtrace
❯ RUST_BACKTRACE=full target/debug/chip8-iced
thread 'main' panicked at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-hal-0.19.5/src/gles/egl.rs:789:88:
called `Option::unwrap()` on a `None` value
stack backtrace:
0: 0x56006e427037 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h4886110ae7835fd2
1: 0x56006e45bfa0 - core::fmt::write::h6fab83f0f5bc0c8f
2: 0x56006e43f885 - std::io::Write::write_fmt::h64824cb874054607
3: 0x56006e426e04 - std::sys_common::backtrace::print::hb8fea9d041077138
4: 0x56006e427977 - std::panicking::default_hook::{{closure}}::hc60f0f690c67943c
5: 0x56006e4276d7 - std::panicking::default_hook::h56281bcc5d6e2f17
6: 0x56006e427ee8 - std::panicking::rust_panic_with_hook::hd61e30fe5971d187
7: 0x56006e427d8e - std::panicking::begin_panic_handler::{{closure}}::h95d2684e28f89fd2
8: 0x56006e427266 - std::sys_common::backtrace::__rust_end_short_backtrace::h48780d898316fff8
9: 0x56006e427b14 - rust_begin_unwind
10: 0x56006ce19aa5 - core::panicking::panic_fmt::hdb89b5c14a056cec
11: 0x56006ce19b63 - core::panicking::panic::h0e6608ccd7056721
12: 0x56006ce1a1a6 - core::option::unwrap_failed::h42b5e841a9c29a32
13: 0x56006e026845 - core::option::Option<T>::unwrap::hded2709bd8630a96
at /build/rustc-1.77.2-src/library/core/src/option.rs:931:21
14: 0x56006e026845 - <wgpu_hal::gles::egl::Instance as wgpu_hal::Instance<wgpu_hal::gles::Api>>::init::h150ad6d6bb0c05d4
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-hal-0.19.5/src/gles/egl.rs:789:31
15: 0x56006df31fd0 - wgpu_core::instance::Instance::new::init::h70c041f536e033fd
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-core-0.19.4/src/instance.rs:86:32
16: 0x56006df3139b - wgpu_core::instance::Instance::new::h99a8f9918d86ae8c
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-core-0.19.4/src/instance.rs:115:17
17: 0x56006de835fe - wgpu_core::global::Global<G>::new::h9cf7648d0d7c0260
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-core-0.19.4/src/global.rs:59:23
18: 0x56006dc7ee3b - <wgpu::backend::wgpu_core::ContextWgpuCore as wgpu::context::Context>::init::h3fdcbe4bc89270e4
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.4/src/backend/wgpu_core.rs:513:14
19: 0x56006dca7af8 - wgpu::Instance::new::hf4317dbc8b7b1984
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.4/src/lib.rs:1833:36
20: 0x56006cf84201 - iced_wgpu::window::compositor::Compositor::request::{{closure}}::h8eaf166c5e6c5e29
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_wgpu-0.12.1/src/window/compositor.rs:29:24
21: 0x56006cf723f8 - futures_executor::local_pool::block_on::{{closure}}::h944faef2f58d6edc
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:317:23
22: 0x56006cf72256 - futures_executor::local_pool::run_executor::{{closure}}::hd30626d1802c86a9
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:90:37
23: 0x56006cf2b61b - std::thread::local::LocalKey<T>::try_with::h2acb57e0911de025
at /build/rustc-1.77.2-src/library/std/src/thread/local.rs:286:16
24: 0x56006cf2b4bb - std::thread::local::LocalKey<T>::with::h4b3dee4611e88984
at /build/rustc-1.77.2-src/library/std/src/thread/local.rs:262:9
25: 0x56006cf72194 - futures_executor::local_pool::run_executor::h342d9faa48fc608d
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:86:5
26: 0x56006cf7237a - futures_executor::local_pool::block_on::hc0e617a0d773a824
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-executor-0.3.30/src/local_pool.rs:317:5
27: 0x56006cf87504 - iced_wgpu::window::compositor::new::h2c8c917798a8a837
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_wgpu-0.12.1/src/window/compositor.rs:159:22
28: 0x56006cf5b1f0 - iced_renderer::compositor::Candidate::build::hdc8efa20b4c15d02
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_renderer-0.12.1/src/compositor.rs:247:34
29: 0x56006cf5b9b4 - <iced_renderer::compositor::Compositor as iced_graphics::compositor::Compositor>::new::h1e024a1bb90087a6
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_renderer-0.12.1/src/compositor.rs:35:19
30: 0x56006cf82388 - iced_winit::application::run::h60cf60612157f590
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_winit-0.12.2/src/application.rs:191:22
31: 0x56006cf4c0cf - iced::application::Application::run::hdfb9326dfe9cfc3c
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced-0.12.1/src/application.rs:208:12
32: 0x56006cf4c31d - iced::sandbox::Sandbox::run::h62bd6085464ab4ad
at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced-0.12.1/src/sandbox.rs:153:9
33: 0x56006cf20168 - chip8_iced::main::h6ec256546d329b67
at /home/lukas/Project/chip8/chip8-iced/src/main.rs:11:5
34: 0x56006ce901f2 - core::ops::function::FnOnce::call_once::h66777604bdbe4352
at /build/rustc-1.77.2-src/library/core/src/ops/function.rs:250:5
35: 0x56006ce3fe95 - std::sys_common::backtrace::__rust_begin_short_backtrace::hd59d9815f3064331
at /build/rustc-1.77.2-src/library/std/src/sys_common/backtrace.rs:155:18
36: 0x56006cf76646 - std::rt::lang_start::{{closure}}::hce593592ff2ab62e
at /build/rustc-1.77.2-src/library/std/src/rt.rs:166:18
37: 0x56006e427a14 - std::panicking::try::ha86251cf5daa9bea
38: 0x56006e41818b - std::rt::lang_start_internal::ha6a51778162f8d22
39: 0x56006cf7661a - std::rt::lang_start::h2b2f3d02b5847fbd
at /build/rustc-1.77.2-src/library/std/src/rt.rs:165:17
40: 0x56006cf2064e - main
41: 0x7f2eb181e10e - __libc_start_call_main
42: 0x7f2eb181e1c9 - __libc_start_main@@GLIBC_2.34
43: 0x56006ce1a4e5 - _start
44: 0x0 - <unknown>
This is the unwrap.
https://github.com/gfx-rs/wgpu/blob/db9fb2ef354af7c1da58e4210d6b9cb5c38d5cb8/wgpu-hal/src/gles/egl.rs#L789
khronos_egl maps EGL_NO_DISPLAY to None for eglGetDisplay.
I think we should error instead of panicking.
Still, do you have any idea why that could be None and what lib I am missing?
Maybe the DISPLAY env var is not set? I'm not too familiar with this mechanism. I'd look online for "eglGetDisplay(EGL_DEFAULT_DISPLAY) returns EGL_NO_DISPLAY".
Okay here comes the weird thing: I Just created a little test program
fn main() {
unsafe {
let egl = dbg!(khronos_egl::DynamicInstance::<khronos_egl::EGL1_4>::load_required()).unwrap();
dbg!(egl.get_display(khronos_egl::DEFAULT_DISPLAY)).unwrap();
}
}
Which if I'm correct should produce the same error, right? Wrong
❯ cargo run -p testing
Finished dev [unoptimized + debuginfo] target(s) in 0.18s
Running `target/debug/testing`
[testing/src/main.rs:3:19] khronos_egl::DynamicInstance::<khronos_egl::EGL1_4>::load_required() = Ok(
Instance(Dynamic(Library@0x55aa58a70c10)),
)
[testing/src/main.rs:5:9] egl.get_display(khronos_egl::DEFAULT_DISPLAY) = Some(
Display(
0x000055aa58a7d480,
),
)
Since I just saw there are log statements, I quickly added env_logger
❯ RUST_LOG="trace" target/debug/chip8-iced
[2024-08-27T14:25:51Z DEBUG sctk] Bound new global [47] wl_output v4
[2024-08-27T14:25:51Z DEBUG sctk] Bound new global [9] zxdg_output_manager_v1 v3
[2024-08-27T14:25:51Z DEBUG sctk] Bound new global [1] wl_seat v7
[2024-08-27T14:25:51Z DEBUG sctk] Bound new global [10] wp_cursor_shape_manager_v1 v1
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Argb8888
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Xrgb8888
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Argb2101010
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Xrgb2101010
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Abgr2101010
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Xbgr2101010
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Abgr8888
[2024-08-27T14:25:51Z DEBUG sctk] supported wl_shm format Xbgr8888
[2024-08-27T14:25:51Z TRACE calloop::loop_logic] [calloop] Inserting new source #0
[2024-08-27T14:25:51Z TRACE calloop::loop_logic] [calloop] Inserting new source #1
[2024-08-27T14:25:51Z TRACE calloop::loop_logic] [calloop] Inserting new source #2
[2024-08-27T14:25:51Z DEBUG iced_winit::application] Window builder: WindowBuilder {
window: WindowAttributes {
inner_size: Some(
Logical(
LogicalSize {
width: 1024.0,
height: 768.0,
},
),
),
min_inner_size: None,
max_inner_size: None,
position: None,
resizable: true,
enabled_buttons: WindowButtons(
CLOSE | MINIMIZE | MAXIMIZE,
),
title: "Chip8",
maximized: false,
visible: false,
transparent: false,
blur: false,
decorations: true,
window_icon: None,
preferred_theme: None,
resize_increments: None,
content_protected: false,
window_level: Normal,
active: true,
parent_window: SendSyncWrapper(
None,
),
fullscreen: SendSyncWrapper(
None,
),
},
}
[2024-08-27T14:25:51Z DEBUG wgpu_core::instance] Instance::new: failed to create Vulkan backend: InstanceError { message: "missing Vulkan entry points", source: Some(LibraryLoadFailure(DlOpen { desc: "libvulkan.so.1: cannot open shared object file: No such file or directory" })) }
[2024-08-27T14:25:51Z DEBUG wgpu_hal::gles::egl] Client extensions: []
[2024-08-27T14:25:51Z WARN wgpu_hal::gles::egl] EGL_MESA_platform_surfaceless not available. Using default platform
thread 'main' panicked at /home/lukas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-hal-0.19.5/src/gles/egl.rs:789:88:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Okay i did some more testing with the logging. I ran it via steam-run (a magic nixos tool that loads in libraries at runtime, but itsnt suited for packaging applications, neither is it good when i want to do cargo run)
Then it works and the logs sho me it's going into the wayland platform path while the above is crashing in the default platform path. So either the wayland library is none or the egl1_5 is none. So i threw together a minimal test
use std::{ptr, os::raw};
fn main() {
unsafe {
let egl = khronos_egl::DynamicInstance::<khronos_egl::EGL1_4>::load_required();
let egl = egl.unwrap();
let client_extensions = egl.query_string(None, khronos_egl::EXTENSIONS);
let client_ext_str = match client_extensions {
Ok(ext) => ext.to_string_lossy().into_owned(),
Err(_) => String::new(),
};
println!(
"Client extensions: {:#?}",
client_ext_str.split_whitespace().collect::<Vec<_>>()
);
let egl1_5 = egl.upcast::<khronos_egl::EGL1_5>();
dbg!(egl1_5);
let wayland_library = if client_ext_str.contains("EGL_EXT_platform_wayland") {
test_wayland_display()
} else {
None
};
dbg!(wayland_library);
}
}
fn test_wayland_display() -> Option<DisplayOwner> {
/* We try to connect and disconnect here to simply ensure there
* is an active wayland display available.
*/
let library = unsafe {
let client_library = find_library(&["libwayland-client.so.0", "libwayland-client.so"])?;
let wl_display_connect: libloading::Symbol<WlDisplayConnectFun> =
client_library.get(b"wl_display_connect").unwrap();
let wl_display_disconnect: libloading::Symbol<WlDisplayDisconnectFun> =
client_library.get(b"wl_display_disconnect").unwrap();
let display = ptr::NonNull::new(wl_display_connect(ptr::null()))?;
wl_display_disconnect(display.as_ptr());
find_library(&["libwayland-egl.so.1", "libwayland-egl.so"])?
};
Some(DisplayOwner {
library,
display: DisplayRef::Wayland,
})
}
#[derive(Debug)]
struct DisplayOwner {
library: libloading::Library,
display: DisplayRef,
}
unsafe fn find_library(paths: &[&str]) -> Option<libloading::Library> {
for path in paths {
match unsafe { libloading::Library::new(path) } {
Ok(lib) => return Some(lib),
_ => continue,
};
}
None
}
type WlDisplayConnectFun =
unsafe extern "system" fn(display_name: *const raw::c_char) -> *mut raw::c_void;
type WlDisplayDisconnectFun = unsafe extern "system" fn(display: *const raw::c_void);
#[derive(Debug)]
enum DisplayRef {
X11(ptr::NonNull<raw::c_void>),
Wayland,
}
Which includes all relevant code from the file you linked that sets those two variables. running it in the exact same environment as my binary that crashes gives me this
Client extensions: [
"EGL_EXT_device_base",
"EGL_EXT_device_enumeration",
"EGL_EXT_device_query",
"EGL_EXT_platform_base",
"EGL_KHR_client_get_all_proc_addresses",
"EGL_EXT_client_extensions",
"EGL_KHR_debug",
"EGL_EXT_platform_device",
"EGL_EXT_explicit_device",
"EGL_EXT_platform_wayland",
"EGL_KHR_platform_wayland",
"EGL_EXT_platform_x11",
"EGL_KHR_platform_x11",
"EGL_EXT_platform_xcb",
"EGL_MESA_platform_gbm",
"EGL_KHR_platform_gbm",
"EGL_MESA_platform_surfaceless",
]
[testing/src/main.rs:18:9] egl1_5 = Some(
Instance(Dynamic(Library@0x559982da5c10)),
)
[testing/src/main.rs:24:9] wayland_library = Some(
DisplayOwner {
library: Library@0x559982db30f0,
display: Wayland,
},
)```
The list of client extensions is empty here https://github.com/gfx-rs/wgpu/issues/6165#issuecomment-2312727001, but in https://github.com/gfx-rs/wgpu/issues/6165#issuecomment-2312822413 it's not.
Just to confirm, when using steam-run will the list of client extensions always be populated? And with cargo run it will be empty?
If so, it sounds like an env issue and it would be worth figuring out what steam-run does.
On our end, I think we shouldn't unwrap there and instead report that there is no display available.
Just to confirm, when using steam-run will the list of client extensions always be populated? And with cargo run it will be empty?
Correct. but the second example is still a normal cargo run, but with the minimal test I threw together, no cargo required
By now I found out my issue it was a driver mismatch but it's weird that it affects one project but not the other besides both running in the same environment with the same command
On our end, I think we shouldn't unwrap there and instead report that there is no display available.
My issue is solved but I'll leave this open if you want to track that change
@VoreckLukas, would you mind sharing the config/fix if you were able to get it to run without steam-run
BTW thanks for sharing the workaround.
@VoreckLukas, would you mind sharing the config/fix if you were able to get it to run without
steam-runBTW thanks for sharing the workaround.
The key is to keep your flake at the same version of nixpkgs as the rest of your system