use crate::ir::DataType;
use crate::ops::{AlgebraicLaw, Backend, IntrinsicDescriptor, OpSpec};
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.stack",
INPUTS,
OUTPUTS,
LAWS,
wgsl_only,
IntrinsicDescriptor::new(
"workgroup_stack_push",
"workgroup-sram-atomics",
crate::ops::cpu_op::structured_intrinsic_cpu,
),
);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StackStatus {
Ok = 0,
Overflow = 1,
Underflow = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StackError {
Overflow,
Underflow,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkgroupStack<T> {
capacity: usize,
values: Vec<T>,
}
impl<T: Copy> WorkgroupStack<T> {
#[must_use]
pub fn new(capacity: usize) -> Self {
Self {
capacity,
values: Vec::with_capacity(capacity),
}
}
pub fn push(&mut self, value: T) -> Result<StackStatus, StackError> {
if self.values.len() >= self.capacity {
return Err(StackError::Overflow);
}
self.values.push(value);
Ok(StackStatus::Ok)
}
pub fn pop(&mut self) -> Result<T, StackError> {
self.values.pop().ok_or(StackError::Underflow)
}
pub fn peek(&self) -> Result<T, StackError> {
self.values.last().copied().ok_or(StackError::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)
}