@@ -31,7 +31,7 @@ use super::{
31
31
writer:: { EXTRACT_BITS_FUNCTION , INSERT_BITS_FUNCTION } ,
32
32
BackendResult ,
33
33
} ;
34
- use crate :: { arena:: Handle , proc:: NameKey } ;
34
+ use crate :: { arena:: Handle , proc:: NameKey , ScalarKind } ;
35
35
use std:: fmt:: Write ;
36
36
37
37
#[ derive( Clone , Copy , Debug , Hash , Eq , Ord , PartialEq , PartialOrd ) ]
@@ -128,6 +128,8 @@ impl From<crate::ImageQuery> for ImageQuery {
128
128
}
129
129
}
130
130
131
+ pub ( super ) const IMAGE_STORAGE_LOAD_SCALAR_WRAPPER : & str = "LoadedStorageValueFrom" ;
132
+
131
133
impl < W : Write > super :: Writer < ' _ , W > {
132
134
pub ( super ) fn write_image_type (
133
135
& mut self ,
@@ -513,6 +515,60 @@ impl<W: Write> super::Writer<'_, W> {
513
515
Ok ( ( ) )
514
516
}
515
517
518
+ /// Writes the conversion from a single length storage texture load to a vec4 with the loaded
519
+ /// scalar in its `x` component, 1 in its `a` component and 0 everywhere else.
520
+ fn write_loaded_scalar_to_storage_loaded_value (
521
+ & mut self ,
522
+ scalar_type : crate :: Scalar ,
523
+ ) -> BackendResult {
524
+ const ARGUMENT_VARIABLE_NAME : & str = "arg" ;
525
+ const RETURN_VARIABLE_NAME : & str = "ret" ;
526
+
527
+ let zero;
528
+ let one;
529
+ match scalar_type. kind {
530
+ ScalarKind :: Sint => {
531
+ assert_eq ! (
532
+ scalar_type. width, 4 ,
533
+ "Scalar {scalar_type:?} is not a result from any storage format"
534
+ ) ;
535
+ zero = "0" ;
536
+ one = "1" ;
537
+ }
538
+ ScalarKind :: Uint => match scalar_type. width {
539
+ 4 => {
540
+ zero = "0u" ;
541
+ one = "1u" ;
542
+ }
543
+ 8 => {
544
+ zero = "0uL" ;
545
+ one = "1uL"
546
+ }
547
+ _ => unreachable ! ( "Scalar {scalar_type:?} is not a result from any storage format" ) ,
548
+ } ,
549
+ ScalarKind :: Float => {
550
+ assert_eq ! (
551
+ scalar_type. width, 4 ,
552
+ "Scalar {scalar_type:?} is not a result from any storage format"
553
+ ) ;
554
+ zero = "0.0" ;
555
+ one = "1.0" ;
556
+ }
557
+ _ => unreachable ! ( "Scalar {scalar_type:?} is not a result from any storage format" ) ,
558
+ }
559
+
560
+ let ty = scalar_type. to_hlsl_str ( ) ?;
561
+ writeln ! (
562
+ self . out,
563
+ "{ty}4 {IMAGE_STORAGE_LOAD_SCALAR_WRAPPER}{ty}({ty} {ARGUMENT_VARIABLE_NAME}) {{\
564
+ {ty}4 {RETURN_VARIABLE_NAME} = {ty}4({ARGUMENT_VARIABLE_NAME}, {zero}, {zero}, {one});\
565
+ return {RETURN_VARIABLE_NAME};\
566
+ }}"
567
+ ) ?;
568
+
569
+ Ok ( ( ) )
570
+ }
571
+
516
572
pub ( super ) fn write_wrapped_struct_matrix_get_function_name (
517
573
& mut self ,
518
574
access : WrappedStructMatrixAccess ,
@@ -848,11 +904,12 @@ impl<W: Write> super::Writer<'_, W> {
848
904
Ok ( ( ) )
849
905
}
850
906
851
- /// Helper function that writes compose wrapped functions
852
- pub ( super ) fn write_wrapped_compose_functions (
907
+ /// Helper function that writes wrapped functions for expressions in a function
908
+ pub ( super ) fn write_wrapped_expression_functions (
853
909
& mut self ,
854
910
module : & crate :: Module ,
855
911
expressions : & crate :: Arena < crate :: Expression > ,
912
+ context : Option < & FunctionCtx > ,
856
913
) -> BackendResult {
857
914
for ( handle, _) in expressions. iter ( ) {
858
915
match expressions[ handle] {
@@ -867,6 +924,23 @@ impl<W: Write> super::Writer<'_, W> {
867
924
_ => { }
868
925
} ;
869
926
}
927
+ crate :: Expression :: ImageLoad { image, .. } => {
928
+ // This can only happen in a function as this is not a valid const expression
929
+ match * context. as_ref ( ) . unwrap ( ) . resolve_type ( image, & module. types ) {
930
+ crate :: TypeInner :: Image {
931
+ class : crate :: ImageClass :: Storage { format, .. } ,
932
+ ..
933
+ } => {
934
+ if format. single_component ( ) {
935
+ let scalar: crate :: Scalar = format. into ( ) ;
936
+ if self . wrapped . image_load_scalars . insert ( scalar) {
937
+ self . write_loaded_scalar_to_storage_loaded_value ( scalar) ?;
938
+ }
939
+ }
940
+ }
941
+ _ => { }
942
+ }
943
+ }
870
944
crate :: Expression :: RayQueryGetIntersection { committed, .. } => {
871
945
if committed {
872
946
if !self . written_committed_intersection {
@@ -884,7 +958,7 @@ impl<W: Write> super::Writer<'_, W> {
884
958
Ok ( ( ) )
885
959
}
886
960
887
- // TODO: we could merge this with iteration in write_wrapped_compose_functions ...
961
+ // TODO: we could merge this with iteration in write_wrapped_expression_functions ...
888
962
//
889
963
/// Helper function that writes zero value wrapped functions
890
964
pub ( super ) fn write_wrapped_zero_value_functions (
@@ -1046,7 +1120,7 @@ impl<W: Write> super::Writer<'_, W> {
1046
1120
func_ctx : & FunctionCtx ,
1047
1121
) -> BackendResult {
1048
1122
self . write_wrapped_math_functions ( module, func_ctx) ?;
1049
- self . write_wrapped_compose_functions ( module, func_ctx. expressions ) ?;
1123
+ self . write_wrapped_expression_functions ( module, func_ctx. expressions , Some ( func_ctx ) ) ?;
1050
1124
self . write_wrapped_zero_value_functions ( module, func_ctx. expressions ) ?;
1051
1125
1052
1126
for ( handle, _) in func_ctx. expressions . iter ( ) {
@@ -1476,3 +1550,25 @@ impl<W: Write> super::Writer<'_, W> {
1476
1550
Ok ( ( ) )
1477
1551
}
1478
1552
}
1553
+
1554
+ impl crate :: StorageFormat {
1555
+ /// Returns `true` if there is just one component, otherwise `false`
1556
+ pub ( super ) const fn single_component ( & self ) -> bool {
1557
+ match * self {
1558
+ crate :: StorageFormat :: R16Float
1559
+ | crate :: StorageFormat :: R32Float
1560
+ | crate :: StorageFormat :: R8Unorm
1561
+ | crate :: StorageFormat :: R16Unorm
1562
+ | crate :: StorageFormat :: R8Snorm
1563
+ | crate :: StorageFormat :: R16Snorm
1564
+ | crate :: StorageFormat :: R8Uint
1565
+ | crate :: StorageFormat :: R16Uint
1566
+ | crate :: StorageFormat :: R32Uint
1567
+ | crate :: StorageFormat :: R8Sint
1568
+ | crate :: StorageFormat :: R16Sint
1569
+ | crate :: StorageFormat :: R32Sint
1570
+ | crate :: StorageFormat :: R64Uint => true ,
1571
+ _ => false ,
1572
+ }
1573
+ }
1574
+ }
0 commit comments