The desktop names where a package may have put libonnxruntime — an override variable, beside the executable, the package's own library directory, the Flatpak prefix, the system library directory — and Android points at the APK's native library directory, which is also what Qualcomm's DSP loader must be told for the Hexagon skel. Android starts the engine at the end of the model unpack rather than at launch, because the probe fingerprints the model files and a first launch has none until then. The About panel gains an Inference row beside Graphics, re-read every two seconds while the probe runs and engines land, and faces.model_id carries the detector's form: an int8 detector finds a different set of faces and is a different population (docs/inference.md §7). A low-memory signal drops every idle session with the GPU caches. The APK assembly bundles ONNX Runtime and the Qualcomm HTP libraries from Maven, fetched by tools/fetch-android-runtime.sh with their published checksums; RUNTIME_DIR=none builds the tract-only APK, which is a slower app and not a broken one. The desktop packages carry no runtime yet. Two probe fixes from the first desktop run: the floor must not be built with CPU fallback disabled, and a versioned libonnxruntime.so is a runtime too. On the reference desktop the probe now loads ONNX Runtime 1.30, measures 30 ms on the CPU provider, and selects TensorRT at 1.5 ms.
109 lines
4.9 KiB
Rust
109 lines
4.9 KiB
Rust
//! DarkRoom desktop entry point.
|
|
//!
|
|
//! darkroom-desktop <file-or-directory>...
|
|
//! darkroom-desktop --version
|
|
|
|
// TRACES: FR-PLAT-WIN-2
|
|
// A GUI-subsystem executable, or Windows opens a console window behind the
|
|
// application for the life of the process. Release only: the console is where
|
|
// the log goes when there is no file, and a debug build is run from one.
|
|
// `--version` still prints under this — stdout is simply not attached when
|
|
// launched from Explorer, which is not where anyone asks for a version.
|
|
#![cfg_attr(all(windows, not(debug_assertions)), windows_subsystem = "windows")]
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use dr_plat::diagnostics::Installed;
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
// TRACES: FR-PLAT-WIN-3
|
|
// Before the logger, the crash hook and everything else: this exists so a
|
|
// build made on a machine that cannot run the application — the Linux CI
|
|
// producing the Windows binary, checked under Wine — has an exit that
|
|
// proves the executable starts without opening a window or touching the
|
|
// user's directories (docs/windows.md §6).
|
|
if std::env::args().nth(1).as_deref() == Some("--version") {
|
|
println!("darkroom-desktop {}", env!("CARGO_PKG_VERSION"));
|
|
return Ok(());
|
|
}
|
|
|
|
// Built rather than `init`ed, so the same logger can be handed to the
|
|
// diagnostics tee: `env_logger` keeps writing to stderr exactly as before,
|
|
// and every record it accepts is also appended to the on-disk log
|
|
// (NFR-OPS-1). `filter()` is asked afterwards because the environment may
|
|
// have overridden the default below, and the file must not be quieter than
|
|
// the terminal.
|
|
let console = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(
|
|
"info,wgpu_core=warn,wgpu_hal=warn,zbus=warn,tracing=warn,calloop=warn,rawler=warn",
|
|
))
|
|
.build();
|
|
let level = console.filter();
|
|
let logging = dr_plat::diagnostics::install(Box::new(console), level);
|
|
|
|
// Immediately after the logger and before anything that could fail. Until
|
|
// now a panic on desktop went to stderr and died with the terminal, which
|
|
// means every panic a user has ever hit was unreportable: the process
|
|
// survives (the panicking worker does not), a control goes dead, and there
|
|
// is nothing on disk to say why. The record is local and stays local —
|
|
// there is no upload path, by design; see `dr_plat::crash`.
|
|
dr_plat::crash::install(env!("CARGO_PKG_VERSION"));
|
|
|
|
log::info!("DarkRoom v{}", env!("CARGO_PKG_VERSION"));
|
|
// First thing in the file, so a user asked for "the log" can find it
|
|
// without being told a path over the phone.
|
|
match &logging {
|
|
Installed::ToFile(path) => log::info!("logging to {}", path.display()),
|
|
Installed::ConsoleOnly(why) => log::warn!("no log file this session: {why}"),
|
|
}
|
|
|
|
let paths: Vec<PathBuf> = std::env::args().skip(1).map(PathBuf::from).collect();
|
|
if paths.is_empty() {
|
|
eprintln!("usage: darkroom-desktop <file-or-directory>...");
|
|
}
|
|
|
|
// Before the window: the probe runs on its own thread and the first
|
|
// frame does not wait for it, but the models a background job asks for
|
|
// should already know where the runtime is (docs/inference.md §4).
|
|
dr_ui::inference::init(runtime_dirs());
|
|
|
|
dr_ui::run(paths)?;
|
|
|
|
// Skip Rust's normal static/thread-local teardown on the way out: a
|
|
// background zbus/keyring connection opened by dr_ui::launch_ui can
|
|
// still be alive here, and unwinding through it races its async-io
|
|
// reactor thread, panicking with "thread local ... during or after
|
|
// destruction" when the window is closed.
|
|
std::process::exit(0);
|
|
}
|
|
|
|
/// Where a desktop package may have put `libonnxruntime`, most specific
|
|
/// first. None of these existing is the tract build, which is a complete
|
|
/// application and not an error (docs/inference.md §3).
|
|
///
|
|
/// `DARKROOM_ORT_DIR` is for a developer pointing at a runtime that is not
|
|
/// installed — the wheel's `capi` directory, say. Then beside the executable
|
|
/// and in the package's private library directory, for a package that
|
|
/// bundles its own; then the Flatpak prefix; then the system library
|
|
/// directory, for a distribution that ships ONNX Runtime as a package of its
|
|
/// own. A system copy whose GPU providers do not load is not a problem: the
|
|
/// probe builds a real session before believing a provider.
|
|
fn runtime_dirs() -> Vec<PathBuf> {
|
|
let mut dirs = Vec::new();
|
|
if let Some(dir) = std::env::var_os("DARKROOM_ORT_DIR") {
|
|
dirs.push(PathBuf::from(dir));
|
|
}
|
|
if let Ok(exe) = std::env::current_exe() {
|
|
if let Some(bin) = exe.parent() {
|
|
dirs.push(bin.to_path_buf());
|
|
dirs.push(bin.join("../lib/darkroom"));
|
|
}
|
|
}
|
|
#[cfg(target_os = "linux")]
|
|
dirs.extend([
|
|
PathBuf::from("/app/lib/darkroom"),
|
|
PathBuf::from("/usr/lib/darkroom"),
|
|
PathBuf::from("/usr/lib"),
|
|
]);
|
|
dirs
|
|
}
|