1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Valve Corporation.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief 64-bit data type comparison operations.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktSpvAsm64bitCompareTests.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktSpvAsmUtils.hpp"
28 #include "vkDefs.hpp"
29 #include "vktTestCase.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkCmdUtil.hpp"
36 
37 #include "tcuStringTemplate.hpp"
38 
39 #include <string>
40 #include <vector>
41 #include <utility>
42 #include <cmath>
43 #include <sstream>
44 #include <memory>
45 #include <limits>
46 
47 namespace vkt
48 {
49 namespace SpirVAssembly
50 {
51 namespace
52 {
53 
54 template <typename T>
55 class CompareOperation
56 {
57 public:
~CompareOperation()58     virtual ~CompareOperation()
59     {
60     }
61 
62     virtual std::string spirvName() const   = 0;
63     virtual bool run(T left, T right) const = 0;
64 };
65 
66 // Helper intermediate class to be able to implement Ordered and Unordered floating point operations in a simpler way.
67 class DoubleCompareOperation : public CompareOperation<double>
68 {
69 public:
70     struct BasicImplementation
71     {
~BasicImplementationvkt::SpirVAssembly::__anon071ae8e90111::DoubleCompareOperation::BasicImplementation72         virtual ~BasicImplementation()
73         {
74         }
75         virtual std::string nameSuffix() const            = 0;
76         virtual bool run(double left, double right) const = 0; // No NaNs here.
77     };
78 
spirvName() const79     virtual std::string spirvName() const
80     {
81         return "OpF" + std::string(m_ordered ? "Ord" : "Unord") + m_impl.nameSuffix();
82     }
83 
run(double left,double right) const84     virtual bool run(double left, double right) const
85     {
86         if (nanInvolved(left, right))
87             return !m_ordered; // Ordered operations return false when NaN is involved.
88         return m_impl.run(left, right);
89     }
90 
DoubleCompareOperation(bool ordered,const BasicImplementation & impl)91     DoubleCompareOperation(bool ordered, const BasicImplementation &impl) : m_ordered(ordered), m_impl(impl)
92     {
93     }
94 
95 private:
nanInvolved(double left,double right) const96     bool nanInvolved(double left, double right) const
97     {
98         return std::isnan(left) || std::isnan(right);
99     }
100 
101     const bool m_ordered;
102     const BasicImplementation &m_impl;
103 };
104 
105 #define GEN_DOUBLE_BASIC_IMPL(NAME, OPERATION)                                             \
106     struct NAME##DoubleBasicImplClass : public DoubleCompareOperation::BasicImplementation \
107     {                                                                                      \
108         virtual std::string nameSuffix() const                                             \
109         {                                                                                  \
110             return #NAME;                                                                  \
111         }                                                                                  \
112         virtual bool run(double left, double right) const                                  \
113         {                                                                                  \
114             return left OPERATION right;                                                   \
115         }                                                                                  \
116     };                                                                                     \
117     NAME##DoubleBasicImplClass NAME##DoubleBasicImplInstance;
118 
119 GEN_DOUBLE_BASIC_IMPL(Equal, ==)
120 GEN_DOUBLE_BASIC_IMPL(NotEqual, !=)
121 GEN_DOUBLE_BASIC_IMPL(LessThan, <)
122 GEN_DOUBLE_BASIC_IMPL(GreaterThan, >)
123 GEN_DOUBLE_BASIC_IMPL(LessThanEqual, <=)
124 GEN_DOUBLE_BASIC_IMPL(GreaterThanEqual, >=)
125 
126 #define GEN_FORDERED_OP(NAME) DoubleCompareOperation FOrdered##NAME##Op(true, NAME##DoubleBasicImplInstance)
127 #define GEN_FUNORDERED_OP(NAME) DoubleCompareOperation FUnordered##NAME##Op(false, NAME##DoubleBasicImplInstance)
128 #define GEN_FBOTH_OP(NAME) \
129     GEN_FORDERED_OP(NAME); \
130     GEN_FUNORDERED_OP(NAME);
131 
132 GEN_FBOTH_OP(Equal)
133 GEN_FBOTH_OP(NotEqual)
134 GEN_FBOTH_OP(LessThan)
135 GEN_FBOTH_OP(GreaterThan)
136 GEN_FBOTH_OP(LessThanEqual)
137 GEN_FBOTH_OP(GreaterThanEqual)
138 
139 template <typename IntClass>
140 class IntCompareOperation : public CompareOperation<IntClass>
141 {
142 public:
143     struct Implementation
144     {
~Implementationvkt::SpirVAssembly::__anon071ae8e90111::IntCompareOperation::Implementation145         virtual ~Implementation()
146         {
147         }
148 
149         virtual std::string typeChar() const                  = 0;
150         virtual std::string opName() const                    = 0;
151         virtual bool run(IntClass left, IntClass right) const = 0;
152     };
153 
spirvName() const154     virtual std::string spirvName() const
155     {
156         return "Op" + m_impl.typeChar() + m_impl.opName();
157     }
158 
run(IntClass left,IntClass right) const159     virtual bool run(IntClass left, IntClass right) const
160     {
161         return m_impl.run(left, right);
162     }
163 
IntCompareOperation(const Implementation & impl)164     IntCompareOperation(const Implementation &impl) : m_impl(impl)
165     {
166     }
167 
168 private:
169     const Implementation &m_impl;
170 };
171 
172 #define GEN_INT_IMPL(INTTYPE, PREFIX, TYPECHAR, OPNAME, OPERATOR)                             \
173     struct PREFIX##OPNAME##IntImplClass : public IntCompareOperation<INTTYPE>::Implementation \
174     {                                                                                         \
175         virtual std::string typeChar() const                                                  \
176         {                                                                                     \
177             return #TYPECHAR;                                                                 \
178         }                                                                                     \
179         virtual std::string opName() const                                                    \
180         {                                                                                     \
181             return #OPNAME;                                                                   \
182         }                                                                                     \
183         virtual bool run(INTTYPE left, INTTYPE right) const                                   \
184         {                                                                                     \
185             return left OPERATOR right;                                                       \
186         }                                                                                     \
187     };                                                                                        \
188     PREFIX##OPNAME##IntImplClass PREFIX##OPNAME##IntImplInstance;
189 
190 #define GEN_ALL_INT_TYPE_IMPL(INTTYPE, PREFIX, TYPECHAR)          \
191     GEN_INT_IMPL(INTTYPE, PREFIX, I, Equal, ==)                   \
192     GEN_INT_IMPL(INTTYPE, PREFIX, I, NotEqual, !=)                \
193     GEN_INT_IMPL(INTTYPE, PREFIX, TYPECHAR, GreaterThan, >)       \
194     GEN_INT_IMPL(INTTYPE, PREFIX, TYPECHAR, GreaterThanEqual, >=) \
195     GEN_INT_IMPL(INTTYPE, PREFIX, TYPECHAR, LessThan, <)          \
196     GEN_INT_IMPL(INTTYPE, PREFIX, TYPECHAR, LessThanEqual, <=)
197 
198 GEN_ALL_INT_TYPE_IMPL(int64_t, int64, S)
199 GEN_ALL_INT_TYPE_IMPL(uint64_t, uint64, U)
200 
201 #define GEN_INT_OP(INTTYPE, PREFIX, OPNAME)                                                       \
202     struct PREFIX##OPNAME##OpClass : public IntCompareOperation<INTTYPE>                          \
203     {                                                                                             \
204         PREFIX##OPNAME##OpClass() : IntCompareOperation<INTTYPE>(PREFIX##OPNAME##IntImplInstance) \
205         {                                                                                         \
206         }                                                                                         \
207     };                                                                                            \
208     PREFIX##OPNAME##OpClass PREFIX##OPNAME##Op;
209 
210 #define GEN_ALL_INT_OPS(INTTYPE, PREFIX)          \
211     GEN_INT_OP(INTTYPE, PREFIX, Equal)            \
212     GEN_INT_OP(INTTYPE, PREFIX, NotEqual)         \
213     GEN_INT_OP(INTTYPE, PREFIX, GreaterThan)      \
214     GEN_INT_OP(INTTYPE, PREFIX, GreaterThanEqual) \
215     GEN_INT_OP(INTTYPE, PREFIX, LessThan)         \
216     GEN_INT_OP(INTTYPE, PREFIX, LessThanEqual)
217 
218 GEN_ALL_INT_OPS(int64_t, int64)
219 GEN_ALL_INT_OPS(uint64_t, uint64)
220 
221 enum DataType
222 {
223     DATA_TYPE_SINGLE = 0,
224     DATA_TYPE_VECTOR,
225     DATA_TYPE_MAX_ENUM,
226 };
227 
228 template <class T>
229 using OperandsVector = std::vector<std::pair<T, T>>;
230 
231 template <class T>
232 struct TestParameters
233 {
234     DataType dataType;
235     const CompareOperation<T> &operation;
236     vk::VkShaderStageFlagBits stage;
237     const OperandsVector<T> &operands;
238     bool requireNanPreserve;
239 };
240 
241 // Shader template for the compute stage using single scalars.
242 // Generated from the following GLSL shader, replacing some bits by template parameters.
243 #if 0
244 #version 430
245 
246 // Left operands, right operands and results.
247 layout(binding = 0) buffer Input1  { double values[];    } input1;
248 layout(binding = 1) buffer Input2  { double values[];    } input2;
249 layout(binding = 2) buffer Output1 { int values[];        } output1;
250 
251 void main()
252 {
253         for (int i = 0; i < 20; i++) {
254                 output1.values[i] = int(input1.values[i] == input2.values[i]);
255         }
256 }
257 #endif
258 const tcu::StringTemplate CompShaderSingle(R"(
259                         OpCapability Shader
260                         ${OPCAPABILITY}
261                         ${NANCAP}
262                         ${NANEXT}
263                    %1 = OpExtInstImport "GLSL.std.450"
264                         OpMemoryModel Logical GLSL450
265                         OpEntryPoint GLCompute %main "main"
266                         ${NANMODE}
267                         OpExecutionMode %main LocalSize 1 1 1
268                         OpName %main "main"
269                         OpName %i "i"
270                         OpName %Output1 "Output1"
271                         OpMemberName %Output1 0 "values"
272                         OpName %output1 "output1"
273                         OpName %Input1 "Input1"
274                         OpMemberName %Input1 0 "values"
275                         OpName %input1 "input1"
276                         OpName %Input2 "Input2"
277                         OpMemberName %Input2 0 "values"
278                         OpName %input2 "input2"
279                         OpDecorate %_runtimearr_int ArrayStride 4
280                         OpMemberDecorate %Output1 0 Offset 0
281                         OpDecorate %Output1 BufferBlock
282                         OpDecorate %output1 DescriptorSet 0
283                         OpDecorate %output1 Binding 2
284                         OpDecorate %_runtimearr_tinput ArrayStride 8
285                         OpMemberDecorate %Input1 0 Offset 0
286                         OpDecorate %Input1 BufferBlock
287                         OpDecorate %input1 DescriptorSet 0
288                         OpDecorate %input1 Binding 0
289                         OpDecorate %_runtimearr_tinput_0 ArrayStride 8
290                         OpMemberDecorate %Input2 0 Offset 0
291                         OpDecorate %Input2 BufferBlock
292                         OpDecorate %input2 DescriptorSet 0
293                         OpDecorate %input2 Binding 1
294                 %void = OpTypeVoid
295                    %3 = OpTypeFunction %void
296                  %int = OpTypeInt 32 1
297    %_ptr_Function_int = OpTypePointer Function %int
298                %int_0 = OpConstant %int 0
299               %niters = OpConstant %int ${ITERS}
300                 %bool = OpTypeBool
301      %_runtimearr_int = OpTypeRuntimeArray %int
302              %Output1 = OpTypeStruct %_runtimearr_int
303 %_ptr_Uniform_Output1 = OpTypePointer Uniform %Output1
304              %output1 = OpVariable %_ptr_Uniform_Output1 Uniform
305               %tinput = ${OPTYPE}
306   %_runtimearr_tinput = OpTypeRuntimeArray %tinput
307               %Input1 = OpTypeStruct %_runtimearr_tinput
308  %_ptr_Uniform_Input1 = OpTypePointer Uniform %Input1
309               %input1 = OpVariable %_ptr_Uniform_Input1 Uniform
310  %_ptr_Uniform_tinput = OpTypePointer Uniform %tinput
311 %_runtimearr_tinput_0 = OpTypeRuntimeArray %tinput
312               %Input2 = OpTypeStruct %_runtimearr_tinput_0
313  %_ptr_Uniform_Input2 = OpTypePointer Uniform %Input2
314               %input2 = OpVariable %_ptr_Uniform_Input2 Uniform
315                %int_1 = OpConstant %int 1
316     %_ptr_Uniform_int = OpTypePointer Uniform %int
317                 %main = OpFunction %void None %3
318                    %5 = OpLabel
319                    %i = OpVariable %_ptr_Function_int Function
320                         OpStore %i %int_0
321                         OpBranch %10
322                   %10 = OpLabel
323                         OpLoopMerge %12 %13 None
324                         OpBranch %14
325                   %14 = OpLabel
326                   %15 = OpLoad %int %i
327                   %18 = OpSLessThan %bool %15 %niters
328                         OpBranchConditional %18 %11 %12
329                   %11 = OpLabel
330                   %23 = OpLoad %int %i
331                   %29 = OpLoad %int %i
332                   %31 = OpAccessChain %_ptr_Uniform_tinput %input1 %int_0 %29
333                   %32 = OpLoad %tinput %31
334                   %37 = OpLoad %int %i
335                   %38 = OpAccessChain %_ptr_Uniform_tinput %input2 %int_0 %37
336                   %39 = OpLoad %tinput %38
337                   %40 = ${OPNAME} %bool %32 %39
338                   %42 = OpSelect %int %40 %int_1 %int_0
339                   %44 = OpAccessChain %_ptr_Uniform_int %output1 %int_0 %23
340                         OpStore %44 %42
341                         OpBranch %13
342                   %13 = OpLabel
343                   %45 = OpLoad %int %i
344                   %46 = OpIAdd %int %45 %int_1
345                         OpStore %i %46
346                         OpBranch %10
347                   %12 = OpLabel
348                         OpReturn
349                         OpFunctionEnd
350 )");
351 
352 // Shader template for the compute stage using vectors.
353 // Generated from the following GLSL shader, replacing some bits by template parameters.
354 // Note the number of iterations needs to be divided by 4 as the shader will consume 4 doubles at a time.
355 #if 0
356 #version 430
357 
358 // Left operands, right operands and results.
359 layout(binding = 0) buffer Input1  { dvec4 values[];    } input1;
360 layout(binding = 1) buffer Input2  { dvec4 values[];    } input2;
361 layout(binding = 2) buffer Output1 { ivec4 values[];    } output1;
362 
363 void main()
364 {
365         for (int i = 0; i < 5; i++) {
366                 output1.values[i] = ivec4(equal(input1.values[i], input2.values[i]));
367         }
368 }
369 #endif
370 const tcu::StringTemplate CompShaderVector(R"(
371                           OpCapability Shader
372                           ${OPCAPABILITY}
373                           ${NANCAP}
374                           ${NANEXT}
375                      %1 = OpExtInstImport "GLSL.std.450"
376                           OpMemoryModel Logical GLSL450
377                           OpEntryPoint GLCompute %main "main"
378                           ${NANMODE}
379                           OpExecutionMode %main LocalSize 1 1 1
380                           OpName %main "main"
381                           OpName %i "i"
382                           OpName %Output1 "Output1"
383                           OpMemberName %Output1 0 "values"
384                           OpName %output1 "output1"
385                           OpName %Input1 "Input1"
386                           OpMemberName %Input1 0 "values"
387                           OpName %input1 "input1"
388                           OpName %Input2 "Input2"
389                           OpMemberName %Input2 0 "values"
390                           OpName %input2 "input2"
391                           OpDecorate %_runtimearr_v4int ArrayStride 16
392                           OpMemberDecorate %Output1 0 Offset 0
393                           OpDecorate %Output1 BufferBlock
394                           OpDecorate %output1 DescriptorSet 0
395                           OpDecorate %output1 Binding 2
396                           OpDecorate %_runtimearr_v4tinput ArrayStride 32
397                           OpMemberDecorate %Input1 0 Offset 0
398                           OpDecorate %Input1 BufferBlock
399                           OpDecorate %input1 DescriptorSet 0
400                           OpDecorate %input1 Binding 0
401                           OpDecorate %_runtimearr_v4tinput_0 ArrayStride 32
402                           OpMemberDecorate %Input2 0 Offset 0
403                           OpDecorate %Input2 BufferBlock
404                           OpDecorate %input2 DescriptorSet 0
405                           OpDecorate %input2 Binding 1
406                   %void = OpTypeVoid
407                      %3 = OpTypeFunction %void
408                    %int = OpTypeInt 32 1
409      %_ptr_Function_int = OpTypePointer Function %int
410                  %int_0 = OpConstant %int 0
411                 %niters = OpConstant %int ${ITERS}
412                   %bool = OpTypeBool
413                  %v4int = OpTypeVector %int 4
414      %_runtimearr_v4int = OpTypeRuntimeArray %v4int
415                %Output1 = OpTypeStruct %_runtimearr_v4int
416   %_ptr_Uniform_Output1 = OpTypePointer Uniform %Output1
417                %output1 = OpVariable %_ptr_Uniform_Output1 Uniform
418                 %tinput = ${OPTYPE}
419               %v4tinput = OpTypeVector %tinput 4
420   %_runtimearr_v4tinput = OpTypeRuntimeArray %v4tinput
421                 %Input1 = OpTypeStruct %_runtimearr_v4tinput
422    %_ptr_Uniform_Input1 = OpTypePointer Uniform %Input1
423                 %input1 = OpVariable %_ptr_Uniform_Input1 Uniform
424  %_ptr_Uniform_v4tinput = OpTypePointer Uniform %v4tinput
425 %_runtimearr_v4tinput_0 = OpTypeRuntimeArray %v4tinput
426                 %Input2 = OpTypeStruct %_runtimearr_v4tinput_0
427    %_ptr_Uniform_Input2 = OpTypePointer Uniform %Input2
428                 %input2 = OpVariable %_ptr_Uniform_Input2 Uniform
429                 %v4bool = OpTypeVector %bool 4
430                  %int_1 = OpConstant %int 1
431                     %45 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
432                     %46 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
433     %_ptr_Uniform_v4int = OpTypePointer Uniform %v4int
434                   %main = OpFunction %void None %3
435                      %5 = OpLabel
436                      %i = OpVariable %_ptr_Function_int Function
437                           OpStore %i %int_0
438                           OpBranch %10
439                     %10 = OpLabel
440                           OpLoopMerge %12 %13 None
441                           OpBranch %14
442                     %14 = OpLabel
443                     %15 = OpLoad %int %i
444                     %18 = OpSLessThan %bool %15 %niters
445                           OpBranchConditional %18 %11 %12
446                     %11 = OpLabel
447                     %24 = OpLoad %int %i
448                     %31 = OpLoad %int %i
449                     %33 = OpAccessChain %_ptr_Uniform_v4tinput %input1 %int_0 %31
450                     %34 = OpLoad %v4tinput %33
451                     %39 = OpLoad %int %i
452                     %40 = OpAccessChain %_ptr_Uniform_v4tinput %input2 %int_0 %39
453                     %41 = OpLoad %v4tinput %40
454                     %43 = ${OPNAME} %v4bool %34 %41
455                     %47 = OpSelect %v4int %43 %46 %45
456                     %49 = OpAccessChain %_ptr_Uniform_v4int %output1 %int_0 %24
457                           OpStore %49 %47
458                           OpBranch %13
459                     %13 = OpLabel
460                     %50 = OpLoad %int %i
461                     %51 = OpIAdd %int %50 %int_1
462                           OpStore %i %51
463                           OpBranch %10
464                     %12 = OpLabel
465                           OpReturn
466                           OpFunctionEnd
467 )");
468 
469 // Shader template for the vertex stage using single scalars.
470 // Generated from the following GLSL shader, replacing some bits by template parameters.
471 #if 0
472 #version 430
473 
474 // Left operands, right operands and results.
475 layout(binding = 0) buffer Input1  { double values[];    } input1;
476 layout(binding = 1) buffer Input2  { double values[];    } input2;
477 layout(binding = 2) buffer Output1 { int values[];        } output1;
478 
479 void main()
480 {
481       gl_PointSize = 1;
482       gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
483 
484       for (int i = 0; i < 20; i++) {
485               output1.values[i] = int(input1.values[i] == input2.values[i]);
486       }
487 }
488 #endif
489 const tcu::StringTemplate VertShaderSingle(R"(
490                             OpCapability Shader
491                             ${OPCAPABILITY}
492                             ${NANCAP}
493                             ${NANEXT}
494                        %1 = OpExtInstImport "GLSL.std.450"
495                             OpMemoryModel Logical GLSL450
496                             OpEntryPoint Vertex %main "main" %_
497                             ${NANMODE}
498                             OpName %main "main"
499                             OpName %gl_PerVertex "gl_PerVertex"
500                             OpMemberName %gl_PerVertex 0 "gl_Position"
501                             OpMemberName %gl_PerVertex 1 "gl_PointSize"
502                             OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
503                             OpName %_ ""
504                             OpName %i "i"
505                             OpName %Output1 "Output1"
506                             OpMemberName %Output1 0 "values"
507                             OpName %output1 "output1"
508                             OpName %Input1 "Input1"
509                             OpMemberName %Input1 0 "values"
510                             OpName %input1 "input1"
511                             OpName %Input2 "Input2"
512                             OpMemberName %Input2 0 "values"
513                             OpName %input2 "input2"
514                             OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
515                             OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
516                             OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
517                             OpDecorate %gl_PerVertex Block
518                             OpDecorate %_runtimearr_int ArrayStride 4
519                             OpMemberDecorate %Output1 0 Offset 0
520                             OpDecorate %Output1 BufferBlock
521                             OpDecorate %output1 DescriptorSet 0
522                             OpDecorate %output1 Binding 2
523                             OpDecorate %_runtimearr_tinput ArrayStride 8
524                             OpMemberDecorate %Input1 0 Offset 0
525                             OpDecorate %Input1 BufferBlock
526                             OpDecorate %input1 DescriptorSet 0
527                             OpDecorate %input1 Binding 0
528                             OpDecorate %_runtimearr_tinput_0 ArrayStride 8
529                             OpMemberDecorate %Input2 0 Offset 0
530                             OpDecorate %Input2 BufferBlock
531                             OpDecorate %input2 DescriptorSet 0
532                             OpDecorate %input2 Binding 1
533                     %void = OpTypeVoid
534                        %3 = OpTypeFunction %void
535                    %float = OpTypeFloat 32
536                  %v4float = OpTypeVector %float 4
537                     %uint = OpTypeInt 32 0
538                   %uint_1 = OpConstant %uint 1
539        %_arr_float_uint_1 = OpTypeArray %float %uint_1
540             %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1
541 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
542                        %_ = OpVariable %_ptr_Output_gl_PerVertex Output
543                      %int = OpTypeInt 32 1
544                    %int_1 = OpConstant %int 1
545                  %float_1 = OpConstant %float 1
546        %_ptr_Output_float = OpTypePointer Output %float
547                    %int_0 = OpConstant %int 0
548                  %float_0 = OpConstant %float 0
549                       %21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
550      %_ptr_Output_v4float = OpTypePointer Output %v4float
551        %_ptr_Function_int = OpTypePointer Function %int
552                   %niters = OpConstant %int ${ITERS}
553                     %bool = OpTypeBool
554          %_runtimearr_int = OpTypeRuntimeArray %int
555                  %Output1 = OpTypeStruct %_runtimearr_int
556     %_ptr_Uniform_Output1 = OpTypePointer Uniform %Output1
557                  %output1 = OpVariable %_ptr_Uniform_Output1 Uniform
558                   %tinput = ${OPTYPE}
559       %_runtimearr_tinput = OpTypeRuntimeArray %tinput
560                   %Input1 = OpTypeStruct %_runtimearr_tinput
561      %_ptr_Uniform_Input1 = OpTypePointer Uniform %Input1
562                   %input1 = OpVariable %_ptr_Uniform_Input1 Uniform
563      %_ptr_Uniform_tinput = OpTypePointer Uniform %tinput
564     %_runtimearr_tinput_0 = OpTypeRuntimeArray %tinput
565                   %Input2 = OpTypeStruct %_runtimearr_tinput_0
566      %_ptr_Uniform_Input2 = OpTypePointer Uniform %Input2
567                   %input2 = OpVariable %_ptr_Uniform_Input2 Uniform
568         %_ptr_Uniform_int = OpTypePointer Uniform %int
569                     %main = OpFunction %void None %3
570                        %5 = OpLabel
571                        %i = OpVariable %_ptr_Function_int Function
572                       %18 = OpAccessChain %_ptr_Output_float %_ %int_1
573                             OpStore %18 %float_1
574                       %23 = OpAccessChain %_ptr_Output_v4float %_ %int_0
575                             OpStore %23 %21
576                             OpStore %i %int_0
577                             OpBranch %26
578                       %26 = OpLabel
579                             OpLoopMerge %28 %29 None
580                             OpBranch %30
581                       %30 = OpLabel
582                       %31 = OpLoad %int %i
583                       %34 = OpSLessThan %bool %31 %niters
584                             OpBranchConditional %34 %27 %28
585                       %27 = OpLabel
586                       %39 = OpLoad %int %i
587                       %45 = OpLoad %int %i
588                       %47 = OpAccessChain %_ptr_Uniform_tinput %input1 %int_0 %45
589                       %48 = OpLoad %tinput %47
590                       %53 = OpLoad %int %i
591                       %54 = OpAccessChain %_ptr_Uniform_tinput %input2 %int_0 %53
592                       %55 = OpLoad %tinput %54
593                       %56 = ${OPNAME} %bool %48 %55
594                       %57 = OpSelect %int %56 %int_1 %int_0
595                       %59 = OpAccessChain %_ptr_Uniform_int %output1 %int_0 %39
596                             OpStore %59 %57
597                             OpBranch %29
598                       %29 = OpLabel
599                       %60 = OpLoad %int %i
600                       %61 = OpIAdd %int %60 %int_1
601                             OpStore %i %61
602                             OpBranch %26
603                       %28 = OpLabel
604                             OpReturn
605                             OpFunctionEnd
606 )");
607 
608 // Shader template for the vertex stage using vectors.
609 // Generated from the following GLSL shader, replacing some bits by template parameters.
610 // Note the number of iterations needs to be divided by 4 as the shader will consume 4 doubles at a time.
611 #if 0
612 #version 430
613 
614 // Left operands, right operands and results.
615 layout(binding = 0) buffer Input1  { dvec4 values[]; } input1;
616 layout(binding = 1) buffer Input2  { dvec4 values[]; } input2;
617 layout(binding = 2) buffer Output1 { ivec4 values[]; } output1;
618 
619 void main()
620 {
621       gl_PointSize = 1;
622       gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
623 
624       for (int i = 0; i < 5; i++) {
625               output1.values[i] = ivec4(equal(input1.values[i], input2.values[i]));
626       }
627 }
628 #endif
629 const tcu::StringTemplate VertShaderVector(R"(
630                             OpCapability Shader
631                             ${OPCAPABILITY}
632                             ${NANCAP}
633                             ${NANEXT}
634                        %1 = OpExtInstImport "GLSL.std.450"
635                             OpMemoryModel Logical GLSL450
636                             OpEntryPoint Vertex %main "main" %_
637                             ${NANMODE}
638                             OpName %main "main"
639                             OpName %gl_PerVertex "gl_PerVertex"
640                             OpMemberName %gl_PerVertex 0 "gl_Position"
641                             OpMemberName %gl_PerVertex 1 "gl_PointSize"
642                             OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
643                             OpName %_ ""
644                             OpName %i "i"
645                             OpName %Output1 "Output1"
646                             OpMemberName %Output1 0 "values"
647                             OpName %output1 "output1"
648                             OpName %Input1 "Input1"
649                             OpMemberName %Input1 0 "values"
650                             OpName %input1 "input1"
651                             OpName %Input2 "Input2"
652                             OpMemberName %Input2 0 "values"
653                             OpName %input2 "input2"
654                             OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
655                             OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
656                             OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
657                             OpDecorate %gl_PerVertex Block
658                             OpDecorate %_runtimearr_v4int ArrayStride 16
659                             OpMemberDecorate %Output1 0 Offset 0
660                             OpDecorate %Output1 BufferBlock
661                             OpDecorate %output1 DescriptorSet 0
662                             OpDecorate %output1 Binding 2
663                             OpDecorate %_runtimearr_v4tinput ArrayStride 32
664                             OpMemberDecorate %Input1 0 Offset 0
665                             OpDecorate %Input1 BufferBlock
666                             OpDecorate %input1 DescriptorSet 0
667                             OpDecorate %input1 Binding 0
668                             OpDecorate %_runtimearr_v4tinput_0 ArrayStride 32
669                             OpMemberDecorate %Input2 0 Offset 0
670                             OpDecorate %Input2 BufferBlock
671                             OpDecorate %input2 DescriptorSet 0
672                             OpDecorate %input2 Binding 1
673                     %void = OpTypeVoid
674                        %3 = OpTypeFunction %void
675                    %float = OpTypeFloat 32
676                  %v4float = OpTypeVector %float 4
677                     %uint = OpTypeInt 32 0
678                   %uint_1 = OpConstant %uint 1
679        %_arr_float_uint_1 = OpTypeArray %float %uint_1
680             %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1
681 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
682                        %_ = OpVariable %_ptr_Output_gl_PerVertex Output
683                      %int = OpTypeInt 32 1
684                    %int_1 = OpConstant %int 1
685                  %float_1 = OpConstant %float 1
686        %_ptr_Output_float = OpTypePointer Output %float
687                    %int_0 = OpConstant %int 0
688                  %float_0 = OpConstant %float 0
689                       %21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
690      %_ptr_Output_v4float = OpTypePointer Output %v4float
691        %_ptr_Function_int = OpTypePointer Function %int
692                   %niters = OpConstant %int ${ITERS}
693                     %bool = OpTypeBool
694                    %v4int = OpTypeVector %int 4
695        %_runtimearr_v4int = OpTypeRuntimeArray %v4int
696                  %Output1 = OpTypeStruct %_runtimearr_v4int
697     %_ptr_Uniform_Output1 = OpTypePointer Uniform %Output1
698                  %output1 = OpVariable %_ptr_Uniform_Output1 Uniform
699                   %tinput = ${OPTYPE}
700                 %v4tinput = OpTypeVector %tinput 4
701     %_runtimearr_v4tinput = OpTypeRuntimeArray %v4tinput
702                   %Input1 = OpTypeStruct %_runtimearr_v4tinput
703      %_ptr_Uniform_Input1 = OpTypePointer Uniform %Input1
704                   %input1 = OpVariable %_ptr_Uniform_Input1 Uniform
705    %_ptr_Uniform_v4tinput = OpTypePointer Uniform %v4tinput
706   %_runtimearr_v4tinput_0 = OpTypeRuntimeArray %v4tinput
707                   %Input2 = OpTypeStruct %_runtimearr_v4tinput_0
708      %_ptr_Uniform_Input2 = OpTypePointer Uniform %Input2
709                   %input2 = OpVariable %_ptr_Uniform_Input2 Uniform
710                   %v4bool = OpTypeVector %bool 4
711                       %60 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
712                       %61 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
713       %_ptr_Uniform_v4int = OpTypePointer Uniform %v4int
714                     %main = OpFunction %void None %3
715                        %5 = OpLabel
716                        %i = OpVariable %_ptr_Function_int Function
717                       %18 = OpAccessChain %_ptr_Output_float %_ %int_1
718                             OpStore %18 %float_1
719                       %23 = OpAccessChain %_ptr_Output_v4float %_ %int_0
720                             OpStore %23 %21
721                             OpStore %i %int_0
722                             OpBranch %26
723                       %26 = OpLabel
724                             OpLoopMerge %28 %29 None
725                             OpBranch %30
726                       %30 = OpLabel
727                       %31 = OpLoad %int %i
728                       %34 = OpSLessThan %bool %31 %niters
729                             OpBranchConditional %34 %27 %28
730                       %27 = OpLabel
731                       %40 = OpLoad %int %i
732                       %47 = OpLoad %int %i
733                       %49 = OpAccessChain %_ptr_Uniform_v4tinput %input1 %int_0 %47
734                       %50 = OpLoad %v4tinput %49
735                       %55 = OpLoad %int %i
736                       %56 = OpAccessChain %_ptr_Uniform_v4tinput %input2 %int_0 %55
737                       %57 = OpLoad %v4tinput %56
738                       %59 = ${OPNAME} %v4bool %50 %57
739                       %62 = OpSelect %v4int %59 %61 %60
740                       %64 = OpAccessChain %_ptr_Uniform_v4int %output1 %int_0 %40
741                             OpStore %64 %62
742                             OpBranch %29
743                       %29 = OpLabel
744                       %65 = OpLoad %int %i
745                       %66 = OpIAdd %int %65 %int_1
746                             OpStore %i %66
747                             OpBranch %26
748                       %28 = OpLabel
749                             OpReturn
750                             OpFunctionEnd
751 )");
752 
753 // GLSL passthrough vertex shader to test the fragment shader.
754 const std::string VertShaderPassThrough = R"(
755 #version 430
756 
757 layout(location = 0) out vec4 out_color;
758 
759 void main()
760 {
761         gl_PointSize = 1;
762         gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
763         out_color = vec4(0.0, 0.0, 0.0, 1.0);
764 }
765 )";
766 
767 // Shader template for the fragment stage using single scalars.
768 // Generated from the following GLSL shader, replacing some bits by template parameters.
769 #if 0
770 #version 430
771 
772 // Left operands, right operands and results.
773 layout(binding = 0) buffer Input1  { double values[];    } input1;
774 layout(binding = 1) buffer Input2  { double values[];    } input2;
775 layout(binding = 2) buffer Output1 { int values[];        } output1;
776 
777 void main()
778 {
779       for (int i = 0; i < 20; i++) {
780               output1.values[i] = int(input1.values[i] == input2.values[i]);
781       }
782 }
783 #endif
784 const tcu::StringTemplate FragShaderSingle(R"(
785                         OpCapability Shader
786                         ${OPCAPABILITY}
787                         ${NANCAP}
788                         ${NANEXT}
789                    %1 = OpExtInstImport "GLSL.std.450"
790                         OpMemoryModel Logical GLSL450
791                         OpEntryPoint Fragment %main "main"
792                         ${NANMODE}
793                         OpExecutionMode %main OriginUpperLeft
794                         OpSource GLSL 430
795                         OpName %main "main"
796                         OpName %i "i"
797                         OpName %Output1 "Output1"
798                         OpMemberName %Output1 0 "values"
799                         OpName %output1 "output1"
800                         OpName %Input1 "Input1"
801                         OpMemberName %Input1 0 "values"
802                         OpName %input1 "input1"
803                         OpName %Input2 "Input2"
804                         OpMemberName %Input2 0 "values"
805                         OpName %input2 "input2"
806                         OpDecorate %_runtimearr_int ArrayStride 4
807                         OpMemberDecorate %Output1 0 Offset 0
808                         OpDecorate %Output1 BufferBlock
809                         OpDecorate %output1 DescriptorSet 0
810                         OpDecorate %output1 Binding 2
811                         OpDecorate %_runtimearr_tinput ArrayStride 8
812                         OpMemberDecorate %Input1 0 Offset 0
813                         OpDecorate %Input1 BufferBlock
814                         OpDecorate %input1 DescriptorSet 0
815                         OpDecorate %input1 Binding 0
816                         OpDecorate %_runtimearr_tinput_0 ArrayStride 8
817                         OpMemberDecorate %Input2 0 Offset 0
818                         OpDecorate %Input2 BufferBlock
819                         OpDecorate %input2 DescriptorSet 0
820                         OpDecorate %input2 Binding 1
821                 %void = OpTypeVoid
822                    %3 = OpTypeFunction %void
823                  %int = OpTypeInt 32 1
824    %_ptr_Function_int = OpTypePointer Function %int
825                %int_0 = OpConstant %int 0
826               %niters = OpConstant %int ${ITERS}
827                 %bool = OpTypeBool
828      %_runtimearr_int = OpTypeRuntimeArray %int
829              %Output1 = OpTypeStruct %_runtimearr_int
830 %_ptr_Uniform_Output1 = OpTypePointer Uniform %Output1
831              %output1 = OpVariable %_ptr_Uniform_Output1 Uniform
832               %tinput = ${OPTYPE}
833   %_runtimearr_tinput = OpTypeRuntimeArray %tinput
834               %Input1 = OpTypeStruct %_runtimearr_tinput
835  %_ptr_Uniform_Input1 = OpTypePointer Uniform %Input1
836               %input1 = OpVariable %_ptr_Uniform_Input1 Uniform
837  %_ptr_Uniform_tinput = OpTypePointer Uniform %tinput
838 %_runtimearr_tinput_0 = OpTypeRuntimeArray %tinput
839               %Input2 = OpTypeStruct %_runtimearr_tinput_0
840  %_ptr_Uniform_Input2 = OpTypePointer Uniform %Input2
841               %input2 = OpVariable %_ptr_Uniform_Input2 Uniform
842                %int_1 = OpConstant %int 1
843     %_ptr_Uniform_int = OpTypePointer Uniform %int
844                 %main = OpFunction %void None %3
845                    %5 = OpLabel
846                    %i = OpVariable %_ptr_Function_int Function
847                         OpStore %i %int_0
848                         OpBranch %10
849                   %10 = OpLabel
850                         OpLoopMerge %12 %13 None
851                         OpBranch %14
852                   %14 = OpLabel
853                   %15 = OpLoad %int %i
854                   %18 = OpSLessThan %bool %15 %niters
855                         OpBranchConditional %18 %11 %12
856                   %11 = OpLabel
857                   %23 = OpLoad %int %i
858                   %29 = OpLoad %int %i
859                   %31 = OpAccessChain %_ptr_Uniform_tinput %input1 %int_0 %29
860                   %32 = OpLoad %tinput %31
861                   %37 = OpLoad %int %i
862                   %38 = OpAccessChain %_ptr_Uniform_tinput %input2 %int_0 %37
863                   %39 = OpLoad %tinput %38
864                   %40 = ${OPNAME} %bool %32 %39
865                   %42 = OpSelect %int %40 %int_1 %int_0
866                   %44 = OpAccessChain %_ptr_Uniform_int %output1 %int_0 %23
867                         OpStore %44 %42
868                         OpBranch %13
869                   %13 = OpLabel
870                   %45 = OpLoad %int %i
871                   %46 = OpIAdd %int %45 %int_1
872                         OpStore %i %46
873                         OpBranch %10
874                   %12 = OpLabel
875                         OpReturn
876                         OpFunctionEnd
877 )");
878 
879 // Shader template for the fragment stage using vectors.
880 // Generated from the following GLSL shader, replacing some bits by template parameters.
881 // Note the number of iterations needs to be divided by 4 as the shader will consume 4 doubles at a time.
882 #if 0
883 #version 430
884 
885 // Left operands, right operands and results.
886 layout(binding = 0) buffer Input1  { dvec4 values[]; } input1;
887 layout(binding = 1) buffer Input2  { dvec4 values[]; } input2;
888 layout(binding = 2) buffer Output1 { ivec4 values[]; } output1;
889 
890 void main()
891 {
892       for (int i = 0; i < 5; i++) {
893               output1.values[i] = ivec4(equal(input1.values[i], input2.values[i]));
894       }
895 }
896 #endif
897 const tcu::StringTemplate FragShaderVector(R"(
898                           OpCapability Shader
899                           ${OPCAPABILITY}
900                           ${NANCAP}
901                           ${NANEXT}
902                      %1 = OpExtInstImport "GLSL.std.450"
903                           OpMemoryModel Logical GLSL450
904                           OpEntryPoint Fragment %main "main"
905                           ${NANMODE}
906                           OpExecutionMode %main OriginUpperLeft
907                           OpName %main "main"
908                           OpName %i "i"
909                           OpName %Output1 "Output1"
910                           OpMemberName %Output1 0 "values"
911                           OpName %output1 "output1"
912                           OpName %Input1 "Input1"
913                           OpMemberName %Input1 0 "values"
914                           OpName %input1 "input1"
915                           OpName %Input2 "Input2"
916                           OpMemberName %Input2 0 "values"
917                           OpName %input2 "input2"
918                           OpDecorate %_runtimearr_v4int ArrayStride 16
919                           OpMemberDecorate %Output1 0 Offset 0
920                           OpDecorate %Output1 BufferBlock
921                           OpDecorate %output1 DescriptorSet 0
922                           OpDecorate %output1 Binding 2
923                           OpDecorate %_runtimearr_v4tinput ArrayStride 32
924                           OpMemberDecorate %Input1 0 Offset 0
925                           OpDecorate %Input1 BufferBlock
926                           OpDecorate %input1 DescriptorSet 0
927                           OpDecorate %input1 Binding 0
928                           OpDecorate %_runtimearr_v4tinput_0 ArrayStride 32
929                           OpMemberDecorate %Input2 0 Offset 0
930                           OpDecorate %Input2 BufferBlock
931                           OpDecorate %input2 DescriptorSet 0
932                           OpDecorate %input2 Binding 1
933                   %void = OpTypeVoid
934                      %3 = OpTypeFunction %void
935                    %int = OpTypeInt 32 1
936      %_ptr_Function_int = OpTypePointer Function %int
937                  %int_0 = OpConstant %int 0
938                 %niters = OpConstant %int ${ITERS}
939                   %bool = OpTypeBool
940                  %v4int = OpTypeVector %int 4
941      %_runtimearr_v4int = OpTypeRuntimeArray %v4int
942                %Output1 = OpTypeStruct %_runtimearr_v4int
943   %_ptr_Uniform_Output1 = OpTypePointer Uniform %Output1
944                %output1 = OpVariable %_ptr_Uniform_Output1 Uniform
945                 %tinput = ${OPTYPE}
946               %v4tinput = OpTypeVector %tinput 4
947   %_runtimearr_v4tinput = OpTypeRuntimeArray %v4tinput
948                 %Input1 = OpTypeStruct %_runtimearr_v4tinput
949    %_ptr_Uniform_Input1 = OpTypePointer Uniform %Input1
950                 %input1 = OpVariable %_ptr_Uniform_Input1 Uniform
951  %_ptr_Uniform_v4tinput = OpTypePointer Uniform %v4tinput
952 %_runtimearr_v4tinput_0 = OpTypeRuntimeArray %v4tinput
953                 %Input2 = OpTypeStruct %_runtimearr_v4tinput_0
954    %_ptr_Uniform_Input2 = OpTypePointer Uniform %Input2
955                 %input2 = OpVariable %_ptr_Uniform_Input2 Uniform
956                 %v4bool = OpTypeVector %bool 4
957                  %int_1 = OpConstant %int 1
958                     %45 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
959                     %46 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
960     %_ptr_Uniform_v4int = OpTypePointer Uniform %v4int
961                   %main = OpFunction %void None %3
962                      %5 = OpLabel
963                      %i = OpVariable %_ptr_Function_int Function
964                           OpStore %i %int_0
965                           OpBranch %10
966                     %10 = OpLabel
967                           OpLoopMerge %12 %13 None
968                           OpBranch %14
969                     %14 = OpLabel
970                     %15 = OpLoad %int %i
971                     %18 = OpSLessThan %bool %15 %niters
972                           OpBranchConditional %18 %11 %12
973                     %11 = OpLabel
974                     %24 = OpLoad %int %i
975                     %31 = OpLoad %int %i
976                     %33 = OpAccessChain %_ptr_Uniform_v4tinput %input1 %int_0 %31
977                     %34 = OpLoad %v4tinput %33
978                     %39 = OpLoad %int %i
979                     %40 = OpAccessChain %_ptr_Uniform_v4tinput %input2 %int_0 %39
980                     %41 = OpLoad %v4tinput %40
981                     %43 = ${OPNAME} %v4bool %34 %41
982                     %47 = OpSelect %v4int %43 %46 %45
983                     %49 = OpAccessChain %_ptr_Uniform_v4int %output1 %int_0 %24
984                           OpStore %49 %47
985                           OpBranch %13
986                     %13 = OpLabel
987                     %50 = OpLoad %int %i
988                     %51 = OpIAdd %int %50 %int_1
989                           OpStore %i %51
990                           OpBranch %10
991                     %12 = OpLabel
992                           OpReturn
993                           OpFunctionEnd
994 )");
995 
996 struct SpirvTemplateManager
997 {
getTemplatevkt::SpirVAssembly::__anon071ae8e90111::SpirvTemplateManager998     static const tcu::StringTemplate &getTemplate(DataType type, vk::VkShaderStageFlagBits stage)
999     {
1000         DE_ASSERT(type == DATA_TYPE_SINGLE || type == DATA_TYPE_VECTOR);
1001         DE_ASSERT(stage == vk::VK_SHADER_STAGE_COMPUTE_BIT || stage == vk::VK_SHADER_STAGE_VERTEX_BIT ||
1002                   stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1003 
1004         if (type == DATA_TYPE_SINGLE)
1005         {
1006             if (stage == vk::VK_SHADER_STAGE_COMPUTE_BIT)
1007                 return CompShaderSingle;
1008             if (stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
1009                 return VertShaderSingle;
1010             else
1011                 return FragShaderSingle;
1012         }
1013         else
1014         {
1015             if (stage == vk::VK_SHADER_STAGE_COMPUTE_BIT)
1016                 return CompShaderVector;
1017             if (stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
1018                 return VertShaderVector;
1019             else
1020                 return FragShaderVector;
1021         }
1022     }
1023 
1024     // Specialized below for different types.
1025     template <class T>
1026     static std::string getOpCapability();
1027 
1028     // Same.
1029     template <class T>
1030     static std::string getOpType();
1031 
1032     // Return the capabilities, extensions and execution modes for NaN preservation.
1033     static std::string getNanCapability(bool preserve);
1034     static std::string getNanExtension(bool preserve);
1035     static std::string getNanExeMode(bool preserve);
1036 };
1037 
1038 template <>
getOpCapability()1039 std::string SpirvTemplateManager::getOpCapability<double>()
1040 {
1041     return "OpCapability Float64";
1042 }
1043 template <>
getOpCapability()1044 std::string SpirvTemplateManager::getOpCapability<int64_t>()
1045 {
1046     return "OpCapability Int64";
1047 }
1048 template <>
getOpCapability()1049 std::string SpirvTemplateManager::getOpCapability<uint64_t>()
1050 {
1051     return "OpCapability Int64";
1052 }
1053 
1054 template <>
getOpType()1055 std::string SpirvTemplateManager::getOpType<double>()
1056 {
1057     return "OpTypeFloat 64";
1058 }
1059 template <>
getOpType()1060 std::string SpirvTemplateManager::getOpType<int64_t>()
1061 {
1062     return "OpTypeInt 64 1";
1063 }
1064 template <>
getOpType()1065 std::string SpirvTemplateManager::getOpType<uint64_t>()
1066 {
1067     return "OpTypeInt 64 0";
1068 }
1069 
getNanCapability(bool preserve)1070 std::string SpirvTemplateManager::getNanCapability(bool preserve)
1071 {
1072     return (preserve ? "OpCapability SignedZeroInfNanPreserve" : "");
1073 }
1074 
getNanExtension(bool preserve)1075 std::string SpirvTemplateManager::getNanExtension(bool preserve)
1076 {
1077     return (preserve ? "OpExtension \"SPV_KHR_float_controls\"" : "");
1078 }
1079 
getNanExeMode(bool preserve)1080 std::string SpirvTemplateManager::getNanExeMode(bool preserve)
1081 {
1082     return (preserve ? "OpExecutionMode %main SignedZeroInfNanPreserve 64" : "");
1083 }
1084 
1085 struct BufferWithMemory
1086 {
1087     vk::Move<vk::VkBuffer> buffer;
1088     de::MovePtr<vk::Allocation> allocation;
1089 
BufferWithMemoryvkt::SpirVAssembly::__anon071ae8e90111::BufferWithMemory1090     BufferWithMemory() : buffer(), allocation()
1091     {
1092     }
1093 
BufferWithMemoryvkt::SpirVAssembly::__anon071ae8e90111::BufferWithMemory1094     BufferWithMemory(BufferWithMemory &&other) : buffer(other.buffer), allocation(other.allocation)
1095     {
1096     }
1097 
operator =vkt::SpirVAssembly::__anon071ae8e90111::BufferWithMemory1098     BufferWithMemory &operator=(BufferWithMemory &&other)
1099     {
1100         buffer     = other.buffer;
1101         allocation = other.allocation;
1102         return *this;
1103     }
1104 };
1105 
1106 // Create storage buffer, bind memory to it and return both things.
createStorageBuffer(const vk::DeviceInterface & vkdi,const vk::VkDevice device,vk::Allocator & allocator,size_t numBytes)1107 BufferWithMemory createStorageBuffer(const vk::DeviceInterface &vkdi, const vk::VkDevice device,
1108                                      vk::Allocator &allocator, size_t numBytes)
1109 {
1110     const vk::VkBufferCreateInfo bufferCreateInfo = {
1111         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
1112         DE_NULL,                                  // pNext
1113         0u,                                       // flags
1114         numBytes,                                 // size
1115         vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,   // usage
1116         vk::VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
1117         0u,                                       // queueFamilyCount
1118         DE_NULL,                                  // pQueueFamilyIndices
1119     };
1120 
1121     BufferWithMemory bufmem;
1122 
1123     bufmem.buffer                               = vk::createBuffer(vkdi, device, &bufferCreateInfo);
1124     const vk::VkMemoryRequirements requirements = getBufferMemoryRequirements(vkdi, device, *bufmem.buffer);
1125     bufmem.allocation                           = allocator.allocate(requirements, vk::MemoryRequirement::HostVisible);
1126 
1127     VK_CHECK(
1128         vkdi.bindBufferMemory(device, *bufmem.buffer, bufmem.allocation->getMemory(), bufmem.allocation->getOffset()));
1129 
1130     return bufmem;
1131 }
1132 
1133 // Make sure the length of the following vectors is a multiple of 4. This will make sure operands can be reused for vectorized tests.
1134 const OperandsVector<double> DOUBLE_OPERANDS = {
1135     {-8.0, -5.0}, {-5.0, -8.0}, {-5.0, -5.0}, {-5.0, 0.0}, {0.0, -5.0}, {5.0, 0.0}, {0.0, 5.0},
1136     {0.0, 0.0},   {-5.0, 5.0},  {5.0, -5.0},  {5.0, 8.0},  {8.0, 5.0},  {5.0, 5.0}, {-6.0, -5.0},
1137     {6.0, 5.0},   {0.0, 1.0},   {1.0, 0.0},   {0.0, NAN},  {NAN, 0.0},  {NAN, NAN},
1138 };
1139 
1140 const OperandsVector<int64_t> INT64_OPERANDS = {
1141     {-8, -5}, {-5, -8}, {-5, -5}, {-5, 0}, {0, -5}, {5, 0},   {0, 5}, {0, 0},
1142     {-5, 5},  {5, -5},  {5, 8},   {8, 5},  {5, 5},  {-6, -5}, {6, 5}, {0, 1},
1143 };
1144 
1145 constexpr auto MAX_DEUINT64                    = std::numeric_limits<uint64_t>::max();
1146 const OperandsVector<uint64_t> UINT64_OPERANDS = {
1147     {0, 0},
1148     {1, 0},
1149     {0, 1},
1150     {1, 1},
1151     {5, 8},
1152     {8, 5},
1153     {5, 5},
1154     {0, MAX_DEUINT64},
1155     {MAX_DEUINT64, 0},
1156     {MAX_DEUINT64 - 1, MAX_DEUINT64},
1157     {MAX_DEUINT64, MAX_DEUINT64 - 1},
1158     {MAX_DEUINT64, MAX_DEUINT64},
1159 };
1160 
1161 template <class T>
1162 class T64bitCompareTestInstance : public TestInstance
1163 {
1164 public:
1165     T64bitCompareTestInstance(Context &ctx, const TestParameters<T> &params);
1166     tcu::TestStatus iterate(void);
1167 
1168 private:
1169     const TestParameters<T> m_params;
1170     const size_t m_numOperations;
1171     const size_t m_inputBufferSize;
1172     const size_t m_outputBufferSize;
1173 };
1174 
1175 template <class T>
T64bitCompareTestInstance(Context & ctx,const TestParameters<T> & params)1176 T64bitCompareTestInstance<T>::T64bitCompareTestInstance(Context &ctx, const TestParameters<T> &params)
1177     : TestInstance(ctx)
1178     , m_params(params)
1179     , m_numOperations(m_params.operands.size())
1180     , m_inputBufferSize(m_numOperations * sizeof(T))
1181     , m_outputBufferSize(m_numOperations * sizeof(int))
1182 {
1183 }
1184 
1185 template <class T>
genericIsNan(T)1186 bool genericIsNan(T)
1187 {
1188     return false;
1189 }
1190 
1191 template <>
genericIsNan(double value)1192 bool genericIsNan<double>(double value)
1193 {
1194     return std::isnan(value);
1195 }
1196 
1197 template <class T>
iterate(void)1198 tcu::TestStatus T64bitCompareTestInstance<T>::iterate(void)
1199 {
1200     DE_ASSERT(m_params.stage == vk::VK_SHADER_STAGE_COMPUTE_BIT || m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT ||
1201               m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1202 
1203     auto &vkdi      = m_context.getDeviceInterface();
1204     auto device     = m_context.getDevice();
1205     auto &allocator = m_context.getDefaultAllocator();
1206 
1207     // Create storage buffers (left operands, right operands and results buffer).
1208     BufferWithMemory input1  = createStorageBuffer(vkdi, device, allocator, m_inputBufferSize);
1209     BufferWithMemory input2  = createStorageBuffer(vkdi, device, allocator, m_inputBufferSize);
1210     BufferWithMemory output1 = createStorageBuffer(vkdi, device, allocator, m_outputBufferSize);
1211 
1212     // Create an array of buffers.
1213     std::vector<vk::VkBuffer> buffers;
1214     buffers.push_back(input1.buffer.get());
1215     buffers.push_back(input2.buffer.get());
1216     buffers.push_back(output1.buffer.get());
1217 
1218     // Create descriptor set layout.
1219     std::vector<vk::VkDescriptorSetLayoutBinding> bindings;
1220     for (size_t i = 0; i < buffers.size(); ++i)
1221     {
1222         vk::VkDescriptorSetLayoutBinding binding = {
1223             static_cast<uint32_t>(i),                            // uint32_t              binding;
1224             vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,               // VkDescriptorType      descriptorType;
1225             1u,                                                  // uint32_t              descriptorCount;
1226             static_cast<vk::VkShaderStageFlags>(m_params.stage), // VkShaderStageFlags    stageFlags;
1227             DE_NULL                                              // const VkSampler*      pImmutableSamplers;
1228         };
1229         bindings.push_back(binding);
1230     }
1231 
1232     const vk::VkDescriptorSetLayoutCreateInfo layoutCreateInfo = {
1233         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType;
1234         DE_NULL,                                                 // const void*                            pNext;
1235         0,                                                       // VkDescriptorSetLayoutCreateFlags       flags;
1236         static_cast<uint32_t>(bindings.size()),                  // uint32_t                               bindingCount;
1237         bindings.data()                                          // const VkDescriptorSetLayoutBinding*    pBindings;
1238     };
1239     auto descriptorSetLayout = vk::createDescriptorSetLayout(vkdi, device, &layoutCreateInfo);
1240 
1241     // Create descriptor set.
1242     vk::DescriptorPoolBuilder poolBuilder;
1243     poolBuilder.addType(bindings[0].descriptorType, static_cast<uint32_t>(bindings.size()));
1244     auto descriptorPool = poolBuilder.build(vkdi, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1245 
1246     const vk::VkDescriptorSetAllocateInfo allocateInfo = {
1247         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                 sType;
1248         DE_NULL,                                            // const void*                     pNext;
1249         *descriptorPool,                                    // VkDescriptorPool                descriptorPool;
1250         1u,                                                 // uint32_t                        descriptorSetCount;
1251         &descriptorSetLayout.get()                          // const VkDescriptorSetLayout*    pSetLayouts;
1252     };
1253     auto descriptorSet = vk::allocateDescriptorSet(vkdi, device, &allocateInfo);
1254 
1255     // Update descriptor set.
1256     std::vector<vk::VkDescriptorBufferInfo> descriptorBufferInfos;
1257     std::vector<vk::VkWriteDescriptorSet> descriptorWrites;
1258 
1259     descriptorBufferInfos.reserve(buffers.size());
1260     descriptorWrites.reserve(buffers.size());
1261 
1262     for (size_t i = 0; i < buffers.size(); ++i)
1263     {
1264         vk::VkDescriptorBufferInfo bufferInfo = {
1265             buffers[i],    // VkBuffer        buffer;
1266             0u,            // VkDeviceSize    offset;
1267             VK_WHOLE_SIZE, // VkDeviceSize    range;
1268         };
1269         descriptorBufferInfos.push_back(bufferInfo);
1270     }
1271 
1272     for (size_t i = 0; i < buffers.size(); ++i)
1273     {
1274         vk::VkWriteDescriptorSet write = {
1275             vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                  sType;
1276             DE_NULL,                                    // const void*                      pNext;
1277             *descriptorSet,                             // VkDescriptorSet                  dstSet;
1278             static_cast<uint32_t>(i),                   // uint32_t                         dstBinding;
1279             0u,                                         // uint32_t                         dstArrayElement;
1280             1u,                                         // uint32_t                         descriptorCount;
1281             bindings[i].descriptorType,                 // VkDescriptorType                 descriptorType;
1282             DE_NULL,                                    // const VkDescriptorImageInfo*     pImageInfo;
1283             &descriptorBufferInfos[i],                  // const VkDescriptorBufferInfo*    pBufferInfo;
1284             DE_NULL,                                    // const VkBufferView*              pTexelBufferView;
1285         };
1286         descriptorWrites.push_back(write);
1287     }
1288     vkdi.updateDescriptorSets(device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0u,
1289                               DE_NULL);
1290 
1291     // Fill storage buffers with data. Note: VkPhysicalDeviceLimits.minMemoryMapAlignment guarantees this cast is safe.
1292     T *input1Ptr    = reinterpret_cast<T *>(input1.allocation->getHostPtr());
1293     T *input2Ptr    = reinterpret_cast<T *>(input2.allocation->getHostPtr());
1294     int *output1Ptr = reinterpret_cast<int *>(output1.allocation->getHostPtr());
1295 
1296     for (size_t i = 0; i < m_numOperations; ++i)
1297     {
1298         input1Ptr[i]  = m_params.operands[i].first;
1299         input2Ptr[i]  = m_params.operands[i].second;
1300         output1Ptr[i] = -9;
1301     }
1302 
1303     // Flush memory.
1304     vk::flushAlloc(vkdi, device, *input1.allocation);
1305     vk::flushAlloc(vkdi, device, *input2.allocation);
1306     vk::flushAlloc(vkdi, device, *output1.allocation);
1307 
1308     // Prepare barriers in advance so data is visible to the shaders and the host.
1309     std::vector<vk::VkBufferMemoryBarrier> hostToDevBarriers;
1310     std::vector<vk::VkBufferMemoryBarrier> devToHostBarriers;
1311     for (size_t i = 0; i < buffers.size(); ++i)
1312     {
1313         const vk::VkBufferMemoryBarrier hostDev = {
1314             vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,                      // VkStructureType sType;
1315             DE_NULL,                                                          // const void* pNext;
1316             vk::VK_ACCESS_HOST_WRITE_BIT,                                     // VkAccessFlags srcAccessMask;
1317             (vk::VK_ACCESS_SHADER_READ_BIT | vk::VK_ACCESS_SHADER_WRITE_BIT), // VkAccessFlags dstAccessMask;
1318             VK_QUEUE_FAMILY_IGNORED,                                          // uint32_t srcQueueFamilyIndex;
1319             VK_QUEUE_FAMILY_IGNORED,                                          // uint32_t dstQueueFamilyIndex;
1320             buffers[i],                                                       // VkBuffer buffer;
1321             0u,                                                               // VkDeviceSize offset;
1322             VK_WHOLE_SIZE,                                                    // VkDeviceSize size;
1323         };
1324         hostToDevBarriers.push_back(hostDev);
1325 
1326         const vk::VkBufferMemoryBarrier devHost = {
1327             vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1328             DE_NULL,                                     // const void* pNext;
1329             vk::VK_ACCESS_SHADER_WRITE_BIT,              // VkAccessFlags srcAccessMask;
1330             vk::VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
1331             VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
1332             VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
1333             buffers[i],                                  // VkBuffer buffer;
1334             0u,                                          // VkDeviceSize offset;
1335             VK_WHOLE_SIZE,                               // VkDeviceSize size;
1336         };
1337         devToHostBarriers.push_back(devHost);
1338     }
1339 
1340     // Create command pool and command buffer.
1341     auto queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1342 
1343     const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
1344         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
1345         DE_NULL,                                        // const void* pNext;
1346         vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // VkCommandPoolCreateFlags flags;
1347         queueFamilyIndex,                               // uint32_t queueFamilyIndex;
1348     };
1349     auto cmdPool = vk::createCommandPool(vkdi, device, &cmdPoolCreateInfo);
1350 
1351     const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo = {
1352         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1353         DE_NULL,                                            // const void* pNext;
1354         *cmdPool,                                           // VkCommandPool commandPool;
1355         vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1356         1u,                                                 // uint32_t commandBufferCount;
1357     };
1358     auto cmdBuffer = vk::allocateCommandBuffer(vkdi, device, &cmdBufferAllocateInfo);
1359 
1360     // Create pipeline layout.
1361     const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
1362         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1363         DE_NULL,                                           // const void* pNext;
1364         0,                                                 // VkPipelineLayoutCreateFlags flags;
1365         1u,                                                // uint32_t setLayoutCount;
1366         &descriptorSetLayout.get(),                        // const VkDescriptorSetLayout* pSetLayouts;
1367         0u,                                                // uint32_t pushConstantRangeCount;
1368         DE_NULL,                                           // const VkPushConstantRange* pPushConstantRanges;
1369     };
1370     auto pipelineLayout = vk::createPipelineLayout(vkdi, device, &pipelineLayoutCreateInfo);
1371 
1372     if (m_params.stage == vk::VK_SHADER_STAGE_COMPUTE_BIT)
1373     {
1374         // Create compute pipeline.
1375         auto compShaderModule = createShaderModule(vkdi, device, m_context.getBinaryCollection().get("comp"));
1376 
1377         const vk::VkComputePipelineCreateInfo computeCreateInfo = {
1378             vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType                    sType;
1379             DE_NULL,                                            // const void*                        pNext;
1380             0,                                                  // VkPipelineCreateFlags              flags;
1381             {
1382                 // VkPipelineShaderStageCreateInfo    stage;
1383                 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                     sType;
1384                 DE_NULL,                                                 // const void*                         pNext;
1385                 0,                                                       // VkPipelineShaderStageCreateFlags    flags;
1386                 vk::VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits               stage;
1387                 *compShaderModule,                                       // VkShaderModule                      module;
1388                 "main",                                                  // const char*                         pName;
1389                 DE_NULL, // const VkSpecializationInfo*         pSpecializationInfo;
1390             },
1391             *pipelineLayout, // VkPipelineLayout                   layout;
1392             DE_NULL,         // VkPipeline                         basePipelineHandle;
1393             0,               // int32_t                            basePipelineIndex;
1394         };
1395         auto computePipeline = vk::createComputePipeline(vkdi, device, DE_NULL, &computeCreateInfo);
1396 
1397         // Run the shader.
1398         vk::beginCommandBuffer(vkdi, *cmdBuffer);
1399         vkdi.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1400         vkdi.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1u,
1401                                    &descriptorSet.get(), 0u, DE_NULL);
1402         vkdi.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0,
1403                                 0u, DE_NULL, static_cast<uint32_t>(hostToDevBarriers.size()), hostToDevBarriers.data(),
1404                                 0u, DE_NULL);
1405         vkdi.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
1406         vkdi.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0,
1407                                 0u, DE_NULL, static_cast<uint32_t>(devToHostBarriers.size()), devToHostBarriers.data(),
1408                                 0u, DE_NULL);
1409         vk::endCommandBuffer(vkdi, *cmdBuffer);
1410         vk::submitCommandsAndWait(vkdi, device, m_context.getUniversalQueue(), *cmdBuffer);
1411     }
1412     else if (m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT || m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
1413     {
1414         const bool isFrag = (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1415 
1416         // Create graphics pipeline.
1417         auto vertShaderModule = createShaderModule(vkdi, device, m_context.getBinaryCollection().get("vert"));
1418         vk::Move<vk::VkShaderModule> fragShaderModule;
1419         std::vector<vk::VkPipelineShaderStageCreateInfo> shaderStages;
1420 
1421         const vk::VkPipelineShaderStageCreateInfo vertexStage = {
1422             vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1423             DE_NULL,                                                 // const void* pNext;
1424             0,                                                       // VkPipelineShaderStageCreateFlags flags;
1425             vk::VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits stage;
1426             *vertShaderModule,                                       // VkShaderModule module;
1427             "main",                                                  // const char* pName;
1428             DE_NULL,                                                 // const VkSpecializationInfo* pSpecializationInfo;
1429         };
1430         shaderStages.push_back(vertexStage);
1431 
1432         if (isFrag)
1433         {
1434             fragShaderModule = createShaderModule(vkdi, device, m_context.getBinaryCollection().get("frag"));
1435 
1436             const vk::VkPipelineShaderStageCreateInfo fragmentStage = {
1437                 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1438                 DE_NULL,                                                 // const void* pNext;
1439                 0,                                                       // VkPipelineShaderStageCreateFlags flags;
1440                 vk::VK_SHADER_STAGE_FRAGMENT_BIT,                        // VkShaderStageFlagBits stage;
1441                 *fragShaderModule,                                       // VkShaderModule module;
1442                 "main",                                                  // const char* pName;
1443                 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
1444             };
1445             shaderStages.push_back(fragmentStage);
1446         }
1447 
1448         const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo = {
1449             vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1450             DE_NULL,                                                       // const void* pNext;
1451             0,       // VkPipelineVertexInputStateCreateFlags flags;
1452             0u,      // uint32_t vertexBindingDescriptionCount;
1453             DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1454             0u,      // uint32_t vertexAttributeDescriptionCount;
1455             DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1456         };
1457 
1458         const vk::VkPipelineInputAssemblyStateCreateInfo inputAssembly = {
1459             vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1460             DE_NULL,                                                         // const void* pNext;
1461             0u,                                   // VkPipelineInputAssemblyStateCreateFlags flags;
1462             vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology;
1463             VK_FALSE,                             // VkBool32 primitiveRestartEnable;
1464         };
1465 
1466         const vk::VkPipelineRasterizationStateCreateInfo rasterizationState = {
1467             vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1468             DE_NULL,                                                        // const void* pNext;
1469             0,                                   // VkPipelineRasterizationStateCreateFlags flags;
1470             VK_FALSE,                            // VkBool32 depthClampEnable;
1471             (isFrag ? VK_FALSE : VK_TRUE),       // VkBool32 rasterizerDiscardEnable;
1472             vk::VK_POLYGON_MODE_FILL,            // VkPolygonMode polygonMode;
1473             vk::VK_CULL_MODE_NONE,               // VkCullModeFlags cullMode;
1474             vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
1475             VK_FALSE,                            // VkBool32 depthBiasEnable;
1476             0.0f,                                // float depthBiasConstantFactor;
1477             0.0f,                                // float depthBiasClamp;
1478             0.0f,                                // float depthBiasSlopeFactor;
1479             1.0f,                                // float lineWidth;
1480         };
1481 
1482         const vk::VkSubpassDescription subpassDescription = {
1483             0,                                   // VkSubpassDescriptionFlags flags;
1484             vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1485             0u,                                  // uint32_t inputAttachmentCount;
1486             DE_NULL,                             // const VkAttachmentReference* pInputAttachments;
1487             0u,                                  // uint32_t colorAttachmentCount;
1488             DE_NULL,                             // const VkAttachmentReference* pColorAttachments;
1489             DE_NULL,                             // const VkAttachmentReference* pResolveAttachments;
1490             DE_NULL,                             // const VkAttachmentReference* pDepthStencilAttachment;
1491             0u,                                  // uint32_t preserveAttachmentCount;
1492             0u,                                  // const uint32_t* pPreserveAttachments;
1493         };
1494 
1495         const vk::VkRenderPassCreateInfo renderPassCreateInfo = {
1496             vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1497             DE_NULL,                                       // const void* pNext;
1498             0,                                             // VkRenderPassCreateFlags flags;
1499             0u,                                            // uint32_t attachmentCount;
1500             DE_NULL,                                       // const VkAttachmentDescription* pAttachments;
1501             1u,                                            // uint32_t subpassCount;
1502             &subpassDescription,                           // const VkSubpassDescription* pSubpasses;
1503             0u,                                            // uint32_t dependencyCount;
1504             DE_NULL,                                       // const VkSubpassDependency* pDependencies;
1505         };
1506         auto renderPass = vk::createRenderPass(vkdi, device, &renderPassCreateInfo);
1507 
1508         std::unique_ptr<vk::VkPipelineMultisampleStateCreateInfo> multisampleState;
1509         if (isFrag)
1510         {
1511             multisampleState.reset(new vk::VkPipelineMultisampleStateCreateInfo);
1512             *multisampleState = {
1513                 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1514                 DE_NULL,                                                      // const void* pNext;
1515                 0,                         // VkPipelineMultisampleStateCreateFlags flags;
1516                 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1517                 VK_FALSE,                  // VkBool32 sampleShadingEnable;
1518                 0.0f,                      // float minSampleShading;
1519                 DE_NULL,                   // const VkSampleMask* pSampleMask;
1520                 VK_FALSE,                  // VkBool32 alphaToCoverageEnable;
1521                 VK_FALSE,                  // VkBool32 alphaToOneEnable;
1522             };
1523         }
1524 
1525         const vk::VkViewport viewport = {
1526             0.0f, // float x;
1527             0.0f, // float y;
1528             1.0f, // float width;
1529             1.0f, // float height;
1530             0.0f, // float minDepth;
1531             1.0f, // float maxDepth;
1532         };
1533 
1534         const vk::VkRect2D renderArea = {{0u, 0u}, {1u, 1u}};
1535 
1536         std::unique_ptr<vk::VkPipelineViewportStateCreateInfo> viewportState;
1537 
1538         if (isFrag)
1539         {
1540             viewportState.reset(new vk::VkPipelineViewportStateCreateInfo);
1541             *viewportState = {
1542                 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1543                 DE_NULL,                                                   // const void* pNext;
1544                 0,                                                         // VkPipelineViewportStateCreateFlags flags;
1545                 1u,                                                        // uint32_t viewportCount;
1546                 &viewport,                                                 // const VkViewport* pViewports;
1547                 1u,                                                        // uint32_t scissorCount;
1548                 &renderArea,                                               // const VkRect2D* pScissors;
1549             };
1550         }
1551 
1552         const vk::VkGraphicsPipelineCreateInfo graphicsCreateInfo = {
1553             vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1554             DE_NULL,                                             // const void* pNext;
1555             0,                                                   // VkPipelineCreateFlags flags;
1556             static_cast<uint32_t>(shaderStages.size()),          // uint32_t stageCount;
1557             shaderStages.data(),                                 // const VkPipelineShaderStageCreateInfo* pStages;
1558             &vertexInputInfo,       // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1559             &inputAssembly,         // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1560             DE_NULL,                // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1561             viewportState.get(),    // const VkPipelineViewportStateCreateInfo* pViewportState;
1562             &rasterizationState,    // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
1563             multisampleState.get(), // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1564             DE_NULL,                // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1565             DE_NULL,                // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1566             DE_NULL,                // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1567             *pipelineLayout,        // VkPipelineLayout layout;
1568             *renderPass,            // VkRenderPass renderPass;
1569             0u,                     // uint32_t subpass;
1570             DE_NULL,                // VkPipeline basePipelineHandle;
1571             0u,                     // int32_t basePipelineIndex;
1572         };
1573         auto graphicsPipeline = vk::createGraphicsPipeline(vkdi, device, DE_NULL, &graphicsCreateInfo);
1574 
1575         const vk::VkFramebufferCreateInfo frameBufferCreateInfo = {
1576             vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1577             DE_NULL,                                       // const void* pNext;
1578             0,                                             // VkFramebufferCreateFlags flags;
1579             *renderPass,                                   // VkRenderPass renderPass;
1580             0u,                                            // uint32_t attachmentCount;
1581             DE_NULL,                                       // const VkImageView* pAttachments;
1582             1u,                                            // uint32_t width;
1583             1u,                                            // uint32_t height;
1584             1u,                                            // uint32_t layers;
1585         };
1586         auto frameBuffer = vk::createFramebuffer(vkdi, device, &frameBufferCreateInfo);
1587 
1588         const vk::VkRenderPassBeginInfo renderPassBeginInfo = {
1589             vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1590             DE_NULL,                                      // const void* pNext;
1591             *renderPass,                                  // VkRenderPass renderPass;
1592             *frameBuffer,                                 // VkFramebuffer framebuffer;
1593             renderArea,                                   // VkRect2D renderArea;
1594             0u,                                           // uint32_t clearValueCount;
1595             DE_NULL,                                      // const VkClearValue* pClearValues;
1596         };
1597 
1598         // Run the shader.
1599         vk::VkPipelineStageFlags pipelineStage =
1600             (isFrag ? vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT : vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
1601 
1602         vk::beginCommandBuffer(vkdi, *cmdBuffer);
1603         vkdi.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, pipelineStage, 0, 0u, DE_NULL,
1604                                 static_cast<uint32_t>(hostToDevBarriers.size()), hostToDevBarriers.data(), 0u, DE_NULL);
1605         vkdi.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
1606         vkdi.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1607         vkdi.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1u,
1608                                    &descriptorSet.get(), 0u, DE_NULL);
1609         vkdi.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1610         vkdi.cmdEndRenderPass(*cmdBuffer);
1611         vkdi.cmdPipelineBarrier(*cmdBuffer, pipelineStage, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0u, DE_NULL,
1612                                 static_cast<uint32_t>(devToHostBarriers.size()), devToHostBarriers.data(), 0u, DE_NULL);
1613         vk::endCommandBuffer(vkdi, *cmdBuffer);
1614         vk::submitCommandsAndWait(vkdi, device, m_context.getUniversalQueue(), *cmdBuffer);
1615     }
1616 
1617     // Invalidate allocations.
1618     vk::invalidateAlloc(vkdi, device, *input1.allocation);
1619     vk::invalidateAlloc(vkdi, device, *input2.allocation);
1620     vk::invalidateAlloc(vkdi, device, *output1.allocation);
1621 
1622     // Read and verify results.
1623     std::vector<int> results(m_numOperations);
1624     deMemcpy(results.data(), output1.allocation->getHostPtr(), m_outputBufferSize);
1625     for (size_t i = 0; i < m_numOperations; ++i)
1626     {
1627         int expected =
1628             static_cast<int>(m_params.operation.run(m_params.operands[i].first, m_params.operands[i].second));
1629         if (results[i] != expected && (m_params.requireNanPreserve || (!genericIsNan<T>(m_params.operands[i].first) &&
1630                                                                        !genericIsNan<T>(m_params.operands[i].second))))
1631         {
1632             std::ostringstream msg;
1633             msg << "Invalid result found in position " << i << ": expected " << expected << " and found " << results[i];
1634             return tcu::TestStatus::fail(msg.str());
1635         }
1636     }
1637 
1638     return tcu::TestStatus::pass("Pass");
1639 }
1640 
1641 template <class T>
1642 class T64bitCompareTest : public TestCase
1643 {
1644 public:
1645     T64bitCompareTest(tcu::TestContext &testCtx, const std::string &name, const TestParameters<T> &params);
1646     virtual void checkSupport(Context &context) const;
1647     virtual void initPrograms(vk::SourceCollections &programCollection) const;
1648     virtual TestInstance *createInstance(Context &ctx) const;
1649 
1650 private:
1651     const TestParameters<T> m_params;
1652 };
1653 
1654 template <class T>
T64bitCompareTest(tcu::TestContext & testCtx,const std::string & name,const TestParameters<T> & params)1655 T64bitCompareTest<T>::T64bitCompareTest(tcu::TestContext &testCtx, const std::string &name,
1656                                         const TestParameters<T> &params)
1657     : TestCase(testCtx, name)
1658     , m_params(params)
1659 {
1660     // This is needed so that the same operands can be used for single-element comparisons or for vectorized comparisons (which use *vec4 types).
1661     DE_ASSERT(m_params.operands.size() % 4 == 0);
1662 }
1663 
1664 // This template checks the needed type support features in shaders for type T.
1665 // Specializations are provided below.
1666 template <class T>
1667 void checkTypeSupport(const vk::VkPhysicalDeviceFeatures &features);
1668 
1669 template <>
checkTypeSupport(const vk::VkPhysicalDeviceFeatures & features)1670 void checkTypeSupport<double>(const vk::VkPhysicalDeviceFeatures &features)
1671 {
1672     if (!features.shaderFloat64)
1673         TCU_THROW(NotSupportedError, "64-bit floats not supported in shaders");
1674 }
1675 
check64bitIntegers(const vk::VkPhysicalDeviceFeatures & features)1676 void check64bitIntegers(const vk::VkPhysicalDeviceFeatures &features)
1677 {
1678     if (!features.shaderInt64)
1679         TCU_THROW(NotSupportedError, "64-bit integer types not supported in shaders");
1680 }
1681 
1682 template <>
checkTypeSupport(const vk::VkPhysicalDeviceFeatures & features)1683 void checkTypeSupport<int64_t>(const vk::VkPhysicalDeviceFeatures &features)
1684 {
1685     check64bitIntegers(features);
1686 }
1687 
1688 template <>
checkTypeSupport(const vk::VkPhysicalDeviceFeatures & features)1689 void checkTypeSupport<uint64_t>(const vk::VkPhysicalDeviceFeatures &features)
1690 {
1691     check64bitIntegers(features);
1692 }
1693 
1694 template <class T>
checkSupport(Context & context) const1695 void T64bitCompareTest<T>::checkSupport(Context &context) const
1696 {
1697     auto &vki           = context.getInstanceInterface();
1698     auto physicalDevice = context.getPhysicalDevice();
1699     auto features       = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
1700 
1701     checkTypeSupport<T>(features);
1702 
1703     switch (m_params.stage)
1704     {
1705     case vk::VK_SHADER_STAGE_COMPUTE_BIT:
1706         break;
1707     case vk::VK_SHADER_STAGE_VERTEX_BIT:
1708         if (!features.vertexPipelineStoresAndAtomics)
1709             TCU_THROW(NotSupportedError, "Vertex shader does not support stores");
1710         break;
1711     case vk::VK_SHADER_STAGE_FRAGMENT_BIT:
1712         if (!features.fragmentStoresAndAtomics)
1713             TCU_THROW(NotSupportedError, "Fragment shader does not support stores");
1714         break;
1715     default:
1716         DE_ASSERT(DE_NULL == "Invalid shader stage specified");
1717     }
1718 
1719     vk::VkPhysicalDeviceFloatControlsProperties fcFeatures;
1720     deMemset(&fcFeatures, 0, sizeof(fcFeatures));
1721     fcFeatures.shaderSignedZeroInfNanPreserveFloat64 = VK_TRUE;
1722 
1723     const char *unused;
1724     if (m_params.requireNanPreserve && !isFloatControlsFeaturesSupported(context, fcFeatures, &unused))
1725         TCU_THROW(NotSupportedError, "NaN preservation not supported");
1726 }
1727 
1728 template <class T>
initPrograms(vk::SourceCollections & programCollection) const1729 void T64bitCompareTest<T>::initPrograms(vk::SourceCollections &programCollection) const
1730 {
1731     DE_ASSERT(m_params.stage == vk::VK_SHADER_STAGE_COMPUTE_BIT || m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT ||
1732               m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1733 
1734     std::map<std::string, std::string> replacements;
1735     replacements["ITERS"] =
1736         de::toString((m_params.dataType == DATA_TYPE_SINGLE) ? m_params.operands.size() : m_params.operands.size() / 4);
1737     replacements["OPNAME"]       = m_params.operation.spirvName();
1738     replacements["OPCAPABILITY"] = SpirvTemplateManager::getOpCapability<T>();
1739     replacements["OPTYPE"]       = SpirvTemplateManager::getOpType<T>();
1740     replacements["NANCAP"]       = SpirvTemplateManager::getNanCapability(m_params.requireNanPreserve);
1741     replacements["NANEXT"]       = SpirvTemplateManager::getNanExtension(m_params.requireNanPreserve);
1742     replacements["NANMODE"]      = SpirvTemplateManager::getNanExeMode(m_params.requireNanPreserve);
1743 
1744     static const std::map<vk::VkShaderStageFlagBits, std::string> sourceNames = {
1745         std::make_pair(vk::VK_SHADER_STAGE_COMPUTE_BIT, "comp"),
1746         std::make_pair(vk::VK_SHADER_STAGE_VERTEX_BIT, "vert"),
1747         std::make_pair(vk::VK_SHADER_STAGE_FRAGMENT_BIT, "frag"),
1748     };
1749 
1750     // Add the proper template under the proper name.
1751     programCollection.spirvAsmSources.add(sourceNames.find(m_params.stage)->second)
1752         << SpirvTemplateManager::getTemplate(m_params.dataType, m_params.stage).specialize(replacements);
1753 
1754     // Add the passthrough vertex shader needed for the fragment shader.
1755     if (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
1756         programCollection.glslSources.add("vert") << glu::VertexSource(VertShaderPassThrough);
1757 }
1758 
1759 template <class T>
createInstance(Context & ctx) const1760 TestInstance *T64bitCompareTest<T>::createInstance(Context &ctx) const
1761 {
1762     return new T64bitCompareTestInstance<T>(ctx, m_params);
1763 }
1764 
1765 const std::map<bool, std::string> requireNanName = {
1766     std::make_pair(false, "nonan"),
1767     std::make_pair(true, "withnan"),
1768 };
1769 
1770 const std::map<DataType, std::string> dataTypeName = {
1771     std::make_pair(DATA_TYPE_SINGLE, "single"),
1772     std::make_pair(DATA_TYPE_VECTOR, "vector"),
1773 };
1774 
1775 using StageName = std::map<vk::VkShaderStageFlagBits, std::string>;
1776 
createDoubleCompareTestsInGroup(tcu::TestCaseGroup * tests,const StageName * stageNames)1777 void createDoubleCompareTestsInGroup(tcu::TestCaseGroup *tests, const StageName *stageNames)
1778 {
1779     static const std::vector<const CompareOperation<double> *> operationList = {
1780         // Ordered operations.
1781         &FOrderedEqualOp,
1782         &FOrderedNotEqualOp,
1783         &FOrderedLessThanOp,
1784         &FOrderedLessThanEqualOp,
1785         &FOrderedGreaterThanOp,
1786         &FOrderedGreaterThanEqualOp,
1787         // Unordered operations.
1788         &FUnorderedEqualOp,
1789         &FUnorderedNotEqualOp,
1790         &FUnorderedLessThanOp,
1791         &FUnorderedLessThanEqualOp,
1792         &FUnorderedGreaterThanOp,
1793         &FUnorderedGreaterThanEqualOp,
1794     };
1795 
1796     for (const auto &stageNamePair : *stageNames)
1797         for (const auto &typeNamePair : dataTypeName)
1798             for (const auto &requireNanPair : requireNanName)
1799                 for (const auto opPtr : operationList)
1800                 {
1801                     TestParameters<double> params = {typeNamePair.first, *opPtr, stageNamePair.first, DOUBLE_OPERANDS,
1802                                                      requireNanPair.first};
1803                     std::string testName          = stageNamePair.second + "_" + de::toLower(opPtr->spirvName()) + "_" +
1804                                            requireNanPair.second + "_" + typeNamePair.second;
1805                     tests->addChild(new T64bitCompareTest<double>(tests->getTestContext(), testName, params));
1806                 }
1807 }
1808 
createInt64CompareTestsInGroup(tcu::TestCaseGroup * tests,const StageName * stageNames)1809 void createInt64CompareTestsInGroup(tcu::TestCaseGroup *tests, const StageName *stageNames)
1810 {
1811     static const std::vector<const CompareOperation<int64_t> *> operationList = {
1812         &int64EqualOp,         &int64NotEqualOp,    &int64LessThanOp,
1813         &int64LessThanEqualOp, &int64GreaterThanOp, &int64GreaterThanEqualOp,
1814     };
1815 
1816     for (const auto &stageNamePair : *stageNames)
1817         for (const auto &typeNamePair : dataTypeName)
1818             for (const auto opPtr : operationList)
1819             {
1820                 TestParameters<int64_t> params = {typeNamePair.first, *opPtr, stageNamePair.first, INT64_OPERANDS,
1821                                                   false};
1822                 std::string testName =
1823                     stageNamePair.second + "_" + de::toLower(opPtr->spirvName()) + "_" + typeNamePair.second;
1824                 tests->addChild(new T64bitCompareTest<int64_t>(tests->getTestContext(), testName, params));
1825             }
1826 }
1827 
createUint64CompareTestsInGroup(tcu::TestCaseGroup * tests,const StageName * stageNames)1828 void createUint64CompareTestsInGroup(tcu::TestCaseGroup *tests, const StageName *stageNames)
1829 {
1830     static const std::vector<const CompareOperation<uint64_t> *> operationList = {
1831         &uint64EqualOp,         &uint64NotEqualOp,    &uint64LessThanOp,
1832         &uint64LessThanEqualOp, &uint64GreaterThanOp, &uint64GreaterThanEqualOp,
1833     };
1834 
1835     for (const auto &stageNamePair : *stageNames)
1836         for (const auto &typeNamePair : dataTypeName)
1837             for (const auto opPtr : operationList)
1838             {
1839                 TestParameters<uint64_t> params = {typeNamePair.first, *opPtr, stageNamePair.first, UINT64_OPERANDS,
1840                                                    false};
1841                 std::string testName =
1842                     stageNamePair.second + "_" + de::toLower(opPtr->spirvName()) + "_" + typeNamePair.second;
1843                 tests->addChild(new T64bitCompareTest<uint64_t>(tests->getTestContext(), testName, params));
1844             }
1845 }
1846 
1847 struct TestMgr
1848 {
1849     typedef void (*CreationFunctionPtr)(tcu::TestCaseGroup *, const StageName *);
1850 
getParentGroupNamevkt::SpirVAssembly::__anon071ae8e90111::TestMgr1851     static const char *getParentGroupName()
1852     {
1853         return "64bit_compare";
1854     }
getParentGroupDescvkt::SpirVAssembly::__anon071ae8e90111::TestMgr1855     static const char *getParentGroupDesc()
1856     {
1857         return "64-bit type comparison operations";
1858     }
1859 
1860     template <class T>
1861     static std::string getGroupName();
1862 
1863     template <class T>
1864     static CreationFunctionPtr getCreationFunction();
1865 };
1866 
1867 template <>
getGroupName()1868 std::string TestMgr::getGroupName<double>()
1869 {
1870     return "double";
1871 }
1872 template <>
getGroupName()1873 std::string TestMgr::getGroupName<int64_t>()
1874 {
1875     return "int64";
1876 }
1877 template <>
getGroupName()1878 std::string TestMgr::getGroupName<uint64_t>()
1879 {
1880     return "uint64";
1881 }
1882 
1883 template <>
getCreationFunction()1884 TestMgr::CreationFunctionPtr TestMgr::getCreationFunction<double>()
1885 {
1886     return createDoubleCompareTestsInGroup;
1887 }
1888 template <>
getCreationFunction()1889 TestMgr::CreationFunctionPtr TestMgr::getCreationFunction<int64_t>()
1890 {
1891     return createInt64CompareTestsInGroup;
1892 }
1893 template <>
getCreationFunction()1894 TestMgr::CreationFunctionPtr TestMgr::getCreationFunction<uint64_t>()
1895 {
1896     return createUint64CompareTestsInGroup;
1897 }
1898 
1899 } // namespace
1900 
create64bitCompareGraphicsGroup(tcu::TestContext & testCtx)1901 tcu::TestCaseGroup *create64bitCompareGraphicsGroup(tcu::TestContext &testCtx)
1902 {
1903     static const StageName graphicStages = {
1904         std::make_pair(vk::VK_SHADER_STAGE_VERTEX_BIT, "vert"),
1905         std::make_pair(vk::VK_SHADER_STAGE_FRAGMENT_BIT, "frag"),
1906     };
1907 
1908     tcu::TestCaseGroup *newGroup = new tcu::TestCaseGroup(testCtx, TestMgr::getParentGroupName());
1909     newGroup->addChild(createTestGroup(testCtx, TestMgr::getGroupName<double>(), TestMgr::getCreationFunction<double>(),
1910                                        &graphicStages));
1911     newGroup->addChild(createTestGroup(testCtx, TestMgr::getGroupName<int64_t>(),
1912                                        TestMgr::getCreationFunction<int64_t>(), &graphicStages));
1913     newGroup->addChild(createTestGroup(testCtx, TestMgr::getGroupName<uint64_t>(),
1914                                        TestMgr::getCreationFunction<uint64_t>(), &graphicStages));
1915     return newGroup;
1916 }
1917 
create64bitCompareComputeGroup(tcu::TestContext & testCtx)1918 tcu::TestCaseGroup *create64bitCompareComputeGroup(tcu::TestContext &testCtx)
1919 {
1920     static const StageName computeStages = {
1921         std::make_pair(vk::VK_SHADER_STAGE_COMPUTE_BIT, "comp"),
1922     };
1923 
1924     tcu::TestCaseGroup *newGroup = new tcu::TestCaseGroup(testCtx, TestMgr::getParentGroupName());
1925     newGroup->addChild(createTestGroup(testCtx, TestMgr::getGroupName<double>(), TestMgr::getCreationFunction<double>(),
1926                                        &computeStages));
1927     newGroup->addChild(createTestGroup(testCtx, TestMgr::getGroupName<int64_t>(),
1928                                        TestMgr::getCreationFunction<int64_t>(), &computeStages));
1929     newGroup->addChild(createTestGroup(testCtx, TestMgr::getGroupName<uint64_t>(),
1930                                        TestMgr::getCreationFunction<uint64_t>(), &computeStages));
1931     return newGroup;
1932 }
1933 
1934 } // namespace SpirVAssembly
1935 } // namespace vkt
1936