vyre-wgpu 0.1.0

wgpu backend for vyre IR — implements VyreBackend, owns GPU runtime, buffer pool, pipeline cache
Documentation
//! Public GPU decode entry points.

use crate::engine::decode::{
    dispatch::gpu, flatten_regions, recursive_decode, DecodeFormat, DecodeRules, DecodedRegion,
};
use vyre::{Error, Result};

/// GPU-backed decoder using vyre's cached runtime device.
///
/// This struct is `#[non_exhaustive]` to allow adding new internal state
/// (like shader caches or command buffers) without breaking consumers.
///
/// # Examples
///
/// ```
/// use vyre_wgpu::engine::decode::GpuDecoder;
///
/// // Requires a GPU device to succeed.
/// let _ = GpuDecoder::new();
/// ```
#[derive(Debug, Clone, Copy, Default)]
#[non_exhaustive]
pub struct GpuDecoder;

impl GpuDecoder {
    /// Create a decoder backed by `vyre::runtime::cached_device()`.
    ///
    /// # Errors
    ///
    /// Returns an error if the GPU device cannot be initialized or if the
    /// hardware is incompatible with the decode shaders.
    pub fn new() -> Result<Self> {
        Self::try_new()
    }

    /// Try to initialize the shared GPU device.
    ///
    /// # Errors
    ///
    /// Returns `Error::Gpu` if the GPU device cannot be initialized.
    pub fn try_new() -> Result<Self> {
        crate::runtime::cached_device()?;
        Ok(Self)
    }

    /// Decode all supported encodings recursively.
    ///
    /// # Errors
    ///
    /// Returns `Error::Decode` if the GPU decode dispatch or recursive frontier management fails.
    /// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
    pub fn decode_recursive(&self, file_bytes: &[u8]) -> Result<Vec<DecodedRegion>> {
        self.decode_recursive_with_rules(file_bytes, &DecodeRules::default())
    }

    /// Decode recursively using caller-provided rules.
    ///
    /// # Errors
    ///
    /// Returns `Error::Decode` if `max_passes` is zero or the GPU decode dispatch fails.
    /// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
    pub fn decode_recursive_with_rules(
        &self,
        file_bytes: &[u8],
        rules: &DecodeRules,
    ) -> Result<Vec<DecodedRegion>> {
        decode_recursive_gpu(file_bytes, rules)
    }
}

/// Decode a byte buffer as one format and concatenate decoded regions.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the default rules are invalid.
/// Returns `Error::Decode` if the GPU decode dispatch fails.
/// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
///
/// # Examples
///
/// ```
/// use vyre_wgpu::engine::decode::{decode_bytes, DecodeFormat};
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let input = b"SGVsbG8=";
/// let decoded = decode_bytes(input, DecodeFormat::Base64)?;
/// assert_eq!(decoded, b"Hello");
/// # Ok(())
/// # }
/// ```
pub fn decode_bytes(input: &[u8], format: DecodeFormat) -> Result<Vec<u8>> {
    decode_regions(input, format, &DecodeRules::default()).map(flatten_regions)
}

/// Decode base64 regions and concatenate their decoded bytes.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the default rules are invalid.
/// Returns `Error::Decode` if the GPU decode dispatch fails.
/// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
pub fn decode_base64(input: &[u8]) -> Result<Vec<u8>> {
    decode_bytes(input, DecodeFormat::Base64)
}

/// Decode hex regions and concatenate their decoded bytes.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the default rules are invalid.
/// Returns `Error::Decode` if the GPU decode dispatch fails.
/// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
pub fn decode_hex(input: &[u8]) -> Result<Vec<u8>> {
    decode_bytes(input, DecodeFormat::Hex)
}

/// Decode URL percent-encoded regions and concatenate their decoded bytes.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the default rules are invalid.
/// Returns `Error::Decode` if the GPU decode dispatch fails.
/// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
pub fn decode_url(input: &[u8]) -> Result<Vec<u8>> {
    decode_bytes(input, DecodeFormat::Url)
}

/// Decode unicode escape regions and concatenate their decoded bytes.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the default rules are invalid.
/// Returns `Error::Decode` if the GPU decode dispatch fails.
/// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
pub fn decode_unicode(input: &[u8]) -> Result<Vec<u8>> {
    decode_bytes(input, DecodeFormat::Unicode)
}

/// Decode bytes recursively on the GPU.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the default rules are invalid.
/// Returns `Error::Gpu` if the GPU device cannot be initialized.
/// Returns `Error::Decode` if the GPU decode dispatch or recursive frontier management fails.
pub fn decode_file(file_bytes: &[u8]) -> Result<Vec<DecodedRegion>> {
    decode_file_with_rules(file_bytes, &DecodeRules::default())
}

/// Decode bytes recursively using caller-provided rules on the GPU.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the provided rules are invalid.
/// Returns `Error::Gpu` if the GPU device cannot be initialized.
/// Returns `Error::Decode` if the GPU decode dispatch or recursive frontier management fails.
pub fn decode_file_with_rules(
    file_bytes: &[u8],
    rules: &DecodeRules,
) -> Result<Vec<DecodedRegion>> {
    rules.validate().map_err(|error| Error::DecodeConfig {
        message: error.to_string(),
    })?;
    GpuDecoder::try_new()?.decode_recursive_with_rules(file_bytes, rules)
}

/// Decode all regions of `format` using the GPU decoder.
///
/// # Errors
///
/// Returns `Error::DecodeConfig` if the provided rules are invalid.
/// Returns `Error::Decode` if the GPU decode dispatch fails.
/// Returns `Error::Gpu` if the GPU device cannot be initialized or a buffer operation fails.
pub fn decode_regions(
    input: &[u8],
    format: DecodeFormat,
    rules: &DecodeRules,
) -> Result<Vec<DecodedRegion>> {
    rules.validate().map_err(|error| Error::DecodeConfig {
        message: error.to_string(),
    })?;
    gpu::dispatch_decode(format, input, rules, None)
}

/// `decode_recursive_gpu` function.
pub fn decode_recursive_gpu(file_bytes: &[u8], rules: &DecodeRules) -> Result<Vec<DecodedRegion>> {
    recursive_decode(file_bytes, rules, |format, input, rules| {
        gpu::dispatch_decode(format, input, rules, None)
    })
}