@@ -108,6 +108,13 @@ pub(super) enum StoreValue {
108
108
base : Handle < crate :: Type > ,
109
109
member_index : u32 ,
110
110
} ,
111
+ // Access to a single column of a Cx2 matrix within a struct
112
+ TempColumnAccess {
113
+ depth : usize ,
114
+ base : Handle < crate :: Type > ,
115
+ member_index : u32 ,
116
+ column : u32 ,
117
+ } ,
111
118
}
112
119
113
120
impl < W : fmt:: Write > super :: Writer < ' _ , W > {
@@ -290,6 +297,15 @@ impl<W: fmt::Write> super::Writer<'_, W> {
290
297
let name = & self . names [ & NameKey :: StructMember ( base, member_index) ] ;
291
298
write ! ( self . out, "{STORE_TEMP_NAME}{depth}.{name}" ) ?
292
299
}
300
+ StoreValue :: TempColumnAccess {
301
+ depth,
302
+ base,
303
+ member_index,
304
+ column,
305
+ } => {
306
+ let name = & self . names [ & NameKey :: StructMember ( base, member_index) ] ;
307
+ write ! ( self . out, "{STORE_TEMP_NAME}{depth}.{name}_{column}" ) ?
308
+ }
293
309
}
294
310
Ok ( ( ) )
295
311
}
@@ -302,6 +318,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
302
318
value : StoreValue ,
303
319
func_ctx : & FunctionCtx ,
304
320
level : crate :: back:: Level ,
321
+ within_struct : Option < Handle < crate :: Type > > ,
305
322
) -> BackendResult {
306
323
let temp_resolution;
307
324
let ty_resolution = match value {
@@ -325,6 +342,9 @@ impl<W: fmt::Write> super::Writer<'_, W> {
325
342
temp_resolution = TypeResolution :: Handle ( ty_handle) ;
326
343
& temp_resolution
327
344
}
345
+ StoreValue :: TempColumnAccess { .. } => {
346
+ unreachable ! ( "attempting write_storage_store for TempColumnAccess" ) ;
347
+ }
328
348
} ;
329
349
match * ty_resolution. inner_with ( & module. types ) {
330
350
crate :: TypeInner :: Scalar ( scalar) => {
@@ -372,37 +392,92 @@ impl<W: fmt::Write> super::Writer<'_, W> {
372
392
rows,
373
393
scalar,
374
394
} => {
375
- // first, assign the value to a temporary
376
- writeln ! ( self . out, "{level}{{" ) ?;
377
- let depth = level. 0 + 1 ;
378
- write ! (
379
- self . out,
380
- "{}{}{}x{} {}{} = " ,
381
- level. next( ) ,
382
- scalar. to_hlsl_str( ) ?,
383
- columns as u8 ,
384
- rows as u8 ,
385
- STORE_TEMP_NAME ,
386
- depth,
387
- ) ?;
388
- self . write_store_value ( module, & value, func_ctx) ?;
389
- writeln ! ( self . out, ";" ) ?;
390
-
391
395
// Note: Matrices containing vec3s, due to padding, act like they contain vec4s.
392
396
let row_stride = Alignment :: from ( rows) * scalar. width as u32 ;
393
397
394
- // then iterate the stores
395
- for i in 0 ..columns as u32 {
396
- self . temp_access_chain
397
- . push ( SubAccess :: Offset ( i * row_stride) ) ;
398
- let ty_inner = crate :: TypeInner :: Vector { size : rows, scalar } ;
399
- let sv = StoreValue :: TempIndex {
400
- depth,
401
- index : i,
402
- ty : TypeResolution :: Value ( ty_inner) ,
403
- } ;
404
- self . write_storage_store ( module, var_handle, sv, func_ctx, level. next ( ) ) ?;
405
- self . temp_access_chain . pop ( ) ;
398
+ writeln ! ( self . out, "{level}{{" ) ?;
399
+
400
+ match within_struct {
401
+ Some ( containing_struct) if rows == crate :: VectorSize :: Bi => {
402
+ // If we are within a struct, then the struct was already assigned to
403
+ // a temporary, we don't need to make another.
404
+ let mut chain = mem:: take ( & mut self . temp_access_chain ) ;
405
+ for i in 0 ..columns as u32 {
406
+ chain. push ( SubAccess :: Offset ( i * row_stride) ) ;
407
+ // working around the borrow checker in `self.write_expr`
408
+ let var_name = & self . names [ & NameKey :: GlobalVariable ( var_handle) ] ;
409
+ let StoreValue :: TempAccess { member_index, .. } = value else {
410
+ unreachable ! (
411
+ "write_storage_store within_struct but not TempAccess"
412
+ ) ;
413
+ } ;
414
+ let column_value = StoreValue :: TempColumnAccess {
415
+ depth : level. 0 , // note not incrementing, b/c no temp
416
+ base : containing_struct,
417
+ member_index,
418
+ column : i,
419
+ } ;
420
+ // See note about DXC and Load/Store in the module's documentation.
421
+ if scalar. width == 4 {
422
+ write ! (
423
+ self . out,
424
+ "{}{}.Store{}(" ,
425
+ level. next( ) ,
426
+ var_name,
427
+ rows as u8
428
+ ) ?;
429
+ self . write_storage_address ( module, & chain, func_ctx) ?;
430
+ write ! ( self . out, ", asuint(" ) ?;
431
+ self . write_store_value ( module, & column_value, func_ctx) ?;
432
+ writeln ! ( self . out, "));" ) ?;
433
+ } else {
434
+ write ! ( self . out, "{}{var_name}.Store(" , level. next( ) ) ?;
435
+ self . write_storage_address ( module, & chain, func_ctx) ?;
436
+ write ! ( self . out, ", " ) ?;
437
+ self . write_store_value ( module, & column_value, func_ctx) ?;
438
+ writeln ! ( self . out, ");" ) ?;
439
+ }
440
+ chain. pop ( ) ;
441
+ }
442
+ self . temp_access_chain = chain;
443
+ }
444
+ _ => {
445
+ // first, assign the value to a temporary
446
+ let depth = level. 0 + 1 ;
447
+ write ! (
448
+ self . out,
449
+ "{}{}{}x{} {}{} = " ,
450
+ level. next( ) ,
451
+ scalar. to_hlsl_str( ) ?,
452
+ columns as u8 ,
453
+ rows as u8 ,
454
+ STORE_TEMP_NAME ,
455
+ depth,
456
+ ) ?;
457
+ self . write_store_value ( module, & value, func_ctx) ?;
458
+ writeln ! ( self . out, ";" ) ?;
459
+
460
+ // then iterate the stores
461
+ for i in 0 ..columns as u32 {
462
+ self . temp_access_chain
463
+ . push ( SubAccess :: Offset ( i * row_stride) ) ;
464
+ let ty_inner = crate :: TypeInner :: Vector { size : rows, scalar } ;
465
+ let sv = StoreValue :: TempIndex {
466
+ depth,
467
+ index : i,
468
+ ty : TypeResolution :: Value ( ty_inner) ,
469
+ } ;
470
+ self . write_storage_store (
471
+ module,
472
+ var_handle,
473
+ sv,
474
+ func_ctx,
475
+ level. next ( ) ,
476
+ None ,
477
+ ) ?;
478
+ self . temp_access_chain . pop ( ) ;
479
+ }
480
+ }
406
481
}
407
482
// done
408
483
writeln ! ( self . out, "{level}}}" ) ?;
@@ -415,7 +490,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
415
490
// first, assign the value to a temporary
416
491
writeln ! ( self . out, "{level}{{" ) ?;
417
492
write ! ( self . out, "{}" , level. next( ) ) ?;
418
- self . write_value_type ( module, & module . types [ base] . inner ) ?;
493
+ self . write_type ( module, base) ?;
419
494
let depth = level. next ( ) . 0 ;
420
495
write ! ( self . out, " {STORE_TEMP_NAME}{depth}" ) ?;
421
496
self . write_array_size ( module, base, crate :: ArraySize :: Constant ( size) ) ?;
@@ -430,7 +505,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
430
505
index : i,
431
506
ty : TypeResolution :: Handle ( base) ,
432
507
} ;
433
- self . write_storage_store ( module, var_handle, sv, func_ctx, level. next ( ) ) ?;
508
+ self . write_storage_store ( module, var_handle, sv, func_ctx, level. next ( ) , None ) ?;
434
509
self . temp_access_chain . pop ( ) ;
435
510
}
436
511
// done
@@ -461,7 +536,14 @@ impl<W: fmt::Write> super::Writer<'_, W> {
461
536
base : struct_ty,
462
537
member_index : i as u32 ,
463
538
} ;
464
- self . write_storage_store ( module, var_handle, sv, func_ctx, level. next ( ) ) ?;
539
+ self . write_storage_store (
540
+ module,
541
+ var_handle,
542
+ sv,
543
+ func_ctx,
544
+ level. next ( ) ,
545
+ Some ( struct_ty) ,
546
+ ) ?;
465
547
self . temp_access_chain . pop ( ) ;
466
548
}
467
549
// done
0 commit comments