Add a renderer escape hatch (wgpu default, glow fallback)
The desktop forces the wgpu/Vulkan renderer because glow/OpenGL crashes on NVIDIA + Wayland maximize. But on some systems wgpu creates the window and never presents a frame, so nothing appears. Keep wgpu the default but compile glow back in and let it be selected via `--renderer glow` or `YT_OFFLINE_RENDERER=glow` for those machines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2692fa2c9e
commit
9ba375f7b1
4 changed files with 166 additions and 8 deletions
70
Cargo.lock
generated
70
Cargo.lock
generated
|
|
@ -744,6 +744,15 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "cgl"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chacha20"
|
||||
version = "0.10.0"
|
||||
|
|
@ -1048,6 +1057,9 @@ dependencies = [
|
|||
"egui-wgpu",
|
||||
"egui-winit",
|
||||
"egui_glow",
|
||||
"glow 0.14.2",
|
||||
"glutin",
|
||||
"glutin-winit",
|
||||
"image",
|
||||
"js-sys",
|
||||
"log",
|
||||
|
|
@ -1489,6 +1501,63 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"cfg_aliases 0.2.1",
|
||||
"cgl",
|
||||
"dispatch2",
|
||||
"glutin_egl_sys",
|
||||
"glutin_glx_sys",
|
||||
"glutin_wgl_sys",
|
||||
"libloading",
|
||||
"objc2 0.6.4",
|
||||
"objc2-app-kit 0.3.2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation 0.3.2",
|
||||
"once_cell",
|
||||
"raw-window-handle",
|
||||
"wayland-sys",
|
||||
"windows-sys 0.52.0",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin-winit"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f"
|
||||
dependencies = [
|
||||
"cfg_aliases 0.2.1",
|
||||
"glutin",
|
||||
"raw-window-handle",
|
||||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_egl_sys"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_glx_sys"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_wgl_sys"
|
||||
version = "0.6.1"
|
||||
|
|
@ -2366,6 +2435,7 @@ dependencies = [
|
|||
"bitflags 2.11.1",
|
||||
"block2 0.6.2",
|
||||
"objc2 0.6.4",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-foundation 0.3.2",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,12 +10,13 @@ authors = ["InannaBeloved <anassaeneroi@pm.me>"]
|
|||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
# Use the wgpu (Vulkan/Metal/DX) renderer instead of the default glow
|
||||
# Default to the wgpu (Vulkan/Metal/DX) renderer instead of the default glow
|
||||
# (OpenGL) one. NVIDIA + Wayland crashes the GL surface on window resize
|
||||
# (Glutin EGL_BAD_ALLOC / OutOfMemory on maximize); wgpu's Vulkan path
|
||||
# reconfigures the swapchain cleanly. We drop the `glow` default feature
|
||||
# and keep the rest (accesskit, fonts, wayland, x11).
|
||||
eframe = { version = "0.29", default-features = false, features = ["accesskit", "default_fonts", "wayland", "x11", "wgpu"] }
|
||||
# reconfigures the swapchain cleanly. Keep glow compiled in as an escape
|
||||
# hatch for machines where wgpu/Vulkan creates a window but never presents
|
||||
# a frame (`YT_OFFLINE_RENDERER=glow` or `--renderer glow`).
|
||||
eframe = { version = "0.29", default-features = false, features = ["accesskit", "default_fonts", "wayland", "x11", "wgpu", "glow"] }
|
||||
image = { version = "0.25", default-features = false, features = ["webp", "jpeg", "png"] }
|
||||
toml = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -96,6 +96,27 @@ handles the resize cleanly. Make sure you have a working Vulkan driver
|
|||
(`vulkan-icd-loader` + your GPU's Vulkan package), which any desktop with
|
||||
working graphics already has.
|
||||
|
||||
## The desktop window opens but stays blank
|
||||
|
||||
The desktop defaults to the wgpu/Vulkan renderer. On some systems with a
|
||||
broken Vulkan stack, the OS can create the window while wgpu never
|
||||
presents a frame. Try the OpenGL renderer:
|
||||
|
||||
```bash
|
||||
YT_OFFLINE_RENDERER=glow yt-offline
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```bash
|
||||
yt-offline --renderer glow
|
||||
```
|
||||
|
||||
If that works, update/reinstall your Vulkan driver later and switch back
|
||||
to the default renderer. On NVIDIA + Wayland, prefer the default wgpu
|
||||
renderer when possible because OpenGL has historically crashed on window
|
||||
maximize.
|
||||
|
||||
## The web UI looks like an old version after an upgrade
|
||||
|
||||
The SPA is served `Cache-Control: no-store`, so a hard reload
|
||||
|
|
|
|||
74
src/main.rs
74
src/main.rs
|
|
@ -36,6 +36,33 @@ mod vtt;
|
|||
mod web;
|
||||
mod ytdlp_bin;
|
||||
|
||||
fn renderer_from_name(requested: Option<&str>) -> eframe::Renderer {
|
||||
match requested.map(|s| s.trim().to_ascii_lowercase()).as_deref() {
|
||||
Some("glow" | "opengl" | "gl") => eframe::Renderer::Glow,
|
||||
Some("wgpu" | "vulkan" | "vk") | None => eframe::Renderer::Wgpu,
|
||||
Some(name) => {
|
||||
eprintln!(
|
||||
"Warning: unknown renderer '{name}' (expected 'wgpu' or 'glow'); using wgpu."
|
||||
);
|
||||
eframe::Renderer::Wgpu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn renderer_from_args(args: &[String]) -> eframe::Renderer {
|
||||
let requested = args
|
||||
.iter()
|
||||
.position(|a| a == "--renderer")
|
||||
.and_then(|pos| args.get(pos + 1).map(String::as_str));
|
||||
|
||||
if requested.is_some() {
|
||||
renderer_from_name(requested)
|
||||
} else {
|
||||
let env_renderer = std::env::var("YT_OFFLINE_RENDERER").ok();
|
||||
renderer_from_name(env_renderer.as_deref())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> eframe::Result<()> {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
|
|
@ -82,10 +109,11 @@ fn main() -> eframe::Result<()> {
|
|||
.with_inner_size([1280.0, 820.0])
|
||||
.with_min_inner_size([800.0, 500.0])
|
||||
.with_title("yt-offline"),
|
||||
// Force the wgpu (Vulkan) renderer. The default glow/OpenGL path
|
||||
// crashes on NVIDIA + Wayland when the window is maximized
|
||||
// (Glutin EGL_BAD_ALLOC). wgpu reconfigures the swapchain cleanly.
|
||||
renderer: eframe::Renderer::Wgpu,
|
||||
// Default to wgpu (Vulkan): the glow/OpenGL path crashes on some
|
||||
// NVIDIA + Wayland maximizes (Glutin EGL_BAD_ALLOC). Keep a launch
|
||||
// escape hatch for systems where Vulkan/wgpu opens a blank window:
|
||||
// `YT_OFFLINE_RENDERER=glow yt-offline` or `yt-offline --renderer glow`.
|
||||
renderer: renderer_from_args(&args),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
|
|
@ -94,3 +122,41 @@ fn main() -> eframe::Result<()> {
|
|||
Box::new(|cc| Ok(Box::new(app::App::new(cc, tray)))),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn renderer_name_accepts_default_and_aliases() {
|
||||
assert_eq!(super::renderer_from_name(None), eframe::Renderer::Wgpu);
|
||||
assert_eq!(
|
||||
super::renderer_from_name(Some("wgpu")),
|
||||
eframe::Renderer::Wgpu
|
||||
);
|
||||
assert_eq!(
|
||||
super::renderer_from_name(Some("vulkan")),
|
||||
eframe::Renderer::Wgpu
|
||||
);
|
||||
assert_eq!(
|
||||
super::renderer_from_name(Some("glow")),
|
||||
eframe::Renderer::Glow
|
||||
);
|
||||
assert_eq!(
|
||||
super::renderer_from_name(Some("opengl")),
|
||||
eframe::Renderer::Glow
|
||||
);
|
||||
assert_eq!(
|
||||
super::renderer_from_name(Some("unknown")),
|
||||
eframe::Renderer::Wgpu
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renderer_arg_overrides_env_parser_path() {
|
||||
let args = vec![
|
||||
"yt-offline".to_string(),
|
||||
"--renderer".to_string(),
|
||||
"gl".to_string(),
|
||||
];
|
||||
assert_eq!(super::renderer_from_args(&args), eframe::Renderer::Glow);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue