use re_log_types::LogMsg;
pub const APP_ID: &str = "rerun";
type AppCreator =
Box<dyn FnOnce(&eframe::CreationContext<'_>, re_ui::ReUi) -> Box<dyn eframe::App>>;
pub fn run_native_app(app_creator: AppCreator) -> eframe::Result<()> {
let native_options = eframe_options();
let window_title = "Rerun Viewer";
eframe::run_native(
window_title,
native_options,
Box::new(move |cc| {
check_graphics_driver(cc.wgpu_render_state.as_ref());
let re_ui = crate::customize_eframe(cc);
app_creator(cc, re_ui)
}),
)
}
fn check_graphics_driver(wgpu_render_state: Option<&egui_wgpu::RenderState>) {
re_tracing::profile_function!();
let wgpu_render_state = wgpu_render_state.expect("Expected wgpu to be enabled");
let info = wgpu_render_state.adapter.get_info();
let human_readable_summary = {
let wgpu::AdapterInfo {
name,
vendor: _, device: _, device_type,
driver,
driver_info,
backend,
} = &info;
format!(
"wgpu adapter name: {name:?}, \
device_type: {device_type:?}, \
backend: {backend:?}, \
driver: {driver:?}, \
driver_info: {driver_info:?}"
)
};
let is_software_rasterizer_with_known_crashes = {
const KNOWN_SOFTWARE_RASTERIZERS: &[&str] = &[
"lavapipe", "llvmpipe", ];
let info_string = format!("{info:?}").to_lowercase();
KNOWN_SOFTWARE_RASTERIZERS
.iter()
.any(|&software_rasterizer| info_string.contains(software_rasterizer))
};
if is_software_rasterizer_with_known_crashes {
re_log::warn!("Software rasterizer detected - expect poor performance and crashes. See: https://www.rerun.io/docs/getting-started/troubleshooting#graphics-issues");
re_log::info!("{human_readable_summary}");
} else if info.device_type == wgpu::DeviceType::Cpu {
re_log::warn!("Software rasterizer detected - expect poor performance. See: https://www.rerun.io/docs/getting-started/troubleshooting#graphics-issues");
re_log::info!("{human_readable_summary}");
} else {
re_log::debug!("{human_readable_summary}");
}
}
pub fn eframe_options() -> eframe::NativeOptions {
re_tracing::profile_function!();
eframe::NativeOptions {
app_id: Some(APP_ID.to_owned()),
initial_window_size: Some([1600.0, 1200.0].into()),
min_window_size: Some([320.0, 450.0].into()),
icon_data: icon_data(),
#[cfg(target_os = "macos")]
fullsize_content: re_ui::FULLSIZE_CONTENT,
decorated: !re_ui::CUSTOM_WINDOW_DECORATIONS,
transparent: re_ui::CUSTOM_WINDOW_DECORATIONS,
follow_system_theme: false,
default_theme: eframe::Theme::Dark,
renderer: eframe::Renderer::Wgpu,
wgpu_options: crate::wgpu_options(),
depth_buffer: 0,
multisampling: 0,
..Default::default()
}
}
#[allow(clippy::unnecessary_wraps)]
fn icon_data() -> Option<eframe::IconData> {
re_tracing::profile_function!();
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
let app_icon_png_bytes = include_bytes!("../data/app_icon_mac.png");
} else if #[cfg(target_os = "windows")] {
let app_icon_png_bytes = include_bytes!("../data/app_icon_windows.png");
} else {
let app_icon_png_bytes = include_bytes!("../data/app_icon_windows.png");
}
};
match eframe::IconData::try_from_png_bytes(app_icon_png_bytes) {
Ok(icon_data) => Some(icon_data),
Err(err) => {
#[cfg(debug_assertions)]
panic!("Failed to load app icon: {err}");
#[cfg(not(debug_assertions))]
{
re_log::warn!("Failed to load app icon: {err}");
None
}
}
}
}
pub fn run_native_viewer_with_messages(
build_info: re_build_info::BuildInfo,
app_env: crate::AppEnvironment,
startup_options: crate::StartupOptions,
log_messages: Vec<LogMsg>,
) -> eframe::Result<()> {
let (tx, rx) = re_smart_channel::smart_channel(
re_smart_channel::SmartMessageSource::Sdk,
re_smart_channel::SmartChannelSource::Sdk,
);
for log_msg in log_messages {
tx.send(log_msg).ok();
}
run_native_app(Box::new(move |cc, re_ui| {
let mut app = crate::App::new(build_info, &app_env, startup_options, re_ui, cc.storage);
app.add_receiver(rx);
Box::new(app)
}))
}