pub struct BufferDecl {Show 13 fields
pub name: Arc<str>,
pub binding: u32,
pub access: BufferAccess,
pub kind: MemoryKind,
pub element: DataType,
pub count: u32,
pub is_output: bool,
pub pipeline_live_out: bool,
pub output_byte_range: Option<Range<usize>>,
pub hints: MemoryHints,
pub bytes_extraction: bool,
pub linear_type: LinearType,
pub shape_predicate: Option<ShapePredicate>,
}Expand description
A named buffer binding in a program.
§Examples
use vyre::ir::{BufferDecl, BufferAccess, DataType};
let buf = BufferDecl::read("input", 0, DataType::U32);
assert_eq!(buf.name(), "input");
assert_eq!(buf.binding(), 0);Fields§
§name: Arc<str>Human-readable name. Referenced by Expr::Load, Node::Store, etc.
binding: u32Binding slot: @binding(N). All buffers are in @group(0).
Ignored for BufferAccess::Workgroup.
access: BufferAccessAccess mode.
kind: MemoryKindMemory tier.
element: DataTypeElement data type.
count: u32Number of elements.
For Workgroup memory this is the static array length.
For storage and uniform buffers this is 0 (runtime-sized).
is_output: boolWhether this buffer is the scalar expression output for composition inlining.
pipeline_live_out: boolWhether the end-to-end pipeline reads this buffer after Program execution.
Passes must treat this as an externally-visible sink even when the IR itself does not read the buffer again.
output_byte_range: Option<Range<usize>>Optional byte range to read back from this output buffer.
None preserves the historical behavior and reads back the full
declared output buffer.
hints: MemoryHintsNon-binding backend optimization hints.
bytes_extraction: boolWhen true, admits DataType::Bytes load/store despite V013.
Bytes-producing or bytes-extraction ops (decode.base64,
compression.lz4_decompress, match.dfa_scan position emission, etc.)
opt into V013 relaxation per-buffer. Default false keeps scalar
arithmetic protected from accidental bytes-blob reinterpretation.
linear_type: LinearTypeLinear-type discipline for this buffer (P-1.0-V2.1).
Defaults to LinearType::Unrestricted so existing programs
continue to type-check. Authors opt in by calling
BufferDecl::with_linear_type. The type-checker pass
(crate::validate::linear_type) walks the IR and
rejects programs that violate the declared discipline; backends
that hit a violation surface it as a validation error before
lowering.
shape_predicate: Option<ShapePredicate>Optional shape-refinement predicate (P-1.0-V3.1).
None is the default (no shape constraint, identical to the
pre-V3.x IR). Authors opt in via
BufferDecl::with_shape_predicate. The validator
(crate::validate::shape_predicate::check_shape_predicates)
evaluates each predicate against the program’s static count
at validate() time and rejects programs whose static shape
contradicts the declaration.
Implementations§
Source§impl BufferDecl
impl BufferDecl
Sourcepub fn storage(
name: &str,
binding: u32,
access: BufferAccess,
element: DataType,
) -> BufferDecl
pub fn storage( name: &str, binding: u32, access: BufferAccess, element: DataType, ) -> BufferDecl
Create a storage buffer declaration.
§Examples
use vyre::ir::{BufferDecl, BufferAccess, DataType};
let _ = BufferDecl::storage("a", 0, BufferAccess::ReadOnly, DataType::U32);Sourcepub fn read(name: &str, binding: u32, element: DataType) -> BufferDecl
pub fn read(name: &str, binding: u32, element: DataType) -> BufferDecl
Shorthand for a read-only storage buffer.
§Examples
use vyre::ir::{BufferDecl, DataType};
let _ = BufferDecl::read("a", 0, DataType::U32);Sourcepub fn read_write(name: &str, binding: u32, element: DataType) -> BufferDecl
pub fn read_write(name: &str, binding: u32, element: DataType) -> BufferDecl
Shorthand for a read-write storage buffer.
§Examples
use vyre::ir::{BufferDecl, DataType};
let _ = BufferDecl::read_write("a", 0, DataType::U32);Sourcepub fn output(name: &str, binding: u32, element: DataType) -> BufferDecl
pub fn output(name: &str, binding: u32, element: DataType) -> BufferDecl
Shorthand for the read-write result buffer used by call inlining.
§Examples
use vyre::ir::{BufferDecl, DataType};
let _ = BufferDecl::output("a", 0, DataType::U32);Sourcepub fn with_pipeline_live_out(self, flag: bool) -> BufferDecl
pub fn with_pipeline_live_out(self, flag: bool) -> BufferDecl
Mark whether a caller/backend observes this buffer after Program execution.
Sourcepub fn with_output_byte_range(self, range: Range<usize>) -> BufferDecl
pub fn with_output_byte_range(self, range: Range<usize>) -> BufferDecl
Attach an output byte range for backends that can read back a slice.
Sourcepub fn with_count(self, count: u32) -> BufferDecl
pub fn with_count(self, count: u32) -> BufferDecl
Set the static element count for storage-style buffers.
Set the element count. A count of 0 retains the IR’s
runtime-sized-buffer representation; validators reject zero-sized
workgroup allocations before dispatch.
Sourcepub fn uniform(name: &str, binding: u32, element: DataType) -> BufferDecl
pub fn uniform(name: &str, binding: u32, element: DataType) -> BufferDecl
Shorthand for a uniform buffer.
§Examples
use vyre::ir::{BufferDecl, DataType};
let _ = BufferDecl::uniform("a", 0, DataType::U32);Sourcepub fn workgroup(name: &str, count: u32, element: DataType) -> BufferDecl
pub fn workgroup(name: &str, count: u32, element: DataType) -> BufferDecl
Shorthand for a workgroup-local shared array.
count is the static number of elements visible to all invocations
in the same workgroup.
§Examples
use vyre::ir::{BufferAccess, BufferDecl, DataType, MemoryKind};
let scratch = BufferDecl::workgroup("scratch", 64, DataType::U32);
assert_eq!(scratch.name(), "scratch");
assert_eq!(scratch.access(), BufferAccess::Workgroup);
assert_eq!(scratch.kind(), MemoryKind::Shared);
assert_eq!(scratch.count(), 64);Sourcepub fn with_bytes_extraction(self, flag: bool) -> BufferDecl
pub fn with_bytes_extraction(self, flag: bool) -> BufferDecl
Mark this buffer as a bytes-extraction context so V013 admits Bytes load/store.
Sourcepub fn with_linear_type(self, linear_type: LinearType) -> BufferDecl
pub fn with_linear_type(self, linear_type: LinearType) -> BufferDecl
Set the linear-type discipline (P-1.0-V2.1).
Defaults to LinearType::Unrestricted from the constructor;
the type-checker pass enforces stricter disciplines when set.
Sourcepub fn with_shape_predicate(self, predicate: ShapePredicate) -> BufferDecl
pub fn with_shape_predicate(self, predicate: ShapePredicate) -> BufferDecl
Set the shape-refinement predicate (P-1.0-V3.1).
Defaults to None (unconstrained); the validator
(crate::validate::shape_predicate::check_shape_predicates)
rejects programs whose static count violates the predicate.
Sourcepub fn with_kind(self, kind: MemoryKind) -> BufferDecl
pub fn with_kind(self, kind: MemoryKind) -> BufferDecl
Override the memory tier.
Sourcepub fn with_hints(self, hints: MemoryHints) -> BufferDecl
pub fn with_hints(self, hints: MemoryHints) -> BufferDecl
Override memory optimization hints.
Sourcepub fn access(&self) -> BufferAccess
pub fn access(&self) -> BufferAccess
Buffer access mode.
Sourcepub fn kind(&self) -> MemoryKind
pub fn kind(&self) -> MemoryKind
Memory tier.
Sourcepub fn hints(&self) -> MemoryHints
pub fn hints(&self) -> MemoryHints
Non-binding memory hints.
Sourcepub fn has_static_element_count(&self) -> bool
pub fn has_static_element_count(&self) -> bool
Whether Self::count is a static array length that reaches generated
backend code, rather than a runtime-sized binding length.
This mirrors, arm for arm, the MemoryClass::Shared and
MemoryClass::Scratch cases of vyre_lower::lower::memory_class, which
is the single Program-to-descriptor boundary every emitter reads. Those
two classes are the ones whose element_count becomes a fixed-length
array in emitted code (.shared byte length in PTX,
array<T, N> in WGSL); every other class emits a runtime-sized array
and ignores the count.
Persistent is excluded because it is rejected before classification.
Compiled-pipeline cache identity uses this to decide whether count
belongs in the cache key: including it for a runtime-sized storage
buffer would recompile the shader on every buffer resize, and omitting
it for a workgroup buffer would let two different shared-memory array
lengths share one cache entry.
Sourcepub fn static_byte_len(&self) -> Result<Option<usize>, String>
pub fn static_byte_len(&self) -> Result<Option<usize>, String>
Static packed byte length for fixed-size buffers.
Returns Ok(None) for runtime-sized buffer declarations (count == 0)
and for fixed-count buffers whose element type is runtime-sized. Sub-byte
element types use their packed bit width, so three I4 elements occupy
two bytes rather than three conservative one-byte lanes.
§Errors
Returns an actionable diagnostic when the packed byte count overflows.
Sourcepub fn is_output(&self) -> bool
pub fn is_output(&self) -> bool
Return true when this buffer is the unique inlining result buffer.
Sourcepub fn is_pipeline_live_out(&self) -> bool
pub fn is_pipeline_live_out(&self) -> bool
Return true when the buffer must survive IR-local deadness analysis.
Sourcepub fn is_backend_allocated_output(&self) -> bool
pub fn is_backend_allocated_output(&self) -> bool
True when a backend ALLOCATES this buffer’s storage (an output it writes) rather
than reading it from the dispatch inputs: an is_output buffer, any WriteOnly
buffer, or a pipeline_live_out ReadWrite intermediate.
This is the SINGLE cross-backend definition of “backend-allocated output”: the reference interpreter, the CpuRef backend, and the device drivers MUST all agree on which buffers they allocate-and-write vs. read from inputs, so each calls this method instead of re-deriving the predicate. Drift here would make the interpreter and a backend disagree on a program’s outputs (a silent readback bug).
Sourcepub fn require_static_readback_size(&self) -> Result<(), String>
pub fn require_static_readback_size(&self) -> Result<(), String>
Refuse this buffer when it is backend-allocated and has no static size.
A buffer selected by Self::is_backend_allocated_output never receives
host bytes, so count == 0 leaves an executor nothing to size its
allocation or its readback from. Every execution path calls this rather
than re-deriving the condition, so the reference interpreter refuses
exactly what the device backends refuse. An oracle that accepts what its
targets reject certifies programs that cannot run.
A writable buffer that is NOT backend-allocated (a plain ReadWrite) is
deliberately accepted: it consumes one host input slot, so its element
count is inferable from the bytes the caller supplies and is resolved per
dispatch.
§Examples
use vyre::ir::{BufferDecl, DataType};
// No count and backend-allocated: refused, and the message names the remedy.
let error = BufferDecl::output("out", 0, DataType::U32)
.require_static_readback_size()
.expect_err("a countless output has no readback size");
assert!(error.contains(".with_count(n)"));
// A count makes it well-formed.
assert!(BufferDecl::output("out", 0, DataType::U32)
.with_count(4)
.require_static_readback_size()
.is_ok());
// A plain read_write takes its size from the caller's bytes, so it is fine.
assert!(BufferDecl::read_write("rw", 1, DataType::U32)
.require_static_readback_size()
.is_ok());§Errors
Returns the operator-facing message when this buffer is backend-allocated
and its readback size cannot be determined. A count of zero means
“runtime-sized” rather than “zero elements”, since count defaults to
zero and so cannot represent a declared empty buffer. An explicit
output_byte_range states the readback size directly, so it satisfies
this check on its own: that is how a legitimately EMPTY output declares
itself, with .with_output_byte_range(0..0). Without that escape an
empty-input program is indistinguishable from a mis-declared one, and the
only way to pass is to inflate the count to a nonzero value the buffer
does not have.
Sourcepub fn output_byte_range(&self) -> Option<Range<usize>>
pub fn output_byte_range(&self) -> Option<Range<usize>>
Byte range the consumer needs from this output buffer, if declared.
Sourcepub fn linear_type(&self) -> LinearType
pub fn linear_type(&self) -> LinearType
Linear-type discipline (P-1.0-V2.1).
Sourcepub fn shape_predicate(&self) -> Option<&ShapePredicate>
pub fn shape_predicate(&self) -> Option<&ShapePredicate>
Shape-refinement predicate (P-1.0-V3.1).
Trait Implementations§
Source§impl Clone for BufferDecl
impl Clone for BufferDecl
Source§fn clone(&self) -> BufferDecl
fn clone(&self) -> BufferDecl
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BufferDecl
impl Debug for BufferDecl
impl Eq for BufferDecl
Source§impl Hash for BufferDecl
impl Hash for BufferDecl
Source§impl PartialEq for BufferDecl
impl PartialEq for BufferDecl
impl StructuralPartialEq for BufferDecl
Auto Trait Implementations§
impl Freeze for BufferDecl
impl RefUnwindSafe for BufferDecl
impl Send for BufferDecl
impl Sync for BufferDecl
impl Unpin for BufferDecl
impl UnsafeUnpin for BufferDecl
impl UnwindSafe for BufferDecl
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more