@@ -78,6 +78,7 @@ impl Writer {
78
78
bounds_check_policies : options. bounds_check_policies ,
79
79
zero_initialize_workgroup_memory : options. zero_initialize_workgroup_memory ,
80
80
force_loop_bounding : options. force_loop_bounding ,
81
+ use_storage_input_output_16 : options. use_storage_input_output_16 ,
81
82
void_type,
82
83
lookup_type : crate :: FastHashMap :: default ( ) ,
83
84
lookup_function : crate :: FastHashMap :: default ( ) ,
@@ -92,6 +93,9 @@ impl Writer {
92
93
temp_list : Vec :: new ( ) ,
93
94
ray_get_committed_intersection_function : None ,
94
95
ray_get_candidate_intersection_function : None ,
96
+ io_f16_polyfills : super :: f16_polyfill:: F16IoPolyfill :: new (
97
+ options. use_storage_input_output_16 ,
98
+ ) ,
95
99
} )
96
100
}
97
101
@@ -125,6 +129,7 @@ impl Writer {
125
129
bounds_check_policies : self . bounds_check_policies ,
126
130
zero_initialize_workgroup_memory : self . zero_initialize_workgroup_memory ,
127
131
force_loop_bounding : self . force_loop_bounding ,
132
+ use_storage_input_output_16 : self . use_storage_input_output_16 ,
128
133
capabilities_available : take ( & mut self . capabilities_available ) ,
129
134
binding_map : take ( & mut self . binding_map ) ,
130
135
@@ -151,6 +156,7 @@ impl Writer {
151
156
temp_list : take ( & mut self . temp_list ) . recycle ( ) ,
152
157
ray_get_candidate_intersection_function : None ,
153
158
ray_get_committed_intersection_function : None ,
159
+ io_f16_polyfills : take ( & mut self . io_f16_polyfills ) . recycle ( ) ,
154
160
} ;
155
161
156
162
* self = fresh;
@@ -726,10 +732,11 @@ impl Writer {
726
732
binding,
727
733
) ?;
728
734
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
+ ) ;
733
740
734
741
if binding == & crate :: Binding :: BuiltIn ( crate :: BuiltIn :: LocalInvocationId ) {
735
742
local_invocation_id = Some ( id) ;
@@ -754,10 +761,8 @@ impl Writer {
754
761
binding,
755
762
) ?;
756
763
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) ;
761
766
constituent_ids. push ( id) ;
762
767
763
768
if binding == & crate :: Binding :: BuiltIn ( crate :: BuiltIn :: LocalInvocationId ) {
@@ -1220,8 +1225,10 @@ impl Writer {
1220
1225
. insert ( spirv:: Capability :: StorageBuffer16BitAccess ) ;
1221
1226
self . capabilities_used
1222
1227
. 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
+ }
1225
1232
}
1226
1233
Instruction :: type_float ( id, bits)
1227
1234
}
@@ -1905,8 +1912,26 @@ impl Writer {
1905
1912
ty : Handle < crate :: Type > ,
1906
1913
binding : & crate :: Binding ,
1907
1914
) -> Result < Word , Error > {
1915
+ use crate :: TypeInner ;
1916
+
1908
1917
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
+
1910
1935
Instruction :: variable ( pointer_type_id, id, class, None )
1911
1936
. to_words ( & mut self . logical_layout . declarations ) ;
1912
1937
@@ -2089,8 +2114,9 @@ impl Writer {
2089
2114
// > shader, must be decorated Flat
2090
2115
if class == spirv:: StorageClass :: Input && stage == crate :: ShaderStage :: Fragment {
2091
2116
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
+ {
2094
2120
Sk :: Uint | Sk :: Sint | Sk :: Bool => true ,
2095
2121
Sk :: Float => false ,
2096
2122
Sk :: AbstractInt | Sk :: AbstractFloat => {
@@ -2112,6 +2138,49 @@ impl Writer {
2112
2138
Ok ( id)
2113
2139
}
2114
2140
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
+
2115
2184
fn write_global_variable (
2116
2185
& mut self ,
2117
2186
ir_module : & crate :: Module ,
@@ -2585,6 +2654,10 @@ impl Writer {
2585
2654
self . decorate ( id, spirv:: Decoration :: NonUniform , & [ ] ) ;
2586
2655
Ok ( ( ) )
2587
2656
}
2657
+
2658
+ pub ( super ) fn needs_f16_polyfill ( & self , ty_inner : & crate :: TypeInner ) -> bool {
2659
+ self . io_f16_polyfills . needs_polyfill ( ty_inner)
2660
+ }
2588
2661
}
2589
2662
2590
2663
#[ test]
0 commit comments