vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Integration tests for wgpu dispatch correctness.
//!
//! Tests cover adapter discovery, identity shader dispatch, and the
//! non-word-aligned input length contract.

use crate::pipeline::backend::{ConformDispatchConfig, WgslBackend};

#[test]
fn wgpu_backend_creates_if_gpu_available() {
    let _backend =
        crate::pipeline::backend::require_gpu().expect("vyre-conform test needs a GPU adapter");
}

#[test]
fn wgpu_backend_dispatches_identity_shader() {
    let backend =
        crate::pipeline::backend::require_gpu().expect("vyre-conform test needs a GPU adapter");

    let wgsl = r"
fn vyre_op(index: u32, input_len: u32) -> u32 {
    return input.data[index];
}
";
    let shader = crate::pipeline::backend::wrap_shader(wgsl, &ConformDispatchConfig::default());
    let input = 42u32.to_le_bytes().to_vec();
    let result = backend
        .dispatch(&shader, &input, 4, ConformDispatchConfig::default())
        .expect("identity dispatch must succeed");
    assert_eq!(result, input, "identity shader must return input unchanged");
}

#[test]
fn wgpu_backend_non_word_aligned_input_len_parity() {
    let backend =
        crate::pipeline::backend::require_gpu().expect("vyre-conform test needs a GPU adapter");

    // Shader returns input_len so we can verify the backend passes the
    // original byte count, not the padded word count. Mix `input.data[0u]`
    // into the returned value (masked out by `0u`) so naga cannot drop
    // the input storage binding — the runtime bind group layout (input,
    // output) must match the shader's declared bindings.
    let wgsl = r"
fn vyre_op(index: u32, input_len: u32) -> u32 {
    return input_len | (input.data[0u] & 0u);
}
";
    let shader = crate::pipeline::backend::wrap_shader(wgsl, &ConformDispatchConfig::default());
    let input = vec![0x01, 0x02, 0x03, 0x04, 0x05]; // 5 bytes, not a multiple of 4
    let result = backend
        .dispatch(&shader, &input, 4, ConformDispatchConfig::default())
        .expect("dispatch must succeed");

    let gpu_input_len = u32::from_le_bytes([result[0], result[1], result[2], result[3]]);
    assert_eq!(
        gpu_input_len, 5,
        "input_len must be the original byte length (5), not the padded word count (2). \
             Catches shaders that ignore input_len and use arrayLength(&input.data)."
    );
}