vyre-wgpu 0.1.0

wgpu backend for vyre IR — implements VyreBackend, owns GPU runtime, buffer pool, pipeline cache
Documentation
//! GPU buffer and bind-group construction helpers for the DFA scan engine.
//!
//! All DFA scan dispatches share the same 4-binding layout (input,
//! matches, match_count, params). These helpers keep the allocation
//! shapes consistent across the one-shot `scan` path and the
//! reusable `ScanResources` path, so a single place owns match-buffer
//! sizing, stride math, and wgpu error translation.

use crate::bytemuck_safe::safe_bytes_of_slice;
use crate::engine::dfa::MAX_DFA_MATCHES;
use vyre::error::{Error, Result};
use wgpu::util::DeviceExt;

pub(crate) fn buffer(
    device: &wgpu::Device,
    label: &'static str,
    size: u64,
    usage: wgpu::BufferUsages,
) -> wgpu::Buffer {
    device.create_buffer(&wgpu::BufferDescriptor {
        label: Some(label),
        size,
        usage,
        mapped_at_creation: false,
    })
}

pub(crate) fn entry(binding: u32, buffer: &wgpu::Buffer) -> wgpu::BindGroupEntry<'_> {
    wgpu::BindGroupEntry {
        binding,
        resource: buffer.as_entire_binding(),
    }
}

pub(crate) fn storage_buffer(
    device: &wgpu::Device,
    label: &'static str,
    data: &[u32],
) -> wgpu::Buffer {
    if data.is_empty() {
        return buffer(device, label, 4, wgpu::BufferUsages::STORAGE);
    }
    device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
        label: Some(label),
        contents: safe_bytes_of_slice(data),
        usage: wgpu::BufferUsages::STORAGE,
    })
}

pub(crate) fn buffer_bytes(items: usize) -> Result<u64> {
    items
        .checked_mul(std::mem::size_of::<u32>())
        .map(u64::try_from)
        .transpose()
        .map_err(|source| Error::Dfa {
            message: format!(
                "DFA buffer byte count cannot fit u64: {source}. Fix: reduce buffer size."
            ),
        })?
        .ok_or_else(|| Error::Dfa {
            message: format!(
                "DFA buffer item count {items} overflows byte sizing. Fix: reduce buffer size."
            ),
        })
}

pub(crate) fn match_buffer_size(max_matches: u32) -> Result<u64> {
    if max_matches > MAX_DFA_MATCHES {
        return Err(Error::Dfa {
            message: format!(
                "DFA max_matches {max_matches} exceeds {MAX_DFA_MATCHES}. Fix: lower max_matches."
            ),
        });
    }
    u64::from(max_matches)
        .checked_mul(3)
        .and_then(|items| items.checked_mul(u64::try_from(std::mem::size_of::<u32>()).ok()?))
        .ok_or_else(|| Error::Dfa {
            message: format!(
                "DFA max_matches {max_matches} overflows output buffer sizing. Fix: lower max_matches."
            ),
        })
}

pub(crate) fn gpu_err<T>(message: &str) -> Result<T> {
    Err(Error::Dfa {
        message: message.to_string(),
    })
}