@@ -30,8 +30,8 @@ impl<T: AsStd430, U: AsStd430 + Default> Default for StorageBuffer<T, U> {
30
30
impl < T : AsStd430 , U : AsStd430 > StorageBuffer < T , U > {
31
31
// NOTE: AsStd430::std430_size_static() uses size_of internally but trait functions cannot be
32
32
// marked as const functions
33
- const BODY_SIZE : usize = std:: mem:: size_of :: < U > ( ) ;
34
- const ITEM_SIZE : usize = std:: mem:: size_of :: < T > ( ) ;
33
+ const BODY_SIZE : usize = std:: mem:: size_of :: < U :: Output > ( ) ;
34
+ const ITEM_SIZE : usize = std:: mem:: size_of :: < T :: Output > ( ) ;
35
35
36
36
/// Gets the reference to the underlying buffer, if one has been allocated.
37
37
#[ inline]
@@ -139,3 +139,76 @@ impl<T: AsStd430, U: AsStd430> StorageBuffer<T, U> {
139
139
self . values . append ( values) ;
140
140
}
141
141
}
142
+
143
+ #[ cfg( test) ]
144
+ mod tests {
145
+ use super :: StorageBuffer ;
146
+ use bevy_crevice:: std430;
147
+ use bevy_crevice:: std430:: AsStd430 ;
148
+ use bevy_crevice:: std430:: Std430 ;
149
+ use bevy_math:: Vec3 ;
150
+ use bevy_math:: Vec4 ;
151
+
152
+ //Note:
153
+ //A Vec3 has 12 bytes and needs to be padded to 16 bytes, when converted to std430
154
+ //https://www.w3.org/TR/WGSL/#alignment-and-size
155
+ #[ derive( AsStd430 , Default ) ]
156
+ struct NotInherentlyAligned {
157
+ data : Vec3 ,
158
+ }
159
+
160
+ //Note:
161
+ //A Vec4 has 16 bytes and does not need to be padded to fit in std430
162
+ //https://www.w3.org/TR/WGSL/#alignment-and-size
163
+ #[ derive( AsStd430 ) ]
164
+ struct InherentlyAligned {
165
+ data : Vec4 ,
166
+ }
167
+
168
+ #[ test]
169
+ fn storage_buffer_correctly_sized_nonaligned ( ) {
170
+ let mut buffer: StorageBuffer < NotInherentlyAligned > = StorageBuffer :: default ( ) ;
171
+ buffer. push ( NotInherentlyAligned { data : Vec3 :: ONE } ) ;
172
+
173
+ let actual_size = buffer. size ( ) ;
174
+
175
+ let data = [ NotInherentlyAligned { data : Vec3 :: ONE } ] . as_std430 ( ) ;
176
+ let data_as_bytes = data. as_bytes ( ) ;
177
+
178
+ assert_eq ! ( actual_size, data_as_bytes. len( ) ) ;
179
+ }
180
+
181
+ #[ test]
182
+ fn storage_buffer_correctly_sized_aligned ( ) {
183
+ let mut buffer: StorageBuffer < InherentlyAligned > = StorageBuffer :: default ( ) ;
184
+ buffer. push ( InherentlyAligned { data : Vec4 :: ONE } ) ;
185
+
186
+ let actual_size = buffer. size ( ) ;
187
+
188
+ let data = [ InherentlyAligned { data : Vec4 :: ONE } ] . as_std430 ( ) ;
189
+ let data_as_bytes = data. as_bytes ( ) ;
190
+
191
+ assert_eq ! ( actual_size, data_as_bytes. len( ) ) ;
192
+ }
193
+
194
+ #[ test]
195
+ fn storage_buffer_correctly_sized_item_and_body ( ) {
196
+ let mut buffer: StorageBuffer < NotInherentlyAligned , NotInherentlyAligned > =
197
+ StorageBuffer :: default ( ) ;
198
+ buffer. push ( NotInherentlyAligned { data : Vec3 :: ONE } ) ;
199
+ buffer. set_body ( NotInherentlyAligned { data : Vec3 :: ONE } ) ;
200
+
201
+ let calculated_size = buffer. size ( ) ;
202
+
203
+ //Emulate Write
204
+ let mut scratch = Vec :: < u8 > :: new ( ) ;
205
+ scratch. resize ( calculated_size, 0 ) ;
206
+ let mut writer = std430:: Writer :: new ( & mut scratch[ 0 ..calculated_size] ) ;
207
+ writer
208
+ . write ( & buffer. body )
209
+ . expect ( "Buffer has enough space to write the body." ) ;
210
+ writer
211
+ . write ( buffer. values . as_slice ( ) )
212
+ . expect ( "Buffer has enough space to write the values." ) ;
213
+ }
214
+ }
0 commit comments