vyre-driver 0.4.1

Driver layer: registry, runtime, pipeline, routing, diagnostics. Substrate-agnostic backend machinery. Part of the vyre GPU compiler.
docs.rs failed to build vyre-driver-0.4.1
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

vyre-driver

Substrate-agnostic backend machinery for the vyre GPU compiler.

vyre-driver is the second layer in vyre's four-layer model. It sits between vyre-foundation (the IR + validator) and concrete backend crates. It owns the frozen contract every backend must implement, the registry that routes a Program to the right backend, the pipeline-cache key machinery, and the capability surface consumer tools use to decide whether a backend can execute a given program.

vyre-foundation (IR + validator)
   ↓
vyre-driver        ← you are here
   ↓
concrete driver crates

Invariants

  1. Backend trait is frozen. VyreBackend and CompiledPipeline signatures do not change within a major version. New capability flows through BackendCapability registration, never through trait mutation.
  2. Dispatch is deterministic per (program, inputs, config). Two calls with the same triple produce byte-identical outputs on every registered backend. Divergence is a backend bug, caught by the shadow pipeline in shadow.rs.
  3. Registration is side-effect-free at import. Registering a backend inserts a BackendRegistration into the inventory-backed registry but does not initialise devices, allocate memory, or open adapters. Initialisation is deferred to the caller's first dispatch / compile_native.
  4. Precedence is stable. registered_backends_by_precedence() returns backends in ascending BackendPrecedence order and this order is part of the public API; consumer tools rely on it to pick a default backend without inspecting internal state.
  5. Pipeline-cache keys hash the complete Program. Fingerprints use blake3 over the canonical wire form, so two programs with identical IR share a cached pipeline regardless of how they were constructed.
  6. Errors carry a Fix: section. Every BackendError variant's Display implementation ends in Fix: <remediation> so users do not need to guess at recovery.

Boundaries

Concrete-driver isolation is part of the driver contract:

  • Concrete backend crates own their own runtime objects, codegen objects, feature names, tests, target-specific terminology, and concrete API/type names such as adapter objects or launch objects.
  • Shared crates and tools must not import concrete backend crates or spell concrete backend APIs. They depend on vyre-driver traits, registrations, capabilities, shared binding layouts, validation helpers, tuners, and opaque backend ids.
  • If two concrete drivers need the same decision logic, move that logic here as a backend-neutral module. The concrete drivers keep only the target mechanics that cannot be shared.

vyre-driver does:

  • Define VyreBackend, CompiledPipeline, PendingDispatch, DispatchConfig, BackendCapability, and the sealed Backend marker trait.
  • Host backend::registry (inventory-backed discovery), pipeline (compile/dispatch indirection), shadow (reference-diff instrumentation), migration (deprecation + semver registries), binding (neutral ABI plans), fusion (cross-dispatch decisions), specialization (neutral override values), subgroup (operation taxonomy), tuner (candidate/cache framework), and validation (program-level preconditions plus shared validation caches).
  • Expose core_supported_ops() so backend crates and consumer tools can ask "does this backend execute this Program?" without importing any concrete backend.

vyre-driver does NOT:

  • Touch a GPU, open an adapter, or allocate device memory. Those are backend-crate responsibilities.
  • Own the IR (vyre-foundation), the evaluator (vyre-reference), or intrinsics (vyre-intrinsics).
  • Declare workload-specific primitives. Those live in vyre-primitives / vyre-libs and compose over Program.

Three worked examples

1. Pick the best-available backend and dispatch

use vyre_driver::backend::acquire_preferred_dispatch_backend;
use vyre_foundation::ir::Program;

fn run(program: &Program, inputs: &[Vec<u8>]) -> Result<Vec<Vec<u8>>, vyre_driver::BackendError> {
    let backend = acquire_preferred_dispatch_backend()?;
    backend.dispatch(program, inputs, &Default::default())
}

2. Gate a feature on backend capability

use vyre_driver::backend::{registered_backends, core_supported_ops};
use vyre_foundation::ir::Program;

fn can_run(program: &Program) -> bool {
    let ops = core_supported_ops();
    registered_backends()
        .iter()
        .any(|reg| program.ops().all(|op| ops.contains(&op)))
}

3. Instrument with the shadow pipeline

use vyre_driver::shadow::ShadowedPipeline;
use vyre_driver::pipeline::compile;

fn compile_with_shadow(
    primary: &dyn vyre_driver::VyreBackend,
    reference: &dyn vyre_driver::VyreBackend,
    program: &vyre_foundation::ir::Program,
) -> Result<ShadowedPipeline, vyre_driver::BackendError> {
    let main = compile(primary, program)?;
    let refp = compile(reference, program)?;
    Ok(ShadowedPipeline::new(main, refp))
}

Extension guide — adding a new backend

  1. Create a concrete driver crate. Depend on vyre-foundation, vyre-driver, and any backend-neutral shared crate needed by the contract. Do not make shared crates depend back on the concrete driver.
  2. Implement VyreBackend for your backend struct. Include a BackendCapability describing the ops, memory model, subgroup size, and max workgroup extent your hardware supports.
  3. Implement CompiledPipeline for your cached pipeline form. It MUST be bit-identical to the trait's dispatch path.
  4. Register with inventory::submit! — the registry picks it up at link time. No lazy_static, no initializer function.
  5. Add your backend to the conformance matrix under conform/vyre-conform-runner so parity against the reference interpreter is enforced on every CI run.
  6. Expose a BackendPrecedence value so callers that want "the best available backend" pick yours when appropriate.

See capability.rs, registry.rs, and shadow.rs for the exact contracts; see conform/vyre-conform-runner/tests/parity_matrix.rs for a worked wiring that brings a third-party backend online.