use crate::ir::DataType;
use crate::ops::{AlgebraicLaw, Backend, IntrinsicDescriptor, OpSpec};
use std::collections::VecDeque;
pub const INPUTS: &[DataType] = &[DataType::U32, DataType::U32];
pub const OUTPUTS: &[DataType] = &[DataType::U32, DataType::U32];
pub const LAWS: &[AlgebraicLaw] = &[];
pub const SPEC: OpSpec = OpSpec::intrinsic(
"workgroup.queue_fifo",
INPUTS,
OUTPUTS,
LAWS,
wgsl_only,
IntrinsicDescriptor::new(
"workgroup_queue_fifo_enqueue",
"workgroup-sram-atomic-tail",
crate::ops::cpu_op::structured_intrinsic_cpu,
),
);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FifoStatus {
Ok = 0,
Overflow = 1,
Underflow = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FifoError {
Overflow,
Underflow,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkgroupQueueFifo<T> {
capacity: usize,
values: VecDeque<T>,
}
impl<T: Copy> WorkgroupQueueFifo<T> {
#[must_use]
pub fn new(capacity: usize) -> Self {
Self {
capacity,
values: VecDeque::with_capacity(capacity),
}
}
pub fn enqueue(&mut self, value: T) -> Result<FifoStatus, FifoError> {
if self.values.len() >= self.capacity {
return Err(FifoError::Overflow);
}
self.values.push_back(value);
Ok(FifoStatus::Ok)
}
pub fn dequeue(&mut self) -> Result<T, FifoError> {
self.values.pop_front().ok_or(FifoError::Underflow)
}
#[must_use]
pub fn len(&self) -> usize {
self.values.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
#[must_use]
pub fn capacity(&self) -> usize {
self.capacity
}
}
pub fn wgsl_only(backend: &Backend) -> bool {
matches!(backend, Backend::Wgsl)
}