vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Dispatch configuration for conformance tests.
//!
//! [`ConformDispatchConfig`] encodes the workgroup geometry, calling convention,
//! and buffer initialization policy for a single backend dispatch. The helper
//! [`run_with_all_init_policies`] exists because a correct shader must produce
//! identical results regardless of whether the output buffer is zeroed or
//! poisoned before dispatch.

use crate::spec::types::Convention;

/// Configuration for a single conformance dispatch.
#[derive(Debug, Clone)]
pub struct ConformDispatchConfig {
    /// Workgroup size for this dispatch.
    /// Conformance tests run at both 1 (single-thread correctness) and 64
    /// (parallel correctness) to catch parallelism bugs.
    pub workgroup_size: u32,
    /// Required to cover the full input buffer when the element count exceeds
    /// one workgroup.
    pub workgroup_count: u32,
    /// Determines the buffer layout (bindings and optional lookup table) that
    /// the shader and backend must agree on.
    pub convention: Convention,
    /// Optional: additional lookup table buffer for `Convention::V2`.
    pub lookup_data: Option<Vec<u8>>,
    /// How the backend should initialize the output buffer.
    ///
    /// Conformance tests should pass with any policy. If a test only
    /// passes under `Zero`, the op's WGSL has unwritten output bytes —
    /// that's a bug in the shader, not a conformance requirement.
    pub buffer_init: crate::spec::types::BufferInitPolicy,
}

impl ConformDispatchConfig {
    /// Convert conformance-only dispatch policy into the frozen core backend
    /// policy at the `VyreBackend::dispatch` boundary.
    #[must_use]
    #[inline]
    pub fn to_core(&self) -> vyre::DispatchConfig {
        let mut config = vyre::DispatchConfig::default();
        config.profile = Some(format!(
            "conform:wg_size={};wg_count={};convention={:?};buffer_init={:?};lookup_bytes={}",
            self.workgroup_size,
            self.workgroup_count,
            self.convention,
            self.buffer_init,
            self.lookup_data.as_ref().map_or(0, Vec::len)
        ));
        config
    }
}

impl Default for ConformDispatchConfig {
    fn default() -> Self {
        Self {
            workgroup_size: 1,
            workgroup_count: 1,
            convention: Convention::V1,
            lookup_data: None,
            buffer_init: crate::spec::types::BufferInitPolicy::Zero,
        }
    }
}

/// Run a closure with both `Zero` and `Poison` buffer initialization policies.
///
/// If a test passes under `Zero` but fails under `Poison`, the shader has
/// unwritten output bytes — that is a shader bug, not a backend quirk.
#[inline]
pub fn run_with_all_init_policies<F>(mut op: F)
where
    F: FnMut(crate::spec::types::BufferInitPolicy),
{
    op(crate::spec::types::BufferInitPolicy::Zero);
    op(crate::spec::types::BufferInitPolicy::Poison);
}