@@ -78,6 +78,7 @@ impl Writer {
7878 bounds_check_policies : options. bounds_check_policies ,
7979 zero_initialize_workgroup_memory : options. zero_initialize_workgroup_memory ,
8080 force_loop_bounding : options. force_loop_bounding ,
81+ use_storage_input_output_16 : options. use_storage_input_output_16 ,
8182 void_type,
8283 lookup_type : crate :: FastHashMap :: default ( ) ,
8384 lookup_function : crate :: FastHashMap :: default ( ) ,
@@ -92,6 +93,9 @@ impl Writer {
9293 temp_list : Vec :: new ( ) ,
9394 ray_get_committed_intersection_function : None ,
9495 ray_get_candidate_intersection_function : None ,
96+ io_f16_polyfills : super :: f16_polyfill:: F16IoPolyfill :: new (
97+ options. use_storage_input_output_16 ,
98+ ) ,
9599 } )
96100 }
97101
@@ -125,6 +129,7 @@ impl Writer {
125129 bounds_check_policies : self . bounds_check_policies ,
126130 zero_initialize_workgroup_memory : self . zero_initialize_workgroup_memory ,
127131 force_loop_bounding : self . force_loop_bounding ,
132+ use_storage_input_output_16 : self . use_storage_input_output_16 ,
128133 capabilities_available : take ( & mut self . capabilities_available ) ,
129134 binding_map : take ( & mut self . binding_map ) ,
130135
@@ -151,6 +156,7 @@ impl Writer {
151156 temp_list : take ( & mut self . temp_list ) . recycle ( ) ,
152157 ray_get_candidate_intersection_function : None ,
153158 ray_get_committed_intersection_function : None ,
159+ io_f16_polyfills : take ( & mut self . io_f16_polyfills ) . recycle ( ) ,
154160 } ;
155161
156162 * self = fresh;
@@ -726,10 +732,11 @@ impl Writer {
726732 binding,
727733 ) ?;
728734 iface. varying_ids . push ( varying_id) ;
729- let id = self . id_gen . next ( ) ;
730- prelude
731- . body
732- . push ( Instruction :: load ( argument_type_id, id, varying_id, None ) ) ;
735+ let id = self . load_io_with_f16_polyfill (
736+ & mut prelude. body ,
737+ varying_id,
738+ argument_type_id,
739+ ) ;
733740
734741 if binding == & crate :: Binding :: BuiltIn ( crate :: BuiltIn :: LocalInvocationId ) {
735742 local_invocation_id = Some ( id) ;
@@ -754,10 +761,8 @@ impl Writer {
754761 binding,
755762 ) ?;
756763 iface. varying_ids . push ( varying_id) ;
757- let id = self . id_gen . next ( ) ;
758- prelude
759- . body
760- . push ( Instruction :: load ( type_id, id, varying_id, None ) ) ;
764+ let id =
765+ self . load_io_with_f16_polyfill ( & mut prelude. body , varying_id, type_id) ;
761766 constituent_ids. push ( id) ;
762767
763768 if binding == & crate :: Binding :: BuiltIn ( crate :: BuiltIn :: LocalInvocationId ) {
@@ -1220,8 +1225,10 @@ impl Writer {
12201225 . insert ( spirv:: Capability :: StorageBuffer16BitAccess ) ;
12211226 self . capabilities_used
12221227 . insert ( spirv:: Capability :: UniformAndStorageBuffer16BitAccess ) ;
1223- self . capabilities_used
1224- . insert ( spirv:: Capability :: StorageInputOutput16 ) ;
1228+ if self . use_storage_input_output_16 {
1229+ self . capabilities_used
1230+ . insert ( spirv:: Capability :: StorageInputOutput16 ) ;
1231+ }
12251232 }
12261233 Instruction :: type_float ( id, bits)
12271234 }
@@ -1905,8 +1912,26 @@ impl Writer {
19051912 ty : Handle < crate :: Type > ,
19061913 binding : & crate :: Binding ,
19071914 ) -> Result < Word , Error > {
1915+ use crate :: TypeInner ;
1916+
19081917 let id = self . id_gen . next ( ) ;
1909- let pointer_type_id = self . get_handle_pointer_type_id ( ty, class) ;
1918+ let ty_inner = & ir_module. types [ ty] . inner ;
1919+ let needs_polyfill = self . needs_f16_polyfill ( ty_inner) ;
1920+
1921+ let pointer_type_id = if needs_polyfill {
1922+ let f32_value_local =
1923+ super :: f16_polyfill:: F16IoPolyfill :: create_polyfill_type ( ty_inner)
1924+ . expect ( "needs_polyfill returned true but create_polyfill_type returned None" ) ;
1925+
1926+ let f32_type_id = self . get_localtype_id ( f32_value_local) ;
1927+ let ptr_id = self . get_pointer_type_id ( f32_type_id, class) ;
1928+ self . io_f16_polyfills . register_io_var ( id, f32_type_id) ;
1929+
1930+ ptr_id
1931+ } else {
1932+ self . get_handle_pointer_type_id ( ty, class)
1933+ } ;
1934+
19101935 Instruction :: variable ( pointer_type_id, id, class, None )
19111936 . to_words ( & mut self . logical_layout . declarations ) ;
19121937
@@ -2089,8 +2114,9 @@ impl Writer {
20892114 // > shader, must be decorated Flat
20902115 if class == spirv:: StorageClass :: Input && stage == crate :: ShaderStage :: Fragment {
20912116 let is_flat = match ir_module. types [ ty] . inner {
2092- crate :: TypeInner :: Scalar ( scalar)
2093- | crate :: TypeInner :: Vector { scalar, .. } => match scalar. kind {
2117+ TypeInner :: Scalar ( scalar) | TypeInner :: Vector { scalar, .. } => match scalar
2118+ . kind
2119+ {
20942120 Sk :: Uint | Sk :: Sint | Sk :: Bool => true ,
20952121 Sk :: Float => false ,
20962122 Sk :: AbstractInt | Sk :: AbstractFloat => {
@@ -2112,6 +2138,49 @@ impl Writer {
21122138 Ok ( id)
21132139 }
21142140
2141+ /// Load an IO variable, converting from `f32` to `f16` if polyfill is active.
2142+ /// Returns the id of the loaded value matching `target_type_id`.
2143+ pub ( super ) fn load_io_with_f16_polyfill (
2144+ & mut self ,
2145+ body : & mut Vec < Instruction > ,
2146+ varying_id : Word ,
2147+ target_type_id : Word ,
2148+ ) -> Word {
2149+ let tmp = self . id_gen . next ( ) ;
2150+ if let Some ( f32_ty) = self . io_f16_polyfills . get_f32_io_type ( varying_id) {
2151+ body. push ( Instruction :: load ( f32_ty, tmp, varying_id, None ) ) ;
2152+ let converted = self . id_gen . next ( ) ;
2153+ super :: f16_polyfill:: F16IoPolyfill :: emit_f32_to_f16_conversion (
2154+ tmp,
2155+ target_type_id,
2156+ converted,
2157+ body,
2158+ ) ;
2159+ converted
2160+ } else {
2161+ body. push ( Instruction :: load ( target_type_id, tmp, varying_id, None ) ) ;
2162+ tmp
2163+ }
2164+ }
2165+
2166+ /// Store an IO variable, converting from `f16` to `f32` if polyfill is active.
2167+ pub ( super ) fn store_io_with_f16_polyfill (
2168+ & mut self ,
2169+ body : & mut Vec < Instruction > ,
2170+ varying_id : Word ,
2171+ value_id : Word ,
2172+ ) {
2173+ if let Some ( f32_ty) = self . io_f16_polyfills . get_f32_io_type ( varying_id) {
2174+ let converted = self . id_gen . next ( ) ;
2175+ super :: f16_polyfill:: F16IoPolyfill :: emit_f16_to_f32_conversion (
2176+ value_id, f32_ty, converted, body,
2177+ ) ;
2178+ body. push ( Instruction :: store ( varying_id, converted, None ) ) ;
2179+ } else {
2180+ body. push ( Instruction :: store ( varying_id, value_id, None ) ) ;
2181+ }
2182+ }
2183+
21152184 fn write_global_variable (
21162185 & mut self ,
21172186 ir_module : & crate :: Module ,
@@ -2585,6 +2654,10 @@ impl Writer {
25852654 self . decorate ( id, spirv:: Decoration :: NonUniform , & [ ] ) ;
25862655 Ok ( ( ) )
25872656 }
2657+
2658+ pub ( super ) fn needs_f16_polyfill ( & self , ty_inner : & crate :: TypeInner ) -> bool {
2659+ self . io_f16_polyfills . needs_polyfill ( ty_inner)
2660+ }
25882661}
25892662
25902663#[ test]
0 commit comments