#![deny(unsafe_code)]
use std::process::ExitCode;
use vyre_driver::{DispatchConfig, VyreBackend};
use vyre_foundation::ir::{BufferAccess, BufferDecl, DataType, Expr, Node, Program};
fn main() -> ExitCode {
match run() {
Ok(()) => ExitCode::SUCCESS,
Err(message) => {
eprintln!("{message}");
ExitCode::FAILURE
}
}
}
fn run() -> Result<(), String> {
let mut args = std::env::args().skip(1);
match args.next().as_deref() {
Some("--version") | Some("-V") => {
println!("vyre {}", env!("CARGO_PKG_VERSION"));
Ok(())
}
Some("demo") => {
let value = run_demo()?;
println!("vyre demo gpu_u32={value}");
Ok(())
}
Some("--help") | Some("-h") | None => {
print_help();
Ok(())
}
Some(other) => Err(format!(
"unknown vyre command `{other}`. Fix: use `vyre --version` or `vyre demo`."
)),
}
}
fn print_help() {
println!("vyre {}", env!("CARGO_PKG_VERSION"));
println!("usage: vyre --version | vyre demo");
println!();
println!(" demo build a minimal vyre IR Program, dispatch on the local GPU,");
println!(" and print the resulting u32 (expected: 42).");
}
fn run_demo() -> Result<u32, String> {
let program = Program::wrapped(
vec![
BufferDecl::storage("out", 0, BufferAccess::ReadWrite, DataType::U32)
.with_count(1)
.with_output_byte_range(0..4),
],
[1, 1, 1],
vec![Node::store("out", Expr::u32(0), Expr::u32(42))],
);
let backend = vyre_driver_wgpu::WgpuBackend::acquire().map_err(|error| {
format!(
"failed to acquire wgpu backend: {error}. Fix: install a compatible GPU driver \
(Vulkan / Metal / DX12) or run on a host with GPU access."
)
})?;
let outputs = backend
.dispatch(&program, &[], &DispatchConfig::default())
.map_err(|error| {
format!("demo dispatch failed: {error}. Fix: inspect the GPU driver logs.")
})?;
let bytes = outputs
.first()
.ok_or_else(|| "demo returned no output buffers; expected one.".to_string())?;
let slice: [u8; 4] = bytes[..4]
.try_into()
.map_err(|_| "demo output buffer shorter than 4 bytes.".to_string())?;
Ok(u32::from_le_bytes(slice))
}