use pagesift_gpu::GpuInfo;
use crate::models::{MEDIUM_DET, MEDIUM_REC, Model, SMALL_DET, SMALL_REC};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Device {
Cpu,
Gpu { index: usize },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DeviceStatus {
pub requested: Device,
pub actual: Device,
pub gpu: Option<GpuInfo>,
pub fallback: Option<String>,
}
impl DeviceStatus {
pub fn fell_back(&self) -> bool {
self.fallback.is_some()
}
pub(crate) fn cpu() -> DeviceStatus {
DeviceStatus {
requested: Device::Cpu,
actual: Device::Cpu,
gpu: None,
fallback: None,
}
}
pub(crate) fn fallback(index: usize, why: String) -> DeviceStatus {
DeviceStatus {
requested: Device::Gpu { index },
actual: Device::Cpu,
gpu: None,
fallback: Some(why),
}
}
pub(crate) fn on_gpu(index: usize, info: GpuInfo) -> DeviceStatus {
let device = Device::Gpu { index };
DeviceStatus {
requested: device,
actual: device,
gpu: Some(info),
fallback: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Quality {
Auto,
Fast,
Accurate,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ModelChoice {
pub det: Model,
pub rec: Model,
pub tier: &'static str,
}
impl ModelChoice {
fn small() -> ModelChoice {
ModelChoice {
det: SMALL_DET,
rec: SMALL_REC,
tier: "small",
}
}
fn medium() -> ModelChoice {
ModelChoice {
det: MEDIUM_DET,
rec: MEDIUM_REC,
tier: "medium",
}
}
}
pub fn medium_vram_bytes() -> u64 {
2288 << 20
}
pub fn select_models(quality: Quality, device: Device) -> ModelChoice {
match (quality, device) {
(Quality::Fast, _) | (Quality::Auto, Device::Cpu) => ModelChoice::small(),
(Quality::Accurate, _) => ModelChoice::medium(),
(Quality::Auto, Device::Gpu { index }) => match pagesift_gpu::probe(index) {
Ok(info) if info.memory_free >= medium_vram_bytes() => ModelChoice::medium(),
_ => ModelChoice::small(),
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn 按质量档选模型() {
let g = Device::Gpu { index: 0 };
assert_eq!(select_models(Quality::Fast, g).tier, "small");
assert_eq!(select_models(Quality::Auto, Device::Cpu).tier, "small");
assert_eq!(select_models(Quality::Accurate, Device::Cpu).tier, "medium");
}
#[test]
fn 不存在的显卡退回_cpu_并带原因() {
let e = pagesift_gpu::probe(9999).unwrap_err();
let s = DeviceStatus::fallback(9999, e);
assert_eq!(s.actual, Device::Cpu);
assert!(s.fell_back());
assert_eq!(s.requested, Device::Gpu { index: 9999 });
assert_eq!(
select_models(Quality::Auto, Device::Gpu { index: 9999 }).tier,
"small"
);
}
}