vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
use vyre::ir::{self, Program};
use vyre::lower::wgsl;
use vyre::ops::{Category, Compose, OpSpec};

mod compression;
mod decode;
mod graph;
mod hash;
mod match_ops;
mod reductions;
mod rule;

fn assert_structural_spec(spec: &OpSpec) -> Program {
    assert!(
        matches!(spec.category(), Category::A),
        "{} must be a Category A composition",
        spec.id()
    );
    assert!(
        matches!(spec.compose(), Compose::Composition(_)),
        "{} must expose Compose::Composition",
        spec.id()
    );

    let program = spec
        .program()
        .unwrap_or_else(|| panic!("{} must return a Program", spec.id()));
    assert!(
        !program.entry().is_empty(),
        "{} composition must return a non-empty Program",
        spec.id()
    );

    let errors = ir::validate(&program);
    assert!(
        errors.is_empty(),
        "{} composition must validate cleanly: {errors:?}",
        spec.id()
    );

    let lowered = wgsl::lower(&program).unwrap_or_else(|error| {
        panic!(
            "{} composition must lower without LowerError: {error}",
            spec.id()
        )
    });
    assert_reasonable_wgsl(spec.id(), &lowered);
    program
}

fn assert_reasonable_wgsl(id: &str, wgsl: &str) {
    let line_count = wgsl.lines().count();
    assert!(
        !wgsl.trim().is_empty(),
        "{id} lowered WGSL must not be empty"
    );
    assert!(
        wgsl.contains("@compute") && wgsl.contains("fn main"),
        "{id} lowered WGSL must contain a compute entry point"
    );
    assert!(
        line_count < 1_000_000,
        "{id} lowered WGSL has unreasonable line count: {line_count}"
    );
}