@@ -108,6 +108,13 @@ pub(super) enum StoreValue {
108108 base : Handle < crate :: Type > ,
109109 member_index : u32 ,
110110 } ,
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+ } ,
111118}
112119
113120impl < W : fmt:: Write > super :: Writer < ' _ , W > {
@@ -290,6 +297,15 @@ impl<W: fmt::Write> super::Writer<'_, W> {
290297 let name = & self . names [ & NameKey :: StructMember ( base, member_index) ] ;
291298 write ! ( self . out, "{STORE_TEMP_NAME}{depth}.{name}" ) ?
292299 }
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+ }
293309 }
294310 Ok ( ( ) )
295311 }
@@ -302,6 +318,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
302318 value : StoreValue ,
303319 func_ctx : & FunctionCtx ,
304320 level : crate :: back:: Level ,
321+ within_struct : Option < Handle < crate :: Type > > ,
305322 ) -> BackendResult {
306323 let temp_resolution;
307324 let ty_resolution = match value {
@@ -325,6 +342,9 @@ impl<W: fmt::Write> super::Writer<'_, W> {
325342 temp_resolution = TypeResolution :: Handle ( ty_handle) ;
326343 & temp_resolution
327344 }
345+ StoreValue :: TempColumnAccess { .. } => {
346+ unreachable ! ( "attempting write_storage_store for TempColumnAccess" ) ;
347+ }
328348 } ;
329349 match * ty_resolution. inner_with ( & module. types ) {
330350 crate :: TypeInner :: Scalar ( scalar) => {
@@ -372,37 +392,92 @@ impl<W: fmt::Write> super::Writer<'_, W> {
372392 rows,
373393 scalar,
374394 } => {
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-
391395 // Note: Matrices containing vec3s, due to padding, act like they contain vec4s.
392396 let row_stride = Alignment :: from ( rows) * scalar. width as u32 ;
393397
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+ }
406481 }
407482 // done
408483 writeln ! ( self . out, "{level}}}" ) ?;
@@ -415,7 +490,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
415490 // first, assign the value to a temporary
416491 writeln ! ( self . out, "{level}{{" ) ?;
417492 write ! ( self . out, "{}" , level. next( ) ) ?;
418- self . write_value_type ( module, & module . types [ base] . inner ) ?;
493+ self . write_type ( module, base) ?;
419494 let depth = level. next ( ) . 0 ;
420495 write ! ( self . out, " {STORE_TEMP_NAME}{depth}" ) ?;
421496 self . write_array_size ( module, base, crate :: ArraySize :: Constant ( size) ) ?;
@@ -430,7 +505,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
430505 index : i,
431506 ty : TypeResolution :: Handle ( base) ,
432507 } ;
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 ) ?;
434509 self . temp_access_chain . pop ( ) ;
435510 }
436511 // done
@@ -461,7 +536,14 @@ impl<W: fmt::Write> super::Writer<'_, W> {
461536 base : struct_ty,
462537 member_index : i as u32 ,
463538 } ;
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+ ) ?;
465547 self . temp_access_chain . pop ( ) ;
466548 }
467549 // done
0 commit comments