vyre-driver-wgpu 0.6.2

wgpu backend for vyre IR - implements VyreBackend, owns GPU runtime, buffer pool, pipeline cache
Documentation
use std::borrow::Cow;
use std::path::{Path, PathBuf};
#[cfg(test)]
use std::sync::{Mutex, OnceLock};

pub(crate) fn invalidate_impacted(
    dispatcher: &dyn vyre_self_substrate::optimizer::dispatcher::OptimizerDispatcher,
    intervention_mask: &[u32],
    rule_adj: &[u32],
    state: &[u32],
    join_rules: &[u32],
    n: u32,
    max_iterations: u32,
    pipeline_lineage_cell: &[u32],
    cache_keys: &[String],
) -> std::io::Result<()> {
    let dir = disk_pipeline_cache_dir();
    let impact_mask = vyre_driver::cache_invalidation::impacted_entries(
        dispatcher,
        intervention_mask,
        rule_adj,
        state,
        join_rules,
        n,
        max_iterations,
        pipeline_lineage_cell,
    )
    .map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error.to_string()))?;

    for (i, &is_impacted) in impact_mask.iter().enumerate() {
        if is_impacted != 0 {
            if let Some(key) = cache_keys.get(i) {
                let wgsl_path = cache_entry_path(&dir, key, ".wgsl");
                let meta_wgsl = cache_entry_path(&dir, key, ".wgsl.toml");
                let bin_path = cache_entry_path(&dir, key, ".pipeline.bin");
                let meta_bin = cache_entry_path(&dir, key, ".pipeline.toml");

                remove_cache_entry_file(&wgsl_path)?;
                remove_cache_entry_file(&meta_wgsl)?;
                remove_cache_entry_file(&bin_path)?;
                remove_cache_entry_file(&meta_bin)?;
            }
        }
    }
    Ok(())
}

fn remove_cache_entry_file(path: &Path) -> std::io::Result<()> {
    match std::fs::remove_file(path) {
        Ok(()) => Ok(()),
        Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
        Err(error) => Err(std::io::Error::new(
            error.kind(),
            format!(
                "Fix: failed to remove invalidated WGPU pipeline cache file `{}`: {error}",
                path.display()
            ),
        )),
    }
}

pub(crate) fn cache_entry_path(dir: &Path, key: &str, suffix: &str) -> PathBuf {
    let file_name_len = key.len().checked_add(suffix.len()).unwrap_or_else(|| {
        panic!(
            "pipeline disk-cache file name length overflowed usize. Fix: reject oversized cache keys before path construction."
        )
    });
    let mut file_name = String::with_capacity(file_name_len);
    file_name.push_str(key);
    file_name.push_str(suffix);
    dir.join(file_name)
}

#[cfg(test)]
static TEST_DISK_PIPELINE_CACHE_ROOT: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();

#[cfg(test)]
pub(crate) fn set_test_disk_pipeline_cache_root(path: Option<PathBuf>) -> Option<PathBuf> {
    let mut guard = TEST_DISK_PIPELINE_CACHE_ROOT
        .get_or_init(|| Mutex::new(None))
        .lock()
        .unwrap_or_else(|poisoned| poisoned.into_inner());
    std::mem::replace(&mut *guard, path)
}

pub(crate) fn disk_pipeline_cache_dir() -> PathBuf {
    #[cfg(test)]
    if let Some(root) = TEST_DISK_PIPELINE_CACHE_ROOT
        .get_or_init(|| Mutex::new(None))
        .lock()
        .unwrap_or_else(|poisoned| poisoned.into_inner())
        .clone()
    {
        return root.join("pipeline");
    }

    std::env::var_os("VYRE_CACHE_DIR")
        .map(PathBuf::from)
        .unwrap_or_else(|| {
            std::env::var_os("HOME")
                .map(PathBuf::from)
                .unwrap_or_else(|| PathBuf::from("."))
                .join(".cache")
                .join("vyre")
        })
        .join("pipeline")
}

#[derive(serde::Deserialize, serde::Serialize)]
pub(crate) struct DiskPipelineMetadata {
    pub version: u32,
    pub cache_key: [u8; 32],
    pub wgsl_bytes: usize,
    pub adapter_fingerprint: [u8; 32],
    pub program_abi_version: u32,
    pub naga_version: Cow<'static, str>,
    pub wgsl_lowering_contract: Cow<'static, str>,
    pub policy: String,
    pub wgsl_blake3: String,
}

#[derive(serde::Deserialize, serde::Serialize)]
pub(crate) struct CompiledPipelineMetadata {
    pub version: u32,
    pub cache_key: [u8; 32],
    pub adapter_fingerprint: [u8; 32],
    pub wgsl_blake3: String,
    pub program_abi_version: u32,
    pub naga_version: Cow<'static, str>,
    pub blob_bytes: usize,
    pub blob_blake3: String,
}