@@ -182,35 +182,15 @@ impl SpirvType<'_> {
182
182
Self :: Vector { element, count } => cx. emit_global ( ) . type_vector_id ( id, element, count) ,
183
183
Self :: Matrix { element, count } => cx. emit_global ( ) . type_matrix_id ( id, element, count) ,
184
184
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) ;
198
189
result
199
190
}
200
191
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) ;
214
194
result
215
195
}
216
196
Self :: Pointer { pointee } => {
@@ -278,6 +258,19 @@ impl SpirvType<'_> {
278
258
result
279
259
}
280
260
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
+
281
274
/// `def_with_id` is used by the `RecursivePointeeCache` to handle `OpTypeForwardPointer`: when
282
275
/// emitting the subsequent `OpTypePointer`, the ID is already known and must be re-used.
283
276
pub fn def_with_id ( self , cx : & CodegenCx < ' _ > , def_span : Span , id : Word ) -> Word {
@@ -386,6 +379,35 @@ impl SpirvType<'_> {
386
379
}
387
380
}
388
381
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
+
389
411
/// Replace `&[T]` fields with `&'tcx [T]` ones produced by calling
390
412
/// `tcx.arena.dropless.alloc_slice(...)` - this is done late for two reasons:
391
413
/// 1. it avoids allocating in the arena when the cache would be hit anyway,
0 commit comments