use crate::ir::model::program::BufferDecl;
use crate::ir::model::types::{BufferAccess, DataType};
use crate::lower::wgsl::emit::wgsl_element_type;
use crate::lower::wgsl::Error;
use std::fmt::Write as _;
#[inline]
pub(crate) fn emit_buffer_decl(
out: &mut String,
buf: &BufferDecl,
uses_atomics: bool,
) -> Result<(), Error> {
let wgsl_type = wgsl_element_type(buf.element.clone())?;
match &buf.access {
BufferAccess::ReadOnly => {
write!(
out,
"struct _vyre_buf_{name} {{ data: array<{wgsl_type}>, }};\n\
@group(0) @binding({binding})\n\
var<storage, read> {name}: _vyre_buf_{name};\n\n",
name = buf.name,
binding = buf.binding,
)
.expect("write into String never fails");
}
BufferAccess::ReadWrite => {
if uses_atomics {
if buf.element != DataType::U32 {
return Err(Error::lowering(format!(
"atomic buffer `{}` has element type `{:?}` but WGSL atomics require u32. Fix: use DataType::U32 for atomic buffers or remove atomic operations from this buffer.",
buf.name, buf.element,
)));
}
write!(
out,
"struct _vyre_buf_{name} {{ data: array<atomic<u32>>, }};\n\
@group(0) @binding({binding})\n\
var<storage, read_write> {name}: _vyre_buf_{name};\n\n",
name = buf.name,
binding = buf.binding,
)
.expect("write into String never fails");
} else {
write!(
out,
"struct _vyre_buf_{name} {{ data: array<{wgsl_type}>, }};\n\
@group(0) @binding({binding})\n\
var<storage, read_write> {name}: _vyre_buf_{name};\n\n",
name = buf.name,
binding = buf.binding,
)
.expect("write into String never fails");
}
}
BufferAccess::Uniform => {
write!(
out,
"struct _vyre_buf_{name} {{ data: array<{wgsl_type}>, }};\n\
@group(0) @binding({binding})\n\
var<uniform> {name}: _vyre_buf_{name};\n\n",
name = buf.name,
binding = buf.binding,
)
.expect("write into String never fails");
}
BufferAccess::Workgroup => {
write!(
out,
"var<workgroup> {name}: array<{wgsl_type}, {count}>;\n\n",
name = buf.name,
wgsl_type = wgsl_element_type(buf.element.clone())?,
count = buf.count,
)
.expect("write into String never fails");
}
}
Ok(())
}