@@ -43,74 +43,126 @@ unsafe fn buffer_store_intrinsic<T>(
4343 . write ( value) ;
4444}
4545
46- /// `ByteAddressableBuffer` is an untyped blob of data, allowing loads and stores of arbitrary
47- /// basic data types at arbitrary indices. However, all data must be aligned to size 4, each
48- /// element within the data (e.g. struct fields) must have a size and alignment of a multiple of 4,
49- /// and the `byte_index` passed to load and store must be a multiple of 4 (`byte_index` will be
50- /// rounded down to the nearest multiple of 4). So, it's not technically a *byte* addressable
51- /// buffer, but rather a *word* buffer, but this naming and behavior was inherited from HLSL (where
52- /// it's UB to pass in an index not a multiple of 4).
46+ /// `ByteAddressableBuffer` is a read-only untyped blob of data, allowing loads
47+ /// of arbitrary basic data types at arbitrary indices. See
48+ /// [`MutByteAddressableBuffer`] for a writeable variant.
49+ ///
50+ /// # Alignment
51+ /// All data must be aligned to size 4, each element within the data (e.g.
52+ /// struct fields) must have a size and alignment of a multiple of 4, and the
53+ /// `byte_index` passed to load and store must be a multiple of 4. Technically
54+ /// it's not a *byte* addressable buffer, but rather a *word* buffer, but this
55+ /// naming and behavior was inherited from HLSL (where it's UB to pass in an
56+ /// index not a multiple of 4).
57+ ///
58+ /// # Safety
59+ /// Using these functions allows reading a different type from the buffer than
60+ /// was originally written (by [`MutByteAddressableBuffer`] or the host API),
61+ /// allowing all sorts of safety guarantees to be bypassed (effectively a
62+ /// transmute).
5363#[ repr( transparent) ]
5464pub struct ByteAddressableBuffer < ' a > {
5565 /// The underlying array of bytes, able to be directly accessed.
56- pub data : & ' a mut [ u32 ] ,
66+ pub data : & ' a [ u32 ] ,
5767}
5868
5969impl < ' a > ByteAddressableBuffer < ' a > {
70+ /// Creates a `ByteAddressableBuffer` from the untyped blob of data.
71+ #[ inline]
72+ pub fn new ( data : & ' a [ u32 ] ) -> Self {
73+ Self { data }
74+ }
75+
76+ /// Loads an arbitrary type from the buffer. `byte_index` must be a
77+ /// multiple of 4.
78+ ///
79+ /// # Safety
80+ /// See [`Self`].
81+ pub unsafe fn load < T > ( & self , byte_index : u32 ) -> T {
82+ if byte_index % 4 != 0 {
83+ panic ! ( "`byte_index` should be a multiple of 4" ) ;
84+ }
85+ if byte_index + mem:: size_of :: < T > ( ) as u32 > self . data . len ( ) as u32 {
86+ panic ! (
87+ "index out of bounds: the len is {} but the `byte_index` is {}" ,
88+ self . data. len( ) ,
89+ byte_index
90+ ) ;
91+ }
92+ buffer_load_intrinsic ( self . data , byte_index)
93+ }
94+
95+ /// Loads an arbitrary type from the buffer. `byte_index` must be a
96+ /// multiple of 4.
97+ ///
98+ /// # Safety
99+ /// See [`Self`]. Additionally, bounds or alignment checking is not performed.
100+ pub unsafe fn load_unchecked < T > ( & self , byte_index : u32 ) -> T {
101+ buffer_load_intrinsic ( self . data , byte_index)
102+ }
103+ }
104+
105+ /// `MutByteAddressableBuffer` is a mutable untyped blob of data, allowing
106+ /// loads and stores of arbitrary basic data types at arbitrary indices. See
107+ /// [`ByteAddressableBuffer`] for details.
108+ #[ repr( transparent) ]
109+ pub struct MutByteAddressableBuffer < ' a > {
110+ /// The underlying array of bytes, able to be directly accessed.
111+ pub data : & ' a mut [ u32 ] ,
112+ }
113+
114+ impl < ' a > MutByteAddressableBuffer < ' a > {
60115 /// Creates a `ByteAddressableBuffer` from the untyped blob of data.
61116 #[ inline]
62117 pub fn new ( data : & ' a mut [ u32 ] ) -> Self {
63118 Self { data }
64119 }
65120
66- /// Loads an arbitrary type from the buffer. `byte_index` must be a multiple of 4, otherwise,
67- /// it will get silently rounded down to the nearest multiple of 4.
121+ /// Loads an arbitrary type from the buffer. `byte_index` must be a
122+ /// multiple of 4.
68123 ///
69124 /// # Safety
70- /// This function allows writing a type to an untyped buffer, then reading a different type
71- /// from the same buffer, allowing all sorts of safety guarantees to be bypassed (effectively a
72- /// transmute)
125+ /// See [`Self`].
73126 pub unsafe fn load < T > ( & self , byte_index : u32 ) -> T {
127+ if byte_index % 4 != 0 {
128+ panic ! ( "`byte_index` should be a multiple of 4" ) ;
129+ }
74130 if byte_index + mem:: size_of :: < T > ( ) as u32 > self . data . len ( ) as u32 {
75- panic ! ( "Index out of range" ) ;
131+ panic ! (
132+ "index out of bounds: the len is {} but the `byte_index` is {}" ,
133+ self . data. len( ) ,
134+ byte_index
135+ ) ;
76136 }
77137 buffer_load_intrinsic ( self . data , byte_index)
78138 }
79139
80- /// Loads an arbitrary type from the buffer. `byte_index` must be a multiple of 4, otherwise,
81- /// it will get silently rounded down to the nearest multiple of 4. Bounds checking is not
82- /// performed.
140+ /// Loads an arbitrary type from the buffer. `byte_index` must be a
141+ /// multiple of 4.
83142 ///
84143 /// # Safety
85- /// This function allows writing a type to an untyped buffer, then reading a different type
86- /// from the same buffer, allowing all sorts of safety guarantees to be bypassed (effectively a
87- /// transmute). Additionally, bounds checking is not performed.
144+ /// See [`Self`]. Additionally, bounds or alignment checking is not performed.
88145 pub unsafe fn load_unchecked < T > ( & self , byte_index : u32 ) -> T {
89146 buffer_load_intrinsic ( self . data , byte_index)
90147 }
91148
92- /// Stores an arbitrary type int the buffer. `byte_index` must be a multiple of 4, otherwise,
93- /// it will get silently rounded down to the nearest multiple of 4.
149+ /// Stores an arbitrary type into the buffer. `byte_index` must be a
150+ /// multiple of 4.
94151 ///
95152 /// # Safety
96- /// This function allows writing a type to an untyped buffer, then reading a different type
97- /// from the same buffer, allowing all sorts of safety guarantees to be bypassed (effectively a
98- /// transmute)
153+ /// See [`Self`].
99154 pub unsafe fn store < T > ( & mut self , byte_index : u32 , value : T ) {
100155 if byte_index + mem:: size_of :: < T > ( ) as u32 > self . data . len ( ) as u32 {
101156 panic ! ( "Index out of range" ) ;
102157 }
103158 buffer_store_intrinsic ( self . data , byte_index, value) ;
104159 }
105160
106- /// Stores an arbitrary type int the buffer. `byte_index` must be a multiple of 4, otherwise,
107- /// it will get silently rounded down to the nearest multiple of 4. Bounds checking is not
108- /// performed.
161+ /// Stores an arbitrary type into the buffer. `byte_index` must be a
162+ /// multiple of 4.
109163 ///
110164 /// # Safety
111- /// This function allows writing a type to an untyped buffer, then reading a different type
112- /// from the same buffer, allowing all sorts of safety guarantees to be bypassed (effectively a
113- /// transmute). Additionally, bounds checking is not performed.
165+ /// See [`Self`]. Additionally, bounds or alignment checking is not performed.
114166 pub unsafe fn store_unchecked < T > ( & mut self , byte_index : u32 , value : T ) {
115167 buffer_store_intrinsic ( self . data , byte_index, value) ;
116168 }
0 commit comments