@@ -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,11 @@ 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
+ return Err ( Error :: Unreachable (
347
+ "attempting write_storage_store for TempColumnAccess" . into ( ) ,
348
+ ) ) ;
349
+ }
328
350
} ;
329
351
match * ty_resolution. inner_with ( & module. types ) {
330
352
crate :: TypeInner :: Scalar ( scalar) => {
@@ -372,37 +394,89 @@ impl<W: fmt::Write> super::Writer<'_, W> {
372
394
rows,
373
395
scalar,
374
396
} => {
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
397
// Note: Matrices containing vec3s, due to padding, act like they contain vec4s.
392
398
let row_stride = Alignment :: from ( rows) * scalar. width as u32 ;
393
399
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
+ writeln ! ( self . out, "{level}{{" ) ?;
401
+
402
+ if let Some ( containing_struct) = within_struct {
403
+ // If we are within a struct, then the struct was already assigned to
404
+ // a temporary, we don't need to make another.
405
+ let mut chain = mem:: take ( & mut self . temp_access_chain ) ;
406
+ for i in 0 ..columns as u32 {
407
+ chain. push ( SubAccess :: Offset ( i * row_stride) ) ;
408
+ // working around the borrow checker in `self.write_expr`
409
+ let var_name = & self . names [ & NameKey :: GlobalVariable ( var_handle) ] ;
410
+ let StoreValue :: TempAccess { member_index, .. } = value else {
411
+ return Err ( Error :: Unreachable (
412
+ "write_storage_store within_struct but not TempAccess" . into ( ) ,
413
+ ) ) ;
414
+ } ;
415
+ let column_value = StoreValue :: TempColumnAccess {
416
+ depth : level. 0 , // note not incrementing, b/c no temp
417
+ base : containing_struct,
418
+ member_index,
419
+ column : i,
420
+ } ;
421
+ // See note about DXC and Load/Store in the module's documentation.
422
+ if scalar. width == 4 {
423
+ write ! (
424
+ self . out,
425
+ "{}{}.Store{}(" ,
426
+ level. next( ) ,
427
+ var_name,
428
+ rows as u8
429
+ ) ?;
430
+ self . write_storage_address ( module, & chain, func_ctx) ?;
431
+ write ! ( self . out, ", asuint(" ) ?;
432
+ self . write_store_value ( module, & column_value, func_ctx) ?;
433
+ writeln ! ( self . out, "));" ) ?;
434
+ } else {
435
+ write ! ( self . out, "{}{var_name}.Store(" , level. next( ) ) ?;
436
+ self . write_storage_address ( module, & chain, func_ctx) ?;
437
+ write ! ( self . out, ", " ) ?;
438
+ self . write_store_value ( module, & column_value, func_ctx) ?;
439
+ writeln ! ( self . out, ");" ) ?;
440
+ }
441
+ chain. pop ( ) ;
442
+ }
443
+ self . temp_access_chain = chain;
444
+ } else {
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 ,
400
455
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 ( ) ;
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
+ }
406
480
}
407
481
// done
408
482
writeln ! ( self . out, "{level}}}" ) ?;
@@ -415,7 +489,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
415
489
// first, assign the value to a temporary
416
490
writeln ! ( self . out, "{level}{{" ) ?;
417
491
write ! ( self . out, "{}" , level. next( ) ) ?;
418
- self . write_value_type ( module, & module . types [ base] . inner ) ?;
492
+ self . write_type ( module, base) ?;
419
493
let depth = level. next ( ) . 0 ;
420
494
write ! ( self . out, " {STORE_TEMP_NAME}{depth}" ) ?;
421
495
self . write_array_size ( module, base, crate :: ArraySize :: Constant ( size) ) ?;
@@ -430,7 +504,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
430
504
index : i,
431
505
ty : TypeResolution :: Handle ( base) ,
432
506
} ;
433
- self . write_storage_store ( module, var_handle, sv, func_ctx, level. next ( ) ) ?;
507
+ self . write_storage_store ( module, var_handle, sv, func_ctx, level. next ( ) , None ) ?;
434
508
self . temp_access_chain . pop ( ) ;
435
509
}
436
510
// done
@@ -461,7 +535,14 @@ impl<W: fmt::Write> super::Writer<'_, W> {
461
535
base : struct_ty,
462
536
member_index : i as u32 ,
463
537
} ;
464
- self . write_storage_store ( module, var_handle, sv, func_ctx, level. next ( ) ) ?;
538
+ self . write_storage_store (
539
+ module,
540
+ var_handle,
541
+ sv,
542
+ func_ctx,
543
+ level. next ( ) ,
544
+ Some ( struct_ty) ,
545
+ ) ?;
465
546
self . temp_access_chain . pop ( ) ;
466
547
}
467
548
// done
0 commit comments