@@ -182,35 +182,15 @@ impl SpirvType<'_> {
182182 Self :: Vector { element, count } => cx. emit_global ( ) . type_vector_id ( id, element, count) ,
183183 Self :: Matrix { element, count } => cx. emit_global ( ) . type_matrix_id ( id, element, count) ,
184184 Self :: Array { element, count } => {
185- // ArrayStride decoration wants in *bytes*
186- let element_size = cx
187- . lookup_type ( element)
188- . sizeof ( cx)
189- . expect ( "Element of sized array must be sized" )
190- . bytes ( ) ;
191- let mut emit = cx. emit_global ( ) ;
192- let result = emit. type_array_id ( id, element, count. def_cx ( cx) ) ;
193- emit. decorate (
194- result,
195- Decoration :: ArrayStride ,
196- iter:: once ( Operand :: LiteralBit32 ( element_size as u32 ) ) ,
197- ) ;
185+ let result = cx
186+ . emit_global ( )
187+ . type_array_id ( id, element, count. def_cx ( cx) ) ;
188+ self . decorate_array_stride ( result, element, cx) ;
198189 result
199190 }
200191 Self :: RuntimeArray { element } => {
201- let mut emit = cx. emit_global ( ) ;
202- let result = emit. type_runtime_array_id ( id, element) ;
203- // ArrayStride decoration wants in *bytes*
204- let element_size = cx
205- . lookup_type ( element)
206- . sizeof ( cx)
207- . expect ( "Element of sized array must be sized" )
208- . bytes ( ) ;
209- emit. decorate (
210- result,
211- Decoration :: ArrayStride ,
212- iter:: once ( Operand :: LiteralBit32 ( element_size as u32 ) ) ,
213- ) ;
192+ let result = cx. emit_global ( ) . type_runtime_array_id ( id, element) ;
193+ self . decorate_array_stride ( result, element, cx) ;
214194 result
215195 }
216196 Self :: Pointer { pointee } => {
@@ -278,6 +258,19 @@ impl SpirvType<'_> {
278258 result
279259 }
280260
261+ fn decorate_array_stride ( self , result : u32 , element : u32 , cx : & CodegenCx < ' _ > ) {
262+ let mut emit = cx. emit_global ( ) ;
263+ let ty = cx. lookup_type ( element) ;
264+ if let Some ( element_size) = ty. physical_size ( cx) {
265+ // ArrayStride decoration wants in *bytes*
266+ emit. decorate (
267+ result,
268+ Decoration :: ArrayStride ,
269+ iter:: once ( Operand :: LiteralBit32 ( element_size. bytes ( ) as u32 ) ) ,
270+ ) ;
271+ }
272+ }
273+
281274 /// `def_with_id` is used by the `RecursivePointeeCache` to handle `OpTypeForwardPointer`: when
282275 /// emitting the subsequent `OpTypePointer`, the ID is already known and must be re-used.
283276 pub fn def_with_id ( self , cx : & CodegenCx < ' _ > , def_span : Span , id : Word ) -> Word {
@@ -386,6 +379,35 @@ impl SpirvType<'_> {
386379 }
387380 }
388381
382+ /// Get the physical size of the type needed for explicit layout decorations.
383+ pub fn physical_size ( & self , cx : & CodegenCx < ' _ > ) -> Option < Size > {
384+ match * self {
385+ // TODO(jwollen) Handle physical pointers (PhysicalStorageBuffer)
386+ Self :: Pointer { .. } => None ,
387+
388+ // TODO(jwollen) Handle unsized elements
389+ Self :: Adt { size, .. } => size,
390+
391+ Self :: Array { element, count } => Some (
392+ cx. lookup_type ( element) . physical_size ( cx) ?
393+ * cx. builder
394+ . lookup_const_scalar ( count)
395+ . unwrap ( )
396+ . try_into ( )
397+ . unwrap ( ) ,
398+ ) ,
399+
400+ // Always unsized types
401+ Self :: InterfaceBlock { .. } | Self :: RayQueryKhr | Self :: SampledImage { .. } => None ,
402+
403+ // Descriptor types
404+ Self :: Image { .. } | Self :: AccelerationStructureKhr | Self :: Sampler => None ,
405+
406+ // Primitive types
407+ ty => ty. sizeof ( cx) ,
408+ }
409+ }
410+
389411 /// Replace `&[T]` fields with `&'tcx [T]` ones produced by calling
390412 /// `tcx.arena.dropless.alloc_slice(...)` - this is done late for two reasons:
391413 /// 1. it avoids allocating in the arena when the cache would be hit anyway,
0 commit comments