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,ConvertToHalfWithDrefSample)207 TEST_F(ConvertToHalfTest, ConvertToHalfWithDrefSample) {
208 // The resulting SPIR-V was processed with --relax-float-ops.
209 //
210 // clang-format off
211 //
212 // SamplerComparisonState g_sSamp : register(s0);
213 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
214 //
215 // cbuffer cbuff{
216 // float c1;
217 // float c2;
218 // };
219 //
220 // struct PS_INPUT
221 // {
222 // float Tex0 : TEXCOORD0;
223 // float Tex1 : TEXCOORD1;
224 // };
225 //
226 // struct PS_OUTPUT
227 // {
228 // float Color : SV_Target0;
229 // };
230 //
231 // PS_OUTPUT main(PS_INPUT i)
232 // {
233 // PS_OUTPUT psout;
234 // float txval10 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex0 * 0.1, c1 + 0.1);
235 // float txval11 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex1 * 0.2, c2 + 0.2);
236 // float t = txval10 + txval11;
237 // float t2 = t / 2.0;
238 // psout.Color = t2;
239 // return psout;
240 // }
241 //
242 // clang-format on
243
244 const std::string defs_before =
245 R"(OpCapability Shader
246 OpCapability Sampled1D
247 %1 = OpExtInstImport "GLSL.std.450"
248 OpMemoryModel Logical GLSL450
249 OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color
250 OpExecutionMode %main OriginUpperLeft
251 OpSource HLSL 500
252 OpName %main "main"
253 OpName %g_tTex1df4 "g_tTex1df4"
254 OpName %g_sSamp "g_sSamp"
255 OpName %cbuff "cbuff"
256 OpMemberName %cbuff 0 "c1"
257 OpMemberName %cbuff 1 "c2"
258 OpName %_ ""
259 OpName %i_Tex0 "i.Tex0"
260 OpName %i_Tex1 "i.Tex1"
261 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
262 OpDecorate %g_tTex1df4 DescriptorSet 0
263 OpDecorate %g_tTex1df4 Binding 0
264 OpDecorate %g_sSamp DescriptorSet 0
265 OpDecorate %g_sSamp Binding 0
266 OpMemberDecorate %cbuff 0 Offset 0
267 OpMemberDecorate %cbuff 1 Offset 4
268 OpDecorate %cbuff Block
269 OpDecorate %_ DescriptorSet 0
270 OpDecorate %_ Binding 1
271 OpDecorate %i_Tex0 Location 0
272 OpDecorate %i_Tex1 Location 1
273 OpDecorate %_entryPointOutput_Color Location 0
274 OpDecorate %100 RelaxedPrecision
275 OpDecorate %76 RelaxedPrecision
276 OpDecorate %79 RelaxedPrecision
277 OpDecorate %98 RelaxedPrecision
278 OpDecorate %101 RelaxedPrecision
279 OpDecorate %110 RelaxedPrecision
280 OpDecorate %102 RelaxedPrecision
281 OpDecorate %112 RelaxedPrecision
282 OpDecorate %104 RelaxedPrecision
283 OpDecorate %113 RelaxedPrecision
284 OpDecorate %114 RelaxedPrecision
285 OpDecorate %116 RelaxedPrecision
286 OpDecorate %119 RelaxedPrecision
287 OpDecorate %121 RelaxedPrecision
288 %void = OpTypeVoid
289 %3 = OpTypeFunction %void
290 %float = OpTypeFloat 32
291 %16 = OpTypeImage %float 1D 1 0 0 1 Unknown
292 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
293 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_16 UniformConstant
294 %20 = OpTypeSampler
295 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
296 %g_sSamp = OpVariable %_ptr_UniformConstant_20 UniformConstant
297 %24 = OpTypeSampledImage %16
298 %int = OpTypeInt 32 1
299 %int_0 = OpConstant %int 0
300 %float_0_100000001 = OpConstant %float 0.100000001
301 %cbuff = OpTypeStruct %float %float
302 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
303 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
304 %_ptr_Uniform_float = OpTypePointer Uniform %float
305 %v2float = OpTypeVector %float 2
306 %int_1 = OpConstant %int 1
307 %float_0_200000003 = OpConstant %float 0.200000003
308 %_ptr_Input_float = OpTypePointer Input %float
309 %i_Tex0 = OpVariable %_ptr_Input_float Input
310 %i_Tex1 = OpVariable %_ptr_Input_float Input
311 %_ptr_Output_float = OpTypePointer Output %float
312 %_entryPointOutput_Color = OpVariable %_ptr_Output_float Output
313 %float_0_5 = OpConstant %float 0.5
314 )";
315
316 const std::string defs_after =
317 R"(OpCapability Shader
318 OpCapability Sampled1D
319 OpCapability Float16
320 %1 = OpExtInstImport "GLSL.std.450"
321 OpMemoryModel Logical GLSL450
322 OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color
323 OpExecutionMode %main OriginUpperLeft
324 OpSource HLSL 500
325 OpName %main "main"
326 OpName %g_tTex1df4 "g_tTex1df4"
327 OpName %g_sSamp "g_sSamp"
328 OpName %cbuff "cbuff"
329 OpMemberName %cbuff 0 "c1"
330 OpMemberName %cbuff 1 "c2"
331 OpName %_ ""
332 OpName %i_Tex0 "i.Tex0"
333 OpName %i_Tex1 "i.Tex1"
334 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
335 OpDecorate %g_tTex1df4 DescriptorSet 0
336 OpDecorate %g_tTex1df4 Binding 0
337 OpDecorate %g_sSamp DescriptorSet 0
338 OpDecorate %g_sSamp Binding 0
339 OpMemberDecorate %cbuff 0 Offset 0
340 OpMemberDecorate %cbuff 1 Offset 4
341 OpDecorate %cbuff Block
342 OpDecorate %_ DescriptorSet 0
343 OpDecorate %_ Binding 1
344 OpDecorate %i_Tex0 Location 0
345 OpDecorate %i_Tex1 Location 1
346 OpDecorate %_entryPointOutput_Color Location 0
347 %void = OpTypeVoid
348 %25 = OpTypeFunction %void
349 %float = OpTypeFloat 32
350 %27 = OpTypeImage %float 1D 1 0 0 1 Unknown
351 %_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27
352 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_27 UniformConstant
353 %29 = OpTypeSampler
354 %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
355 %g_sSamp = OpVariable %_ptr_UniformConstant_29 UniformConstant
356 %31 = OpTypeSampledImage %27
357 %int = OpTypeInt 32 1
358 %int_0 = OpConstant %int 0
359 %float_0_100000001 = OpConstant %float 0.100000001
360 %cbuff = OpTypeStruct %float %float
361 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
362 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
363 %_ptr_Uniform_float = OpTypePointer Uniform %float
364 %v2float = OpTypeVector %float 2
365 %int_1 = OpConstant %int 1
366 %float_0_200000003 = OpConstant %float 0.200000003
367 %_ptr_Input_float = OpTypePointer Input %float
368 %i_Tex0 = OpVariable %_ptr_Input_float Input
369 %i_Tex1 = OpVariable %_ptr_Input_float Input
370 %_ptr_Output_float = OpTypePointer Output %float
371 %_entryPointOutput_Color = OpVariable %_ptr_Output_float Output
372 %float_0_5 = OpConstant %float 0.5
373 %half = OpTypeFloat 16
374 %v2half = OpTypeVector %half 2
375 )";
376
377 const std::string func_before =
378 R"(%main = OpFunction %void None %3
379 %5 = OpLabel
380 %76 = OpLoad %float %i_Tex0
381 %79 = OpLoad %float %i_Tex1
382 %93 = OpLoad %16 %g_tTex1df4
383 %94 = OpLoad %20 %g_sSamp
384 %95 = OpSampledImage %24 %93 %94
385 %98 = OpFMul %float %76 %float_0_100000001
386 %99 = OpAccessChain %_ptr_Uniform_float %_ %int_0
387 %100 = OpLoad %float %99
388 %101 = OpFAdd %float %100 %float_0_100000001
389 %102 = OpCompositeConstruct %v2float %98 %101
390 %104 = OpImageSampleDrefImplicitLod %float %95 %102 %101
391 %105 = OpLoad %16 %g_tTex1df4
392 %106 = OpLoad %20 %g_sSamp
393 %107 = OpSampledImage %24 %105 %106
394 %110 = OpFMul %float %79 %float_0_200000003
395 %111 = OpAccessChain %_ptr_Uniform_float %_ %int_1
396 %112 = OpLoad %float %111
397 %113 = OpFAdd %float %112 %float_0_200000003
398 %114 = OpCompositeConstruct %v2float %110 %113
399 %116 = OpImageSampleDrefImplicitLod %float %107 %114 %113
400 %119 = OpFAdd %float %104 %116
401 %121 = OpFMul %float %119 %float_0_5
402 OpStore %_entryPointOutput_Color %121
403 OpReturn
404 OpFunctionEnd
405 )";
406
407 const std::string func_after =
408 R"(%main = OpFunction %void None %25
409 %43 = OpLabel
410 %11 = OpLoad %float %i_Tex0
411 %12 = OpLoad %float %i_Tex1
412 %44 = OpLoad %27 %g_tTex1df4
413 %45 = OpLoad %29 %g_sSamp
414 %46 = OpSampledImage %31 %44 %45
415 %53 = OpFConvert %half %11
416 %54 = OpFConvert %half %float_0_100000001
417 %13 = OpFMul %half %53 %54
418 %47 = OpAccessChain %_ptr_Uniform_float %_ %int_0
419 %10 = OpLoad %float %47
420 %55 = OpFConvert %half %10
421 %56 = OpFConvert %half %float_0_100000001
422 %14 = OpFAdd %half %55 %56
423 %16 = OpCompositeConstruct %v2half %13 %14
424 %58 = OpFConvert %float %14
425 %18 = OpImageSampleDrefImplicitLod %float %46 %16 %58
426 %48 = OpLoad %27 %g_tTex1df4
427 %49 = OpLoad %29 %g_sSamp
428 %50 = OpSampledImage %31 %48 %49
429 %59 = OpFConvert %half %12
430 %60 = OpFConvert %half %float_0_200000003
431 %15 = OpFMul %half %59 %60
432 %51 = OpAccessChain %_ptr_Uniform_float %_ %int_1
433 %17 = OpLoad %float %51
434 %61 = OpFConvert %half %17
435 %62 = OpFConvert %half %float_0_200000003
436 %19 = OpFAdd %half %61 %62
437 %20 = OpCompositeConstruct %v2half %15 %19
438 %63 = OpFConvert %float %19
439 %21 = OpImageSampleDrefImplicitLod %float %50 %20 %63
440 %64 = OpFConvert %half %18
441 %65 = OpFConvert %half %21
442 %22 = OpFAdd %half %64 %65
443 %66 = OpFConvert %half %float_0_5
444 %23 = OpFMul %half %22 %66
445 %67 = OpFConvert %float %23
446 OpStore %_entryPointOutput_Color %67
447 OpReturn
448 OpFunctionEnd
449 )";
450
451 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
452 defs_after + func_after, true, true);
453 }
454
TEST_F(ConvertToHalfTest,ConvertToHalfWithVectorMatrixMult)455 TEST_F(ConvertToHalfTest, ConvertToHalfWithVectorMatrixMult) {
456 // The resulting SPIR-V was processed with --relax-float-ops.
457 //
458 // clang-format off
459 //
460 // SamplerState g_sSamp : register(s0);
461 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
462 //
463 // struct PS_OUTPUT
464 // {
465 // float4 Color : SV_Target0;
466 // };
467 //
468 // cbuffer cbuff{
469 // float4x4 M;
470 // }
471 //
472 // PS_OUTPUT main()
473 // {
474 // PS_OUTPUT psout;
475 // float4 txval10 = g_tTex1df4.Sample(g_sSamp, 0.1);
476 // float4 t = mul(txval10, M);
477 // psout.Color = t;
478 // return psout;
479 //}
480 //
481 // clang-format on
482
483 const std::string defs_before =
484 R"(OpCapability Shader
485 OpCapability Sampled1D
486 %1 = OpExtInstImport "GLSL.std.450"
487 OpMemoryModel Logical GLSL450
488 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
489 OpExecutionMode %main OriginUpperLeft
490 OpSource HLSL 500
491 OpName %main "main"
492 OpName %g_tTex1df4 "g_tTex1df4"
493 OpName %g_sSamp "g_sSamp"
494 OpName %cbuff "cbuff"
495 OpMemberName %cbuff 0 "M"
496 OpName %_ ""
497 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
498 OpDecorate %g_tTex1df4 DescriptorSet 0
499 OpDecorate %g_tTex1df4 Binding 0
500 OpDecorate %g_sSamp DescriptorSet 0
501 OpDecorate %g_sSamp Binding 0
502 OpMemberDecorate %cbuff 0 RowMajor
503 OpMemberDecorate %cbuff 0 Offset 0
504 OpMemberDecorate %cbuff 0 MatrixStride 16
505 OpDecorate %cbuff Block
506 OpDecorate %_ DescriptorSet 0
507 OpDecorate %_ Binding 1
508 OpDecorate %_entryPointOutput_Color Location 0
509 OpDecorate %56 RelaxedPrecision
510 OpDecorate %58 RelaxedPrecision
511 OpDecorate %60 RelaxedPrecision
512 %void = OpTypeVoid
513 %3 = OpTypeFunction %void
514 %float = OpTypeFloat 32
515 %v4float = OpTypeVector %float 4
516 %14 = OpTypeImage %float 1D 0 0 0 1 Unknown
517 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
518 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant
519 %18 = OpTypeSampler
520 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
521 %g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant
522 %22 = OpTypeSampledImage %14
523 %float_0_100000001 = OpConstant %float 0.100000001
524 %mat4v4float = OpTypeMatrix %v4float 4
525 %cbuff = OpTypeStruct %mat4v4float
526 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
527 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
528 %int = OpTypeInt 32 1
529 %int_0 = OpConstant %int 0
530 %_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
531 %_ptr_Output_v4float = OpTypePointer Output %v4float
532 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
533 )";
534
535 const std::string defs_after =
536 R"(OpCapability Shader
537 OpCapability Sampled1D
538 OpCapability Float16
539 %1 = OpExtInstImport "GLSL.std.450"
540 OpMemoryModel Logical GLSL450
541 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
542 OpExecutionMode %main OriginUpperLeft
543 OpSource HLSL 500
544 OpName %main "main"
545 OpName %g_tTex1df4 "g_tTex1df4"
546 OpName %g_sSamp "g_sSamp"
547 OpName %cbuff "cbuff"
548 OpMemberName %cbuff 0 "M"
549 OpName %_ ""
550 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
551 OpDecorate %g_tTex1df4 DescriptorSet 0
552 OpDecorate %g_tTex1df4 Binding 0
553 OpDecorate %g_sSamp DescriptorSet 0
554 OpDecorate %g_sSamp Binding 0
555 OpMemberDecorate %cbuff 0 RowMajor
556 OpMemberDecorate %cbuff 0 Offset 0
557 OpMemberDecorate %cbuff 0 MatrixStride 16
558 OpDecorate %cbuff Block
559 OpDecorate %_ DescriptorSet 0
560 OpDecorate %_ Binding 1
561 OpDecorate %_entryPointOutput_Color Location 0
562 %void = OpTypeVoid
563 %3 = OpTypeFunction %void
564 %float = OpTypeFloat 32
565 %v4float = OpTypeVector %float 4
566 %14 = OpTypeImage %float 1D 0 0 0 1 Unknown
567 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
568 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant
569 %18 = OpTypeSampler
570 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
571 %g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant
572 %22 = OpTypeSampledImage %14
573 %float_0_100000001 = OpConstant %float 0.100000001
574 %mat4v4float = OpTypeMatrix %v4float 4
575 %cbuff = OpTypeStruct %mat4v4float
576 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
577 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
578 %int = OpTypeInt 32 1
579 %int_0 = OpConstant %int 0
580 %_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
581 %_ptr_Output_v4float = OpTypePointer Output %v4float
582 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
583 %half = OpTypeFloat 16
584 %v4half = OpTypeVector %half 4
585 %mat4v4half = OpTypeMatrix %v4half 4
586 )";
587
588 const std::string func_before =
589 R"(%main = OpFunction %void None %3
590 %5 = OpLabel
591 %53 = OpLoad %14 %g_tTex1df4
592 %54 = OpLoad %18 %g_sSamp
593 %55 = OpSampledImage %22 %53 %54
594 %56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001
595 %57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0
596 %58 = OpLoad %mat4v4float %57
597 %60 = OpMatrixTimesVector %v4float %58 %56
598 OpStore %_entryPointOutput_Color %60
599 OpReturn
600 OpFunctionEnd
601 )";
602
603 const std::string func_after =
604 R"(%main = OpFunction %void None %3
605 %5 = OpLabel
606 %53 = OpLoad %14 %g_tTex1df4
607 %54 = OpLoad %18 %g_sSamp
608 %55 = OpSampledImage %22 %53 %54
609 %56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001
610 %57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0
611 %58 = OpLoad %mat4v4float %57
612 %67 = OpCompositeExtract %v4float %58 0
613 %68 = OpFConvert %v4half %67
614 %69 = OpCompositeExtract %v4float %58 1
615 %70 = OpFConvert %v4half %69
616 %71 = OpCompositeExtract %v4float %58 2
617 %72 = OpFConvert %v4half %71
618 %73 = OpCompositeExtract %v4float %58 3
619 %74 = OpFConvert %v4half %73
620 %75 = OpCompositeConstruct %mat4v4half %68 %70 %72 %74
621 %64 = OpCopyObject %mat4v4float %58
622 %65 = OpFConvert %v4half %56
623 %60 = OpMatrixTimesVector %v4half %75 %65
624 %66 = OpFConvert %v4float %60
625 OpStore %_entryPointOutput_Color %66
626 OpReturn
627 OpFunctionEnd
628 )";
629
630 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
631 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
632 defs_after + func_after, true, true);
633 }
634
TEST_F(ConvertToHalfTest,ConvertToHalfWithPhi)635 TEST_F(ConvertToHalfTest, ConvertToHalfWithPhi) {
636 // The resulting SPIR-V was processed with --relax-float-ops.
637 //
638 // clang-format off
639 //
640 // SamplerState g_sSamp : register(s0);
641 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
642 //
643 // struct PS_OUTPUT
644 // {
645 // float4 Color : SV_Target0;
646 // };
647 //
648 // cbuffer cbuff{
649 // bool b;
650 // float4x4 M;
651 // }
652 //
653 // PS_OUTPUT main()
654 // {
655 // PS_OUTPUT psout;
656 // float4 t;
657 //
658 // if (b)
659 // t = g_tTex1df4.Sample(g_sSamp, 0.1);
660 // else
661 // t = float4(0.0, 0.0, 0.0, 0.0);
662 //
663 // float4 t2 = t * 2.0;
664 // psout.Color = t2;
665 // return psout;
666 // }
667 //
668 // clang-format on
669
670 const std::string defs_before =
671 R"(OpCapability Shader
672 OpCapability Sampled1D
673 %1 = OpExtInstImport "GLSL.std.450"
674 OpMemoryModel Logical GLSL450
675 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
676 OpExecutionMode %main OriginUpperLeft
677 OpSource HLSL 500
678 OpName %main "main"
679 OpName %cbuff "cbuff"
680 OpMemberName %cbuff 0 "b"
681 OpMemberName %cbuff 1 "M"
682 OpName %_ ""
683 OpName %g_tTex1df4 "g_tTex1df4"
684 OpName %g_sSamp "g_sSamp"
685 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
686 OpMemberDecorate %cbuff 0 Offset 0
687 OpMemberDecorate %cbuff 1 RowMajor
688 OpMemberDecorate %cbuff 1 Offset 16
689 OpMemberDecorate %cbuff 1 MatrixStride 16
690 OpDecorate %cbuff Block
691 OpDecorate %_ DescriptorSet 0
692 OpDecorate %_ Binding 1
693 OpDecorate %g_tTex1df4 DescriptorSet 0
694 OpDecorate %g_tTex1df4 Binding 0
695 OpDecorate %g_sSamp DescriptorSet 0
696 OpDecorate %g_sSamp Binding 0
697 OpDecorate %_entryPointOutput_Color Location 0
698 OpDecorate %72 RelaxedPrecision
699 OpDecorate %85 RelaxedPrecision
700 OpDecorate %74 RelaxedPrecision
701 %void = OpTypeVoid
702 %3 = OpTypeFunction %void
703 %float = OpTypeFloat 32
704 %v4float = OpTypeVector %float 4
705 %uint = OpTypeInt 32 0
706 %mat4v4float = OpTypeMatrix %v4float 4
707 %cbuff = OpTypeStruct %uint %mat4v4float
708 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
709 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
710 %int = OpTypeInt 32 1
711 %int_0 = OpConstant %int 0
712 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
713 %bool = OpTypeBool
714 %uint_0 = OpConstant %uint 0
715 %29 = OpTypeImage %float 1D 0 0 0 1 Unknown
716 %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
717 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant
718 %33 = OpTypeSampler
719 %_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33
720 %g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant
721 %37 = OpTypeSampledImage %29
722 %float_0_100000001 = OpConstant %float 0.100000001
723 %float_0 = OpConstant %float 0
724 %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
725 %float_2 = OpConstant %float 2
726 %_ptr_Output_v4float = OpTypePointer Output %v4float
727 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
728 )";
729
730 const std::string defs_after =
731 R"(OpCapability Shader
732 OpCapability Sampled1D
733 OpCapability Float16
734 %1 = OpExtInstImport "GLSL.std.450"
735 OpMemoryModel Logical GLSL450
736 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
737 OpExecutionMode %main OriginUpperLeft
738 OpSource HLSL 500
739 OpName %main "main"
740 OpName %cbuff "cbuff"
741 OpMemberName %cbuff 0 "b"
742 OpMemberName %cbuff 1 "M"
743 OpName %_ ""
744 OpName %g_tTex1df4 "g_tTex1df4"
745 OpName %g_sSamp "g_sSamp"
746 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
747 OpMemberDecorate %cbuff 0 Offset 0
748 OpMemberDecorate %cbuff 1 RowMajor
749 OpMemberDecorate %cbuff 1 Offset 16
750 OpMemberDecorate %cbuff 1 MatrixStride 16
751 OpDecorate %cbuff Block
752 OpDecorate %_ DescriptorSet 0
753 OpDecorate %_ Binding 1
754 OpDecorate %g_tTex1df4 DescriptorSet 0
755 OpDecorate %g_tTex1df4 Binding 0
756 OpDecorate %g_sSamp DescriptorSet 0
757 OpDecorate %g_sSamp Binding 0
758 OpDecorate %_entryPointOutput_Color Location 0
759 %void = OpTypeVoid
760 %3 = OpTypeFunction %void
761 %float = OpTypeFloat 32
762 %v4float = OpTypeVector %float 4
763 %uint = OpTypeInt 32 0
764 %mat4v4float = OpTypeMatrix %v4float 4
765 %cbuff = OpTypeStruct %uint %mat4v4float
766 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
767 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
768 %int = OpTypeInt 32 1
769 %int_0 = OpConstant %int 0
770 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
771 %bool = OpTypeBool
772 %uint_0 = OpConstant %uint 0
773 %29 = OpTypeImage %float 1D 0 0 0 1 Unknown
774 %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
775 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant
776 %33 = OpTypeSampler
777 %_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33
778 %g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant
779 %37 = OpTypeSampledImage %29
780 %float_0_100000001 = OpConstant %float 0.100000001
781 %float_0 = OpConstant %float 0
782 %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
783 %float_2 = OpConstant %float 2
784 %_ptr_Output_v4float = OpTypePointer Output %v4float
785 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
786 %half = OpTypeFloat 16
787 %v4half = OpTypeVector %half 4
788 )";
789
790 const std::string func_before =
791 R"(%main = OpFunction %void None %3
792 %5 = OpLabel
793 %63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
794 %64 = OpLoad %uint %63
795 %65 = OpINotEqual %bool %64 %uint_0
796 OpSelectionMerge %66 None
797 OpBranchConditional %65 %67 %68
798 %67 = OpLabel
799 %69 = OpLoad %29 %g_tTex1df4
800 %70 = OpLoad %33 %g_sSamp
801 %71 = OpSampledImage %37 %69 %70
802 %72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001
803 OpBranch %66
804 %68 = OpLabel
805 OpBranch %66
806 %66 = OpLabel
807 %85 = OpPhi %v4float %72 %67 %43 %68
808 %74 = OpVectorTimesScalar %v4float %85 %float_2
809 OpStore %_entryPointOutput_Color %74
810 OpReturn
811 OpFunctionEnd
812 )";
813
814 const std::string func_after =
815 R"(%main = OpFunction %void None %3
816 %5 = OpLabel
817 %63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
818 %64 = OpLoad %uint %63
819 %65 = OpINotEqual %bool %64 %uint_0
820 OpSelectionMerge %66 None
821 OpBranchConditional %65 %67 %68
822 %67 = OpLabel
823 %69 = OpLoad %29 %g_tTex1df4
824 %70 = OpLoad %33 %g_sSamp
825 %71 = OpSampledImage %37 %69 %70
826 %72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001
827 %88 = OpFConvert %v4half %72
828 OpBranch %66
829 %68 = OpLabel
830 %89 = OpFConvert %v4half %43
831 OpBranch %66
832 %66 = OpLabel
833 %85 = OpPhi %v4half %88 %67 %89 %68
834 %90 = OpFConvert %half %float_2
835 %74 = OpVectorTimesScalar %v4half %85 %90
836 %91 = OpFConvert %v4float %74
837 OpStore %_entryPointOutput_Color %91
838 OpReturn
839 OpFunctionEnd
840 )";
841
842 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
843 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
844 defs_after + func_after, true, true);
845 }
846
TEST_F(ConvertToHalfTest,ConvertToHalfWithLoopAndFConvert)847 TEST_F(ConvertToHalfTest, ConvertToHalfWithLoopAndFConvert) {
848 // The resulting SPIR-V was processed with --relax-float-ops.
849 //
850 // The loop causes an FConvert to be generated at the bottom of the loop
851 // for the Phi. The FConvert is later processed and turned into a (dead)
852 // copy.
853 //
854 // clang-format off
855 //
856 // struct PS_OUTPUT
857 // {
858 // float4 Color : SV_Target0;
859 // };
860 //
861 // cbuffer cbuff{
862 // float4 a[10];
863 // }
864 //
865 // PS_OUTPUT main()
866 // {
867 // PS_OUTPUT psout;
868 // float4 t = 0.0;;
869 //
870 // for (int i = 0; i<10; ++i)
871 // t = t + a[i];
872 //
873 // float4 t2 = t / 10.0;
874 // psout.Color = t2;
875 // return psout;
876 // }
877 //
878 // clang-format on
879
880 const std::string defs_before =
881 R"(OpCapability Shader
882 %1 = OpExtInstImport "GLSL.std.450"
883 OpMemoryModel Logical GLSL450
884 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
885 OpExecutionMode %main OriginUpperLeft
886 OpSource HLSL 500
887 OpName %main "main"
888 OpName %cbuff "cbuff"
889 OpMemberName %cbuff 0 "a"
890 OpName %_ ""
891 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
892 OpDecorate %_arr_v4float_uint_10 ArrayStride 16
893 OpMemberDecorate %cbuff 0 Offset 0
894 OpDecorate %cbuff Block
895 OpDecorate %_ DescriptorSet 0
896 OpDecorate %_ Binding 0
897 OpDecorate %_entryPointOutput_Color Location 0
898 OpDecorate %96 RelaxedPrecision
899 OpDecorate %81 RelaxedPrecision
900 OpDecorate %75 RelaxedPrecision
901 OpDecorate %76 RelaxedPrecision
902 %void = OpTypeVoid
903 %3 = OpTypeFunction %void
904 %float = OpTypeFloat 32
905 %v4float = OpTypeVector %float 4
906 %float_0 = OpConstant %float 0
907 %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
908 %int = OpTypeInt 32 1
909 %int_0 = OpConstant %int 0
910 %int_10 = OpConstant %int 10
911 %bool = OpTypeBool
912 %uint = OpTypeInt 32 0
913 %uint_10 = OpConstant %uint 10
914 %_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10
915 %cbuff = OpTypeStruct %_arr_v4float_uint_10
916 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
917 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
918 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
919 %int_1 = OpConstant %int 1
920 %_ptr_Output_v4float = OpTypePointer Output %v4float
921 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
922 %float_0_100000001 = OpConstant %float 0.100000001
923 %94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001
924 )";
925
926 const std::string defs_after =
927 R"(OpCapability Shader
928 OpCapability Float16
929 %1 = OpExtInstImport "GLSL.std.450"
930 OpMemoryModel Logical GLSL450
931 OpEntryPoint Fragment %main "main" %_entryPointOutput_Color
932 OpExecutionMode %main OriginUpperLeft
933 OpSource HLSL 500
934 OpName %main "main"
935 OpName %cbuff "cbuff"
936 OpMemberName %cbuff 0 "a"
937 OpName %_ ""
938 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
939 OpDecorate %_arr_v4float_uint_10 ArrayStride 16
940 OpMemberDecorate %cbuff 0 Offset 0
941 OpDecorate %cbuff Block
942 OpDecorate %_ DescriptorSet 0
943 OpDecorate %_ Binding 0
944 OpDecorate %_entryPointOutput_Color Location 0
945 %void = OpTypeVoid
946 %3 = OpTypeFunction %void
947 %float = OpTypeFloat 32
948 %v4float = OpTypeVector %float 4
949 %float_0 = OpConstant %float 0
950 %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
951 %int = OpTypeInt 32 1
952 %int_0 = OpConstant %int 0
953 %int_10 = OpConstant %int 10
954 %bool = OpTypeBool
955 %uint = OpTypeInt 32 0
956 %uint_10 = OpConstant %uint 10
957 %_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10
958 %cbuff = OpTypeStruct %_arr_v4float_uint_10
959 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
960 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
961 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
962 %int_1 = OpConstant %int 1
963 %_ptr_Output_v4float = OpTypePointer Output %v4float
964 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
965 %float_0_100000001 = OpConstant %float 0.100000001
966 %94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001
967 %half = OpTypeFloat 16
968 %v4half = OpTypeVector %half 4
969 )";
970
971 const std::string func_before =
972 R"(%main = OpFunction %void None %3
973 %5 = OpLabel
974 OpBranch %65
975 %65 = OpLabel
976 %96 = OpPhi %v4float %15 %5 %76 %71
977 %95 = OpPhi %int %int_0 %5 %78 %71
978 %70 = OpSLessThan %bool %95 %int_10
979 OpLoopMerge %66 %71 None
980 OpBranchConditional %70 %71 %66
981 %71 = OpLabel
982 %74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95
983 %75 = OpLoad %v4float %74
984 %76 = OpFAdd %v4float %96 %75
985 %78 = OpIAdd %int %95 %int_1
986 OpBranch %65
987 %66 = OpLabel
988 %81 = OpFMul %v4float %96 %94
989 OpStore %_entryPointOutput_Color %81
990 OpReturn
991 OpFunctionEnd
992 )";
993
994 const std::string func_after =
995 R"(%main = OpFunction %void None %3
996 %5 = OpLabel
997 %99 = OpFConvert %v4half %15
998 OpBranch %65
999 %65 = OpLabel
1000 %96 = OpPhi %v4half %99 %5 %100 %71
1001 %95 = OpPhi %int %int_0 %5 %78 %71
1002 %70 = OpSLessThan %bool %95 %int_10
1003 OpLoopMerge %66 %71 None
1004 OpBranchConditional %70 %71 %66
1005 %71 = OpLabel
1006 %74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95
1007 %75 = OpLoad %v4float %74
1008 %103 = OpFConvert %v4half %75
1009 %76 = OpFAdd %v4half %96 %103
1010 %78 = OpIAdd %int %95 %int_1
1011 %100 = OpCopyObject %v4half %76
1012 OpBranch %65
1013 %66 = OpLabel
1014 %101 = OpFConvert %v4half %94
1015 %81 = OpFMul %v4half %96 %101
1016 %102 = OpFConvert %v4float %81
1017 OpStore %_entryPointOutput_Color %102
1018 OpReturn
1019 OpFunctionEnd
1020 )";
1021
1022 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1023 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
1024 defs_after + func_after, true, true);
1025 }
1026
TEST_F(ConvertToHalfTest,ConvertToHalfWithExtracts)1027 TEST_F(ConvertToHalfTest, ConvertToHalfWithExtracts) {
1028 // The resulting SPIR-V was processed with --relax-float-ops.
1029 //
1030 // The extra converts in the func_after can be DCE'd.
1031 //
1032 // clang-format off
1033 //
1034 // SamplerState g_sSamp : register(s0);
1035 // uniform Texture1D <float4> g_tTex1df4 : register(t0);
1036 //
1037 // struct PS_INPUT
1038 // {
1039 // float Tex0 : TEXCOORD0;
1040 // };
1041 //
1042 // struct PS_OUTPUT
1043 // {
1044 // float4 Color : SV_Target0;
1045 // };
1046 //
1047 // cbuffer cbuff{
1048 // float c;
1049 // }
1050 //
1051 // PS_OUTPUT main(PS_INPUT i)
1052 // {
1053 // PS_OUTPUT psout;
1054 // float4 tx = g_tTex1df4.Sample(g_sSamp, i.Tex0);
1055 // float4 t = float4(tx.y, tx.z, tx.x, tx.w) * c;
1056 // psout.Color = t;
1057 // return psout;
1058 // }
1059 //
1060 // clang-format on
1061
1062 const std::string defs_before =
1063 R"(OpCapability Shader
1064 OpCapability Sampled1D
1065 %1 = OpExtInstImport "GLSL.std.450"
1066 OpMemoryModel Logical GLSL450
1067 OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color
1068 OpExecutionMode %main OriginUpperLeft
1069 OpSource HLSL 500
1070 OpName %main "main"
1071 OpName %g_tTex1df4 "g_tTex1df4"
1072 OpName %g_sSamp "g_sSamp"
1073 OpName %cbuff "cbuff"
1074 OpMemberName %cbuff 0 "c"
1075 OpName %_ ""
1076 OpName %i_Tex0 "i.Tex0"
1077 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
1078 OpDecorate %g_tTex1df4 DescriptorSet 0
1079 OpDecorate %g_tTex1df4 Binding 0
1080 OpDecorate %g_sSamp DescriptorSet 0
1081 OpDecorate %g_sSamp Binding 0
1082 OpMemberDecorate %cbuff 0 Offset 0
1083 OpDecorate %cbuff Block
1084 OpDecorate %_ DescriptorSet 0
1085 OpDecorate %_ Binding 1
1086 OpDecorate %i_Tex0 Location 0
1087 OpDecorate %_entryPointOutput_Color Location 0
1088 OpDecorate %65 RelaxedPrecision
1089 OpDecorate %82 RelaxedPrecision
1090 OpDecorate %84 RelaxedPrecision
1091 OpDecorate %86 RelaxedPrecision
1092 OpDecorate %88 RelaxedPrecision
1093 OpDecorate %90 RelaxedPrecision
1094 OpDecorate %91 RelaxedPrecision
1095 OpDecorate %93 RelaxedPrecision
1096 OpDecorate %94 RelaxedPrecision
1097 %void = OpTypeVoid
1098 %3 = OpTypeFunction %void
1099 %float = OpTypeFloat 32
1100 %v4float = OpTypeVector %float 4
1101 %17 = OpTypeImage %float 1D 0 0 0 1 Unknown
1102 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
1103 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant
1104 %21 = OpTypeSampler
1105 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
1106 %g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant
1107 %25 = OpTypeSampledImage %17
1108 %int = OpTypeInt 32 1
1109 %int_0 = OpConstant %int 0
1110 %cbuff = OpTypeStruct %float
1111 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
1112 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
1113 %_ptr_Uniform_float = OpTypePointer Uniform %float
1114 %_ptr_Input_float = OpTypePointer Input %float
1115 %i_Tex0 = OpVariable %_ptr_Input_float Input
1116 %_ptr_Output_v4float = OpTypePointer Output %v4float
1117 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
1118 )";
1119
1120 const std::string defs_after =
1121 R"(OpCapability Shader
1122 OpCapability Sampled1D
1123 OpCapability Float16
1124 %1 = OpExtInstImport "GLSL.std.450"
1125 OpMemoryModel Logical GLSL450
1126 OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color
1127 OpExecutionMode %main OriginUpperLeft
1128 OpSource HLSL 500
1129 OpName %main "main"
1130 OpName %g_tTex1df4 "g_tTex1df4"
1131 OpName %g_sSamp "g_sSamp"
1132 OpName %cbuff "cbuff"
1133 OpMemberName %cbuff 0 "c"
1134 OpName %_ ""
1135 OpName %i_Tex0 "i.Tex0"
1136 OpName %_entryPointOutput_Color "@entryPointOutput.Color"
1137 OpDecorate %g_tTex1df4 DescriptorSet 0
1138 OpDecorate %g_tTex1df4 Binding 0
1139 OpDecorate %g_sSamp DescriptorSet 0
1140 OpDecorate %g_sSamp Binding 0
1141 OpMemberDecorate %cbuff 0 Offset 0
1142 OpDecorate %cbuff Block
1143 OpDecorate %_ DescriptorSet 0
1144 OpDecorate %_ Binding 1
1145 OpDecorate %i_Tex0 Location 0
1146 OpDecorate %_entryPointOutput_Color Location 0
1147 %void = OpTypeVoid
1148 %3 = OpTypeFunction %void
1149 %float = OpTypeFloat 32
1150 %v4float = OpTypeVector %float 4
1151 %17 = OpTypeImage %float 1D 0 0 0 1 Unknown
1152 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
1153 %g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant
1154 %21 = OpTypeSampler
1155 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
1156 %g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant
1157 %25 = OpTypeSampledImage %17
1158 %int = OpTypeInt 32 1
1159 %int_0 = OpConstant %int 0
1160 %cbuff = OpTypeStruct %float
1161 %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff
1162 %_ = OpVariable %_ptr_Uniform_cbuff Uniform
1163 %_ptr_Uniform_float = OpTypePointer Uniform %float
1164 %_ptr_Input_float = OpTypePointer Input %float
1165 %i_Tex0 = OpVariable %_ptr_Input_float Input
1166 %_ptr_Output_v4float = OpTypePointer Output %v4float
1167 %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
1168 %half = OpTypeFloat 16
1169 %v4half = OpTypeVector %half 4
1170 )";
1171
1172 const std::string func_before =
1173 R"(%main = OpFunction %void None %3
1174 %5 = OpLabel
1175 %65 = OpLoad %float %i_Tex0
1176 %77 = OpLoad %17 %g_tTex1df4
1177 %78 = OpLoad %21 %g_sSamp
1178 %79 = OpSampledImage %25 %77 %78
1179 %82 = OpImageSampleImplicitLod %v4float %79 %65
1180 %84 = OpCompositeExtract %float %82 1
1181 %86 = OpCompositeExtract %float %82 2
1182 %88 = OpCompositeExtract %float %82 0
1183 %90 = OpCompositeExtract %float %82 3
1184 %91 = OpCompositeConstruct %v4float %84 %86 %88 %90
1185 %92 = OpAccessChain %_ptr_Uniform_float %_ %int_0
1186 %93 = OpLoad %float %92
1187 %94 = OpVectorTimesScalar %v4float %91 %93
1188 OpStore %_entryPointOutput_Color %94
1189 OpReturn
1190 OpFunctionEnd
1191 )";
1192
1193 const std::string func_after =
1194 R"(%main = OpFunction %void None %3
1195 %5 = OpLabel
1196 %65 = OpLoad %float %i_Tex0
1197 %77 = OpLoad %17 %g_tTex1df4
1198 %78 = OpLoad %21 %g_sSamp
1199 %79 = OpSampledImage %25 %77 %78
1200 %82 = OpImageSampleImplicitLod %v4float %79 %65
1201 %97 = OpFConvert %v4half %82
1202 %84 = OpCompositeExtract %half %97 1
1203 %98 = OpFConvert %v4half %82
1204 %86 = OpCompositeExtract %half %98 2
1205 %99 = OpFConvert %v4half %82
1206 %88 = OpCompositeExtract %half %99 0
1207 %100 = OpFConvert %v4half %82
1208 %90 = OpCompositeExtract %half %100 3
1209 %91 = OpCompositeConstruct %v4half %84 %86 %88 %90
1210 %92 = OpAccessChain %_ptr_Uniform_float %_ %int_0
1211 %93 = OpLoad %float %92
1212 %101 = OpFConvert %half %93
1213 %94 = OpVectorTimesScalar %v4half %91 %101
1214 %102 = OpFConvert %v4float %94
1215 OpStore %_entryPointOutput_Color %102
1216 OpReturn
1217 OpFunctionEnd
1218 )";
1219
1220 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1221 SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before,
1222 defs_after + func_after, true, true);
1223 }
1224
TEST_F(ConvertToHalfTest,ConvertToHalfWithClosure)1225 TEST_F(ConvertToHalfTest, ConvertToHalfWithClosure) {
1226 // Include as many contiguous composite instructions as possible into
1227 // half-precision computations
1228 //
1229 // Compiled with glslang -V -Os
1230 //
1231 // clang-format off
1232 //
1233 // #version 410 core
1234 //
1235 // precision mediump float;
1236 //
1237 // layout(location = 1) in vec3 foo;
1238 // layout(location = 2) in mat2 bar;
1239 // layout(location = 1) out vec3 res;
1240 //
1241 // vec3 func(vec3 tap, mat2 M) {
1242 // return vec3(M * tap.xy, 1.0);
1243 // }
1244 //
1245 // void main() {
1246 // res = func(foo, bar);
1247 // }
1248 //
1249 // clang-format on
1250
1251 const std::string defs =
1252 R"(OpCapability Shader
1253 ; CHECK: OpCapability Float16
1254 %1 = OpExtInstImport "GLSL.std.450"
1255 OpMemoryModel Logical GLSL450
1256 OpEntryPoint Fragment %main "main" %res %foo %bar
1257 OpExecutionMode %main OriginUpperLeft
1258 OpSource GLSL 410
1259 OpName %main "main"
1260 OpName %res "res"
1261 OpName %foo "foo"
1262 OpName %bar "bar"
1263 OpDecorate %res RelaxedPrecision
1264 ; CHECK-NOT: OpDecorate %res RelaxedPrecision
1265 OpDecorate %res Location 1
1266 OpDecorate %foo RelaxedPrecision
1267 ; CHECK-NOT: OpDecorate %foo RelaxedPrecision
1268 OpDecorate %foo Location 1
1269 OpDecorate %bar RelaxedPrecision
1270 ; CHECK-NOT: OpDecorate %bar RelaxedPrecision
1271 OpDecorate %bar Location 2
1272 OpDecorate %34 RelaxedPrecision
1273 OpDecorate %36 RelaxedPrecision
1274 OpDecorate %41 RelaxedPrecision
1275 OpDecorate %42 RelaxedPrecision
1276 ; CHECK-NOT: OpDecorate %34 RelaxedPrecision
1277 ; CHECK-NOT: OpDecorate %36 RelaxedPrecision
1278 ; CHECK-NOT: OpDecorate %41 RelaxedPrecision
1279 ; CHECK-NOT: OpDecorate %42 RelaxedPrecision
1280 %void = OpTypeVoid
1281 %3 = OpTypeFunction %void
1282 %float = OpTypeFloat 32
1283 %v3float = OpTypeVector %float 3
1284 %v2float = OpTypeVector %float 2
1285 %mat2v2float = OpTypeMatrix %v2float 2
1286 %float_1 = OpConstant %float 1
1287 %_ptr_Output_v3float = OpTypePointer Output %v3float
1288 %res = OpVariable %_ptr_Output_v3float Output
1289 %_ptr_Input_v3float = OpTypePointer Input %v3float
1290 %foo = OpVariable %_ptr_Input_v3float Input
1291 %_ptr_Input_mat2v2float = OpTypePointer Input %mat2v2float
1292 %bar = OpVariable %_ptr_Input_mat2v2float Input
1293 )";
1294
1295 const std::string func =
1296 R"(%main = OpFunction %void None %3
1297 %5 = OpLabel
1298 %34 = OpLoad %v3float %foo
1299 %36 = OpLoad %mat2v2float %bar
1300 ; CHECK: %48 = OpFConvert %v3half %34
1301 ; CHECK: %49 = OpFConvert %v3half %34
1302 %41 = OpVectorShuffle %v2float %34 %34 0 1
1303 ; CHECK-NOT: %41 = OpVectorShuffle %v2float %34 %34 0 1
1304 ; CHECK: %41 = OpVectorShuffle %v2half %48 %49 0 1
1305 %42 = OpMatrixTimesVector %v2float %36 %41
1306 ; CHECK-NOT: %42 = OpMatrixTimesVector %v2float %36 %41
1307 ; CHECK: %55 = OpCompositeExtract %v2float %36 0
1308 ; CHECK: %56 = OpFConvert %v2half %55
1309 ; CHECK: %57 = OpCompositeExtract %v2float %36 1
1310 ; CHECK: %58 = OpFConvert %v2half %57
1311 ; CHECK: %59 = OpCompositeConstruct %mat2v2half %56 %58
1312 ; CHECK: %52 = OpCopyObject %mat2v2float %36
1313 ; CHECK: %42 = OpMatrixTimesVector %v2half %59 %41
1314 %43 = OpCompositeExtract %float %42 0
1315 %44 = OpCompositeExtract %float %42 1
1316 ; CHECK-NOT: %43 = OpCompositeExtract %float %42 0
1317 ; CHECK-NOT: %44 = OpCompositeExtract %float %42 1
1318 ; CHECK: %43 = OpCompositeExtract %half %42 0
1319 ; CHECK: %44 = OpCompositeExtract %half %42 1
1320 %45 = OpCompositeConstruct %v3float %43 %44 %float_1
1321 ; CHECK-NOT: %45 = OpCompositeConstruct %v3float %43 %44 %float_1
1322 ; CHECK: %53 = OpFConvert %float %43
1323 ; CHECK: %54 = OpFConvert %float %44
1324 ; CHECK: %45 = OpCompositeConstruct %v3float %53 %54 %float_1
1325 OpStore %res %45
1326 OpReturn
1327 OpFunctionEnd
1328 )";
1329
1330 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1331 SinglePassRunAndMatch<ConvertToHalfPass>(defs + func, true);
1332 }
1333
TEST_F(ConvertToHalfTest,RemoveRelaxDec)1334 TEST_F(ConvertToHalfTest, RemoveRelaxDec) {
1335 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4117
1336
1337 // This test is a case where the relax precision decorations need to be
1338 // removed, but the body of the function does not change because there are not
1339 // arithmetic operations. So, there is not need for the Float16 capability.
1340 const std::string test =
1341 R"(
1342 ; CHECK-NOT: OpCapability Float16
1343 ; GLSL seems to generate this decoration on the load of a texture, which seems odd to me.
1344 ; This pass does not currently remove it, and I'm not sure what we should do with it, so I will leave it.
1345 ; CHECK: OpDecorate [[tex:%\w+]] RelaxedPrecision
1346 ; CHECK-NOT: OpDecorate {{%\w+}} RelaxedPrecision
1347 ; CHECK: OpLabel
1348 ; CHECK: [[tex]] = OpLoad {{%\w+}} %sTexture
1349 ; CHECK: [[coord:%\w+]] = OpLoad %v2float
1350 ; CHECK: [[retval:%\w+]] = OpImageSampleImplicitLod %v4float {{%\w+}} [[coord]]
1351 ; CHECK: OpStore %outFragColor [[retval]]
1352 OpCapability Shader
1353 %1 = OpExtInstImport "GLSL.std.450"
1354 OpMemoryModel Logical GLSL450
1355 OpEntryPoint Fragment %main "main" %outFragColor %v_texcoord
1356 OpExecutionMode %main OriginUpperLeft
1357 OpSource ESSL 310
1358 OpName %main "main"
1359 OpName %outFragColor "outFragColor"
1360 OpName %sTexture "sTexture"
1361 OpName %v_texcoord "v_texcoord"
1362 OpDecorate %outFragColor RelaxedPrecision
1363 OpDecorate %outFragColor Location 0
1364 OpDecorate %sTexture RelaxedPrecision
1365 OpDecorate %sTexture DescriptorSet 0
1366 OpDecorate %sTexture Binding 0
1367 OpDecorate %14 RelaxedPrecision
1368 OpDecorate %v_texcoord RelaxedPrecision
1369 OpDecorate %v_texcoord Location 0
1370 OpDecorate %18 RelaxedPrecision
1371 OpDecorate %19 RelaxedPrecision
1372 %void = OpTypeVoid
1373 %3 = OpTypeFunction %void
1374 %float = OpTypeFloat 32
1375 %v4float = OpTypeVector %float 4
1376 %_ptr_Output_v4float = OpTypePointer Output %v4float
1377 %outFragColor = OpVariable %_ptr_Output_v4float Output
1378 %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
1379 %11 = OpTypeSampledImage %10
1380 %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
1381 %sTexture = OpVariable %_ptr_UniformConstant_11 UniformConstant
1382 %v2float = OpTypeVector %float 2
1383 %_ptr_Input_v2float = OpTypePointer Input %v2float
1384 %v_texcoord = OpVariable %_ptr_Input_v2float Input
1385 %main = OpFunction %void None %3
1386 %5 = OpLabel
1387 %14 = OpLoad %11 %sTexture
1388 %18 = OpLoad %v2float %v_texcoord
1389 %19 = OpImageSampleImplicitLod %v4float %14 %18
1390 OpStore %outFragColor %19
1391 OpReturn
1392 OpFunctionEnd
1393 )";
1394
1395 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1396 auto result = SinglePassRunAndMatch<ConvertToHalfPass>(test, true);
1397 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
1398 }
1399
1400 } // namespace
1401 } // namespace opt
1402 } // namespace spvtools
1403