1 // Copyright (c) 2019 Valve Corporation
2 // Copyright (c) 2019 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 // Convert Relaxed to Half tests
17
18 #include <string>
19 #include <vector>
20
21 #include "test/opt/assembly_builder.h"
22 #include "test/opt/pass_fixture.h"
23 #include "test/opt/pass_utils.h"
24
25 namespace spvtools {
26 namespace opt {
27 namespace {
28
29 using ConvertToHalfTest = PassTest<::testing::Test>;
30
TEST_F(ConvertToHalfTest, ConvertToHalfBasic)31 TEST_F(ConvertToHalfTest, ConvertToHalfBasic) {
32 // The resulting SPIR-V was processed with --relax-float-ops.
33 //
34 // clang-format off
35 //
36 // SamplerState g_sSamp : register(s0);
37 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
38 //
39 // struct PS_INPUT
40 // {
41 // float Tex0 : TEXCOORD0;
42 // };
43 //
44 // struct PS_OUTPUT
45 // {
46 // float4 Color : SV_Target0;
47 // };
48 //
49 // cbuffer cbuff{
50 // float c;
51 // }
52 //
53 // PS_OUTPUT main(PS_INPUT i)
54 // {
55 // PS_OUTPUT psout;
56 // psout.Color = g_tTex1df4.Sample(g_sSamp, i.Tex0) * c;
57 // return psout;
58 // }
59 //
60 // clang-format on
61
62 const std::string defs_before =
63 R"(OpCapability Shader
64 OpCapability Sampled1D
65 %1 = OpExtInstImport "GLSL.std.450"
66 OpMemoryModel Logical GLSL450
67 OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color
68 OpExecutionMode %main OriginUpperLeft
69 OpSource HLSL 500
70 OpName %main "main"
71 OpName %g_tTex1df4 "g_tTex1df4"
72 OpName %g_sSamp "g_sSamp"
73 OpName %cbuff "cbuff"
74 OpMemberName %cbuff 0 "c"
75 OpName %_ ""
76 OpName %i_Tex0 "i.Tex0"
77 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
78 OpDecorate %g_tTex1df4 DescriptorSet 0
79 OpDecorate %g_tTex1df4 Binding 0
80 OpDecorate %g_sSamp DescriptorSet 0
81 OpDecorate %g_sSamp Binding 0
82 OpMemberDecorate %cbuff 0 Offset 0
83 OpDecorate %cbuff Block
84 OpDecorate %_ DescriptorSet 0
85 OpDecorate %_ Binding 1
86 OpDecorate %i_Tex0 Location 0
87 OpDecorate %_entryPointOutput_Color Location 0
88 OpDecorate %48 RelaxedPrecision
89 OpDecorate %63 RelaxedPrecision
90 OpDecorate %65 RelaxedPrecision
91 OpDecorate %66 RelaxedPrecision
92 %void = OpTypeVoid
93 %3 = OpTypeFunction %void
94 %float = OpTypeFloat 32
95 %v4float = OpTypeVector %float 4
96 %int = OpTypeInt 32 1
97 %int_0 = OpConstant %int 0
98 %19 = OpTypeImage %float 1D 0 0 0 1 Unknown
99 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
100 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
101 %23 = OpTypeSampler
102 %_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
103 %g_sSamp = OpVariable %_ptr_UniformConstant_23 UniformConstant
104 %27 = OpTypeSampledImage %19
105 %cbuff = OpTypeStruct %float
106 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
107 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
108 %_ptr_Uniform_float = OpTypePointer Uniform %float
109 %_ptr_Input_float = OpTypePointer Input %float
110 %i_Tex0 = OpVariable %_ptr_Input_float Input
111 %_ptr_Output_v4float = OpTypePointer Output %v4float
112 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
113 )";
114
115 const std::string defs_after =
116 R"(OpCapability Shader
117 OpCapability Sampled1D
118 OpCapability Float16
119 %1 = OpExtInstImport "GLSL.std.450"
120 OpMemoryModel Logical GLSL450
121 OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color
122 OpExecutionMode %main OriginUpperLeft
123 OpSource HLSL 500
124 OpName %main "main"
125 OpName %g_tTex1df4 "g_tTex1df4"
126 OpName %g_sSamp "g_sSamp"
127 OpName %cbuff "cbuff"
128 OpMemberName %cbuff 0 "c"
129 OpName %_ ""
130 OpName %i_Tex0 "i.Tex0"
131 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
132 OpDecorate %g_tTex1df4 DescriptorSet 0
133 OpDecorate %g_tTex1df4 Binding 0
134 OpDecorate %g_sSamp DescriptorSet 0
135 OpDecorate %g_sSamp Binding 0
136 OpMemberDecorate %cbuff 0 Offset 0
137 OpDecorate %cbuff Block
138 OpDecorate %_ DescriptorSet 0
139 OpDecorate %_ Binding 1
140 OpDecorate %i_Tex0 Location 0
141 OpDecorate %_entryPointOutput_Color Location 0
142 %void = OpTypeVoid
143 %3 = OpTypeFunction %void
144 %float = OpTypeFloat 32
145 %v4float = OpTypeVector %float 4
146 %int = OpTypeInt 32 1
147 %int_0 = OpConstant %int 0
148 %19 = OpTypeImage %float 1D 0 0 0 1 Unknown
149 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
150 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
151 %23 = OpTypeSampler
152 %_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
153 %g_sSamp = OpVariable %_ptr_UniformConstant_23 UniformConstant
154 %27 = OpTypeSampledImage %19
155 %cbuff = OpTypeStruct %float
156 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
157 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
158 %_ptr_Uniform_float = OpTypePointer Uniform %float
159 %_ptr_Input_float = OpTypePointer Input %float
160 %i_Tex0 = OpVariable %_ptr_Input_float Input
161 %_ptr_Output_v4float = OpTypePointer Output %v4float
162 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
163 %half = OpTypeFloat 16
164 %v4half = OpTypeVector %half 4
165 )";
166
167 const std::string func_before =
168 R"(%main = OpFunction %void None %3
169 %5 = OpLabel
170 %48 = OpLoad %float %i_Tex0
171 %58 = OpLoad %19 %g_tTex1df4
172 %59 = OpLoad %23 %g_sSamp
173 %60 = OpSampledImage %27 %58 %59
174 %63 = OpImageSampleImplicitLod %v4float %60 %48
175 %64 = OpAccessChain %_ptr_Uniform_float %_ %int_0
176 %65 = OpLoad %float %64
177 %66 = OpVectorTimesScalar %v4float %63 %65
178 OpStore %_entryPointOutput_Color %66
179 OpReturn
180 OpFunctionEnd
181 )";
182
183 const std::string func_after =
184 R"(%main = OpFunction %void None %3
185 %5 = OpLabel
186 %48 = OpLoad %float %i_Tex0
187 %58 = OpLoad %19 %g_tTex1df4
188 %59 = OpLoad %23 %g_sSamp
189 %60 = OpSampledImage %27 %58 %59
190 %63 = OpImageSampleImplicitLod %v4float %60 %48
191 %64 = OpAccessChain %_ptr_Uniform_float %_ %int_0
192 %65 = OpLoad %float %64
193 %69 = OpFConvert %v4half %63
194 %70 = OpFConvert %half %65
195 %66 = OpVectorTimesScalar %v4half %69 %70
196 %71 = OpFConvert %v4float %66
197 OpStore %_entryPointOutput_Color %71
198 OpReturn
199 OpFunctionEnd
200 )";
201
202 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
203 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
204 defs_after + func_after, true, true);
205 }
206
TEST_F(ConvertToHalfTest, ConvertToHalfForLinkage)207 TEST_F(ConvertToHalfTest, ConvertToHalfForLinkage) {
208 const std::string before =
209 R"(OpCapability Shader
210 OpCapability Linkage
211 OpMemoryModel Logical GLSL450
212 OpSource HLSL 630
213 OpName %type_cbuff "type.cbuff"
214 OpMemberName %type_cbuff 0 "c"
215 OpName %cbuff "cbuff"
216 OpName %main "main"
217 OpName %BaseColor "BaseColor"
218 OpName %bb_entry "bb.entry"
219 OpName %v "v"
220 OpDecorate %main LinkageAttributes "main" Export
221 OpDecorate %cbuff DescriptorSet 0
222 OpDecorate %cbuff Binding 0
223 OpMemberDecorate %type_cbuff 0 Offset 0
224 OpDecorate %type_cbuff Block
225 OpDecorate %18 RelaxedPrecision
226 %int = OpTypeInt 32 1
227 %int_0 = OpConstant %int 0
228 %float = OpTypeFloat 32
229 %type_cbuff = OpTypeStruct %float
230 %_ptr_Uniform_type_cbuff = OpTypePointer Uniform %type_cbuff
231 %v4float = OpTypeVector %float 4
232 %_ptr_Function_v4float = OpTypePointer Function %v4float
233 %9 = OpTypeFunction %v4float %_ptr_Function_v4float
234 %_ptr_Uniform_float = OpTypePointer Uniform %float
235 %cbuff = OpVariable %_ptr_Uniform_type_cbuff Uniform
236 %main = OpFunction %v4float None %9
237 %BaseColor = OpFunctionParameter %_ptr_Function_v4float
238 %bb_entry = OpLabel
239 %v = OpVariable %_ptr_Function_v4float Function
240 %14 = OpLoad %v4float %BaseColor
241 %16 = OpAccessChain %_ptr_Uniform_float %cbuff %int_0
242 %17 = OpLoad %float %16
243 %18 = OpVectorTimesScalar %v4float %14 %17
244 OpStore %v %18
245 %19 = OpLoad %v4float %v
246 OpReturnValue %19
247 OpFunctionEnd
248 )";
249
250 const std::string after =
251 R"(OpCapability Shader
252 OpCapability Linkage
253 OpCapability Float16
254 OpMemoryModel Logical GLSL450
255 OpSource HLSL 630
256 OpName %type_cbuff "type.cbuff"
257 OpMemberName %type_cbuff 0 "c"
258 OpName %cbuff "cbuff"
259 OpName %main "main"
260 OpName %BaseColor "BaseColor"
261 OpName %bb_entry "bb.entry"
262 OpName %v "v"
263 OpDecorate %main LinkageAttributes "main" Export
264 OpDecorate %cbuff DescriptorSet 0
265 OpDecorate %cbuff Binding 0
266 OpMemberDecorate %type_cbuff 0 Offset 0
267 OpDecorate %type_cbuff Block
268 %int = OpTypeInt 32 1
269 %int_0 = OpConstant %int 0
270 %float = OpTypeFloat 32
271 %type_cbuff = OpTypeStruct %float
272 %_ptr_Uniform_type_cbuff = OpTypePointer Uniform %type_cbuff
273 %v4float = OpTypeVector %float 4
274 %_ptr_Function_v4float = OpTypePointer Function %v4float
275 %14 = OpTypeFunction %v4float %_ptr_Function_v4float
276 %_ptr_Uniform_float = OpTypePointer Uniform %float
277 %cbuff = OpVariable %_ptr_Uniform_type_cbuff Uniform
278 %half = OpTypeFloat 16
279 %v4half = OpTypeVector %half 4
280 %main = OpFunction %v4float None %14
281 %BaseColor = OpFunctionParameter %_ptr_Function_v4float
282 %bb_entry = OpLabel
283 %v = OpVariable %_ptr_Function_v4float Function
284 %16 = OpLoad %v4float %BaseColor
285 %17 = OpAccessChain %_ptr_Uniform_float %cbuff %int_0
286 %18 = OpLoad %float %17
287 %22 = OpFConvert %v4half %16
288 %23 = OpFConvert %half %18
289 %7 = OpVectorTimesScalar %v4half %22 %23
290 %24 = OpFConvert %v4float %7
291 OpStore %v %24
292 %19 = OpLoad %v4float %v
293 OpReturnValue %19
294 OpFunctionEnd
295 )";
296
297 SinglePassRunAndCheck<ConvertToHalfPass>(before, after, true, true);
298 }
TEST_F(ConvertToHalfTest, ConvertToHalfWithDrefSample)299 TEST_F(ConvertToHalfTest, ConvertToHalfWithDrefSample) {
300 // The resulting SPIR-V was processed with --relax-float-ops.
301 //
302 // clang-format off
303 //
304 // SamplerComparisonState g_sSamp : register(s0);
305 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
306 //
307 // cbuffer cbuff{
308 // float c1;
309 // float c2;
310 // };
311 //
312 // struct PS_INPUT
313 // {
314 // float Tex0 : TEXCOORD0;
315 // float Tex1 : TEXCOORD1;
316 // };
317 //
318 // struct PS_OUTPUT
319 // {
320 // float Color : SV_Target0;
321 // };
322 //
323 // PS_OUTPUT main(PS_INPUT i)
324 // {
325 // PS_OUTPUT psout;
326 // float txval10 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex0 * 0.1, c1 + 0.1);
327 // float txval11 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex1 * 0.2, c2 + 0.2);
328 // float t = txval10 + txval11;
329 // float t2 = t / 2.0;
330 // psout.Color = t2;
331 // return psout;
332 // }
333 //
334 // clang-format on
335
336 const std::string defs_before =
337 R"(OpCapability Shader
338 OpCapability Sampled1D
339 %1 = OpExtInstImport "GLSL.std.450"
340 OpMemoryModel Logical GLSL450
341 OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color
342 OpExecutionMode %main OriginUpperLeft
343 OpSource HLSL 500
344 OpName %main "main"
345 OpName %g_tTex1df4 "g_tTex1df4"
346 OpName %g_sSamp "g_sSamp"
347 OpName %cbuff "cbuff"
348 OpMemberName %cbuff 0 "c1"
349 OpMemberName %cbuff 1 "c2"
350 OpName %_ ""
351 OpName %i_Tex0 "i.Tex0"
352 OpName %i_Tex1 "i.Tex1"
353 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
354 OpDecorate %g_tTex1df4 DescriptorSet 0
355 OpDecorate %g_tTex1df4 Binding 0
356 OpDecorate %g_sSamp DescriptorSet 0
357 OpDecorate %g_sSamp Binding 0
358 OpMemberDecorate %cbuff 0 Offset 0
359 OpMemberDecorate %cbuff 1 Offset 4
360 OpDecorate %cbuff Block
361 OpDecorate %_ DescriptorSet 0
362 OpDecorate %_ Binding 1
363 OpDecorate %i_Tex0 Location 0
364 OpDecorate %i_Tex1 Location 1
365 OpDecorate %_entryPointOutput_Color Location 0
366 OpDecorate %100 RelaxedPrecision
367 OpDecorate %76 RelaxedPrecision
368 OpDecorate %79 RelaxedPrecision
369 OpDecorate %98 RelaxedPrecision
370 OpDecorate %101 RelaxedPrecision
371 OpDecorate %110 RelaxedPrecision
372 OpDecorate %102 RelaxedPrecision
373 OpDecorate %112 RelaxedPrecision
374 OpDecorate %104 RelaxedPrecision
375 OpDecorate %113 RelaxedPrecision
376 OpDecorate %114 RelaxedPrecision
377 OpDecorate %116 RelaxedPrecision
378 OpDecorate %119 RelaxedPrecision
379 OpDecorate %121 RelaxedPrecision
380 %void = OpTypeVoid
381 %3 = OpTypeFunction %void
382 %float = OpTypeFloat 32
383 %16 = OpTypeImage %float 1D 1 0 0 1 Unknown
384 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
385 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_16 UniformConstant
386 %20 = OpTypeSampler
387 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
388 %g_sSamp = OpVariable %_ptr_UniformConstant_20 UniformConstant
389 %24 = OpTypeSampledImage %16
390 %int = OpTypeInt 32 1
391 %int_0 = OpConstant %int 0
392 %float_0_100000001 = OpConstant %float 0.100000001
393 %cbuff = OpTypeStruct %float %float
394 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
395 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
396 %_ptr_Uniform_float = OpTypePointer Uniform %float
397 %v2float = OpTypeVector %float 2
398 %int_1 = OpConstant %int 1
399 %float_0_200000003 = OpConstant %float 0.200000003
400 %_ptr_Input_float = OpTypePointer Input %float
401 %i_Tex0 = OpVariable %_ptr_Input_float Input
402 %i_Tex1 = OpVariable %_ptr_Input_float Input
403 %_ptr_Output_float = OpTypePointer Output %float
404 %_entryPointOutput_Color = OpVariable %_ptr_Output_float Output
405 %float_0_5 = OpConstant %float 0.5
406 )";
407
408 const std::string defs_after =
409 R"(OpCapability Shader
410 OpCapability Sampled1D
411 OpCapability Float16
412 %1 = OpExtInstImport "GLSL.std.450"
413 OpMemoryModel Logical GLSL450
414 OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color
415 OpExecutionMode %main OriginUpperLeft
416 OpSource HLSL 500
417 OpName %main "main"
418 OpName %g_tTex1df4 "g_tTex1df4"
419 OpName %g_sSamp "g_sSamp"
420 OpName %cbuff "cbuff"
421 OpMemberName %cbuff 0 "c1"
422 OpMemberName %cbuff 1 "c2"
423 OpName %_ ""
424 OpName %i_Tex0 "i.Tex0"
425 OpName %i_Tex1 "i.Tex1"
426 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
427 OpDecorate %g_tTex1df4 DescriptorSet 0
428 OpDecorate %g_tTex1df4 Binding 0
429 OpDecorate %g_sSamp DescriptorSet 0
430 OpDecorate %g_sSamp Binding 0
431 OpMemberDecorate %cbuff 0 Offset 0
432 OpMemberDecorate %cbuff 1 Offset 4
433 OpDecorate %cbuff Block
434 OpDecorate %_ DescriptorSet 0
435 OpDecorate %_ Binding 1
436 OpDecorate %i_Tex0 Location 0
437 OpDecorate %i_Tex1 Location 1
438 OpDecorate %_entryPointOutput_Color Location 0
439 %void = OpTypeVoid
440 %25 = OpTypeFunction %void
441 %float = OpTypeFloat 32
442 %27 = OpTypeImage %float 1D 1 0 0 1 Unknown
443 %_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27
444 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_27 UniformConstant
445 %29 = OpTypeSampler
446 %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
447 %g_sSamp = OpVariable %_ptr_UniformConstant_29 UniformConstant
448 %31 = OpTypeSampledImage %27
449 %int = OpTypeInt 32 1
450 %int_0 = OpConstant %int 0
451 %float_0_100000001 = OpConstant %float 0.100000001
452 %cbuff = OpTypeStruct %float %float
453 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
454 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
455 %_ptr_Uniform_float = OpTypePointer Uniform %float
456 %v2float = OpTypeVector %float 2
457 %int_1 = OpConstant %int 1
458 %float_0_200000003 = OpConstant %float 0.200000003
459 %_ptr_Input_float = OpTypePointer Input %float
460 %i_Tex0 = OpVariable %_ptr_Input_float Input
461 %i_Tex1 = OpVariable %_ptr_Input_float Input
462 %_ptr_Output_float = OpTypePointer Output %float
463 %_entryPointOutput_Color = OpVariable %_ptr_Output_float Output
464 %float_0_5 = OpConstant %float 0.5
465 %half = OpTypeFloat 16
466 %v2half = OpTypeVector %half 2
467 )";
468
469 const std::string func_before =
470 R"(%main = OpFunction %void None %3
471 %5 = OpLabel
472 %76 = OpLoad %float %i_Tex0
473 %79 = OpLoad %float %i_Tex1
474 %93 = OpLoad %16 %g_tTex1df4
475 %94 = OpLoad %20 %g_sSamp
476 %95 = OpSampledImage %24 %93 %94
477 %98 = OpFMul %float %76 %float_0_100000001
478 %99 = OpAccessChain %_ptr_Uniform_float %_ %int_0
479 %100 = OpLoad %float %99
480 %101 = OpFAdd %float %100 %float_0_100000001
481 %102 = OpCompositeConstruct %v2float %98 %101
482 %104 = OpImageSampleDrefImplicitLod %float %95 %102 %101
483 %105 = OpLoad %16 %g_tTex1df4
484 %106 = OpLoad %20 %g_sSamp
485 %107 = OpSampledImage %24 %105 %106
486 %110 = OpFMul %float %79 %float_0_200000003
487 %111 = OpAccessChain %_ptr_Uniform_float %_ %int_1
488 %112 = OpLoad %float %111
489 %113 = OpFAdd %float %112 %float_0_200000003
490 %114 = OpCompositeConstruct %v2float %110 %113
491 %116 = OpImageSampleDrefImplicitLod %float %107 %114 %113
492 %119 = OpFAdd %float %104 %116
493 %121 = OpFMul %float %119 %float_0_5
494 OpStore %_entryPointOutput_Color %121
495 OpReturn
496 OpFunctionEnd
497 )";
498
499 const std::string func_after =
500 R"(%main = OpFunction %void None %25
501 %43 = OpLabel
502 %11 = OpLoad %float %i_Tex0
503 %12 = OpLoad %float %i_Tex1
504 %44 = OpLoad %27 %g_tTex1df4
505 %45 = OpLoad %29 %g_sSamp
506 %46 = OpSampledImage %31 %44 %45
507 %53 = OpFConvert %half %11
508 %54 = OpFConvert %half %float_0_100000001
509 %13 = OpFMul %half %53 %54
510 %47 = OpAccessChain %_ptr_Uniform_float %_ %int_0
511 %10 = OpLoad %float %47
512 %55 = OpFConvert %half %10
513 %56 = OpFConvert %half %float_0_100000001
514 %14 = OpFAdd %half %55 %56
515 %16 = OpCompositeConstruct %v2half %13 %14
516 %58 = OpFConvert %float %14
517 %18 = OpImageSampleDrefImplicitLod %float %46 %16 %58
518 %48 = OpLoad %27 %g_tTex1df4
519 %49 = OpLoad %29 %g_sSamp
520 %50 = OpSampledImage %31 %48 %49
521 %59 = OpFConvert %half %12
522 %60 = OpFConvert %half %float_0_200000003
523 %15 = OpFMul %half %59 %60
524 %51 = OpAccessChain %_ptr_Uniform_float %_ %int_1
525 %17 = OpLoad %float %51
526 %61 = OpFConvert %half %17
527 %62 = OpFConvert %half %float_0_200000003
528 %19 = OpFAdd %half %61 %62
529 %20 = OpCompositeConstruct %v2half %15 %19
530 %63 = OpFConvert %float %19
531 %21 = OpImageSampleDrefImplicitLod %float %50 %20 %63
532 %64 = OpFConvert %half %18
533 %65 = OpFConvert %half %21
534 %22 = OpFAdd %half %64 %65
535 %66 = OpFConvert %half %float_0_5
536 %23 = OpFMul %half %22 %66
537 %67 = OpFConvert %float %23
538 OpStore %_entryPointOutput_Color %67
539 OpReturn
540 OpFunctionEnd
541 )";
542
543 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
544 defs_after + func_after, true, true);
545 }
546
TEST_F(ConvertToHalfTest, ConvertToHalfWithVectorMatrixMult)547 TEST_F(ConvertToHalfTest, ConvertToHalfWithVectorMatrixMult) {
548 // The resulting SPIR-V was processed with --relax-float-ops.
549 //
550 // clang-format off
551 //
552 // SamplerState g_sSamp : register(s0);
553 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
554 //
555 // struct PS_OUTPUT
556 // {
557 // float4 Color : SV_Target0;
558 // };
559 //
560 // cbuffer cbuff{
561 // float4x4 M;
562 // }
563 //
564 // PS_OUTPUT main()
565 // {
566 // PS_OUTPUT psout;
567 // float4 txval10 = g_tTex1df4.Sample(g_sSamp, 0.1);
568 // float4 t = mul(txval10, M);
569 // psout.Color = t;
570 // return psout;
571 //}
572 //
573 // clang-format on
574
575 const std::string defs_before =
576 R"(OpCapability Shader
577 OpCapability Sampled1D
578 %1 = OpExtInstImport "GLSL.std.450"
579 OpMemoryModel Logical GLSL450
580 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
581 OpExecutionMode %main OriginUpperLeft
582 OpSource HLSL 500
583 OpName %main "main"
584 OpName %g_tTex1df4 "g_tTex1df4"
585 OpName %g_sSamp "g_sSamp"
586 OpName %cbuff "cbuff"
587 OpMemberName %cbuff 0 "M"
588 OpName %_ ""
589 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
590 OpDecorate %g_tTex1df4 DescriptorSet 0
591 OpDecorate %g_tTex1df4 Binding 0
592 OpDecorate %g_sSamp DescriptorSet 0
593 OpDecorate %g_sSamp Binding 0
594 OpMemberDecorate %cbuff 0 RowMajor
595 OpMemberDecorate %cbuff 0 Offset 0
596 OpMemberDecorate %cbuff 0 MatrixStride 16
597 OpDecorate %cbuff Block
598 OpDecorate %_ DescriptorSet 0
599 OpDecorate %_ Binding 1
600 OpDecorate %_entryPointOutput_Color Location 0
601 OpDecorate %56 RelaxedPrecision
602 OpDecorate %58 RelaxedPrecision
603 OpDecorate %60 RelaxedPrecision
604 %void = OpTypeVoid
605 %3 = OpTypeFunction %void
606 %float = OpTypeFloat 32
607 %v4float = OpTypeVector %float 4
608 %14 = OpTypeImage %float 1D 0 0 0 1 Unknown
609 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
610 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant
611 %18 = OpTypeSampler
612 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
613 %g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant
614 %22 = OpTypeSampledImage %14
615 %float_0_100000001 = OpConstant %float 0.100000001
616 %mat4v4float = OpTypeMatrix %v4float 4
617 %cbuff = OpTypeStruct %mat4v4float
618 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
619 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
620 %int = OpTypeInt 32 1
621 %int_0 = OpConstant %int 0
622 %_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
623 %_ptr_Output_v4float = OpTypePointer Output %v4float
624 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
625 )";
626
627 const std::string defs_after =
628 R"(OpCapability Shader
629 OpCapability Sampled1D
630 OpCapability Float16
631 %1 = OpExtInstImport "GLSL.std.450"
632 OpMemoryModel Logical GLSL450
633 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
634 OpExecutionMode %main OriginUpperLeft
635 OpSource HLSL 500
636 OpName %main "main"
637 OpName %g_tTex1df4 "g_tTex1df4"
638 OpName %g_sSamp "g_sSamp"
639 OpName %cbuff "cbuff"
640 OpMemberName %cbuff 0 "M"
641 OpName %_ ""
642 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
643 OpDecorate %g_tTex1df4 DescriptorSet 0
644 OpDecorate %g_tTex1df4 Binding 0
645 OpDecorate %g_sSamp DescriptorSet 0
646 OpDecorate %g_sSamp Binding 0
647 OpMemberDecorate %cbuff 0 RowMajor
648 OpMemberDecorate %cbuff 0 Offset 0
649 OpMemberDecorate %cbuff 0 MatrixStride 16
650 OpDecorate %cbuff Block
651 OpDecorate %_ DescriptorSet 0
652 OpDecorate %_ Binding 1
653 OpDecorate %_entryPointOutput_Color Location 0
654 %void = OpTypeVoid
655 %3 = OpTypeFunction %void
656 %float = OpTypeFloat 32
657 %v4float = OpTypeVector %float 4
658 %14 = OpTypeImage %float 1D 0 0 0 1 Unknown
659 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
660 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant
661 %18 = OpTypeSampler
662 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
663 %g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant
664 %22 = OpTypeSampledImage %14
665 %float_0_100000001 = OpConstant %float 0.100000001
666 %mat4v4float = OpTypeMatrix %v4float 4
667 %cbuff = OpTypeStruct %mat4v4float
668 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
669 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
670 %int = OpTypeInt 32 1
671 %int_0 = OpConstant %int 0
672 %_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
673 %_ptr_Output_v4float = OpTypePointer Output %v4float
674 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
675 %half = OpTypeFloat 16
676 %v4half = OpTypeVector %half 4
677 %mat4v4half = OpTypeMatrix %v4half 4
678 )";
679
680 const std::string func_before =
681 R"(%main = OpFunction %void None %3
682 %5 = OpLabel
683 %53 = OpLoad %14 %g_tTex1df4
684 %54 = OpLoad %18 %g_sSamp
685 %55 = OpSampledImage %22 %53 %54
686 %56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001
687 %57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0
688 %58 = OpLoad %mat4v4float %57
689 %60 = OpMatrixTimesVector %v4float %58 %56
690 OpStore %_entryPointOutput_Color %60
691 OpReturn
692 OpFunctionEnd
693 )";
694
695 const std::string func_after =
696 R"(%main = OpFunction %void None %3
697 %5 = OpLabel
698 %53 = OpLoad %14 %g_tTex1df4
699 %54 = OpLoad %18 %g_sSamp
700 %55 = OpSampledImage %22 %53 %54
701 %56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001
702 %57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0
703 %58 = OpLoad %mat4v4float %57
704 %67 = OpCompositeExtract %v4float %58 0
705 %68 = OpFConvert %v4half %67
706 %69 = OpCompositeExtract %v4float %58 1
707 %70 = OpFConvert %v4half %69
708 %71 = OpCompositeExtract %v4float %58 2
709 %72 = OpFConvert %v4half %71
710 %73 = OpCompositeExtract %v4float %58 3
711 %74 = OpFConvert %v4half %73
712 %75 = OpCompositeConstruct %mat4v4half %68 %70 %72 %74
713 %64 = OpCopyObject %mat4v4float %58
714 %65 = OpFConvert %v4half %56
715 %60 = OpMatrixTimesVector %v4half %75 %65
716 %66 = OpFConvert %v4float %60
717 OpStore %_entryPointOutput_Color %66
718 OpReturn
719 OpFunctionEnd
720 )";
721
722 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
723 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
724 defs_after + func_after, true, true);
725 }
726
TEST_F(ConvertToHalfTest, ConvertToHalfWithPhi)727 TEST_F(ConvertToHalfTest, ConvertToHalfWithPhi) {
728 // The resulting SPIR-V was processed with --relax-float-ops.
729 //
730 // clang-format off
731 //
732 // SamplerState g_sSamp : register(s0);
733 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
734 //
735 // struct PS_OUTPUT
736 // {
737 // float4 Color : SV_Target0;
738 // };
739 //
740 // cbuffer cbuff{
741 // bool b;
742 // float4x4 M;
743 // }
744 //
745 // PS_OUTPUT main()
746 // {
747 // PS_OUTPUT psout;
748 // float4 t;
749 //
750 // if (b)
751 // t = g_tTex1df4.Sample(g_sSamp, 0.1);
752 // else
753 // t = float4(0.0, 0.0, 0.0, 0.0);
754 //
755 // float4 t2 = t * 2.0;
756 // psout.Color = t2;
757 // return psout;
758 // }
759 //
760 // clang-format on
761
762 const std::string defs_before =
763 R"(OpCapability Shader
764 OpCapability Sampled1D
765 %1 = OpExtInstImport "GLSL.std.450"
766 OpMemoryModel Logical GLSL450
767 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
768 OpExecutionMode %main OriginUpperLeft
769 OpSource HLSL 500
770 OpName %main "main"
771 OpName %cbuff "cbuff"
772 OpMemberName %cbuff 0 "b"
773 OpMemberName %cbuff 1 "M"
774 OpName %_ ""
775 OpName %g_tTex1df4 "g_tTex1df4"
776 OpName %g_sSamp "g_sSamp"
777 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
778 OpMemberDecorate %cbuff 0 Offset 0
779 OpMemberDecorate %cbuff 1 RowMajor
780 OpMemberDecorate %cbuff 1 Offset 16
781 OpMemberDecorate %cbuff 1 MatrixStride 16
782 OpDecorate %cbuff Block
783 OpDecorate %_ DescriptorSet 0
784 OpDecorate %_ Binding 1
785 OpDecorate %g_tTex1df4 DescriptorSet 0
786 OpDecorate %g_tTex1df4 Binding 0
787 OpDecorate %g_sSamp DescriptorSet 0
788 OpDecorate %g_sSamp Binding 0
789 OpDecorate %_entryPointOutput_Color Location 0
790 OpDecorate %72 RelaxedPrecision
791 OpDecorate %85 RelaxedPrecision
792 OpDecorate %74 RelaxedPrecision
793 %void = OpTypeVoid
794 %3 = OpTypeFunction %void
795 %float = OpTypeFloat 32
796 %v4float = OpTypeVector %float 4
797 %uint = OpTypeInt 32 0
798 %mat4v4float = OpTypeMatrix %v4float 4
799 %cbuff = OpTypeStruct %uint %mat4v4float
800 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
801 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
802 %int = OpTypeInt 32 1
803 %int_0 = OpConstant %int 0
804 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
805 %bool = OpTypeBool
806 %uint_0 = OpConstant %uint 0
807 %29 = OpTypeImage %float 1D 0 0 0 1 Unknown
808 %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
809 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant
810 %33 = OpTypeSampler
811 %_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33
812 %g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant
813 %37 = OpTypeSampledImage %29
814 %float_0_100000001 = OpConstant %float 0.100000001
815 %float_0 = OpConstant %float 0
816 %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
817 %float_2 = OpConstant %float 2
818 %_ptr_Output_v4float = OpTypePointer Output %v4float
819 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
820 )";
821
822 const std::string defs_after =
823 R"(OpCapability Shader
824 OpCapability Sampled1D
825 OpCapability Float16
826 %1 = OpExtInstImport "GLSL.std.450"
827 OpMemoryModel Logical GLSL450
828 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
829 OpExecutionMode %main OriginUpperLeft
830 OpSource HLSL 500
831 OpName %main "main"
832 OpName %cbuff "cbuff"
833 OpMemberName %cbuff 0 "b"
834 OpMemberName %cbuff 1 "M"
835 OpName %_ ""
836 OpName %g_tTex1df4 "g_tTex1df4"
837 OpName %g_sSamp "g_sSamp"
838 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
839 OpMemberDecorate %cbuff 0 Offset 0
840 OpMemberDecorate %cbuff 1 RowMajor
841 OpMemberDecorate %cbuff 1 Offset 16
842 OpMemberDecorate %cbuff 1 MatrixStride 16
843 OpDecorate %cbuff Block
844 OpDecorate %_ DescriptorSet 0
845 OpDecorate %_ Binding 1
846 OpDecorate %g_tTex1df4 DescriptorSet 0
847 OpDecorate %g_tTex1df4 Binding 0
848 OpDecorate %g_sSamp DescriptorSet 0
849 OpDecorate %g_sSamp Binding 0
850 OpDecorate %_entryPointOutput_Color Location 0
851 %void = OpTypeVoid
852 %3 = OpTypeFunction %void
853 %float = OpTypeFloat 32
854 %v4float = OpTypeVector %float 4
855 %uint = OpTypeInt 32 0
856 %mat4v4float = OpTypeMatrix %v4float 4
857 %cbuff = OpTypeStruct %uint %mat4v4float
858 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
859 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
860 %int = OpTypeInt 32 1
861 %int_0 = OpConstant %int 0
862 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
863 %bool = OpTypeBool
864 %uint_0 = OpConstant %uint 0
865 %29 = OpTypeImage %float 1D 0 0 0 1 Unknown
866 %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
867 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant
868 %33 = OpTypeSampler
869 %_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33
870 %g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant
871 %37 = OpTypeSampledImage %29
872 %float_0_100000001 = OpConstant %float 0.100000001
873 %float_0 = OpConstant %float 0
874 %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
875 %float_2 = OpConstant %float 2
876 %_ptr_Output_v4float = OpTypePointer Output %v4float
877 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
878 %half = OpTypeFloat 16
879 %v4half = OpTypeVector %half 4
880 )";
881
882 const std::string func_before =
883 R"(%main = OpFunction %void None %3
884 %5 = OpLabel
885 %63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
886 %64 = OpLoad %uint %63
887 %65 = OpINotEqual %bool %64 %uint_0
888 OpSelectionMerge %66 None
889 OpBranchConditional %65 %67 %68
890 %67 = OpLabel
891 %69 = OpLoad %29 %g_tTex1df4
892 %70 = OpLoad %33 %g_sSamp
893 %71 = OpSampledImage %37 %69 %70
894 %72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001
895 OpBranch %66
896 %68 = OpLabel
897 OpBranch %66
898 %66 = OpLabel
899 %85 = OpPhi %v4float %72 %67 %43 %68
900 %74 = OpVectorTimesScalar %v4float %85 %float_2
901 OpStore %_entryPointOutput_Color %74
902 OpReturn
903 OpFunctionEnd
904 )";
905
906 const std::string func_after =
907 R"(%main = OpFunction %void None %3
908 %5 = OpLabel
909 %63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
910 %64 = OpLoad %uint %63
911 %65 = OpINotEqual %bool %64 %uint_0
912 OpSelectionMerge %66 None
913 OpBranchConditional %65 %67 %68
914 %67 = OpLabel
915 %69 = OpLoad %29 %g_tTex1df4
916 %70 = OpLoad %33 %g_sSamp
917 %71 = OpSampledImage %37 %69 %70
918 %72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001
919 %88 = OpFConvert %v4half %72
920 OpBranch %66
921 %68 = OpLabel
922 %89 = OpFConvert %v4half %43
923 OpBranch %66
924 %66 = OpLabel
925 %85 = OpPhi %v4half %88 %67 %89 %68
926 %90 = OpFConvert %half %float_2
927 %74 = OpVectorTimesScalar %v4half %85 %90
928 %91 = OpFConvert %v4float %74
929 OpStore %_entryPointOutput_Color %91
930 OpReturn
931 OpFunctionEnd
932 )";
933
934 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
935 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
936 defs_after + func_after, true, true);
937 }
938
TEST_F(ConvertToHalfTest, ConvertToHalfWithLoopAndFConvert)939 TEST_F(ConvertToHalfTest, ConvertToHalfWithLoopAndFConvert) {
940 // The resulting SPIR-V was processed with --relax-float-ops.
941 //
942 // The loop causes an FConvert to be generated at the bottom of the loop
943 // for the Phi. The FConvert is later processed and turned into a (dead)
944 // copy.
945 //
946 // clang-format off
947 //
948 // struct PS_OUTPUT
949 // {
950 // float4 Color : SV_Target0;
951 // };
952 //
953 // cbuffer cbuff{
954 // float4 a[10];
955 // }
956 //
957 // PS_OUTPUT main()
958 // {
959 // PS_OUTPUT psout;
960 // float4 t = 0.0;;
961 //
962 // for (int i = 0; i<10; ++i)
963 // t = t + a[i];
964 //
965 // float4 t2 = t / 10.0;
966 // psout.Color = t2;
967 // return psout;
968 // }
969 //
970 // clang-format on
971
972 const std::string defs_before =
973 R"(OpCapability Shader
974 %1 = OpExtInstImport "GLSL.std.450"
975 OpMemoryModel Logical GLSL450
976 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
977 OpExecutionMode %main OriginUpperLeft
978 OpSource HLSL 500
979 OpName %main "main"
980 OpName %cbuff "cbuff"
981 OpMemberName %cbuff 0 "a"
982 OpName %_ ""
983 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
984 OpDecorate %_arr_v4float_uint_10 ArrayStride 16
985 OpMemberDecorate %cbuff 0 Offset 0
986 OpDecorate %cbuff Block
987 OpDecorate %_ DescriptorSet 0
988 OpDecorate %_ Binding 0
989 OpDecorate %_entryPointOutput_Color Location 0
990 OpDecorate %96 RelaxedPrecision
991 OpDecorate %81 RelaxedPrecision
992 OpDecorate %75 RelaxedPrecision
993 OpDecorate %76 RelaxedPrecision
994 %void = OpTypeVoid
995 %3 = OpTypeFunction %void
996 %float = OpTypeFloat 32
997 %v4float = OpTypeVector %float 4
998 %float_0 = OpConstant %float 0
999 %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1000 %int = OpTypeInt 32 1
1001 %int_0 = OpConstant %int 0
1002 %int_10 = OpConstant %int 10
1003 %bool = OpTypeBool
1004 %uint = OpTypeInt 32 0
1005 %uint_10 = OpConstant %uint 10
1006 %_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10
1007 %cbuff = OpTypeStruct %_arr_v4float_uint_10
1008 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
1009 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
1010 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
1011 %int_1 = OpConstant %int 1
1012 %_ptr_Output_v4float = OpTypePointer Output %v4float
1013 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
1014 %float_0_100000001 = OpConstant %float 0.100000001
1015 %94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001
1016 )";
1017
1018 const std::string defs_after =
1019 R"(OpCapability Shader
1020 OpCapability Float16
1021 %1 = OpExtInstImport "GLSL.std.450"
1022 OpMemoryModel Logical GLSL450
1023 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
1024 OpExecutionMode %main OriginUpperLeft
1025 OpSource HLSL 500
1026 OpName %main "main"
1027 OpName %cbuff "cbuff"
1028 OpMemberName %cbuff 0 "a"
1029 OpName %_ ""
1030 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
1031 OpDecorate %_arr_v4float_uint_10 ArrayStride 16
1032 OpMemberDecorate %cbuff 0 Offset 0
1033 OpDecorate %cbuff Block
1034 OpDecorate %_ DescriptorSet 0
1035 OpDecorate %_ Binding 0
1036 OpDecorate %_entryPointOutput_Color Location 0
1037 %void = OpTypeVoid
1038 %3 = OpTypeFunction %void
1039 %float = OpTypeFloat 32
1040 %v4float = OpTypeVector %float 4
1041 %float_0 = OpConstant %float 0
1042 %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1043 %int = OpTypeInt 32 1
1044 %int_0 = OpConstant %int 0
1045 %int_10 = OpConstant %int 10
1046 %bool = OpTypeBool
1047 %uint = OpTypeInt 32 0
1048 %uint_10 = OpConstant %uint 10
1049 %_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10
1050 %cbuff = OpTypeStruct %_arr_v4float_uint_10
1051 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
1052 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
1053 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
1054 %int_1 = OpConstant %int 1
1055 %_ptr_Output_v4float = OpTypePointer Output %v4float
1056 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
1057 %float_0_100000001 = OpConstant %float 0.100000001
1058 %94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001
1059 %half = OpTypeFloat 16
1060 %v4half = OpTypeVector %half 4
1061 )";
1062
1063 const std::string func_before =
1064 R"(%main = OpFunction %void None %3
1065 %5 = OpLabel
1066 OpBranch %65
1067 %65 = OpLabel
1068 %96 = OpPhi %v4float %15 %5 %76 %71
1069 %95 = OpPhi %int %int_0 %5 %78 %71
1070 %70 = OpSLessThan %bool %95 %int_10
1071 OpLoopMerge %66 %71 None
1072 OpBranchConditional %70 %71 %66
1073 %71 = OpLabel
1074 %74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95
1075 %75 = OpLoad %v4float %74
1076 %76 = OpFAdd %v4float %96 %75
1077 %78 = OpIAdd %int %95 %int_1
1078 OpBranch %65
1079 %66 = OpLabel
1080 %81 = OpFMul %v4float %96 %94
1081 OpStore %_entryPointOutput_Color %81
1082 OpReturn
1083 OpFunctionEnd
1084 )";
1085
1086 const std::string func_after =
1087 R"(%main = OpFunction %void None %3
1088 %5 = OpLabel
1089 %99 = OpFConvert %v4half %15
1090 OpBranch %65
1091 %65 = OpLabel
1092 %96 = OpPhi %v4half %99 %5 %100 %71
1093 %95 = OpPhi %int %int_0 %5 %78 %71
1094 %70 = OpSLessThan %bool %95 %int_10
1095 OpLoopMerge %66 %71 None
1096 OpBranchConditional %70 %71 %66
1097 %71 = OpLabel
1098 %74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95
1099 %75 = OpLoad %v4float %74
1100 %103 = OpFConvert %v4half %75
1101 %76 = OpFAdd %v4half %96 %103
1102 %78 = OpIAdd %int %95 %int_1
1103 %100 = OpCopyObject %v4half %76
1104 OpBranch %65
1105 %66 = OpLabel
1106 %101 = OpFConvert %v4half %94
1107 %81 = OpFMul %v4half %96 %101
1108 %102 = OpFConvert %v4float %81
1109 OpStore %_entryPointOutput_Color %102
1110 OpReturn
1111 OpFunctionEnd
1112 )";
1113
1114 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1115 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
1116 defs_after + func_after, true, true);
1117 }
1118
TEST_F(ConvertToHalfTest, ConvertToHalfWithExtracts)1119 TEST_F(ConvertToHalfTest, ConvertToHalfWithExtracts) {
1120 // The resulting SPIR-V was processed with --relax-float-ops.
1121 //
1122 // The extra converts in the func_after can be DCE'd.
1123 //
1124 // clang-format off
1125 //
1126 // SamplerState g_sSamp : register(s0);
1127 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
1128 //
1129 // struct PS_INPUT
1130 // {
1131 // float Tex0 : TEXCOORD0;
1132 // };
1133 //
1134 // struct PS_OUTPUT
1135 // {
1136 // float4 Color : SV_Target0;
1137 // };
1138 //
1139 // cbuffer cbuff{
1140 // float c;
1141 // }
1142 //
1143 // PS_OUTPUT main(PS_INPUT i)
1144 // {
1145 // PS_OUTPUT psout;
1146 // float4 tx = g_tTex1df4.Sample(g_sSamp, i.Tex0);
1147 // float4 t = float4(tx.y, tx.z, tx.x, tx.w) * c;
1148 // psout.Color = t;
1149 // return psout;
1150 // }
1151 //
1152 // clang-format on
1153
1154 const std::string defs_before =
1155 R"(OpCapability Shader
1156 OpCapability Sampled1D
1157 %1 = OpExtInstImport "GLSL.std.450"
1158 OpMemoryModel Logical GLSL450
1159 OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color
1160 OpExecutionMode %main OriginUpperLeft
1161 OpSource HLSL 500
1162 OpName %main "main"
1163 OpName %g_tTex1df4 "g_tTex1df4"
1164 OpName %g_sSamp "g_sSamp"
1165 OpName %cbuff "cbuff"
1166 OpMemberName %cbuff 0 "c"
1167 OpName %_ ""
1168 OpName %i_Tex0 "i.Tex0"
1169 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
1170 OpDecorate %g_tTex1df4 DescriptorSet 0
1171 OpDecorate %g_tTex1df4 Binding 0
1172 OpDecorate %g_sSamp DescriptorSet 0
1173 OpDecorate %g_sSamp Binding 0
1174 OpMemberDecorate %cbuff 0 Offset 0
1175 OpDecorate %cbuff Block
1176 OpDecorate %_ DescriptorSet 0
1177 OpDecorate %_ Binding 1
1178 OpDecorate %i_Tex0 Location 0
1179 OpDecorate %_entryPointOutput_Color Location 0
1180 OpDecorate %65 RelaxedPrecision
1181 OpDecorate %82 RelaxedPrecision
1182 OpDecorate %84 RelaxedPrecision
1183 OpDecorate %86 RelaxedPrecision
1184 OpDecorate %88 RelaxedPrecision
1185 OpDecorate %90 RelaxedPrecision
1186 OpDecorate %91 RelaxedPrecision
1187 OpDecorate %93 RelaxedPrecision
1188 OpDecorate %94 RelaxedPrecision
1189 %void = OpTypeVoid
1190 %3 = OpTypeFunction %void
1191 %float = OpTypeFloat 32
1192 %v4float = OpTypeVector %float 4
1193 %17 = OpTypeImage %float 1D 0 0 0 1 Unknown
1194 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
1195 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant
1196 %21 = OpTypeSampler
1197 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
1198 %g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant
1199 %25 = OpTypeSampledImage %17
1200 %int = OpTypeInt 32 1
1201 %int_0 = OpConstant %int 0
1202 %cbuff = OpTypeStruct %float
1203 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
1204 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
1205 %_ptr_Uniform_float = OpTypePointer Uniform %float
1206 %_ptr_Input_float = OpTypePointer Input %float
1207 %i_Tex0 = OpVariable %_ptr_Input_float Input
1208 %_ptr_Output_v4float = OpTypePointer Output %v4float
1209 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
1210 )";
1211
1212 const std::string defs_after =
1213 R"(OpCapability Shader
1214 OpCapability Sampled1D
1215 OpCapability Float16
1216 %1 = OpExtInstImport "GLSL.std.450"
1217 OpMemoryModel Logical GLSL450
1218 OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color
1219 OpExecutionMode %main OriginUpperLeft
1220 OpSource HLSL 500
1221 OpName %main "main"
1222 OpName %g_tTex1df4 "g_tTex1df4"
1223 OpName %g_sSamp "g_sSamp"
1224 OpName %cbuff "cbuff"
1225 OpMemberName %cbuff 0 "c"
1226 OpName %_ ""
1227 OpName %i_Tex0 "i.Tex0"
1228 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
1229 OpDecorate %g_tTex1df4 DescriptorSet 0
1230 OpDecorate %g_tTex1df4 Binding 0
1231 OpDecorate %g_sSamp DescriptorSet 0
1232 OpDecorate %g_sSamp Binding 0
1233 OpMemberDecorate %cbuff 0 Offset 0
1234 OpDecorate %cbuff Block
1235 OpDecorate %_ DescriptorSet 0
1236 OpDecorate %_ Binding 1
1237 OpDecorate %i_Tex0 Location 0
1238 OpDecorate %_entryPointOutput_Color Location 0
1239 %void = OpTypeVoid
1240 %3 = OpTypeFunction %void
1241 %float = OpTypeFloat 32
1242 %v4float = OpTypeVector %float 4
1243 %17 = OpTypeImage %float 1D 0 0 0 1 Unknown
1244 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
1245 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant
1246 %21 = OpTypeSampler
1247 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
1248 %g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant
1249 %25 = OpTypeSampledImage %17
1250 %int = OpTypeInt 32 1
1251 %int_0 = OpConstant %int 0
1252 %cbuff = OpTypeStruct %float
1253 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
1254 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
1255 %_ptr_Uniform_float = OpTypePointer Uniform %float
1256 %_ptr_Input_float = OpTypePointer Input %float
1257 %i_Tex0 = OpVariable %_ptr_Input_float Input
1258 %_ptr_Output_v4float = OpTypePointer Output %v4float
1259 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
1260 %half = OpTypeFloat 16
1261 %v4half = OpTypeVector %half 4
1262 )";
1263
1264 const std::string func_before =
1265 R"(%main = OpFunction %void None %3
1266 %5 = OpLabel
1267 %65 = OpLoad %float %i_Tex0
1268 %77 = OpLoad %17 %g_tTex1df4
1269 %78 = OpLoad %21 %g_sSamp
1270 %79 = OpSampledImage %25 %77 %78
1271 %82 = OpImageSampleImplicitLod %v4float %79 %65
1272 %84 = OpCompositeExtract %float %82 1
1273 %86 = OpCompositeExtract %float %82 2
1274 %88 = OpCompositeExtract %float %82 0
1275 %90 = OpCompositeExtract %float %82 3
1276 %91 = OpCompositeConstruct %v4float %84 %86 %88 %90
1277 %92 = OpAccessChain %_ptr_Uniform_float %_ %int_0
1278 %93 = OpLoad %float %92
1279 %94 = OpVectorTimesScalar %v4float %91 %93
1280 OpStore %_entryPointOutput_Color %94
1281 OpReturn
1282 OpFunctionEnd
1283 )";
1284
1285 const std::string func_after =
1286 R"(%main = OpFunction %void None %3
1287 %5 = OpLabel
1288 %65 = OpLoad %float %i_Tex0
1289 %77 = OpLoad %17 %g_tTex1df4
1290 %78 = OpLoad %21 %g_sSamp
1291 %79 = OpSampledImage %25 %77 %78
1292 %82 = OpImageSampleImplicitLod %v4float %79 %65
1293 %97 = OpFConvert %v4half %82
1294 %84 = OpCompositeExtract %half %97 1
1295 %98 = OpFConvert %v4half %82
1296 %86 = OpCompositeExtract %half %98 2
1297 %99 = OpFConvert %v4half %82
1298 %88 = OpCompositeExtract %half %99 0
1299 %100 = OpFConvert %v4half %82
1300 %90 = OpCompositeExtract %half %100 3
1301 %91 = OpCompositeConstruct %v4half %84 %86 %88 %90
1302 %92 = OpAccessChain %_ptr_Uniform_float %_ %int_0
1303 %93 = OpLoad %float %92
1304 %101 = OpFConvert %half %93
1305 %94 = OpVectorTimesScalar %v4half %91 %101
1306 %102 = OpFConvert %v4float %94
1307 OpStore %_entryPointOutput_Color %102
1308 OpReturn
1309 OpFunctionEnd
1310 )";
1311
1312 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1313 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
1314 defs_after + func_after, true, true);
1315 }
1316
TEST_F(ConvertToHalfTest, ConvertToHalfWithClosure)1317 TEST_F(ConvertToHalfTest, ConvertToHalfWithClosure) {
1318 // Include as many contiguous composite instructions as possible into
1319 // half-precision computations
1320 //
1321 // Compiled with glslang -V -Os
1322 //
1323 // clang-format off
1324 //
1325 // #version 410 core
1326 //
1327 // precision mediump float;
1328 //
1329 // layout(location = 1) in vec3 foo;
1330 // layout(location = 2) in mat2 bar;
1331 // layout(location = 1) out vec3 res;
1332 //
1333 // vec3 func(vec3 tap, mat2 M) {
1334 // return vec3(M * tap.xy, 1.0);
1335 // }
1336 //
1337 // void main() {
1338 // res = func(foo, bar);
1339 // }
1340 //
1341 // clang-format on
1342
1343 const std::string defs =
1344 R"(OpCapability Shader
1345 ; CHECK: OpCapability Float16
1346 %1 = OpExtInstImport "GLSL.std.450"
1347 OpMemoryModel Logical GLSL450
1348 OpEntryPoint Fragment %main "main" %res %foo %bar
1349 OpExecutionMode %main OriginUpperLeft
1350 OpSource GLSL 410
1351 OpName %main "main"
1352 OpName %res "res"
1353 OpName %foo "foo"
1354 OpName %bar "bar"
1355 OpDecorate %res RelaxedPrecision
1356 ; CHECK-NOT: OpDecorate %res RelaxedPrecision
1357 OpDecorate %res Location 1
1358 OpDecorate %foo RelaxedPrecision
1359 ; CHECK-NOT: OpDecorate %foo RelaxedPrecision
1360 OpDecorate %foo Location 1
1361 OpDecorate %bar RelaxedPrecision
1362 ; CHECK-NOT: OpDecorate %bar RelaxedPrecision
1363 OpDecorate %bar Location 2
1364 OpDecorate %34 RelaxedPrecision
1365 OpDecorate %36 RelaxedPrecision
1366 OpDecorate %41 RelaxedPrecision
1367 OpDecorate %42 RelaxedPrecision
1368 ; CHECK-NOT: OpDecorate %34 RelaxedPrecision
1369 ; CHECK-NOT: OpDecorate %36 RelaxedPrecision
1370 ; CHECK-NOT: OpDecorate %41 RelaxedPrecision
1371 ; CHECK-NOT: OpDecorate %42 RelaxedPrecision
1372 %void = OpTypeVoid
1373 %3 = OpTypeFunction %void
1374 %float = OpTypeFloat 32
1375 %v3float = OpTypeVector %float 3
1376 %v2float = OpTypeVector %float 2
1377 %mat2v2float = OpTypeMatrix %v2float 2
1378 %float_1 = OpConstant %float 1
1379 %_ptr_Output_v3float = OpTypePointer Output %v3float
1380 %res = OpVariable %_ptr_Output_v3float Output
1381 %_ptr_Input_v3float = OpTypePointer Input %v3float
1382 %foo = OpVariable %_ptr_Input_v3float Input
1383 %_ptr_Input_mat2v2float = OpTypePointer Input %mat2v2float
1384 %bar = OpVariable %_ptr_Input_mat2v2float Input
1385 )";
1386
1387 const std::string func =
1388 R"(%main = OpFunction %void None %3
1389 %5 = OpLabel
1390 %34 = OpLoad %v3float %foo
1391 %36 = OpLoad %mat2v2float %bar
1392 ; CHECK: %48 = OpFConvert %v3half %34
1393 ; CHECK: %49 = OpFConvert %v3half %34
1394 %41 = OpVectorShuffle %v2float %34 %34 0 1
1395 ; CHECK-NOT: %41 = OpVectorShuffle %v2float %34 %34 0 1
1396 ; CHECK: %41 = OpVectorShuffle %v2half %48 %49 0 1
1397 %42 = OpMatrixTimesVector %v2float %36 %41
1398 ; CHECK-NOT: %42 = OpMatrixTimesVector %v2float %36 %41
1399 ; CHECK: %55 = OpCompositeExtract %v2float %36 0
1400 ; CHECK: %56 = OpFConvert %v2half %55
1401 ; CHECK: %57 = OpCompositeExtract %v2float %36 1
1402 ; CHECK: %58 = OpFConvert %v2half %57
1403 ; CHECK: %59 = OpCompositeConstruct %mat2v2half %56 %58
1404 ; CHECK: %52 = OpCopyObject %mat2v2float %36
1405 ; CHECK: %42 = OpMatrixTimesVector %v2half %59 %41
1406 %43 = OpCompositeExtract %float %42 0
1407 %44 = OpCompositeExtract %float %42 1
1408 ; CHECK-NOT: %43 = OpCompositeExtract %float %42 0
1409 ; CHECK-NOT: %44 = OpCompositeExtract %float %42 1
1410 ; CHECK: %43 = OpCompositeExtract %half %42 0
1411 ; CHECK: %44 = OpCompositeExtract %half %42 1
1412 %45 = OpCompositeConstruct %v3float %43 %44 %float_1
1413 ; CHECK-NOT: %45 = OpCompositeConstruct %v3float %43 %44 %float_1
1414 ; CHECK: %53 = OpFConvert %float %43
1415 ; CHECK: %54 = OpFConvert %float %44
1416 ; CHECK: %45 = OpCompositeConstruct %v3float %53 %54 %float_1
1417 OpStore %res %45
1418 OpReturn
1419 OpFunctionEnd
1420 )";
1421
1422 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1423 SinglePassRunAndMatch<ConvertToHalfPass>(defs + func, true);
1424 }
1425
TEST_F(ConvertToHalfTest, RemoveRelaxDec)1426 TEST_F(ConvertToHalfTest, RemoveRelaxDec) {
1427 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4117
1428
1429 // This test is a case where the relax precision decorations need to be
1430 // removed, but the body of the function does not change because there are not
1431 // arithmetic operations. So, there is not need for the Float16 capability.
1432 const std::string test =
1433 R"(
1434 ; CHECK-NOT: OpCapability Float16
1435 ; GLSL seems to generate this decoration on the load of a texture, which seems odd to me.
1436 ; This pass does not currently remove it, and I'm not sure what we should do with it, so I will leave it.
1437 ; CHECK: OpDecorate [[tex:%\w+]] RelaxedPrecision
1438 ; CHECK-NOT: OpDecorate {{%\w+}} RelaxedPrecision
1439 ; CHECK: OpLabel
1440 ; CHECK: [[tex]] = OpLoad {{%\w+}} %sTexture
1441 ; CHECK: [[coord:%\w+]] = OpLoad %v2float
1442 ; CHECK: [[retval:%\w+]] = OpImageSampleImplicitLod %v4float {{%\w+}} [[coord]]
1443 ; CHECK: OpStore %outFragColor [[retval]]
1444 OpCapability Shader
1445 %1 = OpExtInstImport "GLSL.std.450"
1446 OpMemoryModel Logical GLSL450
1447 OpEntryPoint Fragment %main "main" %outFragColor %v_texcoord
1448 OpExecutionMode %main OriginUpperLeft
1449 OpSource ESSL 310
1450 OpName %main "main"
1451 OpName %outFragColor "outFragColor"
1452 OpName %sTexture "sTexture"
1453 OpName %v_texcoord "v_texcoord"
1454 OpDecorate %outFragColor RelaxedPrecision
1455 OpDecorate %outFragColor Location 0
1456 OpDecorate %sTexture RelaxedPrecision
1457 OpDecorate %sTexture DescriptorSet 0
1458 OpDecorate %sTexture Binding 0
1459 OpDecorate %14 RelaxedPrecision
1460 OpDecorate %v_texcoord RelaxedPrecision
1461 OpDecorate %v_texcoord Location 0
1462 OpDecorate %18 RelaxedPrecision
1463 OpDecorate %19 RelaxedPrecision
1464 %void = OpTypeVoid
1465 %3 = OpTypeFunction %void
1466 %float = OpTypeFloat 32
1467 %v4float = OpTypeVector %float 4
1468 %_ptr_Output_v4float = OpTypePointer Output %v4float
1469 %outFragColor = OpVariable %_ptr_Output_v4float Output
1470 %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
1471 %11 = OpTypeSampledImage %10
1472 %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
1473 %sTexture = OpVariable %_ptr_UniformConstant_11 UniformConstant
1474 %v2float = OpTypeVector %float 2
1475 %_ptr_Input_v2float = OpTypePointer Input %v2float
1476 %v_texcoord = OpVariable %_ptr_Input_v2float Input
1477 %main = OpFunction %void None %3
1478 %5 = OpLabel
1479 %14 = OpLoad %11 %sTexture
1480 %18 = OpLoad %v2float %v_texcoord
1481 %19 = OpImageSampleImplicitLod %v4float %14 %18
1482 OpStore %outFragColor %19
1483 OpReturn
1484 OpFunctionEnd
1485 )";
1486
1487 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1488 auto result = SinglePassRunAndMatch<ConvertToHalfPass>(test, true);
1489 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
1490 }
1491
TEST_F(ConvertToHalfTest, HandleNonRelaxedPhi)1492 TEST_F(ConvertToHalfTest, HandleNonRelaxedPhi) {
1493 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4452
1494
1495 // This test is a case with a non-relaxed phi with a relaxed operand.
1496 // A convert must be inserted at the end of the block associated with
1497 // the operand.
1498 const std::string test =
1499 R"(
1500 ; CHECK: [[fcvt:%\w+]] = OpFConvert %v3float {{%\w+}}
1501 ; CHECK-NEXT: OpSelectionMerge {{%\w+}} None
1502 ; CHECK: {{%\w+}} = OpPhi %v3float [[fcvt]] {{%\w+}} {{%\w+}} {{%\w+}}
1503 OpCapability Shader
1504 %1 = OpExtInstImport "GLSL.std.450"
1505 OpMemoryModel Logical GLSL450
1506 OpEntryPoint Fragment %main "main" %output_color
1507 OpExecutionMode %main OriginUpperLeft
1508 OpSource GLSL 450
1509 OpName %main "main"
1510 OpName %MaterialParams "MaterialParams"
1511 OpMemberName %MaterialParams 0 "foo"
1512 OpName %materialParams "materialParams"
1513 OpName %output_color "output_color"
1514 OpMemberDecorate %MaterialParams 0 Offset 0
1515 OpDecorate %MaterialParams Block
1516 OpDecorate %materialParams DescriptorSet 0
1517 OpDecorate %materialParams Binding 5
1518 OpDecorate %output_color Location 0
1519 OpDecorate %57 RelaxedPrecision
1520 %void = OpTypeVoid
1521 %3 = OpTypeFunction %void
1522 %float = OpTypeFloat 32
1523 %v3float = OpTypeVector %float 3
1524 %MaterialParams = OpTypeStruct %float
1525 %_ptr_Uniform_MaterialParams = OpTypePointer Uniform %MaterialParams
1526 %materialParams = OpVariable %_ptr_Uniform_MaterialParams Uniform
1527 %int = OpTypeInt 32 1
1528 %int_0 = OpConstant %int 0
1529 %_ptr_Uniform_float = OpTypePointer Uniform %float
1530 %float_0 = OpConstant %float 0
1531 %bool = OpTypeBool
1532 %v4float = OpTypeVector %float 4
1533 %_ptr_Output_v4float = OpTypePointer Output %v4float
1534 %output_color = OpVariable %_ptr_Output_v4float Output
1535 %uint = OpTypeInt 32 0
1536 %uint_0 = OpConstant %uint 0
1537 %_ptr_Output_float = OpTypePointer Output %float
1538 %uint_1 = OpConstant %uint 1
1539 %uint_2 = OpConstant %uint 2
1540 %float_0_5 = OpConstant %float 0.5
1541 %61 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5
1542 %main = OpFunction %void None %3
1543 %5 = OpLabel
1544 %55 = OpAccessChain %_ptr_Uniform_float %materialParams %int_0
1545 %56 = OpLoad %float %55
1546 %57 = OpCompositeConstruct %v3float %56 %56 %56
1547 %31 = OpFOrdGreaterThan %bool %56 %float_0
1548 OpSelectionMerge %33 None
1549 OpBranchConditional %31 %32 %33
1550 %32 = OpLabel
1551 %37 = OpFMul %v3float %57 %61
1552 OpBranch %33
1553 %33 = OpLabel
1554 %58 = OpPhi %v3float %57 %5 %37 %32
1555 %45 = OpAccessChain %_ptr_Output_float %output_color %uint_0
1556 %46 = OpCompositeExtract %float %58 0
1557 OpStore %45 %46
1558 %48 = OpAccessChain %_ptr_Output_float %output_color %uint_1
1559 %49 = OpCompositeExtract %float %58 1
1560 OpStore %48 %49
1561 %51 = OpAccessChain %_ptr_Output_float %output_color %uint_2
1562 %52 = OpCompositeExtract %float %58 2
1563 OpStore %51 %52
1564 OpReturn
1565 OpFunctionEnd
1566 )";
1567
1568 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1569 auto result = SinglePassRunAndMatch<ConvertToHalfPass>(test, true);
1570 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
1571 }
1572
TEST_F(ConvertToHalfTest, DoNotReplaceStructMember)1573 TEST_F(ConvertToHalfTest, DoNotReplaceStructMember) {
1574 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4814
1575
1576 // This test is a case with a non-relaxed phi with a relaxed operand.
1577 // A convert must be inserted at the end of the block associated with
1578 // the operand.
1579 const std::string test =
1580 R"(OpCapability Shader
1581 OpMemoryModel Logical GLSL450
1582 OpEntryPoint Fragment %PSMain "PSMain" %out_var_SV_TARGET %MyConstants
1583 OpExecutionMode %PSMain OriginUpperLeft
1584 OpSource HLSL 600
1585 OpName %type_ConstantBuffer_myStruct "type.ConstantBuffer.myStruct"
1586 OpMemberName %type_ConstantBuffer_myStruct 0 "f"
1587 OpName %MyConstants "MyConstants"
1588 OpName %out_var_SV_TARGET "out.var.SV_TARGET"
1589 OpName %PSMain "PSMain"
1590 OpDecorate %out_var_SV_TARGET Location 0
1591 OpDecorate %MyConstants DescriptorSet 1
1592 OpDecorate %MyConstants Binding 2
1593 OpMemberDecorate %type_ConstantBuffer_myStruct 0 Offset 0
1594 OpDecorate %type_ConstantBuffer_myStruct Block
1595 %float = OpTypeFloat 32
1596 %type_ConstantBuffer_myStruct = OpTypeStruct %float
1597 %_ptr_Uniform_type_ConstantBuffer_myStruct = OpTypePointer Uniform %type_ConstantBuffer_myStruct
1598 %_ptr_Output_float = OpTypePointer Output %float
1599 %void = OpTypeVoid
1600 %9 = OpTypeFunction %void
1601 %MyConstants = OpVariable %_ptr_Uniform_type_ConstantBuffer_myStruct Uniform
1602 %out_var_SV_TARGET = OpVariable %_ptr_Output_float Output
1603 %PSMain = OpFunction %void None %9
1604 %10 = OpLabel
1605 %11 = OpLoad %type_ConstantBuffer_myStruct %MyConstants
1606 %12 = OpCompositeExtract %float %11 0
1607 OpStore %out_var_SV_TARGET %12
1608 OpReturn
1609 OpFunctionEnd
1610 )";
1611
1612 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1613 SinglePassRunAndCheck<ConvertToHalfPass>(test, test, true);
1614 }
1615
TEST_F(ConvertToHalfTest, PreserveImageOperandPrecision)1616 TEST_F(ConvertToHalfTest, PreserveImageOperandPrecision) {
1617 // Ensure that a non-relaxed texture coordinate does not get relaxed nor
1618 // converted to half precision if the image instruction is marked relaxed.
1619
1620 // Also ensure that a relaxed local variable does get converted to half
1621 // precision before being passed to an image opeartor.
1622
1623 // #version 310 es
1624 //
1625 // precision mediump float;
1626 //
1627 // layout(location = 10) in highp vec4 vertex_uv01;
1628 // layout(binding = 0, set = 3) uniform sampler2D materialParams_baseColorMap;
1629 //
1630 // layout(location = 0) out vec4 fragColor;
1631 //
1632 // void main() {
1633 // vec4 uv = vec4(2.0);
1634 // fragColor = texture(materialParams_baseColorMap, uv.xy);
1635 // fragColor = texture(materialParams_baseColorMap, vertex_uv01.xy);
1636 // }
1637 const std::string test = R"(
1638 OpCapability Shader
1639 OpCapability Float16
1640 %1 = OpExtInstImport "GLSL.std.450"
1641 OpMemoryModel Logical GLSL450
1642 OpEntryPoint Fragment %4 "main" %13 %25
1643 OpExecutionMode %4 OriginUpperLeft
1644 OpSource ESSL 310
1645 OpDecorate %9 RelaxedPrecision
1646 ;CHECK: OpDecorate [[uv:%\w+]] RelaxedPrecision
1647 OpDecorate %13 Location 0
1648 OpDecorate %17 DescriptorSet 3
1649 OpDecorate %17 Binding 0
1650 OpDecorate %18 RelaxedPrecision
1651 OpDecorate %23 RelaxedPrecision
1652 OpDecorate %25 Location 10
1653 %2 = OpTypeVoid
1654 %3 = OpTypeFunction %2
1655 %6 = OpTypeFloat 32
1656 ;CHECK: [[float32_t:%\w+]] = OpTypeFloat 32
1657 %7 = OpTypeVector %6 4
1658 ;CHECK: [[vec4_t:%\w+]] = OpTypeVector [[float32_t]] 4
1659 %8 = OpTypePointer Function %7
1660 %10 = OpConstant %6 2
1661 %11 = OpConstantComposite %7 %10 %10 %10 %10
1662 %12 = OpTypePointer Output %7
1663 ;CHECK: [[output_ptr_t:%\w+]] = OpTypePointer Output [[vec4_t]]
1664 %13 = OpVariable %12 Output
1665 ;CHECK: [[output:%\w+]] = OpVariable [[output_ptr_t]] Output
1666 %14 = OpTypeImage %6 2D 0 0 0 1 Unknown
1667 %15 = OpTypeSampledImage %14
1668 %16 = OpTypePointer UniformConstant %15
1669 %17 = OpVariable %16 UniformConstant
1670 %19 = OpTypeVector %6 2
1671 ;CHECK: [[vec2_t:%\w+]] = OpTypeVector [[float32_t]] 2
1672 %24 = OpTypePointer Input %7
1673 ;CHECK: [[input_ptr_t:%\w+]] = OpTypePointer Input [[vec4_t]]
1674 %25 = OpVariable %24 Input
1675 %29 = OpTypeFloat 16
1676 ;CHECK: [[float16_t:%\w+]] = OpTypeFloat 16
1677 %30 = OpTypeVector %29 4
1678 %33 = OpTypeVector %29 2
1679 ;CHECK: [[vec2_16b_t:%\w+]] = OpTypeVector [[float16_t]] 2
1680 %4 = OpFunction %2 None %3
1681 %5 = OpLabel
1682
1683 ; The only Function storage variable is marked as relaxed
1684 %9 = OpVariable %8 Function
1685 ;CHECK: [[uv]] = OpVariable {{%\w+}} Function
1686 OpStore %9 %11
1687 %18 = OpLoad %15 %17
1688 %20 = OpLoad %7 %9
1689 %31 = OpFConvert %30 %20
1690 %32 = OpFConvert %30 %20
1691
1692 ; The first sample op should get a 16b coordinate
1693 %21 = OpVectorShuffle %33 %31 %32 0 1
1694 ;CHECK: [[uv_16b:%\w+]] = OpVectorShuffle [[vec2_16b_t]]
1695 %22 = OpImageSampleImplicitLod %7 %18 %21
1696 ;CHECK: OpImageSampleImplicitLod [[vec4_t]] {{%\w+}} [[uv_16b]]
1697
1698 OpStore %13 %22
1699 %23 = OpLoad %15 %17
1700 %26 = OpLoad %7 %25
1701
1702 ; The second sample op should get a 32b coordinate
1703 %27 = OpVectorShuffle %19 %26 %26 0 1
1704 ;CHECK: [[uv_32b:%\w+]] = OpVectorShuffle [[vec2_t]]
1705 %28 = OpImageSampleImplicitLod %7 %23 %27
1706 ;CHECK: OpImageSampleImplicitLod [[vec4_t]] {{%\w+}} [[uv_32b]]
1707
1708 OpStore %13 %28
1709 OpReturn
1710 OpFunctionEnd
1711 )";
1712
1713 SinglePassRunAndMatch<ConvertToHalfPass>(test, true);
1714 }
1715
1716 } // namespace
1717 } // namespace opt
1718 } // namespace spvtools
1719