Refactor: Compatible compute and graphics VerifyIO
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmTypeTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief SPIR-V Assembly Tests for Integer Types
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmTypeTests.hpp"
25
26 #include "tcuRGBA.hpp"
27 #include "tcuStringTemplate.hpp"
28
29 #include "vkMemUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vktTestCase.hpp"
34
35 #include "deStringUtil.hpp"
36
37 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
38 #include "vktTestGroupUtil.hpp"
39 #include "spirv/unified1/spirv.h"
40 #include "spirv/unified1/GLSL.std.450.h"
41
42 #include <cmath>
43
44 #define TEST_DATASET_SIZE 10
45
46 #define UNDEFINED_SPIRV_TEST_TYPE "testtype"
47
48 namespace vkt
49 {
50 namespace SpirVAssembly
51 {
52
53 using namespace vk;
54 using tcu::RGBA;
55 using std::map;
56 using std::string;
57 using std::vector;
58 using tcu::StringTemplate;
59
60 enum InputRange
61 {
62         RANGE_FULL = 0,
63         RANGE_BIT_WIDTH,
64         RANGE_BIT_WIDTH_SUM,
65
66         RANGE_LAST
67 };
68
69 enum InputWidth
70 {
71         WIDTH_DEFAULT = 0,
72         WIDTH_16,
73         WIDTH_32,
74         WIDTH_64,
75         WIDTH_16_16,
76         WIDTH_16_32,
77         WIDTH_16_64,
78         WIDTH_32_16,
79         WIDTH_32_32,
80         WIDTH_32_64,
81         WIDTH_64_16,
82         WIDTH_64_32,
83         WIDTH_64_64,
84
85         WIDTH_LAST
86 };
87
88 enum InputType
89 {
90         TYPE_I16 = 0,
91         TYPE_U16,
92         TYPE_I32,
93         TYPE_U32,
94         TYPE_I64,
95         TYPE_U64,
96
97         TYPE_LAST
98 };
99
100 deUint32 getConstituentIndex (deUint32 ndx, deUint32 vectorSize)
101 {
102         DE_ASSERT(vectorSize != 0u);
103         return (ndx / vectorSize) / (1u + (ndx % vectorSize));
104 }
105
106 bool isScalarInput (deUint32 spirvOperation, deUint32 numInput)
107 {
108         switch (spirvOperation)
109         {
110                 case SpvOpBitFieldInsert:
111                         return (numInput > 1);
112                 case SpvOpBitFieldSExtract:
113                         return (numInput > 0);
114                 case SpvOpBitFieldUExtract:
115                         return (numInput > 0);
116                 default:
117                         return false;
118         }
119 }
120
121 bool isBooleanResultTest (deUint32 spirvOperation)
122 {
123         switch (spirvOperation)
124         {
125                 case SpvOpIEqual:
126                         return true;
127                 case SpvOpINotEqual:
128                         return true;
129                 case SpvOpUGreaterThan:
130                         return true;
131                 case SpvOpSGreaterThan:
132                         return true;
133                 case SpvOpUGreaterThanEqual:
134                         return true;
135                 case SpvOpSGreaterThanEqual:
136                         return true;
137                 case SpvOpULessThan:
138                         return true;
139                 case SpvOpSLessThan:
140                         return true;
141                 case SpvOpULessThanEqual:
142                         return true;
143                 case SpvOpSLessThanEqual:
144                         return true;
145                 default:
146                         return false;
147         }
148 }
149
150 bool isConstantOrVariableTest (deUint32 spirvOperation)
151 {
152         switch (spirvOperation)
153         {
154                 case SpvOpConstantNull:
155                         return true;
156                 case SpvOpConstant:
157                         return true;
158                 case SpvOpConstantComposite:
159                         return true;
160                 case SpvOpVariable:
161                         return true;
162                 case SpvOpSpecConstant:
163                         return true;
164                 case SpvOpSpecConstantComposite:
165                         return true;
166                 default:
167                         return false;
168         }
169 }
170
171 const char* getSpvOperationStr (deUint32 spirvOperation)
172 {
173         switch (spirvOperation)
174         {
175                 case SpvOpSNegate:
176                         return "OpSNegate";
177                 case SpvOpIAdd:
178                         return "OpIAdd";
179                 case SpvOpISub:
180                         return "OpISub";
181                 case SpvOpIMul:
182                         return "OpIMul";
183                 case SpvOpSDiv:
184                         return "OpSDiv";
185                 case SpvOpUDiv:
186                         return "OpUDiv";
187                 case SpvOpSRem:
188                         return "OpSRem";
189                 case SpvOpSMod:
190                         return "OpSMod";
191                 case SpvOpUMod:
192                         return "OpUMod";
193                 case SpvOpShiftRightLogical:
194                         return "OpShiftRightLogical";
195                 case SpvOpShiftRightArithmetic:
196                         return "OpShiftRightArithmetic";
197                 case SpvOpShiftLeftLogical:
198                         return "OpShiftLeftLogical";
199                 case SpvOpBitwiseOr:
200                         return "OpBitwiseOr";
201                 case SpvOpBitwiseXor:
202                         return "OpBitwiseXor";
203                 case SpvOpBitwiseAnd:
204                         return "OpBitwiseAnd";
205                 case SpvOpNot:
206                         return "OpNot";
207                 case SpvOpIEqual:
208                         return "OpIEqual";
209                 case SpvOpINotEqual:
210                         return "OpINotEqual";
211                 case SpvOpUGreaterThan:
212                         return "OpUGreaterThan";
213                 case SpvOpSGreaterThan:
214                         return "OpSGreaterThan";
215                 case SpvOpUGreaterThanEqual:
216                         return "OpUGreaterThanEqual";
217                 case SpvOpSGreaterThanEqual:
218                         return "OpSGreaterThanEqual";
219                 case SpvOpULessThan:
220                         return "OpULessThan";
221                 case SpvOpSLessThan:
222                         return "OpSLessThan";
223                 case SpvOpULessThanEqual:
224                         return "OpULessThanEqual";
225                 case SpvOpSLessThanEqual:
226                         return "OpSLessThanEqual";
227                 case SpvOpBitFieldInsert:
228                         return "OpBitFieldInsert";
229                 case SpvOpBitFieldSExtract:
230                         return "OpBitFieldSExtract";
231                 case SpvOpBitFieldUExtract:
232                         return "OpBitFieldUExtract";
233                 case SpvOpBitReverse:
234                         return "OpBitReverse";
235                 case SpvOpBitCount:
236                         return "OpBitCount";
237                 case SpvOpConstant:
238                         return "OpConstant";
239                 case SpvOpConstantComposite:
240                         return "OpConstantComposite";
241                 case SpvOpConstantNull:
242                         return "OpConstantNull";
243                 case SpvOpVariable:
244                         return "OpVariable";
245                 case SpvOpSpecConstant:
246                         return "OpSpecConstant";
247                 case SpvOpSpecConstantComposite:
248                         return "OpSpecConstantComposite";
249                 default:
250                         return "";
251         }
252 }
253
254 const char* getGLSLstd450OperationStr (deUint32 spirvOperation)
255 {
256         switch (spirvOperation)
257         {
258                 case GLSLstd450SAbs:
259                         return "SAbs";
260                 case GLSLstd450SSign:
261                         return "SSign";
262                 case GLSLstd450SMin:
263                         return "SMin";
264                 case GLSLstd450UMin:
265                         return "UMin";
266                 case GLSLstd450SMax:
267                         return "SMax";
268                 case GLSLstd450UMax:
269                         return "UMax";
270                 case GLSLstd450SClamp:
271                         return "SClamp";
272                 case GLSLstd450UClamp:
273                         return "UClamp";
274                 case GLSLstd450FindILsb:
275                         return "FindILsb";
276                 case GLSLstd450FindSMsb:
277                         return "FindSMsb";
278                 case GLSLstd450FindUMsb:
279                         return "FindUMsb";
280                 default:
281                         DE_FATAL("Not implemented");
282                         return "";
283         }
284 }
285
286 string getBooleanResultType (deUint32 vectorSize)
287 {
288         if (vectorSize > 1)
289                 return "v" + de::toString(vectorSize) + "bool";
290         else
291                 return "bool";
292 }
293
294 deUint32 getInputWidth (InputWidth inputWidth, deUint32 ndx)
295 {
296         switch (inputWidth)
297         {
298                 case WIDTH_16:
299                         DE_ASSERT(ndx < 1);
300                         return 16;
301                 case WIDTH_32:
302                         DE_ASSERT(ndx < 1);
303                         return 32;
304                 case WIDTH_64:
305                         DE_ASSERT(ndx < 1);
306                         return 64;
307                 case WIDTH_16_16:
308                         DE_ASSERT(ndx < 2);
309                         return 16;
310                 case WIDTH_16_32:
311                         DE_ASSERT(ndx < 2);
312                         return (ndx == 0) ? 16 : 32;
313                 case WIDTH_16_64:
314                         DE_ASSERT(ndx < 2);
315                         return (ndx == 0) ? 16 : 64;
316                 case WIDTH_32_16:
317                         DE_ASSERT(ndx < 2);
318                         return (ndx == 0) ? 32 : 16;
319                 case WIDTH_32_32:
320                         DE_ASSERT(ndx < 2);
321                         return 32;
322                 case WIDTH_32_64:
323                         DE_ASSERT(ndx < 2);
324                         return (ndx == 0) ? 32 : 64;
325                 case WIDTH_64_16:
326                         DE_ASSERT(ndx < 2);
327                         return (ndx == 0) ? 64 : 16;
328                 case WIDTH_64_32:
329                         DE_ASSERT(ndx < 2);
330                         return (ndx == 0) ? 64 : 32;
331                 case WIDTH_64_64:
332                         DE_ASSERT(ndx < 2);
333                         return 64;
334                 default:
335                         DE_FATAL("Not implemented");
336                         return 0;
337         }
338 }
339
340 bool has16BitInputWidth (InputWidth inputWidth)
341 {
342         switch (inputWidth)
343         {
344                 case WIDTH_16:
345                         return true;
346                 case WIDTH_32:
347                         return false;
348                 case WIDTH_64:
349                         return false;
350                 case WIDTH_16_16:
351                         return true;
352                 case WIDTH_16_32:
353                         return true;
354                 case WIDTH_16_64:
355                         return true;
356                 case WIDTH_32_16:
357                         return true;
358                 case WIDTH_32_32:
359                         return false;
360                 case WIDTH_32_64:
361                         return false;
362                 case WIDTH_64_16:
363                         return true;
364                 case WIDTH_64_32:
365                         return false;
366                 case WIDTH_64_64:
367                         return false;
368                 default:
369                         return false;
370         }
371 }
372
373 bool has64BitInputWidth (InputWidth inputWidth)
374 {
375         switch (inputWidth)
376         {
377                 case WIDTH_16:
378                         return false;
379                 case WIDTH_32:
380                         return false;
381                 case WIDTH_64:
382                         return true;
383                 case WIDTH_16_16:
384                         return false;
385                 case WIDTH_16_32:
386                         return false;
387                 case WIDTH_16_64:
388                         return true;
389                 case WIDTH_32_16:
390                         return false;
391                 case WIDTH_32_32:
392                         return false;
393                 case WIDTH_32_64:
394                         return true;
395                 case WIDTH_64_16:
396                         return true;
397                 case WIDTH_64_32:
398                         return true;
399                 case WIDTH_64_64:
400                         return true;
401                 default:
402                         return false;
403         }
404 }
405
406 InputType getInputType (deUint32 inputWidth, bool isSigned)
407 {
408         switch (inputWidth)
409         {
410                 case 16:
411                         return (isSigned) ? TYPE_I16 : TYPE_U16;
412                 case 32:
413                         return (isSigned) ? TYPE_I32 : TYPE_U32;
414                 case 64:
415                         return (isSigned) ? TYPE_I64 : TYPE_U64;
416                 default:
417                         DE_FATAL("Not possible");
418                         return TYPE_LAST;
419         }
420 }
421
422 string getOtherSizeTypes (InputType inputType, deUint32 vectorSize, InputWidth inputWidth)
423 {
424         const deUint32 inputWidthValues[] =
425         {
426                 16, 32, 64
427         };
428
429         for (deUint32 widthNdx = 0; widthNdx < 3; widthNdx++)
430         {
431                 const deUint32  typeWidth               = inputWidthValues[widthNdx];
432                 const InputType typeUnsigned    = getInputType(typeWidth, false);
433                 const InputType typeSigned              = getInputType(typeWidth, true);
434
435                 if ((inputType == typeUnsigned) || (inputType == typeSigned))
436                 {
437                         const bool              isSigned        = (inputType == typeSigned);
438                         const string    signPrefix      = (isSigned) ? "i" : "u";
439                         const string    signBit         = (isSigned) ? "1" : "0";
440
441                         string                  str                     = "";
442
443                         if (has16BitInputWidth(inputWidth) && typeWidth != 16)
444                         {
445                                 // 16-bit scalar type
446                                 str += "%" + signPrefix + "16 = OpTypeInt 16 " + signBit + "\n";
447
448                                 // 16-bit vector type
449                                 if (vectorSize > 1)
450                                         str += "%v" + de::toString(vectorSize) + signPrefix + "16 = OpTypeVector %" + signPrefix + "16 " + de::toString(vectorSize) + "\n";
451                         }
452
453                         if (has64BitInputWidth(inputWidth) && typeWidth != 64)
454                         {
455                                 // 64-bit scalar type
456                                 str += "%" + signPrefix + "64 = OpTypeInt 64 " + signBit + "\n";
457
458                                 // 64-bit vector type
459                                 if (vectorSize > 1)
460                                         str += "%v" + de::toString(vectorSize) + signPrefix + "64 = OpTypeVector %" + signPrefix + "64 " + de::toString(vectorSize) + "\n";
461                         }
462
463                         return str;
464                 }
465         }
466
467         DE_FATAL("Not possible");
468         return "";
469 }
470
471 string getSpirvCapabilityStr (const char* spirvCapability, InputWidth inputWidth)
472 {
473         string str = "";
474
475         if (spirvCapability)
476         {
477                 if (has16BitInputWidth(inputWidth) || deStringEqual("Int16", spirvCapability))
478                         str += "OpCapability Int16\n";
479
480                 if (has64BitInputWidth(inputWidth) || deStringEqual("Int64", spirvCapability))
481                         str += "OpCapability Int64\n";
482         }
483         else
484         {
485                 if (has16BitInputWidth(inputWidth))
486                         str += "OpCapability Int16\n";
487
488                 if (has64BitInputWidth(inputWidth))
489                         str += "OpCapability Int64\n";
490         }
491
492         return str;
493 }
494
495 string getBinaryFullOperationWithInputWidthStr (string resultName, string spirvOperation, InputType inputType, string spirvTestType, deUint32 vectorSize, InputWidth inputWidth)
496 {
497         const deUint32 inputWidthValues[] =
498         {
499                 16, 32, 64
500         };
501
502         for (deUint32 widthNdx = 0; widthNdx < 3; widthNdx++)
503         {
504                 const deUint32  typeWidth               = inputWidthValues[widthNdx];
505                 const InputType typeUnsigned    = getInputType(typeWidth, false);
506                 const InputType typeSigned              = getInputType(typeWidth, true);
507
508                 if ((inputType == typeUnsigned) || (inputType == typeSigned))
509                 {
510                         const bool              isSigned                = (inputType == typeSigned);
511                         const string    signPrefix              = (isSigned) ? "i" : "u";
512                         const string    typePrefix              = (vectorSize == 1) ? "%" : "%v" + de::toString(vectorSize);
513                         const deUint32  input1Width             = getInputWidth(inputWidth, 0);
514
515                         const string    inputTypeStr    = (input1Width == typeWidth) ? "%testtype"
516                                                                                         : typePrefix + signPrefix + de::toString(input1Width);
517
518                         string str = "";
519
520                         // Create intermediate value with different width
521                         if (input1Width != typeWidth)
522                                 str += "%input1_val_" + de::toString(input1Width) + " = OpSConvert " + inputTypeStr + " %input1_val\n";
523
524                         // Input with potentially different width
525                         const string input1Str = "%input1_val" + ((input1Width != typeWidth) ? "_" + de::toString(input1Width) : "");
526
527                         str += resultName + " = " + spirvOperation + " %" + spirvTestType + " %input0_val " + input1Str + "\n";
528
529                         return str;
530                 }
531         }
532
533         DE_FATAL("Not possible");
534         return "";
535 }
536
537 string getFullOperationWithDifferentInputWidthStr (string resultName, string spirvOperation, InputType inputType, string spirvTestType, InputWidth inputWidth, bool isQuaternary)
538 {
539         const bool              isSigned        = (inputType == TYPE_I32);
540         const string    inputType16     = (isSigned) ? "i16" : "u16";
541         const string    inputType64     = (isSigned) ? "i64" : "u64";
542
543         const deUint32  offsetWidth     = getInputWidth(inputWidth, 0);
544         const deUint32  countWidth      = getInputWidth(inputWidth, 1);
545
546         const string    offsetNdx       = (isQuaternary) ? "2" : "1";
547         const string    countNdx        = (isQuaternary) ? "3" : "2";
548
549         string str = "";
550
551         // Create intermediate values with different width
552         if (offsetWidth != 32)
553                 str += "%input" + offsetNdx + "_val_" + de::toString(offsetWidth) + " = OpSConvert %" + ((offsetWidth == 16) ? inputType16 : inputType64) + " %input" + offsetNdx + "_val\n";
554         if (countWidth != 32)
555                 str += "%input" + countNdx + "_val_" + de::toString(countWidth) + " = OpSConvert %" + ((countWidth == 16) ? inputType16 : inputType64) + " %input" + countNdx + "_val\n";
556
557         // Inputs with potentially different width
558         const string offsetStr  = "%input" + offsetNdx + "_val" + ((offsetWidth != 32) ? "_" + de::toString(offsetWidth) : "");
559         const string countStr   = "%input" + countNdx + "_val" + ((countWidth != 32) ? "_" + de::toString(countWidth) : "");
560
561         if (isQuaternary)
562                 str += resultName + " = " + spirvOperation + " %" + spirvTestType + " %input0_val %input1_val " + offsetStr + " " + countStr +"\n";
563         else
564                 str += resultName + " = " + spirvOperation + " %" + spirvTestType + " %input0_val " + offsetStr + " " + countStr +"\n";
565
566         return str;
567 }
568
569 template <class T>
570 class SpvAsmTypeTests : public tcu::TestCaseGroup
571 {
572 public:
573         typedef T               (*OpUnaryFuncType)                      (T);
574         typedef T               (*OpBinaryFuncType)                     (T, T);
575         typedef T               (*OpTernaryFuncType)            (T, T, T);
576         typedef T               (*OpQuaternaryFuncType)         (T, T, T, T);
577         typedef bool    (*UnaryFilterFuncType)          (T);
578         typedef bool    (*BinaryFilterFuncType)         (T, T);
579         typedef bool    (*TernaryFilterFuncType)        (T, T, T);
580         typedef bool    (*QuaternaryFilterFuncType)     (T, T, T, T);
581                                         SpvAsmTypeTests                         (tcu::TestContext&                      testCtx,
582                                                                                                  const char*                            name,
583                                                                                                  const char*                            description,
584                                                                                                  const char*                            deviceFeature,
585                                                                                                  const char*                            spirvCapability,
586                                                                                                  const char*                            spirvType,
587                                                                                                  InputType                                      inputType,
588                                                                                                  deUint32                                       typeSize,
589                                                                                                  deUint32                                       vectorSize);
590                                         ~SpvAsmTypeTests                        (void);
591         void                    createTests                                     (const char*                            testName,
592                                                                                                  deUint32                                       spirvOperation,
593                                                                                                  OpUnaryFuncType                        op,
594                                                                                                  UnaryFilterFuncType            filter,
595                                                                                                  InputRange                                     inputRange,
596                                                                                                  InputWidth                                     inputWidth,
597                                                                                                  const char*                            spirvExtension,
598                                                                                                  const bool                                     returnHighPart  = false);
599         void                    createTests                                     (const char*                            testName,
600                                                                                                  deUint32                                       spirvOperation,
601                                                                                                  OpBinaryFuncType                       op,
602                                                                                                  BinaryFilterFuncType           filter,
603                                                                                                  InputRange                                     inputRange,
604                                                                                                  InputWidth                                     inputWidth,
605                                                                                                  const char*                            spirvExtension,
606                                                                                                  const bool                                     returnHighPart  = false);
607         void                    createTests                                     (const char*                            testName,
608                                                                                                  deUint32                                       spirvOperation,
609                                                                                                  OpTernaryFuncType                      op,
610                                                                                                  TernaryFilterFuncType          filter,
611                                                                                                  InputRange                                     inputRange,
612                                                                                                  InputWidth                                     inputWidth,
613                                                                                                  const char*                            spirvExtension,
614                                                                                                  const bool                                     returnHighPart  = false);
615         void                    createTests                                     (const char*                            testName,
616                                                                                                  deUint32                                       spirvOperation,
617                                                                                                  OpQuaternaryFuncType           op,
618                                                                                                  QuaternaryFilterFuncType       filter,
619                                                                                                  InputRange                                     inputRange,
620                                                                                                  InputWidth                                     inputWidth,
621                                                                                                  const char*                            spirvExtension,
622                                                                                                  const bool                                     returnHighPart  = false);
623         void                    createSwitchTests                       (void);
624         void                    getConstantDataset                      (vector<T>                                      inputDataset,
625                                                                                                  vector<T>&                                     outputDataset,
626                                                                                                  deUint32                                       spirvOperation);
627         virtual void    getDataset                                      (vector<T>& input,                      deUint32 numElements) = 0;
628         virtual void    pushResource                            (vector<Resource>&                      resource,
629                                                                                                  vector<T>&                                     data) = 0;
630
631         static bool             filterNone                                      (T a);
632         static bool             filterNone                                      (T a, T b);
633         static bool             filterNone                                      (T a, T b, T c);
634         static bool             filterNone                                      (T a, T b, T c, T d);
635         static bool             filterZero                                      (T a, T b);
636         static bool             filterNegativesAndZero          (T a, T b);
637         static bool             filterMinGtMax                          (T, T a, T b);
638
639         static T                zero                                            (T);
640         static T                zero                                            (T, T);
641         static T                zero                                            (T, T, T);
642         static T                zero                                            (T, T, T, T);
643
644         static string   replicate                                       (const std::string&                     replicant,
645                                                                                                  const deUint32                         count);
646
647 protected:
648         de::Random      m_rnd;
649         T                       m_cases[3];
650
651 private:
652         std::string     createInputDecoration                   (deUint32                                               numInput);
653         std::string     createInputPreMain                              (deUint32                                               numInput,
654                                                                                                  deUint32                                               spirvOpertaion);
655         std::string     createConstantDeclaration               (vector<T>&                                             dataset,
656                                                                                                  deUint32                                               spirvOperation);
657         std::string     createInputTestfun                              (deUint32                                               numInput,
658                                                                                                  deUint32                                               spirvOpertaion);
659         deUint32        combine                                                 (GraphicsResources&                             resources,
660                                                                                                  vector<T>&                                             data,
661                                                                                                  OpUnaryFuncType                                operation,
662                                                                                                  UnaryFilterFuncType                    filter,
663                                                                                                  InputRange                                             inputRange);
664         deUint32        combine                                                 (GraphicsResources&                             resources,
665                                                                                                  vector<T>&                                             data,
666                                                                                                  OpBinaryFuncType                               operation,
667                                                                                                  BinaryFilterFuncType                   filter,
668                                                                                                  InputRange                                             inputRange);
669         deUint32        combine                                                 (GraphicsResources&                             resources,
670                                                                                                  vector<T>&                                             data,
671                                                                                                  OpTernaryFuncType                              operation,
672                                                                                                  TernaryFilterFuncType                  filter,
673                                                                                                  InputRange                                             inputRange);
674         deUint32        combine                                                 (GraphicsResources&                             resources,
675                                                                                                  vector<T>&                                             data,
676                                                                                                  OpQuaternaryFuncType                   operation,
677                                                                                                  QuaternaryFilterFuncType               filter,
678                                                                                                  InputRange                                             inputRange);
679         deUint32        fillResources                                   (GraphicsResources&                             resources,
680                                                                                                  vector<T>&                                             data);
681         void            createStageTests                                (const char*                                    testName,
682                                                                                                  GraphicsResources&                             resources,
683                                                                                                  deUint32                                               numElements,
684                                                                                                  vector<string>&                                decorations,
685                                                                                                  vector<string>&                                pre_mains,
686                                                                                                  vector<string>&                                testfuns,
687                                                                                                  string&                                                operation,
688                                                                                                  InputWidth                                             inputWidth,
689                                                                                                  const char*                                    funVariables,
690                                                                                                  const char*                                    spirvExtension  = DE_NULL);
691         void            finalizeFullOperation                   (string&                                                fullOperation,
692                                                                                                  const string&                                  resultName,
693                                                                                                  const bool                                             returnHighPart,
694                                                                                                  const bool                                             isBooleanResult);
695
696         static bool     verifyResult                                    (const vector<Resource>&                inputs,
697                                                                                                  const vector<AllocationSp>&    outputAllocations,
698                                                                                                  const vector<Resource>&                expectedOutputs,
699                                                                                                  deUint32                                               skip,
700                                                                                                  tcu::TestLog&                                  log);
701         static bool     verifyDefaultResult                             (const vector<Resource>&                inputs,
702                                                                                                  const vector<AllocationSp>&    outputAllocations,
703                                                                                                  const vector<Resource>&                expectedOutputs,
704                                                                                                  tcu::TestLog&                                  log);
705         static bool     verifyVec3Result                                (const vector<Resource>&                inputs,
706                                                                                                  const vector<AllocationSp>&    outputAllocations,
707                                                                                                  const vector<Resource>&                expectedOutputs,
708                                                                                                  tcu::TestLog&                                  log);
709         const char* const       m_deviceFeature;
710         const char* const       m_spirvCapability;
711         const char* const       m_spirvType;
712         InputType                       m_inputType;
713         deUint32                        m_typeSize;
714         deUint32                        m_vectorSize;
715         std::string                     m_spirvTestType;
716 };
717
718 template <class T>
719 SpvAsmTypeTests<T>::SpvAsmTypeTests     (tcu::TestContext&      testCtx,
720                                                                          const char*            name,
721                                                                          const char*            description,
722                                                                          const char*            deviceFeature,
723                                                                          const char*            spirvCapability,
724                                                                          const char*            spirvType,
725                                                                          InputType                      inputType,
726                                                                          deUint32                       typeSize,
727                                                                          deUint32                       vectorSize)
728         : tcu::TestCaseGroup    (testCtx, name, description)
729         , m_rnd                                 (deStringHash(name))
730         , m_deviceFeature               (deviceFeature)
731         , m_spirvCapability             (spirvCapability)
732         , m_spirvType                   (spirvType)
733         , m_inputType                   (inputType)
734         , m_typeSize                    (typeSize)
735         , m_vectorSize                  (vectorSize)
736 {
737         std::string scalarType;
738
739         DE_ASSERT(vectorSize >= 1 && vectorSize <= 4);
740
741         if (m_inputType == TYPE_I32)
742                 scalarType = "i32";
743         else if (m_inputType == TYPE_U32)
744                 scalarType = "u32";
745         else
746                 scalarType = "";
747
748         if (scalarType.empty())
749         {
750                 m_spirvTestType = UNDEFINED_SPIRV_TEST_TYPE;
751         }
752         else
753         {
754                 if (m_vectorSize > 1)
755                         m_spirvTestType = "v" + numberToString(m_vectorSize) + scalarType;
756                 else
757                         m_spirvTestType = scalarType;
758         }
759 }
760
761 template <class T>
762 SpvAsmTypeTests<T>::~SpvAsmTypeTests    (void)
763 {
764 }
765
766 template <class T>
767 std::string SpvAsmTypeTests<T>::createInputDecoration (deUint32 numInput)
768 {
769         const StringTemplate    decoration      ("OpDecorate %input${n_input} DescriptorSet 0\n"
770                                                                                  "OpDecorate %input${n_input} Binding ${n_input}\n");
771         map<string, string>             specs;
772
773         specs["n_input"] = numberToString(numInput);
774
775         return decoration.specialize(specs);
776 }
777
778 template <class T>
779 std::string SpvAsmTypeTests<T>::createInputPreMain (deUint32 numInput, deUint32 spirvOpertaion)
780 {
781         const bool                              scalarInput = (m_vectorSize != 1) && isScalarInput(spirvOpertaion, numInput);
782         const string                    bufferType      = (scalarInput) ? "%scalarbufptr" : "%bufptr";
783
784         return "%input" + numberToString(numInput) + " = OpVariable " + bufferType + " Uniform\n";
785 }
786
787 template <class T>
788 std::string SpvAsmTypeTests<T>::createInputTestfun (deUint32 numInput, deUint32 spirvOpertaion)
789 {
790         const bool                              scalarInput     = (m_vectorSize != 1) && isScalarInput(spirvOpertaion, numInput);
791         const string                    pointerType     = (scalarInput) ? "%up_scalartype" : "%up_testtype";
792         const string                    valueType       = (scalarInput) ? "%u32" : "%${testtype}";
793
794         const StringTemplate    testfun         ("%input${n_input}_loc = OpAccessChain " + pointerType + " %input${n_input} "
795                                                                                  "%c_i32_0 %counter_val\n"
796                                                                                  "%input${n_input}_val = OpLoad " + valueType + " %input${n_input}_loc\n");
797         map<string, string>             specs;
798
799         specs["n_input"] = numberToString(numInput);
800         specs["testtype"] = m_spirvTestType;
801
802         return testfun.specialize(specs);
803 }
804
805 template <class T>
806 deUint32 SpvAsmTypeTests<T>::combine (GraphicsResources&        resources,
807                                                                           vector<T>&                    data,
808                                                                           OpUnaryFuncType               operation,
809                                                                           UnaryFilterFuncType   filter,
810                                                                           InputRange                    inputRange)
811 {
812         DE_UNREF(inputRange);
813         const deUint32  datasize                = static_cast<deUint32>(data.size());
814         const deUint32  sizeWithPadding = (m_vectorSize == 3) ? 4 : m_vectorSize;
815         const deUint32  totalPadding    = (m_vectorSize == 3) ? (datasize / m_vectorSize) : 0;
816         const deUint32  total                   = datasize + totalPadding;
817         deUint32                padCount                = m_vectorSize;
818         deUint32                outputsSize;
819         vector<T>               inputs;
820         vector<T>               outputs;
821
822         inputs.reserve(total);
823         outputs.reserve(total);
824
825         /* According to spec, a three-component vector, with components of size N,
826            has a base alignment of 4 N */
827         for (deUint32 elemNdx = 0; elemNdx < datasize; ++elemNdx)
828         {
829                 if (filter(data[elemNdx]))
830                 {
831                         inputs.push_back(data[elemNdx]);
832                         outputs.push_back(operation(data[elemNdx]));
833                         if (m_vectorSize == 3)
834                         {
835                                 padCount--;
836                                 if (padCount == 0)
837                                 {
838                                         inputs.push_back(0);
839                                         outputs.push_back(0);
840                                         padCount = m_vectorSize;
841                                 }
842                         }
843                 }
844         }
845
846         outputsSize = static_cast<deUint32>(outputs.size());
847
848         /* Ensure we have pushed a multiple of vector size, including padding if
849            required */
850         while (outputsSize % sizeWithPadding != 0)
851         {
852                 inputs.pop_back();
853                 outputs.pop_back();
854                 outputsSize--;
855         }
856
857         pushResource(resources.inputs, inputs);
858         pushResource(resources.outputs, outputs);
859
860         return outputsSize / sizeWithPadding;
861 }
862
863 template <class T>
864 deUint32 SpvAsmTypeTests<T>::combine (GraphicsResources&        resources,
865                                                                           vector<T>&                    data,
866                                                                           OpBinaryFuncType              operation,
867                                                                           BinaryFilterFuncType  filter,
868                                                                           InputRange                    inputRange)
869 {
870         const deUint32  datasize                = static_cast<deUint32>(data.size());
871         const deUint32  sizeWithPadding = (m_vectorSize == 3) ? 4 : m_vectorSize;
872         const deUint32  totalData               = datasize * datasize;
873         const deUint32  totalPadding    = (m_vectorSize == 3) ? (totalData / m_vectorSize) : 0;
874         const deUint32  total                   = totalData + totalPadding;
875         deUint32                padCount                = m_vectorSize;
876         deUint32                outputsSize;
877         vector<T>               inputs0;
878         vector<T>               inputs1;
879         vector<T>               outputs;
880
881         inputs0.reserve(total);
882         inputs1.reserve(total);
883         outputs.reserve(total);
884
885         /* According to spec, a three-component vector, with components of size N,
886            has a base alignment of 4 N */
887         for (deUint32 elemNdx1 = 0; elemNdx1 < datasize; ++elemNdx1)
888         for (deUint32 elemNdx2 = 0; elemNdx2 < datasize; ++elemNdx2)
889         {
890                 if (filter(data[elemNdx1], data[elemNdx2]))
891                 {
892                         switch (inputRange)
893                         {
894                                 case RANGE_FULL:
895                                 {
896                                         inputs0.push_back(data[elemNdx1]);
897                                         inputs1.push_back(data[elemNdx2]);
898                                         outputs.push_back(operation(data[elemNdx1], data[elemNdx2]));
899                                         break;
900                                 }
901                                 case RANGE_BIT_WIDTH:
902                                 {
903                                         // Make sure shift count doesn't exceed the bit width
904                                         const T shift = data[elemNdx2] & static_cast<T>(m_typeSize - 1u);
905                                         inputs0.push_back(data[elemNdx1]);
906                                         inputs1.push_back(shift);
907                                         outputs.push_back(operation(data[elemNdx1], shift));
908                                         break;
909                                 }
910                                 default:
911                                         DE_FATAL("Not implemented");
912                         }
913
914                         if (m_vectorSize == 3)
915                         {
916                                 padCount--;
917                                 if (padCount == 0)
918                                 {
919                                         inputs0.push_back(0);
920                                         inputs1.push_back(0);
921                                         outputs.push_back(0);
922                                         padCount = m_vectorSize;
923                                 }
924                         }
925                 }
926         }
927
928         outputsSize = static_cast<deUint32>(outputs.size());
929
930         /* Ensure we have pushed a multiple of vector size, including padding if
931            required */
932         while (outputsSize % sizeWithPadding != 0)
933         {
934                 inputs0.pop_back();
935                 inputs1.pop_back();
936                 outputs.pop_back();
937                 outputsSize--;
938         }
939
940         pushResource(resources.inputs, inputs0);
941         pushResource(resources.inputs, inputs1);
942         pushResource(resources.outputs, outputs);
943
944         return outputsSize / sizeWithPadding;
945 }
946
947 template <class T>
948 deUint32 SpvAsmTypeTests<T>::combine (GraphicsResources&        resources,
949                                                                           vector<T>&                    data,
950                                                                           OpTernaryFuncType             operation,
951                                                                           TernaryFilterFuncType filter,
952                                                                           InputRange                    inputRange)
953 {
954         const deUint32  datasize                = static_cast<deUint32>(data.size());
955         const deUint32  sizeWithPadding = (m_vectorSize == 3) ? 4 : m_vectorSize;
956         const deUint32  totalData               = datasize * datasize * datasize;
957         const deUint32  totalPadding    = (m_vectorSize == 3) ? (totalData / m_vectorSize) : 0;
958         const deUint32  total                   = totalData + totalPadding;
959         deUint32                padCount                = m_vectorSize;
960         deUint32                outputsSize;
961         vector<T>               inputs0;
962         vector<T>               inputs1;
963         vector<T>               inputs2;
964         vector<T>               outputs;
965
966         inputs0.reserve(total);
967         inputs1.reserve(total);
968         inputs2.reserve(total);
969         outputs.reserve(total);
970
971         // Reduce the amount of input data in tests without filtering
972         deUint32                datasize2               = (inputRange == RANGE_BIT_WIDTH_SUM) ? 4u * m_vectorSize : datasize;
973         T                               bitOffset               = static_cast<T>(0);
974         T                               bitCount                = static_cast<T>(0);
975
976         /* According to spec, a three-component vector, with components of size N,
977            has a base alignment of 4 N */
978         for (deUint32 elemNdx1 = 0; elemNdx1 < datasize; ++elemNdx1)
979         for (deUint32 elemNdx2 = 0; elemNdx2 < datasize2; ++elemNdx2)
980         for (deUint32 elemNdx3 = 0; elemNdx3 < datasize2; ++elemNdx3)
981         {
982                 if (filter(data[elemNdx1], data[elemNdx2], data[elemNdx3]))
983                 {
984                         switch (inputRange)
985                         {
986                                 case RANGE_FULL:
987                                 {
988                                         inputs0.push_back(data[elemNdx1]);
989                                         inputs1.push_back(data[elemNdx2]);
990                                         inputs2.push_back(data[elemNdx3]);
991                                         outputs.push_back(operation(data[elemNdx1], data[elemNdx2], data[elemNdx3]));
992                                         break;
993                                 }
994                                 case RANGE_BIT_WIDTH_SUM:
995                                 {
996                                         if (elemNdx3 % m_vectorSize == 0)
997                                         {
998                                                 bitOffset       = static_cast<T>(m_rnd.getUint32() & (m_typeSize - 1u));
999                                                 bitCount        = static_cast<T>(m_rnd.getUint32() & (m_typeSize - 1u));
1000                                         }
1001
1002                                         // Make sure the sum of offset and count doesn't exceed bit width
1003                                         if ((deUint32)(bitOffset + bitCount) > m_typeSize)
1004                                                 bitCount = static_cast<T>(m_typeSize - bitOffset);
1005
1006                                         inputs0.push_back(data[elemNdx1]);
1007                                         inputs1.push_back(bitOffset);
1008                                         inputs2.push_back(bitCount);
1009                                         outputs.push_back(operation(data[elemNdx1], bitOffset, bitCount));
1010                                         break;
1011                                 }
1012                                 default:
1013                                         DE_FATAL("Not implemented");
1014                         }
1015                         if (m_vectorSize == 3)
1016                         {
1017                                 padCount--;
1018                                 if (padCount == 0)
1019                                 {
1020                                         inputs0.push_back(0);
1021                                         inputs1.push_back(0);
1022                                         inputs2.push_back(0);
1023                                         outputs.push_back(0);
1024                                         padCount = m_vectorSize;
1025                                 }
1026                         }
1027                 }
1028         }
1029         outputsSize = static_cast<deUint32>(outputs.size());
1030
1031         /* Ensure we have pushed a multiple of vector size, including padding if
1032            required */
1033         while (outputsSize % sizeWithPadding != 0)
1034         {
1035                 inputs0.pop_back();
1036                 inputs1.pop_back();
1037                 inputs2.pop_back();
1038                 outputs.pop_back();
1039                 outputsSize--;
1040         }
1041
1042         pushResource(resources.inputs, inputs0);
1043         pushResource(resources.inputs, inputs1);
1044         pushResource(resources.inputs, inputs2);
1045         pushResource(resources.outputs, outputs);
1046
1047         return outputsSize / sizeWithPadding;
1048 }
1049
1050 template <class T>
1051 deUint32 SpvAsmTypeTests<T>::combine (GraphicsResources&                resources,
1052                                                                           vector<T>&                            data,
1053                                                                           OpQuaternaryFuncType          operation,
1054                                                                           QuaternaryFilterFuncType      filter,
1055                                                                           InputRange                            inputRange)
1056 {
1057         const deUint32  datasize                = static_cast<deUint32>(data.size());
1058         const deUint32  sizeWithPadding = (m_vectorSize == 3) ? 4 : m_vectorSize;
1059         const deUint32  totalData               = datasize * datasize;
1060         const deUint32  totalPadding    = (m_vectorSize == 3) ? (totalData / m_vectorSize) : 0;
1061         const deUint32  total                   = totalData + totalPadding;
1062         deUint32                padCount                = m_vectorSize;
1063         deUint32                outputsSize;
1064         vector<T>               inputs0;
1065         vector<T>               inputs1;
1066         vector<T>               inputs2;
1067         vector<T>               inputs3;
1068         vector<T>               outputs;
1069
1070         inputs0.reserve(total);
1071         inputs1.reserve(total);
1072         inputs2.reserve(total);
1073         inputs3.reserve(total);
1074         outputs.reserve(total);
1075
1076         // Reduce the amount of input data in tests without filtering
1077         deUint32                datasize2               = (inputRange == RANGE_BIT_WIDTH_SUM) ? 2u * m_vectorSize : datasize;
1078         T                               bitOffset               = static_cast<T>(0);
1079         T                               bitCount                = static_cast<T>(0);
1080
1081         /* According to spec, a three-component vector, with components of size N,
1082            has a base alignment of 4 N */
1083         for (deUint32 elemNdx1 = 0; elemNdx1 < datasize; ++elemNdx1)
1084         for (deUint32 elemNdx2 = 0; elemNdx2 < datasize2; ++elemNdx2)
1085         for (deUint32 elemNdx3 = 0; elemNdx3 < datasize2; ++elemNdx3)
1086         for (deUint32 elemNdx4 = 0; elemNdx4 < datasize2; ++elemNdx4)
1087         {
1088                 if (filter(data[elemNdx1], data[elemNdx2], data[elemNdx3], data[elemNdx4]))
1089                 {
1090                         switch (inputRange)
1091                         {
1092                                 case RANGE_FULL:
1093                                 {
1094                                         inputs0.push_back(data[elemNdx1]);
1095                                         inputs1.push_back(data[elemNdx2]);
1096                                         inputs2.push_back(data[elemNdx3]);
1097                                         inputs3.push_back(data[elemNdx3]);
1098                                         outputs.push_back(operation(data[elemNdx1], data[elemNdx2], data[elemNdx3], data[elemNdx4]));
1099                                         break;
1100                                 }
1101                                 case RANGE_BIT_WIDTH_SUM:
1102                                 {
1103                                         if (elemNdx4 % m_vectorSize == 0)
1104                                         {
1105                                                 bitOffset       = static_cast<T>(m_rnd.getUint32() & (m_typeSize - 1u));
1106                                                 bitCount        = static_cast<T>(m_rnd.getUint32() & (m_typeSize - 1u));
1107                                         }
1108
1109                                         // Make sure the sum of offset and count doesn't exceed bit width
1110                                         if ((deUint32)(bitOffset + bitCount) > m_typeSize)
1111                                                 bitCount -= bitOffset + bitCount - static_cast<T>(m_typeSize);
1112
1113                                         inputs0.push_back(data[elemNdx1]);
1114                                         inputs1.push_back(data[elemNdx2]);
1115                                         inputs2.push_back(bitOffset);
1116                                         inputs3.push_back(bitCount);
1117                                         outputs.push_back(operation(data[elemNdx1], data[elemNdx2], bitOffset, bitCount));
1118                                         break;
1119                                 }
1120                                 default:
1121                                         DE_FATAL("Not implemented");
1122                         }
1123                         if (m_vectorSize == 3)
1124                         {
1125                                 padCount--;
1126                                 if (padCount == 0)
1127                                 {
1128                                         inputs0.push_back(0);
1129                                         inputs1.push_back(0);
1130                                         inputs2.push_back(0);
1131                                         inputs3.push_back(0);
1132                                         outputs.push_back(0);
1133                                         padCount = m_vectorSize;
1134                                 }
1135                         }
1136                 }
1137         }
1138
1139         outputsSize = static_cast<deUint32>(outputs.size());
1140
1141         /* Ensure we have pushed a multiple of vector size, including padding if
1142            required */
1143         while (outputsSize % sizeWithPadding != 0)
1144         {
1145                 inputs0.pop_back();
1146                 inputs1.pop_back();
1147                 inputs2.pop_back();
1148                 inputs3.pop_back();
1149                 outputs.pop_back();
1150                 outputsSize--;
1151         }
1152
1153         pushResource(resources.inputs, inputs0);
1154         pushResource(resources.inputs, inputs1);
1155         pushResource(resources.inputs, inputs2);
1156         pushResource(resources.inputs, inputs3);
1157         pushResource(resources.outputs, outputs);
1158
1159         return outputsSize / sizeWithPadding;
1160 }
1161
1162 template <class T>
1163 deUint32 SpvAsmTypeTests<T>::fillResources (GraphicsResources&  resources,
1164                                                                                         vector<T>&                      data)
1165 {
1166         vector<T>       outputs;
1167
1168         outputs.reserve(data.size());
1169
1170         for (deUint32 elemNdx = 0; elemNdx < data.size(); ++elemNdx)
1171         {
1172                 if (data[elemNdx] == m_cases[0])
1173                         outputs.push_back(1000);
1174                 else if (data[elemNdx] == m_cases[1])
1175                         outputs.push_back(1100);
1176                 else if (data[elemNdx] == m_cases[2])
1177                         outputs.push_back(1200);
1178                 else
1179                         outputs.push_back(10);
1180         }
1181
1182         pushResource(resources.inputs, data);
1183         pushResource(resources.inputs, outputs);
1184
1185         return static_cast<deUint32>(outputs.size());
1186 }
1187
1188 template <class T>
1189 void SpvAsmTypeTests<T>::createStageTests (const char*                  testName,
1190                                                                                    GraphicsResources&   resources,
1191                                                                                    deUint32                             numElements,
1192                                                                                    vector<string>&              decorations,
1193                                                                                    vector<string>&              pre_mains,
1194                                                                                    vector<string>&              testfuns,
1195                                                                                    string&                              operation,
1196                                                                                    InputWidth                   inputWidth,
1197                                                                                    const char*                  funVariables,
1198                                                                                    const char*                  spirvExtension)
1199 {
1200         const StringTemplate            decoration              ("OpDecorate %output DescriptorSet 0\n"
1201                                                                                                  "OpDecorate %output Binding ${output_binding}\n"
1202                                                                                                  "OpDecorate %a${num_elements}testtype ArrayStride ${typesize}\n"
1203                                                                                                  "OpDecorate %buf BufferBlock\n"
1204                                                                                                  "OpMemberDecorate %buf 0 Offset 0\n");
1205
1206         const StringTemplate            vecDecoration   ("OpDecorate %a${num_elements}scalartype ArrayStride ${typesize}\n"
1207                                                                                                  "OpDecorate %scalarbuf BufferBlock\n"
1208                                                                                                  "OpMemberDecorate %scalarbuf 0 Offset 0\n");
1209
1210         const StringTemplate            pre_pre_main    ("%c_u32_${num_elements} = OpConstant %u32 ${num_elements}\n"
1211                                                                                                  "%c_i32_${num_elements} = OpConstant %i32 ${num_elements}\n");
1212
1213         const StringTemplate            scalar_pre_main ("%testtype = ${scalartype}\n");
1214
1215         const StringTemplate            vector_pre_main ("%scalartype = ${scalartype}\n"
1216                                                                                                  "%testtype = OpTypeVector %scalartype ${vector_size}\n");
1217
1218         const StringTemplate            pre_main_consts ("%c_shift  = OpConstant %u32 16\n"
1219                                                                                                  "${constant_zero}\n"
1220                                                                                                  "${constant_one}\n");
1221
1222         const StringTemplate            pre_main_constv ("%c_shift1 = OpConstant %u32 16\n"
1223                                                                                                  "%c_shift  = OpConstantComposite %v${vector_size}u32 ${shift_initializers}\n"
1224                                                                                                  "${bvec}\n"
1225                                                                                                  "${constant_zero}\n"
1226                                                                                                  "${constant_one}\n"
1227                                                                                                  "%a${num_elements}scalartype = OpTypeArray %u32 %c_u32_${num_elements}\n"
1228                                                                                                  "%up_scalartype = OpTypePointer Uniform %u32\n"
1229                                                                                                  "%scalarbuf = OpTypeStruct %a${num_elements}scalartype\n"
1230                                                                                                  "%scalarbufptr = OpTypePointer Uniform %scalarbuf\n");
1231
1232         const StringTemplate            post_pre_main   ("%a${num_elements}testtype = OpTypeArray %${testtype} "
1233                                                                                                  "%c_u32_${num_elements}\n"
1234                                                                                                  "%up_testtype = OpTypePointer Uniform %${testtype}\n"
1235                                                                                                  "%buf = OpTypeStruct %a${num_elements}testtype\n"
1236                                                                                                  "%bufptr = OpTypePointer Uniform %buf\n"
1237                                                                                                  "%output = OpVariable %bufptr Uniform\n"
1238                                                                                                  "${other_size_types}\n"
1239                                                                                                  "${u32_function_pointer}\n");
1240
1241         const StringTemplate            pre_testfun             ("%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1242                                                                                                  "%param = OpFunctionParameter %v4f32\n"
1243                                                                                                  "%entry = OpLabel\n"
1244                                                                                                  "%op_constant = OpVariable %fp_${testtype} Function\n"
1245                                                                                                  + string(funVariables) +
1246                                                                                                  "%counter = OpVariable %fp_i32 Function\n"
1247                                                                                                  "OpStore %counter %c_i32_0\n"
1248                                                                                                  "OpBranch %loop\n"
1249
1250                                                                                                  "%loop = OpLabel\n"
1251                                                                                                  "%counter_val = OpLoad %i32 %counter\n"
1252                                                                                                  "%lt = OpSLessThan %bool %counter_val %c_i32_${num_elements}\n"
1253                                                                                                  "OpLoopMerge %exit %inc None\n"
1254                                                                                                  "OpBranchConditional %lt %write %exit\n"
1255
1256                                                                                                  "%write = OpLabel\n"
1257                                                                                                  "%output_loc = OpAccessChain %up_testtype %output %c_i32_0 "
1258                                                                                                  "%counter_val\n");
1259
1260         const StringTemplate            post_testfun    ("OpStore %output_loc %op_result\n"
1261                                                                                                  "OpBranch %inc\n"
1262
1263                                                                                                  "%inc = OpLabel\n"
1264                                                                                                  "%counter_val_next = OpIAdd %i32 %counter_val %c_i32_1\n"
1265                                                                                                  "OpStore %counter %counter_val_next\n"
1266                                                                                                  "OpBranch %loop\n"
1267
1268                                                                                                  "%exit = OpLabel\n"
1269                                                                                                  "OpReturnValue %param\n"
1270
1271                                                                                                  "OpFunctionEnd\n");
1272
1273         std::vector<std::string>        noExtensions;
1274         std::vector<std::string>        features;
1275         RGBA                                            defaultColors[4];
1276         map<string, string>                     fragments;
1277         map<string, string>                     specs;
1278         VulkanFeatures                          requiredFeatures;
1279
1280         getDefaultColors(defaultColors);
1281
1282         if (m_vectorSize == 3)
1283                 resources.verifyIO = verifyVec3Result;
1284         else
1285                 resources.verifyIO = verifyDefaultResult;
1286
1287         // All of the following tests write their results into an output SSBO, therefore they require the following features.
1288         requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
1289         requiredFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
1290
1291         if (m_deviceFeature)
1292                 features.insert(features.begin(), m_deviceFeature);
1293
1294         if (inputWidth != WIDTH_DEFAULT)
1295         {
1296                 if (has16BitInputWidth(inputWidth))
1297                         features.insert(features.begin(), "shaderInt16");
1298                 if (has64BitInputWidth(inputWidth))
1299                         features.insert(features.begin(), "shaderInt64");
1300         }
1301
1302         const string                            vectorSizeStr   = numberToString(m_vectorSize);
1303
1304         specs["testtype"]                               = m_spirvTestType;
1305         specs["scalartype"]                             = m_spirvType;
1306         specs["typesize"]                               = numberToString(((m_vectorSize == 3) ? 4 : m_vectorSize) * m_typeSize / 8);
1307         specs["vector_size"]                    = vectorSizeStr;
1308         specs["num_elements"]                   = numberToString(numElements);
1309         specs["output_binding"]                 = numberToString(resources.inputs.size());
1310         specs["shift_initializers"]             = replicate(" %c_shift1", m_vectorSize);
1311
1312         specs["bvec"]                                   = (m_vectorSize == 1 || m_vectorSize == 4) ? ("")
1313                                                                         : ("%v" + vectorSizeStr + "bool = OpTypeVector %bool " + vectorSizeStr);
1314
1315         specs["constant_zero"]                  = (m_vectorSize == 1)
1316                                                                         ? ("%c_zero = OpConstant %u32 0\n")
1317                                                                         : ("%c_zero = OpConstantComposite %v" + vectorSizeStr + "u32" + replicate(" %c_u32_0", m_vectorSize));
1318
1319         specs["constant_one"]                   = (m_vectorSize == 1)
1320                                                                         ? ("%c_one = OpConstant %u32 1\n")
1321                                                                         : ("%c_one = OpConstantComposite %v" + vectorSizeStr + "u32" + replicate(" %c_u32_1", m_vectorSize));
1322
1323         specs["other_size_types"]               = (inputWidth == WIDTH_DEFAULT) ? ("")
1324                                                                         : getOtherSizeTypes(m_inputType, m_vectorSize, inputWidth);
1325
1326         specs["u32_function_pointer"]   = deStringEqual(m_spirvTestType.c_str(), "i32") ? ("")
1327                                                                         : ("%fp_" + m_spirvTestType + " = OpTypePointer Function %" + m_spirvTestType + "\n");
1328
1329         if (spirvExtension)
1330                 fragments["extension"] = "%ext1 = OpExtInstImport \"" + string(spirvExtension) + "\"";
1331
1332         for (deUint32 elemNdx = 0; elemNdx < decorations.size(); ++elemNdx)
1333                 fragments["decoration"] += decorations[elemNdx];
1334         fragments["decoration"] += decoration.specialize(specs);
1335
1336         if (m_vectorSize > 1)
1337                 fragments["decoration"] += vecDecoration.specialize(specs);
1338
1339         fragments["pre_main"] = pre_pre_main.specialize(specs);
1340         if (specs["testtype"].compare(UNDEFINED_SPIRV_TEST_TYPE) == 0)
1341         {
1342                 if (m_vectorSize > 1)
1343                         fragments["pre_main"] += vector_pre_main.specialize(specs);
1344                 else
1345                         fragments["pre_main"] += scalar_pre_main.specialize(specs);
1346         }
1347
1348         if (m_vectorSize > 1)
1349                 fragments["pre_main"] += pre_main_constv.specialize(specs);
1350         else
1351                 fragments["pre_main"] += pre_main_consts.specialize(specs);
1352
1353         fragments["pre_main"] += post_pre_main.specialize(specs);
1354         for (deUint32 elemNdx = 0; elemNdx < pre_mains.size(); ++elemNdx)
1355                 fragments["pre_main"] += pre_mains[elemNdx];
1356
1357         fragments["testfun"] = pre_testfun.specialize(specs);
1358         for (deUint32 elemNdx = 0; elemNdx < testfuns.size(); ++elemNdx)
1359                 fragments["testfun"] += testfuns[elemNdx];
1360         fragments["testfun"] += operation + post_testfun.specialize(specs);
1361
1362         fragments["capability"] = getSpirvCapabilityStr(m_spirvCapability, inputWidth);
1363
1364         createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, noExtensions, features, this, requiredFeatures);
1365 }
1366
1367 template <class T>
1368 bool SpvAsmTypeTests<T>::verifyResult (const vector<Resource>&          inputs,
1369                                                                            const vector<AllocationSp>&  outputAllocations,
1370                                                                            const vector<Resource>&              expectedOutputs,
1371                                                                            deUint32                                             skip,
1372                                                                            tcu::TestLog&                                log)
1373 {
1374         DE_ASSERT(outputAllocations.size() == 1);
1375         DE_ASSERT(inputs.size() > 0 && inputs.size() < 5);
1376
1377         const T*                input[4]                = { DE_NULL };
1378         vector<deUint8> inputBytes[4];
1379         vector<deUint8> expectedBytes;
1380
1381         expectedOutputs[0].getBytes(expectedBytes);
1382         const deUint32 count    = static_cast<deUint32>(expectedBytes.size() / sizeof(T));
1383         const T* obtained               = static_cast<const T *>(outputAllocations[0]->getHostPtr());
1384         const T* expected               = reinterpret_cast<const T*>(&expectedBytes.front());
1385
1386         for (deUint32 ndxCount = 0; ndxCount < inputs.size(); ndxCount++)
1387         {
1388                 inputs[ndxCount].getBytes(inputBytes[ndxCount]);
1389                 input[ndxCount] = reinterpret_cast<const T*>(&inputBytes[ndxCount].front());
1390         }
1391
1392         for (deUint32 ndxCount = 0 ; ndxCount < count; ++ndxCount)
1393         {
1394                 /* Skip padding */
1395                 if (((ndxCount + 1) % skip) == 0)
1396                         continue;
1397
1398                 if (obtained[ndxCount] != expected[ndxCount])
1399                 {
1400                         std::stringstream inputStream;
1401                         inputStream << "(";
1402                         for (deUint32 ndxIndex = 0 ; ndxIndex < inputs.size(); ++ndxIndex)
1403                         {
1404                                 inputStream << input[ndxIndex][ndxCount];
1405                                 if (ndxIndex < inputs.size() - 1)
1406                                         inputStream << ",";
1407                         }
1408                         inputStream << ")";
1409                         log << tcu::TestLog::Message
1410                                 << "Error: found unexpected result for inputs " << inputStream.str()
1411                                 << ": expected " << expected[ndxCount] << ", obtained "
1412                                 << obtained[ndxCount] << tcu::TestLog::EndMessage;
1413                         return false;
1414                 }
1415         }
1416
1417         return true;
1418 }
1419
1420 template <class T>
1421 bool SpvAsmTypeTests<T>::verifyDefaultResult (const vector<Resource>&           inputs,
1422                                                                                           const vector<AllocationSp>&   outputAllocations,
1423                                                                                           const vector<Resource>&               expectedOutputs,
1424                                                                                           tcu::TestLog&                                 log)
1425 {
1426         return verifyResult(inputs, outputAllocations, expectedOutputs, ~0, log);
1427 }
1428
1429 template <class T>
1430 bool SpvAsmTypeTests<T>::verifyVec3Result (const vector<Resource>&              inputs,
1431                                                                                    const vector<AllocationSp>&  outputAllocations,
1432                                                                                    const vector<Resource>&              expectedOutputs,
1433                                                                                    tcu::TestLog&                                log)
1434 {
1435         return verifyResult(inputs, outputAllocations, expectedOutputs, 4, log);
1436 }
1437
1438 template <class T>
1439 string SpvAsmTypeTests<T>::createConstantDeclaration (vector<T>& dataset, deUint32 spirvOperation)
1440 {
1441         const bool              isVariableTest                          = (SpvOpVariable == spirvOperation);
1442         const bool              isConstantNullTest                      = (SpvOpConstantNull == spirvOperation) || isVariableTest;
1443         const bool              isConstantCompositeTest         = (SpvOpConstantComposite == spirvOperation) || (isConstantNullTest && m_vectorSize > 1);
1444         const bool              isConstantTest                          = (SpvOpConstant == spirvOperation) || isConstantCompositeTest || isConstantNullTest;
1445         const bool              isSpecConstantTest                      = (SpvOpSpecConstant == spirvOperation);
1446         const bool              isSpecConstantCompositeTest     = (SpvOpSpecConstantComposite == spirvOperation);
1447
1448         const string    testScalarType                          = (m_inputType == TYPE_I32) ? "i32"
1449                                                                                                 : (m_inputType == TYPE_U32) ? "u32"
1450                                                                                                 : "scalartype";
1451         const string    constantType                            = (m_vectorSize > 1) ? testScalarType : m_spirvTestType;
1452         const string    constantName                            = (m_vectorSize > 1) ? "%c_constituent_" : "%c_testtype_";
1453
1454         string                  str                                                     = "";
1455
1456         // Declare scalar specialization constants
1457         if (isSpecConstantTest)
1458         {
1459                 for (size_t constantNdx = 0u; constantNdx < dataset.size(); constantNdx++)
1460                         str += constantName + de::toString(constantNdx) + " = OpSpecConstant %" + constantType + " " + de::toString(dataset[constantNdx]) + "\n";
1461         }
1462
1463         // Declare specialization constant composites
1464         if (isSpecConstantCompositeTest)
1465         {
1466                 // Constituents are a mix of OpConstantNull, OpConstants and OpSpecializationConstants
1467                 for (size_t constantNdx = 0u; constantNdx < dataset.size(); constantNdx++)
1468                 {
1469                         const char* constantOp[] =
1470                         {
1471                                 "OpConstant",
1472                                 "OpSpecConstant"
1473                         };
1474
1475                         if (constantNdx == 0u)
1476                                 str += constantName + de::toString(constantNdx) + " = OpConstantNull %" + constantType + "\n";
1477                         else
1478                                 str += constantName + de::toString(constantNdx) + " = " + constantOp[constantNdx % 2] + " %" + constantType + " " + de::toString(dataset[constantNdx]) + "\n";
1479                 }
1480
1481                 for (deUint32 compositeNdx = 0u; compositeNdx < (deUint32)dataset.size(); compositeNdx++)
1482                 {
1483                         str += "%c_testtype_" + de::toString(compositeNdx) + " = OpSpecConstantComposite %" + m_spirvTestType;
1484
1485                         for (deUint32 componentNdx = 0u; componentNdx < m_vectorSize; componentNdx++)
1486                                 str += " %c_constituent_" + de::toString(getConstituentIndex(compositeNdx * m_vectorSize + componentNdx, m_vectorSize));
1487
1488                         str += "\n";
1489                 }
1490         }
1491
1492         // Declare scalar constants
1493         if (isConstantTest || isVariableTest)
1494         {
1495                 for (size_t constantNdx = 0u; constantNdx < dataset.size(); constantNdx++)
1496                 {
1497                         if (isConstantNullTest && constantNdx == 0u)
1498                                 str += constantName + de::toString(constantNdx) + " = OpConstantNull %" + constantType + "\n";
1499                         else
1500                                 str += constantName + de::toString(constantNdx) + " = OpConstant %" + constantType + " " + de::toString(dataset[constantNdx]) + "\n";
1501                 }
1502         }
1503
1504         // Declare constant composites
1505         if (isConstantCompositeTest)
1506         {
1507                 for (deUint32 compositeNdx = 0u; compositeNdx < (deUint32)dataset.size(); compositeNdx++)
1508                 {
1509                         str += "%c_testtype_" + de::toString(compositeNdx) + " = OpConstantComposite %" + m_spirvTestType;
1510
1511                         for (deUint32 componentNdx = 0u; componentNdx < m_vectorSize; componentNdx++)
1512                                 str += " %c_constituent_" + de::toString(getConstituentIndex(compositeNdx * m_vectorSize + componentNdx, m_vectorSize));
1513
1514                         str += "\n";
1515                 }
1516         }
1517
1518         return str;
1519 }
1520
1521 template <class T>
1522 string getVariableStr (vector<T>& dataset, const char* spirvType, deUint32 spirvOperation)
1523 {
1524         const bool              isVariableTest = (SpvOpVariable == spirvOperation);
1525         string                  str = "";
1526
1527         // Declare variables with initializers
1528         if (isVariableTest)
1529                 for (size_t i = 0u; i < dataset.size(); i++)
1530                         str += "%testvariable_" + de::toString(i) + " = OpVariable %fp_" + spirvType + " Function %c_testtype_" + de::toString(i) + "\n";
1531
1532         return str;
1533 }
1534
1535 template <class T>
1536 void SpvAsmTypeTests<T>::createTests (const char*                       testName,
1537                                                                           deUint32                              spirvOperation,
1538                                                                           OpUnaryFuncType               operation,
1539                                                                           UnaryFilterFuncType   filter,
1540                                                                           InputRange                    inputRange,
1541                                                                           InputWidth                    inputWidth,
1542                                                                           const char*                   spirvExtension,
1543                                                                           const bool                    returnHighPart)
1544 {
1545         DE_ASSERT(!isBooleanResultTest(spirvOperation));
1546
1547         const string            resultName      = returnHighPart ? "%op_result_pre" : "%op_result";
1548         OpUnaryFuncType         zeroFunc        = &zero;
1549         vector<T>                       dataset;
1550         vector<string>          decorations;
1551         vector<string>          pre_mains;
1552         vector<string>          testfuns;
1553         GraphicsResources       resources;
1554         map<string, string>     fragments;
1555         map<string, string>     specs;
1556
1557         if (isConstantOrVariableTest(spirvOperation))
1558         {
1559                 DE_ASSERT(!spirvExtension);
1560
1561                 const deUint32          inputSize               = TEST_DATASET_SIZE;
1562                 const deUint32          outputSize              = TEST_DATASET_SIZE * m_vectorSize;
1563                 vector<T>                       inputDataset;
1564
1565                 inputDataset.reserve(inputSize);
1566                 dataset.reserve(outputSize);
1567
1568                 getDataset(inputDataset, inputSize);
1569                 getConstantDataset(inputDataset, dataset, spirvOperation);
1570
1571                 const deUint32          totalElements   = combine(resources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1572
1573                 pre_mains.reserve(1);
1574                 pre_mains.push_back(createConstantDeclaration(inputDataset, spirvOperation));
1575
1576                 string                          fullOperation   = "OpBranch %switchStart\n"
1577                                                                                           "%switchStart = OpLabel\n"
1578                                                                                           "OpSelectionMerge %switchEnd None\n"
1579                                                                                           "OpSwitch %counter_val %caseDefault";
1580
1581                 for (deUint32 caseNdx = 0u; caseNdx < inputSize; caseNdx++)
1582                         fullOperation += " " + de::toString(caseNdx) + " " + "%case" + de::toString(caseNdx);
1583
1584                 fullOperation += "\n";
1585
1586                 const string            funVariables    = getVariableStr(inputDataset, m_spirvTestType.c_str(), spirvOperation);
1587
1588                 if (SpvOpVariable == spirvOperation)
1589                 {
1590                         for (deUint32 caseNdx = 0u; caseNdx < inputSize; caseNdx++)
1591                                 fullOperation +=        "%case" + de::toString(caseNdx) + " = OpLabel\n"
1592                                                                         "%temp_" + de::toString(caseNdx) + " = OpLoad %" + m_spirvTestType + " %testvariable_" + de::toString(caseNdx) + "\n"
1593                                                                         "OpStore %op_constant %temp_" + de::toString(caseNdx) + "\n"
1594                                                                         "OpBranch %switchEnd\n";
1595                 }
1596                 else
1597                 {
1598                         for (deUint32 caseNdx = 0u; caseNdx < inputSize; caseNdx++)
1599                                 fullOperation +=        "%case" + de::toString(caseNdx) + " = OpLabel\n"
1600                                                                         "OpStore %op_constant %c_testtype_" + de::toString(caseNdx) + "\n"
1601                                                                         "OpBranch %switchEnd\n";
1602                 }
1603
1604                 fullOperation +=        "%caseDefault = OpLabel\n"
1605                                                         "OpBranch %switchEnd\n"
1606                                                         "%switchEnd = OpLabel\n"
1607                                                         + resultName + " = OpLoad %" + m_spirvTestType + " %op_constant\n";
1608
1609
1610                 finalizeFullOperation(fullOperation, resultName, returnHighPart, false);
1611
1612                 createStageTests(testName, resources, totalElements, decorations,
1613                                                  pre_mains, testfuns, fullOperation, inputWidth, funVariables.c_str(), spirvExtension);
1614         }
1615         else
1616         {
1617                 dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
1618                 getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
1619                 const deUint32  totalElements   = combine(resources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1620
1621                 decorations.reserve(1);
1622                 pre_mains.reserve(1);
1623                 testfuns.reserve(1);
1624
1625                 decorations.push_back(createInputDecoration(0));
1626                 pre_mains.push_back(createInputPreMain(0, spirvOperation));
1627                 testfuns.push_back(createInputTestfun(0, spirvOperation));
1628
1629                 string                  full_operation  (spirvExtension ? resultName + " = OpExtInst %" + m_spirvTestType + " %ext1 " + getGLSLstd450OperationStr(spirvOperation) + " %input0_val\n"
1630                                                                                 : resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + m_spirvTestType + " %input0_val\n");
1631
1632                 finalizeFullOperation(full_operation, resultName, returnHighPart, false);
1633
1634                 createStageTests(testName, resources, totalElements, decorations,
1635                                                  pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
1636         }
1637 }
1638
1639 template <class T>
1640 void SpvAsmTypeTests<T>::createTests (const char*                       testName,
1641                                                                           deUint32                              spirvOperation,
1642                                                                           OpBinaryFuncType              operation,
1643                                                                           BinaryFilterFuncType  filter,
1644                                                                           InputRange                    inputRange,
1645                                                                           InputWidth                    inputWidth,
1646                                                                           const char*                   spirvExtension,
1647                                                                           const bool                    returnHighPart)
1648 {
1649         const bool                      isBoolean               = isBooleanResultTest(spirvOperation);
1650         const string            resultName              = (returnHighPart || isBoolean) ? "%op_result_pre" : "%op_result";
1651         const string            resultType              = isBoolean ? getBooleanResultType(m_vectorSize) : m_spirvTestType;
1652         OpBinaryFuncType        zeroFunc                = &zero;
1653         vector<T>                       dataset;
1654         vector<string>          decorations;
1655         vector<string>          pre_mains;
1656         vector<string>          testfuns;
1657         GraphicsResources       resources;
1658         map<string, string>     fragments;
1659         map<string, string>     specs;
1660         string                          full_operation;
1661
1662         dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
1663         getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
1664         const deUint32          totalElements   = combine(resources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1665
1666         decorations.reserve(2);
1667         pre_mains.reserve(2);
1668         testfuns.reserve(2);
1669
1670         for (deUint32 elemNdx = 0; elemNdx < 2; ++elemNdx)
1671         {
1672                 decorations.push_back(createInputDecoration(elemNdx));
1673                 pre_mains.push_back(createInputPreMain(elemNdx, spirvOperation));
1674                 testfuns.push_back(createInputTestfun(elemNdx, spirvOperation));
1675         }
1676
1677         if (spirvOperation != DE_NULL)
1678         {
1679                 if (inputWidth == WIDTH_DEFAULT)
1680                         full_operation = spirvExtension ? resultName + " = OpExtInst %" + resultType + " %ext1 " + getGLSLstd450OperationStr(spirvOperation) + " %input0_val %input1_val\n"
1681                                                                                         : resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + resultType + " %input0_val %input1_val\n";
1682                 else
1683                         full_operation = getBinaryFullOperationWithInputWidthStr(resultName, getSpvOperationStr(spirvOperation), m_inputType, m_spirvTestType, m_vectorSize, inputWidth);
1684         }
1685         else
1686         {
1687                 if (deStringBeginsWith(testName, "mul_sdiv"))
1688                 {
1689                         DE_ASSERT(spirvExtension == DE_NULL);
1690                         full_operation = "%op_result2 = OpIMul %" + m_spirvTestType + " %input0_val %input1_val\n";
1691                         full_operation += resultName + " = OpSDiv %" + m_spirvTestType + " %op_result2 %input1_val\n";
1692                 }
1693                 if (deStringBeginsWith(testName, "mul_udiv"))
1694                 {
1695                         DE_ASSERT(spirvExtension == DE_NULL);
1696                         full_operation = "%op_result2 = OpIMul %" + m_spirvTestType + " %input0_val %input1_val\n";
1697                         full_operation += resultName + " = OpUDiv %" + m_spirvTestType + " %op_result2 %input1_val\n";
1698                 }
1699         }
1700
1701         finalizeFullOperation(full_operation, resultName, returnHighPart, isBoolean);
1702
1703         createStageTests(testName, resources, totalElements, decorations,
1704                                          pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
1705 }
1706
1707 template <class T>
1708 void SpvAsmTypeTests<T>::createTests (const char*                       testName,
1709                                                                           deUint32                              spirvOperation,
1710                                                                           OpTernaryFuncType             operation,
1711                                                                           TernaryFilterFuncType filter,
1712                                                                           InputRange                    inputRange,
1713                                                                           InputWidth                    inputWidth,
1714                                                                           const char*                   spirvExtension,
1715                                                                           const bool                    returnHighPart)
1716 {
1717         DE_ASSERT(!isBooleanResultTest(spirvOperation));
1718
1719         const string            resultName              = returnHighPart ? "%op_result_pre" : "%op_result";
1720         OpTernaryFuncType       zeroFunc                = &zero;
1721         vector<T>                       dataset;
1722         vector<string>          decorations;
1723         vector<string>          pre_mains;
1724         vector<string>          testfuns;
1725         GraphicsResources       resources;
1726         map<string, string>     fragments;
1727         map<string, string>     specs;
1728
1729         dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
1730         getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
1731         const deUint32          totalElements   = combine(resources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1732
1733         decorations.reserve(3);
1734         pre_mains.reserve(3);
1735         testfuns.reserve(3);
1736
1737         for (deUint32 elemNdx = 0; elemNdx < 3; ++elemNdx)
1738         {
1739                 decorations.push_back(createInputDecoration(elemNdx));
1740                 pre_mains.push_back(createInputPreMain(elemNdx, spirvOperation));
1741                 testfuns.push_back(createInputTestfun(elemNdx, spirvOperation));
1742         }
1743
1744         string                          full_operation  = "";
1745
1746         if (inputWidth == WIDTH_DEFAULT)
1747                 full_operation = (spirvExtension ? resultName + " = OpExtInst %" + m_spirvTestType + " %ext1 " + getGLSLstd450OperationStr(spirvOperation) + " %input0_val %input1_val %input2_val\n"
1748                                                                                  : resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + m_spirvTestType + " %input0_val %input1_val %input2_val\n");
1749         else
1750                 full_operation = getFullOperationWithDifferentInputWidthStr(resultName, getSpvOperationStr(spirvOperation), m_inputType, m_spirvTestType, inputWidth, false);
1751
1752         finalizeFullOperation(full_operation, resultName, returnHighPart, false);
1753
1754         createStageTests(testName, resources, totalElements, decorations,
1755                                          pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
1756 }
1757
1758 template <class T>
1759 void SpvAsmTypeTests<T>::createTests (const char*                               testName,
1760                                                                           deUint32                                      spirvOperation,
1761                                                                           OpQuaternaryFuncType          operation,
1762                                                                           QuaternaryFilterFuncType      filter,
1763                                                                           InputRange                            inputRange,
1764                                                                           InputWidth                            inputWidth,
1765                                                                           const char*                           spirvExtension,
1766                                                                           const bool                            returnHighPart)
1767 {
1768         DE_ASSERT(!spirvExtension);
1769         DE_ASSERT(!isBooleanResultTest(spirvOperation));
1770
1771         const string                    resultName              = returnHighPart ? "%op_result_pre" : "%op_result";
1772         OpQuaternaryFuncType    zeroFunc                = &zero;
1773         vector<T>                               dataset;
1774         vector<string>                  decorations;
1775         vector<string>                  pre_mains;
1776         vector<string>                  testfuns;
1777         GraphicsResources               resources;
1778         map<string, string>             fragments;
1779         map<string, string>             specs;
1780         string                                  full_operation;
1781
1782         dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
1783         getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
1784         const deUint32                  totalElements   = combine(resources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1785
1786         decorations.reserve(4);
1787         pre_mains.reserve(4);
1788         testfuns.reserve(4);
1789
1790         for (deUint32 elemNdx = 0; elemNdx < 4; ++elemNdx)
1791         {
1792                 decorations.push_back(createInputDecoration(elemNdx));
1793                 pre_mains.push_back(createInputPreMain(elemNdx, spirvOperation));
1794                 testfuns.push_back(createInputTestfun(elemNdx, spirvOperation));
1795         }
1796
1797         if (inputWidth == WIDTH_DEFAULT)
1798                 full_operation  = resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + m_spirvTestType + " %input0_val %input1_val %input2_val %input3_val\n";
1799         else
1800                 full_operation = getFullOperationWithDifferentInputWidthStr(resultName, getSpvOperationStr(spirvOperation), m_inputType, m_spirvTestType, inputWidth, true);
1801
1802         finalizeFullOperation(full_operation, resultName, returnHighPart, false);
1803
1804         createStageTests(testName, resources, totalElements, decorations,
1805                                          pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
1806 }
1807 template <class T>
1808 void SpvAsmTypeTests<T>::createSwitchTests (void)
1809 {
1810         const StringTemplate    decoration              ("OpDecorate %input DescriptorSet 0\n"
1811                                                                                          "OpDecorate %input Binding 0\n"
1812                                                                                          "OpDecorate %input NonWritable\n"
1813                                                                                          "OpDecorate %expectedOutput DescriptorSet 0\n"
1814                                                                                          "OpDecorate %expectedOutput Binding 1\n"
1815                                                                                          "OpDecorate %expectedOutput NonWritable\n"
1816                                                                                          "OpDecorate %a${num_elements}testtype ArrayStride ${typesize}\n"
1817                                                                                          "OpDecorate %buf BufferBlock\n"
1818                                                                                          "OpMemberDecorate %buf 0 Offset 0\n");
1819
1820         const StringTemplate    pre_pre_main    ("%fp_bool = OpTypePointer Function %bool\n"
1821                                                                                          "%c_u32_${num_elements} = OpConstant %u32 ${num_elements}\n"
1822                                                                                          "%c_i32_${num_elements} = OpConstant %i32 ${num_elements}\n");
1823
1824         const StringTemplate    scalar_pre_main ("%testtype = ${scalartype}\n");
1825
1826         const StringTemplate    post_pre_main   ("%c_casedefault = OpConstant %${testtype} 10\n"
1827                                                                                          "%c_case0 = OpConstant %${testtype} 1000\n"
1828                                                                                          "%c_case1 = OpConstant %${testtype} 1100\n"
1829                                                                                          "%c_case2 = OpConstant %${testtype} 1200\n"
1830                                                                                          "%a${num_elements}testtype = OpTypeArray %${testtype} %c_u32_${num_elements}\n"
1831                                                                                          "%up_testtype = OpTypePointer Uniform %${testtype}\n"
1832                                                                                          "%buf = OpTypeStruct %a${num_elements}testtype\n"
1833                                                                                          "%bufptr = OpTypePointer Uniform %buf\n"
1834                                                                                          "%input = OpVariable %bufptr Uniform\n"
1835                                                                                          "%expectedOutput = OpVariable %bufptr Uniform\n");
1836
1837         const StringTemplate    testfun                 ("%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1838                                                                                          "%param = OpFunctionParameter %v4f32\n"
1839
1840                                                                                          "%entry = OpLabel\n"
1841                                                                                          "%counter = OpVariable %fp_i32 Function\n"
1842                                                                                          "%return = OpVariable %fp_v4f32 Function\n"
1843                                                                                          "%works = OpVariable %fp_bool Function\n"
1844                                                                                          "OpStore %counter %c_i32_0\n"
1845                                                                                          "OpStore %return %param\n"
1846                                                                                          "OpBranch %loop\n"
1847
1848                                                                                          "%loop = OpLabel\n"
1849                                                                                          "%counter_val = OpLoad %i32 %counter\n"
1850                                                                                          "%lt = OpSLessThan %bool %counter_val %c_i32_${num_elements}\n"
1851                                                                                          "OpLoopMerge %loop_exit %inc None\n"
1852                                                                                          "OpBranchConditional %lt %load %loop_exit\n"
1853
1854                                                                                          "%load = OpLabel\n"
1855                                                                                          "%input_loc = OpAccessChain %up_testtype %input %c_i32_0 %counter_val\n"
1856                                                                                          "%input_val = OpLoad %${testtype} %input_loc\n"
1857                                                                                          "%expectedOutput_loc = OpAccessChain %up_testtype %expectedOutput %c_i32_0 %counter_val\n"
1858                                                                                          "%expectedOutput_val = OpLoad %${testtype} %expectedOutput_loc\n"
1859
1860                                                                                          "OpSelectionMerge %switch_exit None\n"
1861                                                                                          "OpSwitch %input_val %default ${case0} %case0 ${case1} %case1 ${case2} %case2\n"
1862
1863                                                                                          "%default = OpLabel\n"
1864                                                                                          "%is_default = OpIEqual %bool %expectedOutput_val %c_casedefault\n"
1865                                                                                          "OpBranch %switch_exit\n"
1866
1867                                                                                          "%case0 = OpLabel\n"
1868                                                                                          "%is_case0 = OpIEqual %bool %expectedOutput_val %c_case0\n"
1869                                                                                          "OpBranch %switch_exit\n"
1870
1871                                                                                          "%case1 = OpLabel\n"
1872                                                                                          "%is_case1 = OpIEqual %bool %expectedOutput_val %c_case1\n"
1873                                                                                          "OpBranch %switch_exit\n"
1874
1875                                                                                          "%case2 = OpLabel\n"
1876                                                                                          "%is_case2 = OpIEqual %bool %expectedOutput_val %c_case2\n"
1877                                                                                          "OpBranch %switch_exit\n"
1878
1879                                                                                          "%switch_exit = OpLabel\n"
1880                                                                                          "%case_result = OpPhi %bool %is_default %default %is_case0 %case0 %is_case1 %case1 %is_case2 %case2\n"
1881                                                                                          "OpSelectionMerge %result_end None\n"
1882                                                                                          "OpBranchConditional %case_result %result_correct %result_incorrect\n"
1883
1884                                                                                          "%result_correct = OpLabel\n"
1885                                                                                          "OpBranch %result_end\n"
1886
1887                                                                                          "%result_incorrect = OpLabel\n"
1888                                                                                          "%counter_val_end = OpIAdd %i32 %counter_val %c_i32_${num_elements}\n"
1889                                                                                          "OpStore %counter %counter_val_end\n"
1890                                                                                          "OpStore %return %c_v4f32_1_0_0_1\n"
1891                                                                                          "OpBranch %result_end\n"
1892
1893                                                                                          "%result_end = OpLabel\n"
1894                                                                                          "OpBranch %inc\n"
1895
1896                                                                                          "%inc = OpLabel\n"
1897                                                                                          "%counter_val_next = OpIAdd %i32 %counter_val %c_i32_1\n"
1898                                                                                          "OpStore %counter %counter_val_next\n"
1899                                                                                          "OpBranch %loop\n"
1900
1901                                                                                          "%loop_exit = OpLabel\n"
1902                                                                                          "%return_val = OpLoad %v4f32 %return\n"
1903                                                                                          "OpReturnValue %return_val\n"
1904
1905                                                                                          "OpFunctionEnd\n");
1906
1907         GraphicsResources               resources;
1908         RGBA                                    defaultColors[4];
1909         map<string, string>             fragments;
1910         map<string, string>             specs;
1911         std::vector<string>             noExtensions;
1912         std::vector<string>             features;
1913         VulkanFeatures                  requiredFeatures;
1914         vector<T>                               dataset;
1915         deUint32                                numElements;
1916
1917         getDefaultColors(defaultColors);
1918
1919         dataset.reserve(TEST_DATASET_SIZE);
1920         getDataset(dataset, TEST_DATASET_SIZE);
1921         numElements = fillResources(resources, dataset);
1922
1923         if (m_deviceFeature)
1924                 features.insert(features.begin(), m_deviceFeature);
1925
1926         specs["testtype"] = m_spirvTestType;
1927         specs["scalartype"] = m_spirvType;
1928         specs["typesize"] = numberToString(m_typeSize / 8);
1929         specs["num_elements"] = numberToString(numElements);
1930         specs["case0"] = numberToString(m_cases[0]);
1931         specs["case1"] = numberToString(m_cases[1]);
1932         specs["case2"] = numberToString(m_cases[2]);
1933
1934         fragments["decoration"] = decoration.specialize(specs);
1935
1936         fragments["pre_main"] = pre_pre_main.specialize(specs);
1937         if (specs["testtype"].compare(UNDEFINED_SPIRV_TEST_TYPE) == 0)
1938                 fragments["pre_main"] += scalar_pre_main.specialize(specs);
1939         fragments["pre_main"] += post_pre_main.specialize(specs);
1940
1941         fragments["testfun"] = testfun.specialize(specs);
1942
1943         if (m_spirvCapability)
1944                 fragments["capability"] = "OpCapability " + string(m_spirvCapability);
1945
1946         createTestsForAllStages("switch", defaultColors, defaultColors, fragments, resources, noExtensions, features, this, requiredFeatures);
1947 }
1948
1949 template <class T>
1950 void SpvAsmTypeTests<T>::getConstantDataset (vector<T> inputDataset, vector<T>& outputDataset, deUint32 spirvOperation)
1951 {
1952         const deUint32 numElements = (deUint32)inputDataset.size();
1953
1954         if ((SpvOpConstant == spirvOperation) || (SpvOpSpecConstant == spirvOperation))
1955         {
1956                 for (deUint32 elementNdx = 0u; elementNdx < numElements; elementNdx++)
1957                         outputDataset.push_back(inputDataset[elementNdx]);
1958         }
1959         else
1960         {
1961                 for (deUint32 elementNdx = 0; elementNdx < numElements * m_vectorSize; elementNdx++)
1962                         outputDataset.push_back(inputDataset[getConstituentIndex(elementNdx, m_vectorSize)]);
1963         }
1964 }
1965
1966 template <class T>
1967 void SpvAsmTypeTests<T>::finalizeFullOperation (string&                 fullOperation,
1968                                                                                                 const string&   resultName,
1969                                                                                                 const bool              returnHighPart,
1970                                                                                                 const bool              isBooleanResult)
1971 {
1972         DE_ASSERT(!fullOperation.empty());
1973
1974         if (returnHighPart)
1975         {
1976                 DE_ASSERT(sizeof(T) == sizeof(deInt16));
1977                 DE_ASSERT((m_inputType == TYPE_I16) || (m_inputType == TYPE_U16));
1978
1979                 const bool              signedness              = (m_inputType == TYPE_I16);
1980                 const string    convertOp               = signedness ? "OpSConvert" : "OpUConvert";
1981                 const string    convertPrefix   = (m_vectorSize == 1) ? "" : "v" + de::toString(m_vectorSize);
1982                 const string    convertType             = convertPrefix + "u32";
1983
1984                 // Zero extend value to double-width value, then return high part
1985                 fullOperation += "%op_result_a = OpUConvert %" + convertType + " " + resultName + "\n";
1986                 fullOperation += "%op_result_b = OpShiftRightLogical %" + convertType + " %op_result_a %c_shift\n";
1987                 fullOperation += "%op_result   = " + convertOp + " %" + m_spirvTestType + " %op_result_b\n";
1988         }
1989         else if (isBooleanResult)
1990         {
1991                 const string selectType = (m_vectorSize == 1) ? ("u32") : ("v" + de::toString(m_vectorSize) + "u32");
1992
1993                 // Convert boolean values to result format
1994                 if (m_inputType == TYPE_U32)
1995                 {
1996                         fullOperation += "%op_result     = OpSelect %" + selectType + " %op_result_pre %c_one %c_zero\n";
1997                 }
1998                 else
1999                 {
2000                         fullOperation += "%op_result_u32 = OpSelect %" + selectType + " %op_result_pre %c_one %c_zero\n";
2001
2002                         if (m_typeSize == 32)
2003                                 fullOperation += "%op_result     = OpBitcast %" + m_spirvTestType + " %op_result_u32\n";
2004                         else
2005                                 fullOperation += "%op_result     = OpSConvert %" + m_spirvTestType + " %op_result_u32\n";
2006                 }
2007         }
2008         else
2009         {
2010                 DE_ASSERT(resultName == "%op_result");
2011         }
2012 }
2013
2014 template <class T>
2015 bool SpvAsmTypeTests<T>::filterNone     (T)
2016 {
2017         return true;
2018 }
2019
2020 template <class T>
2021 bool SpvAsmTypeTests<T>::filterNone (T, T)
2022 {
2023         return true;
2024 }
2025
2026 template <class T>
2027 bool SpvAsmTypeTests<T>::filterNone (T, T, T)
2028 {
2029         return true;
2030 }
2031
2032 template <class T>
2033 bool SpvAsmTypeTests<T>::filterNone (T, T, T, T)
2034 {
2035         return true;
2036 }
2037
2038 template <class T>
2039 bool SpvAsmTypeTests<T>::filterZero     (T, T b)
2040 {
2041         if (b == static_cast<T>(0))
2042                 return false;
2043         else
2044                 return true;
2045 }
2046
2047 template <class T>
2048 bool SpvAsmTypeTests<T>::filterNegativesAndZero (T a, T b)
2049 {
2050         if (a < static_cast<T>(0) || b <= static_cast<T>(0))
2051                 return false;
2052         else
2053                 return true;
2054 }
2055
2056 template <class T>
2057 bool SpvAsmTypeTests<T>::filterMinGtMax (T, T a, T b)
2058 {
2059         if (a > b)
2060                 return false;
2061         else
2062                 return true;
2063 }
2064
2065 template <class T>
2066 T SpvAsmTypeTests<T>::zero (T)
2067 {
2068         return static_cast<T>(0.0);
2069 }
2070
2071 template <class T>
2072 T SpvAsmTypeTests<T>::zero (T, T)
2073 {
2074         return static_cast<T>(0.0);
2075 }
2076
2077 template <class T>
2078 T SpvAsmTypeTests<T>::zero (T, T, T)
2079 {
2080         return static_cast<T>(0.0);
2081 }
2082
2083 template <class T>
2084 T SpvAsmTypeTests<T>::zero (T, T, T, T)
2085 {
2086         return static_cast<T>(0.0);
2087 }
2088
2089 template <class T>
2090 std::string     SpvAsmTypeTests<T>::replicate (const std::string&       replicant,
2091                                                                                    const deUint32               count)
2092 {
2093         std::string result;
2094
2095         for (deUint32 i = 0; i < count; ++i)
2096                 result += replicant;
2097
2098         return result;
2099 }
2100
2101 class SpvAsmTypeInt16Tests : public SpvAsmTypeTests<deInt16>
2102 {
2103 public:
2104                                 SpvAsmTypeInt16Tests    (tcu::TestContext&      testCtx,
2105                                                                                  deUint32                       vectorSize);
2106                                 ~SpvAsmTypeInt16Tests   (void);
2107         void            getDataset                              (vector<deInt16>&       input,
2108                                                                                  deUint32                       numElements);
2109         void            pushResource                    (vector<Resource>&      resource,
2110                                                                                  vector<deInt16>&       data);
2111 };
2112
2113 SpvAsmTypeInt16Tests::SpvAsmTypeInt16Tests      (tcu::TestContext&      testCtx,
2114                                                                                          deUint32                       vectorSize)
2115         : SpvAsmTypeTests       (testCtx, "i16", "int16 tests", "shaderInt16", "Int16", "OpTypeInt 16 1", TYPE_I16, 16, vectorSize)
2116 {
2117         m_cases[0] = -3221;
2118         m_cases[1] = 3210;
2119         m_cases[2] = 19597;
2120 }
2121
2122 SpvAsmTypeInt16Tests::~SpvAsmTypeInt16Tests (void)
2123 {
2124 }
2125
2126 void SpvAsmTypeInt16Tests::getDataset (vector<deInt16>& input,
2127                                                                            deUint32                     numElements)
2128 {
2129         // Push first special cases
2130         input.push_back(0);
2131         input.push_back(static_cast<deInt16>(deIntMinValue32(16)));// A 16-bit negative number
2132         input.push_back(static_cast<deInt16>(deIntMaxValue32(16)));// A 16-bit positive number
2133
2134         // Push switch cases
2135         input.push_back(m_cases[0]);
2136         input.push_back(m_cases[1]);
2137         input.push_back(m_cases[2]);
2138
2139         numElements -= static_cast<deUint32>(input.size());
2140
2141         // Random values
2142         for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2143                 input.push_back(static_cast<deInt16>(m_rnd.getUint16()));
2144 }
2145
2146 void SpvAsmTypeInt16Tests::pushResource (vector<Resource>&      resource,
2147                                                                                  vector<deInt16>&       data)
2148 {
2149         resource.push_back(Resource(BufferSp(new Int16Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2150 }
2151
2152 class SpvAsmTypeInt32Tests : public SpvAsmTypeTests<deInt32>
2153 {
2154 public:
2155                                 SpvAsmTypeInt32Tests    (tcu::TestContext&      testCtx,
2156                                                                                  deUint32                       vectorSize);
2157                                 ~SpvAsmTypeInt32Tests   (void);
2158         void            getDataset                              (vector<deInt32>&       input,
2159                                                                                  deUint32                       numElements);
2160         void            pushResource                    (vector<Resource>&      resource,
2161                                                                                  vector<deInt32>&       data);
2162 };
2163
2164 SpvAsmTypeInt32Tests::SpvAsmTypeInt32Tests (tcu::TestContext&   testCtx,
2165                                                                                         deUint32                        vectorSize)
2166         : SpvAsmTypeTests       (testCtx, "i32", "int32 tests", DE_NULL, DE_NULL, "OpTypeInt 32 1", TYPE_I32, 32, vectorSize)
2167 {
2168         m_cases[0] = -3221;
2169         m_cases[1] = 3210;
2170         m_cases[2] = 268438669;
2171 }
2172
2173 SpvAsmTypeInt32Tests::~SpvAsmTypeInt32Tests (void)
2174 {
2175 }
2176
2177 void SpvAsmTypeInt32Tests::getDataset (vector<deInt32>& input,
2178                                                                            deUint32                     numElements)
2179 {
2180         // Push first special cases
2181         input.push_back(0);
2182         input.push_back(deIntMinValue32(32) + 1); // So MIN = -MAX
2183         input.push_back(deIntMaxValue32(32));
2184
2185         // Push switch cases
2186         input.push_back(m_cases[0]);
2187         input.push_back(m_cases[1]);
2188         input.push_back(m_cases[2]);
2189
2190         numElements -= static_cast<deUint32>(input.size());
2191
2192         // Random values
2193         for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2194                 input.push_back(static_cast<deInt32>(m_rnd.getUint32()));
2195 }
2196
2197 void SpvAsmTypeInt32Tests::pushResource (vector<Resource>&      resource,
2198                                                                                  vector<deInt32>&       data)
2199 {
2200         resource.push_back(Resource(BufferSp(new Int32Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2201 }
2202
2203 class SpvAsmTypeInt64Tests : public SpvAsmTypeTests<deInt64>
2204 {
2205 public:
2206                                 SpvAsmTypeInt64Tests    (tcu::TestContext&      testCtx,
2207                                                                                  deUint32                       vectorSize);
2208                                 ~SpvAsmTypeInt64Tests   (void);
2209         void            getDataset                              (vector<deInt64>&       input,
2210                                                                                  deUint32                       numElements);
2211         void            pushResource                    (vector<Resource>&      resource,
2212                                                                                  vector<deInt64>&       data);
2213 };
2214
2215 SpvAsmTypeInt64Tests::SpvAsmTypeInt64Tests (tcu::TestContext&   testCtx,
2216                                                                                         deUint32                        vectorSize)
2217         : SpvAsmTypeTests       (testCtx, "i64", "int64 tests", "shaderInt64", "Int64", "OpTypeInt 64 1", TYPE_I64, 64, vectorSize)
2218 {
2219         m_cases[0] = 3210;
2220         m_cases[1] = -268438669;
2221         m_cases[2] = 26843866939192872;
2222 }
2223
2224 SpvAsmTypeInt64Tests::~SpvAsmTypeInt64Tests (void)
2225 {
2226 }
2227
2228 void SpvAsmTypeInt64Tests::getDataset (vector<deInt64>& input,
2229                                                                            deUint32                     numElements)
2230 {
2231         // Push first special cases
2232         input.push_back(0);
2233         input.push_back(0xFFFF859A3BF78592);// A 64-bit negative number
2234         input.push_back(0x7FFF859A3BF78592);// A 64-bit positive number
2235
2236         // Push switch cases
2237         input.push_back(m_cases[0]);
2238         input.push_back(m_cases[1]);
2239         input.push_back(m_cases[2]);
2240
2241         numElements -= static_cast<deUint32>(input.size());
2242
2243         // Random values
2244         for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2245                 input.push_back(static_cast<deInt64>(m_rnd.getUint64()));
2246 }
2247
2248 void SpvAsmTypeInt64Tests::pushResource (vector<Resource>&      resource,
2249                                                                                  vector<deInt64>&       data)
2250 {
2251         resource.push_back(Resource(BufferSp(new Int64Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2252 }
2253
2254 class SpvAsmTypeUint16Tests : public SpvAsmTypeTests<deUint16>
2255 {
2256 public:
2257                                 SpvAsmTypeUint16Tests   (tcu::TestContext&      testCtx,
2258                                                                                  deUint32                       vectorSize);
2259                                 ~SpvAsmTypeUint16Tests  (void);
2260         void            getDataset                              (vector<deUint16>&      input,
2261                                                                                  deUint32                       numElements);
2262         void            pushResource                    (vector<Resource>&      resource,
2263                                                                                  vector<deUint16>&      data);
2264 };
2265
2266 SpvAsmTypeUint16Tests::SpvAsmTypeUint16Tests    (tcu::TestContext&      testCtx,
2267                                                                                                  deUint32                       vectorSize)
2268         : SpvAsmTypeTests       (testCtx, "u16", "uint16 tests", "shaderInt16", "Int16", "OpTypeInt 16 0", TYPE_U16, 16, vectorSize)
2269 {
2270         m_cases[0] = 0;
2271         m_cases[1] = 3210;
2272         m_cases[2] = 19597;
2273 }
2274
2275 SpvAsmTypeUint16Tests::~SpvAsmTypeUint16Tests (void)
2276 {
2277 }
2278
2279 void SpvAsmTypeUint16Tests::getDataset (vector<deUint16>&       input,
2280                                                                                 deUint32                        numElements)
2281 {
2282         // Push first special cases
2283         input.push_back(0);  // Min value
2284         input.push_back(~0); // Max value
2285
2286         //Push switch cases
2287         input.push_back(m_cases[0]);
2288         input.push_back(m_cases[1]);
2289         input.push_back(m_cases[2]);
2290
2291         numElements -= static_cast<deUint32>(input.size());
2292
2293         // Random values
2294         for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2295                 input.push_back(m_rnd.getUint16());
2296 }
2297
2298 void SpvAsmTypeUint16Tests::pushResource (vector<Resource>&     resource,
2299                                                                                   vector<deUint16>&     data)
2300 {
2301         resource.push_back(Resource(BufferSp(new Uint16Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2302 }
2303
2304 class SpvAsmTypeUint32Tests : public SpvAsmTypeTests<deUint32>
2305 {
2306 public:
2307                                 SpvAsmTypeUint32Tests   (tcu::TestContext&      testCtx,
2308                                                                                  deUint32                       vectorSize);
2309                                 ~SpvAsmTypeUint32Tests  (void);
2310         void            getDataset                              (vector<deUint32>&      input,
2311                                                                                  deUint32                       numElements);
2312         void            pushResource                    (vector<Resource>&      resource,
2313                                                                                  vector<deUint32>&      data);
2314 };
2315
2316 SpvAsmTypeUint32Tests::SpvAsmTypeUint32Tests (tcu::TestContext& testCtx,
2317                                                                                           deUint32                      vectorSize)
2318         : SpvAsmTypeTests       (testCtx, "u32", "uint32 tests", DE_NULL, DE_NULL, "OpTypeInt 32 0", TYPE_U32, 32, vectorSize)
2319 {
2320         m_cases[0] = 0;
2321         m_cases[1] = 3210;
2322         m_cases[2] = 268438669;
2323 }
2324
2325 SpvAsmTypeUint32Tests::~SpvAsmTypeUint32Tests (void)
2326 {
2327 }
2328
2329 void SpvAsmTypeUint32Tests::getDataset (vector<deUint32>&       input,
2330                                                                                 deUint32                        numElements)
2331 {
2332         // Push first special cases
2333         input.push_back(0);  // Min value
2334         input.push_back(~0); // Max value
2335
2336         // Push switch cases
2337         input.push_back(m_cases[0]);
2338         input.push_back(m_cases[1]);
2339         input.push_back(m_cases[2]);
2340
2341         numElements -= static_cast<deUint32>(input.size());
2342
2343         // Random values
2344         for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2345                 input.push_back(m_rnd.getUint32());
2346 }
2347
2348 void SpvAsmTypeUint32Tests::pushResource (vector<Resource>&     resource,
2349                                                                                   vector<deUint32>&     data)
2350 {
2351         resource.push_back(Resource(BufferSp(new Uint32Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2352 }
2353
2354 class SpvAsmTypeUint64Tests : public SpvAsmTypeTests<deUint64>
2355 {
2356 public:
2357                                 SpvAsmTypeUint64Tests   (tcu::TestContext&      testCtx,
2358                                                                                  deUint32                       vectorSize);
2359                                 ~SpvAsmTypeUint64Tests  (void);
2360         void            getDataset                              (vector<deUint64>&      input,
2361                                                                                  deUint32                       numElements);
2362         void            pushResource                    (vector<Resource>&      resource,
2363                                                                                  vector<deUint64>&      data);
2364 };
2365
2366 SpvAsmTypeUint64Tests::SpvAsmTypeUint64Tests (tcu::TestContext& testCtx,
2367                                                                                           deUint32                      vectorSize)
2368         : SpvAsmTypeTests       (testCtx, "u64", "uint64 tests", "shaderInt64", "Int64", "OpTypeInt 64 0", TYPE_U64, 64, vectorSize)
2369 {
2370         m_cases[0] = 3210;
2371         m_cases[1] = 268438669;
2372         m_cases[2] = 26843866939192872;
2373 }
2374
2375 SpvAsmTypeUint64Tests::~SpvAsmTypeUint64Tests (void)
2376 {
2377 }
2378
2379 void SpvAsmTypeUint64Tests::getDataset (vector<deUint64>&       input,
2380                                                                                 deUint32                        numElements)
2381 {
2382         // Push first special cases
2383         input.push_back(0);  // Min value
2384         input.push_back(~0); // Max value
2385
2386         // Push switch cases
2387         input.push_back(m_cases[0]);
2388         input.push_back(m_cases[1]);
2389         input.push_back(m_cases[2]);
2390
2391         numElements -= static_cast<deUint32>(input.size());
2392
2393         // Random values
2394         for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2395                 input.push_back(m_rnd.getUint64());
2396 }
2397
2398 void SpvAsmTypeUint64Tests::pushResource (vector<Resource>&     resource,
2399                                                                                   vector<deUint64>&     data)
2400 {
2401         resource.push_back(Resource(BufferSp(new Uint64Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2402 }
2403
2404 template <class T>
2405 class TestMath
2406 {
2407 public:
2408         static inline T test_abs (T x)
2409         {
2410                 T t0 = static_cast<T>(0.0);
2411
2412                 if (x >= t0)
2413                         return x;
2414                 else
2415                         return test_negate(x);
2416         }
2417
2418         static inline T test_add (T x, T y)
2419         {
2420                 return static_cast<T>(x + y);
2421         }
2422
2423         static inline T test_clamp (T x, T minVal, T maxVal)
2424         {
2425                 return test_min(test_max(x, minVal), maxVal);
2426         }
2427
2428         static inline T test_div (T x, T y)
2429         {
2430                 // In SPIR-V, if "y" is 0, then the result is undefined. In our case,
2431                 // let's return 0
2432                 if (y == static_cast<T>(0))
2433                         return 0;
2434                 else
2435                         return static_cast<T>(x / y);
2436         }
2437
2438         static inline T test_lsb (T x)
2439         {
2440                 for (deUint32 i = 0; i < 8 * sizeof(T); i++)
2441                 {
2442                         if (x & (1u << i))
2443                                 return static_cast<T>(i);
2444                 }
2445
2446                 return static_cast<T>(-1.0);
2447         }
2448
2449         static inline T test_max (T x, T y)
2450         {
2451                 if (x < y)
2452                         return y;
2453                 else
2454                         return x;
2455         }
2456
2457         static inline T test_min (T x, T y)
2458         {
2459                 if (y < x)
2460                         return y;
2461                 else
2462                         return x;
2463         }
2464
2465         static inline T test_mod (T x, T y)
2466         {
2467                 T sign_x, sign_y;
2468
2469                 // In SPIR-V, if "y" is 0, then the result is undefined. In our case,
2470                 // let's return 0
2471                 if (y == static_cast<T>(0))
2472                         return 0;
2473
2474                 if (x >= static_cast<T>(0))
2475                         sign_x = 1;
2476                 else
2477                         sign_x = -1;
2478
2479                 if (y >= static_cast<T>(0))
2480                         sign_y = 1;
2481                 else
2482                         sign_y = -1;
2483
2484                 return static_cast<T>(static_cast<T>(static_cast<T>(x) - static_cast<T>(y * static_cast<T>(x / y))) * static_cast<T>(sign_y * sign_x));
2485         }
2486
2487         static inline T test_mul (T x, T y)
2488         {
2489                 return static_cast<T>(x * y);
2490         }
2491
2492         static inline T test_negate (T x)
2493         {
2494                 return static_cast<T>(static_cast<T>(0.0) - static_cast<T>(x));
2495         }
2496
2497         static inline T test_rem (T x, T y)
2498         {
2499                 // In SPIR-V, if "y" is 0, then the result is undefined. In our case,
2500                 // let's return 0
2501                 if (y == static_cast<T>(0))
2502                         return 0;
2503
2504                 return static_cast<T>(x % y);
2505         }
2506
2507         static inline T test_sign (T x)
2508         {
2509                 T t0 = static_cast<T>(0.0);
2510
2511                 if (x > t0)
2512                         return static_cast<T>(1.0);
2513                 else if (x < t0)
2514                         return static_cast<T>(-1.0);
2515                 else
2516                         return t0;
2517         }
2518
2519         static inline T test_sub (T x, T y)
2520         {
2521                 return static_cast<T>(x - y);
2522         }
2523
2524         static inline T test_msb (T)
2525         {
2526                 TCU_THROW(InternalError, "Not implemented");
2527         }
2528
2529         static inline T test_lsr (T x, T y)
2530         {
2531                 if (x >= static_cast<T>(0) || y == static_cast<T>(0))
2532                 {
2533                         return static_cast<T>(x >> y);
2534                 }
2535                 else
2536                 {
2537                         const T mask = static_cast<T>(~(T)0 << (sizeof(T) * 8 - (y)));
2538                         return static_cast<T>((x >> y) & (~mask));
2539                 }
2540         }
2541
2542         static inline T test_asr (T x, T y)
2543         {
2544                 const T bitmask = static_cast<T>(deUint64(1) << (sizeof(T) * 8u - 1u));
2545
2546                 if ((x & bitmask) && y > 0)
2547                 {
2548                         const T mask    = static_cast<T>(~(T)0 << (sizeof(T) * 8 - (y)));
2549                         const T result  = static_cast<T>((x >> y) | (mask));
2550                         return result;
2551                 }
2552                 else
2553                 {
2554                         return static_cast<T>(x >> y);
2555                 }
2556         }
2557
2558         static inline T test_lsl (T x, T y)
2559         {
2560                 return static_cast<T>(x << y);
2561         }
2562
2563         static inline T test_bitwise_or (T x, T y)
2564         {
2565                 return static_cast<T>(x | y);
2566         }
2567
2568         static inline T test_bitwise_xor (T x, T y)
2569         {
2570                 return static_cast<T>(x ^ y);
2571         }
2572
2573         static inline T test_bitwise_and (T x, T y)
2574         {
2575                 return static_cast<T>(x & y);
2576         }
2577
2578         static inline T test_not (T x)
2579         {
2580                 return static_cast<T>(~x);
2581         }
2582
2583         static inline T test_iequal (T x, T y)
2584         {
2585                 if (x == y)
2586                         return static_cast<T>(1);
2587                 else
2588                         return static_cast<T>(0);
2589         }
2590
2591         static inline T test_inotequal (T x, T y)
2592         {
2593                 if (x != y)
2594                         return static_cast<T>(1);
2595                 else
2596                         return static_cast<T>(0);
2597         }
2598
2599         static inline T test_ugreaterthan (T x, T y)
2600         {
2601                 if (x > y)
2602                         return static_cast<T>(1);
2603                 else
2604                         return static_cast<T>(0);
2605         }
2606
2607         static inline T test_ulessthan (T x, T y)
2608         {
2609                 return test_ugreaterthan(y, x);
2610         }
2611
2612         static inline T test_sgreaterthan (T x, T y)
2613         {
2614                 if (x > y)
2615                         return static_cast<T>(1);
2616                 else
2617                         return static_cast<T>(0);
2618         }
2619
2620         static inline T test_slessthan (T x, T y)
2621         {
2622                 return test_sgreaterthan(y, x);
2623         }
2624
2625         static inline T test_ugreaterthanequal (T x, T y)
2626         {
2627                 if (x >= y)
2628                         return static_cast<T>(1);
2629                 else
2630                         return static_cast<T>(0);
2631         }
2632
2633         static inline T test_ulessthanequal (T x, T y)
2634         {
2635                 return test_ugreaterthanequal(y, x);
2636         }
2637
2638         static inline T test_sgreaterthanequal (T x, T y)
2639         {
2640                 if (x >= y)
2641                         return static_cast<T>(1);
2642                 else
2643                         return static_cast<T>(0);
2644         }
2645
2646         static inline T test_slessthanequal (T x, T y)
2647         {
2648                 return test_sgreaterthanequal(y, x);
2649         }
2650
2651         static inline T test_bitFieldInsert (T base, T insert, T offset, T count)
2652         {
2653                 const T insertMask = static_cast<T>(~(~(static_cast<T>(0)) << count));
2654
2655                 return static_cast<T>((base & ~(insertMask << offset)) | ((insert & insertMask) << offset));
2656         }
2657
2658         static inline T test_bitFieldSExtract (T x, T y, T z)
2659         {
2660                 const T allZeros        = (static_cast<T>(0));
2661                 const T allOnes         = ~allZeros;
2662
2663                 // Count can be 0, in which case the result will be 0
2664                 if (z == allZeros)
2665                         return allZeros;
2666
2667                 const T extractMask     = static_cast<T>((allOnes << z));
2668                 const T signBit         = static_cast<T>(x & (1 << (y + z - 1)));
2669                 const T signMask        = static_cast<T>(signBit ? allOnes : allZeros);
2670
2671                 return static_cast<T>((signMask & extractMask) | ((x >> y) & ~extractMask));
2672         }
2673
2674         static inline T test_bitFieldUExtract (T x, T y, T z)
2675         {
2676                 const T allZeros        = (static_cast<T>(0));
2677                 const T allOnes         = ~allZeros;
2678
2679                 // Count can be 0, in which case the result will be 0
2680                 if (z == allZeros)
2681                         return allZeros;
2682
2683                 const T extractMask     = static_cast<T>((allOnes << z));
2684
2685                 return static_cast<T>((x >> y) & ~extractMask);
2686         }
2687
2688         static inline T test_bitReverse (T x)
2689         {
2690                 T               base    = x;
2691                 T               result  = static_cast<T>(0);
2692
2693                 for (size_t bitNdx = 0u; bitNdx < sizeof(T) * 8u; bitNdx++)
2694                 {
2695                         result = static_cast<T>(result << 1) | (base & 1);
2696                         base >>= 1;
2697                 }
2698
2699                 return result;
2700         }
2701
2702         static inline T test_bitCount (T x)
2703         {
2704                 T count = static_cast<T>(0);
2705
2706                 for (deUint32 bitNdx = 0u; bitNdx < (deUint32)sizeof(T) * 8u; bitNdx++)
2707                         if (x & (static_cast<T>(1) << bitNdx))
2708                                 count++;
2709
2710                 return count;
2711         }
2712
2713         static inline T test_constant (T a)
2714         {
2715                 return a;
2716         }
2717 };
2718
2719 class TestMathInt16 : public TestMath<deInt16>
2720 {
2721 public:
2722         static inline deInt16 test_msb (deInt16 x)
2723         {
2724                 if (x > 0)
2725                         return static_cast<deInt16>(15 - deClz32((deUint32)x));
2726                 else if (x < 0)
2727                         return static_cast<deInt16>(15 - deClz32(~(deUint32)x));
2728                 else
2729                         return -1;
2730         }
2731
2732         static inline deInt16 test_mul_div (deInt16 x, deInt16 y)
2733         {
2734                 deInt32 x32     = static_cast<deInt32>(x);
2735                 deInt32 y32     = static_cast<deInt32>(y);
2736
2737                 // In SPIR-V, if "y" is 0, then the result is undefined. In our case, let's return 0
2738                 if (y == static_cast<deInt16>(0))
2739                         return 0;
2740                 else
2741                         return static_cast<deInt16>(static_cast<deInt16>(x32 * y32) / y32);
2742         }
2743
2744         static inline deInt16 test_ugreaterthan (deInt16 x, deInt16 y)
2745         {
2746                 // Consume signed integers as unsigned integers
2747                 if ((x & 0x8000) ^ (y & 0x8000))
2748                         std::swap(x,y);
2749
2750                 if (x > y)
2751                         return static_cast<deInt16>(1);
2752                 else
2753                         return static_cast<deInt16>(0);
2754         }
2755
2756         static inline deInt16 test_ulessthan (deInt16 x, deInt16 y)
2757         {
2758                 return test_ugreaterthan(y, x);
2759         }
2760
2761         static inline deInt16 test_ugreaterthanequal (deInt16 x, deInt16 y)
2762         {
2763                 // Consume signed integers as unsigned integers
2764                 if ((x & 0x8000) ^ (y & 0x8000))
2765                         std::swap(x,y);
2766
2767                 if (x >= y)
2768                         return static_cast<deInt16>(1);
2769                 else
2770                         return static_cast<deInt16>(0);
2771         }
2772
2773         static inline deInt16 test_ulessthanequal (deInt16 x, deInt16 y)
2774         {
2775                 return test_ugreaterthanequal(y, x);
2776         }
2777 };
2778
2779 class TestMathInt32 : public TestMath<deInt32>
2780 {
2781 public:
2782         static inline deInt32 test_msb (deInt32 x)
2783         {
2784                 if (x > 0)
2785                         return 31 - deClz32((deUint32)x);
2786                 else if (x < 0)
2787                         return 31 - deClz32(~(deUint32)x);
2788                 else
2789                         return -1;
2790         }
2791
2792         static inline deInt32 test_ugreaterthan (deInt32 x, deInt32 y)
2793         {
2794                 // Consume signed integers as unsigned integers
2795                 if ((x & 0x80000000) ^ (y & 0x80000000))
2796                         std::swap(x,y);
2797
2798                 if (x > y)
2799                         return static_cast<deInt32>(1);
2800                 else
2801                         return static_cast<deInt32>(0);
2802         }
2803
2804         static inline deInt32 test_ulessthan (deInt32 x, deInt32 y)
2805         {
2806                 return test_ugreaterthan(y, x);
2807         }
2808
2809         static inline deInt32 test_ugreaterthanequal (deInt32 x, deInt32 y)
2810         {
2811                 // Consume signed integers as unsigned integers
2812                 if ((x & 0x80000000) ^ (y & 0x80000000))
2813                         std::swap(x,y);
2814
2815                 if (x >= y)
2816                         return static_cast<deInt32>(1);
2817                 else
2818                         return static_cast<deInt32>(0);
2819         }
2820
2821         static inline deInt32 test_ulessthanequal (deInt32 x, deInt32 y)
2822         {
2823                 return test_ugreaterthanequal(y, x);
2824         }
2825 };
2826
2827 class TestMathInt64 : public TestMath<deInt64>
2828 {
2829 public:
2830         static inline deInt64 test_ugreaterthan (deInt64 x, deInt64 y)
2831         {
2832                 // Consume signed integers as unsigned integers
2833                 if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
2834                         std::swap(x,y);
2835
2836                 if (x > y)
2837                         return static_cast<deInt64>(1);
2838                 else
2839                         return static_cast<deInt64>(0);
2840         }
2841
2842         static inline deInt64 test_ulessthan (deInt64 x, deInt64 y)
2843         {
2844                 return test_ugreaterthan(y, x);
2845         }
2846
2847         static inline deInt64 test_ugreaterthanequal (deInt64 x, deInt64 y)
2848         {
2849                 // Consume signed integers as unsigned integers
2850                 if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
2851                         std::swap(x,y);
2852
2853                 if (x >= y)
2854                         return static_cast<deInt64>(1);
2855                 else
2856                         return static_cast<deInt64>(0);
2857         }
2858
2859         static inline deInt64 test_ulessthanequal (deInt64 x, deInt64 y)
2860         {
2861                 return test_ugreaterthanequal(y, x);
2862         }
2863 };
2864
2865 class TestMathUint16 : public TestMath<deUint16>
2866 {
2867 public:
2868         static inline deUint32 test_msb (deUint16 x)
2869         {
2870                 if (x > 0)
2871                         return 15 - deClz32((deUint32)x);
2872                 else
2873                         return -1;
2874         }
2875
2876         static inline deUint16 test_mul_div (deUint16 x, deUint16 y)
2877         {
2878                 const deUint32 x32 = static_cast<deUint32>(x);
2879                 const deUint32 y32 = static_cast<deUint32>(y);
2880
2881                 // In SPIR-V, if "y" is 0, then the result is undefined. In our case, let's return 0
2882                 if (y == static_cast<deUint16>(0))
2883                         return 0;
2884                 else
2885                         return static_cast<deUint16>(static_cast<deUint16>(x32 * y32) / y32);
2886         }
2887
2888         static inline deUint16 test_sgreaterthan (deUint16 x, deUint16 y)
2889         {
2890                 // Consume unsigned integers as signed integers
2891                 if ((x & 0x8000) ^ (y & 0x8000))
2892                         std::swap(x,y);
2893
2894                 if (x > y)
2895                         return static_cast<deUint16>(1);
2896                 else
2897                         return static_cast<deUint16>(0);
2898         }
2899
2900         static inline deUint16 test_slessthan (deUint16 x, deUint16 y)
2901         {
2902                 return test_sgreaterthan(y, x);
2903         }
2904
2905         static inline deUint16 test_sgreaterthanequal (deUint16 x, deUint16 y)
2906         {
2907                 // Consume unsigned integers as signed integers
2908                 if ((x & 0x8000) ^ (y & 0x8000))
2909                         std::swap(x,y);
2910
2911                 if (x >= y)
2912                         return static_cast<deUint16>(1);
2913                 else
2914                         return static_cast<deUint16>(0);
2915         }
2916
2917         static inline deUint16 test_slessthanequal (deUint16 x, deUint16 y)
2918         {
2919                 return test_sgreaterthanequal(y, x);
2920         }
2921 };
2922
2923 class TestMathUint32 : public TestMath<deUint32>
2924 {
2925 public:
2926         static inline deUint32 test_msb (deUint32 x)
2927         {
2928                 if (x > 0)
2929                         return 31 - deClz32(x);
2930                 else
2931                         return -1;
2932         }
2933
2934         static inline deUint32 test_sgreaterthan (deUint32 x, deUint32 y)
2935         {
2936                 // Consume unsigned integers as signed integers
2937                 if ((x & 0x80000000) ^ (y & 0x80000000))
2938                         std::swap(x,y);
2939
2940                 if (x > y)
2941                         return static_cast<deUint32>(1);
2942                 else
2943                         return static_cast<deUint32>(0);
2944         }
2945
2946         static inline deUint32 test_slessthan (deUint32 x, deUint32 y)
2947         {
2948                 return test_sgreaterthan(y, x);
2949         }
2950
2951         static inline deUint32 test_sgreaterthanequal (deUint32 x, deUint32 y)
2952         {
2953                 // Consume unsigned integers as signed integers
2954                 if ((x & 0x80000000) ^ (y & 0x80000000))
2955                         std::swap(x,y);
2956
2957                 if (x >= y)
2958                         return static_cast<deUint32>(1);
2959                 else
2960                         return static_cast<deUint32>(0);
2961         }
2962
2963         static inline deUint32 test_slessthanequal (deUint32 x, deUint32 y)
2964         {
2965                 return test_sgreaterthanequal(y, x);
2966         }
2967
2968 };
2969
2970 class TestMathUint64 : public TestMath<deUint64>
2971 {
2972 public:
2973         static inline deUint64 test_sgreaterthan (deUint64 x, deUint64 y)
2974         {
2975                 // Consume unsigned integers as signed integers
2976                 if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
2977                         std::swap(x,y);
2978
2979                 if (x > y)
2980                         return static_cast<deUint64>(1);
2981                 else
2982                         return static_cast<deUint64>(0);
2983         }
2984
2985         static inline deUint64 test_slessthan (deUint64 x, deUint64 y)
2986         {
2987                 return test_sgreaterthan(y, x);
2988         }
2989
2990         static inline deUint64 test_sgreaterthanequal (deUint64 x, deUint64 y)
2991         {
2992                 // Consume unsigned integers as signed integers
2993                 if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
2994                         std::swap(x,y);
2995
2996                 if (x >= y)
2997                         return static_cast<deUint64>(1);
2998                 else
2999                         return static_cast<deUint64>(0);
3000         }
3001
3002         static inline deUint64 test_slessthanequal (deUint64 x, deUint64 y)
3003         {
3004                 return test_sgreaterthanequal(y, x);
3005         }
3006 };
3007
3008 #define I16_FILTER_NONE SpvAsmTypeInt16Tests::filterNone
3009 #define I32_FILTER_NONE SpvAsmTypeInt32Tests::filterNone
3010 #define I64_FILTER_NONE SpvAsmTypeInt64Tests::filterNone
3011 #define U16_FILTER_NONE SpvAsmTypeUint16Tests::filterNone
3012 #define U32_FILTER_NONE SpvAsmTypeUint32Tests::filterNone
3013 #define U64_FILTER_NONE SpvAsmTypeUint64Tests::filterNone
3014
3015 #define I16_FILTER_ZERO SpvAsmTypeInt16Tests::filterZero
3016 #define I32_FILTER_ZERO SpvAsmTypeInt32Tests::filterZero
3017 #define I64_FILTER_ZERO SpvAsmTypeInt64Tests::filterZero
3018 #define U16_FILTER_ZERO SpvAsmTypeUint16Tests::filterZero
3019 #define U32_FILTER_ZERO SpvAsmTypeUint32Tests::filterZero
3020 #define U64_FILTER_ZERO SpvAsmTypeUint64Tests::filterZero
3021
3022 #define I16_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeInt16Tests::filterNegativesAndZero
3023 #define I32_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeInt32Tests::filterNegativesAndZero
3024 #define I64_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeInt64Tests::filterNegativesAndZero
3025 #define U16_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeUint16Tests::filterNegativesAndZero
3026 #define U32_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeUint32Tests::filterNegativesAndZero
3027 #define U64_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeUint64Tests::filterNegativesAndZero
3028
3029 #define I16_FILTER_MIN_GT_MAX SpvAsmTypeInt16Tests::filterMinGtMax
3030 #define I32_FILTER_MIN_GT_MAX SpvAsmTypeInt32Tests::filterMinGtMax
3031 #define I64_FILTER_MIN_GT_MAX SpvAsmTypeInt64Tests::filterMinGtMax
3032 #define U16_FILTER_MIN_GT_MAX SpvAsmTypeUint16Tests::filterMinGtMax
3033 #define U32_FILTER_MIN_GT_MAX SpvAsmTypeUint32Tests::filterMinGtMax
3034 #define U64_FILTER_MIN_GT_MAX SpvAsmTypeUint64Tests::filterMinGtMax
3035
3036 const string bitShiftTestPostfix[] =
3037 {
3038         "_shift16",
3039         "_shift32",
3040         "_shift64"
3041 };
3042
3043 const string bitFieldTestPostfix[] =
3044 {
3045         "_offset16_count16",
3046         "_offset16_count32",
3047         "_offset16_count64",
3048         "_offset32_count16",
3049         "_offset32_count32",
3050         "_offset32_count64",
3051         "_offset64_count16",
3052         "_offset64_count32",
3053         "_offset64_count64",
3054 };
3055
3056 // Macro to create tests.
3057 // Syntax: MAKE_TEST_{S,V}_{I,U}_{1,3,6}
3058 //
3059 //  'S': create scalar test
3060 //  'V': create vector test
3061 //
3062 //  'I': create integer test
3063 //  'U': create unsigned integer test
3064 //
3065 //  '3': create 32-bit test
3066 //  '6': create 64-bit test
3067 //
3068 //  'W': bit width of some parameters in bit field and shift operations can be different from Result and Base
3069 //  'N': create 16-bit tests without 'test_high_part_zero' variants
3070
3071 #define MAKE_TEST_S_I_136(name, spirvOp, op, filter, inputRange, extension) \
3072         for (deUint32 ndx = 0; ndx < 1; ++ndx) \
3073         { \
3074                 int16Tests[ndx]->createTests((name), (spirvOp), \
3075                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3076                 int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3077                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3078                 int32Tests[ndx]->createTests((name), (spirvOp), \
3079                         TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3080                 int64Tests[ndx]->createTests((name), (spirvOp), \
3081                         TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3082         } \
3083
3084 #define MAKE_TEST_V_I_136(name, spirvOp, op, filter, inputRange, extension) \
3085         for (deUint32 ndx = 1; ndx < 4; ++ndx) \
3086         { \
3087                 int16Tests[ndx]->createTests((name), (spirvOp), \
3088                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3089                 int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3090                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3091                 int32Tests[ndx]->createTests((name), (spirvOp), \
3092                         TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3093                 int64Tests[ndx]->createTests((name), (spirvOp), \
3094                         TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3095         } \
3096
3097 #define MAKE_TEST_SV_I_136(name, spirvOp, op, filter, inputRange, extension) \
3098         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3099         { \
3100                 int16Tests[ndx]->createTests((name), (spirvOp), \
3101                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3102                 int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3103                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3104                 int32Tests[ndx]->createTests((name), (spirvOp), \
3105                         TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3106                 int64Tests[ndx]->createTests((name), (spirvOp), \
3107                         TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3108         } \
3109
3110 #define MAKE_TEST_SV_I_136_N(name, spirvOp, op, filter, inputRange, extension) \
3111         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3112         { \
3113                 int16Tests[ndx]->createTests((name), (spirvOp), \
3114                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3115                 int32Tests[ndx]->createTests((name), (spirvOp), \
3116                         TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3117                 int64Tests[ndx]->createTests((name), (spirvOp), \
3118                         TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3119         } \
3120
3121 #define MAKE_TEST_SV_I_136_W(name, spirvOp, op, filter, inputRange, extension) \
3122         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3123         for (deUint32 width = 0; width < 3; ++width) \
3124         { \
3125                 int16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width]).c_str(), (spirvOp), \
3126                         TestMathInt16::test_##op, I16_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension)); \
3127                 int16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width] + "_test_high_part_zero").c_str(), (spirvOp), \
3128                         TestMathInt16::test_##op, I16_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension), true); \
3129                 int32Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width]).c_str(), (spirvOp), \
3130                         TestMathInt32::test_##op, I32_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension)); \
3131                 int64Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width]).c_str(), (spirvOp), \
3132                         TestMathInt64::test_##op, I64_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension)); \
3133         } \
3134
3135 #define MAKE_TEST_SV_I_1(name, spirvOp, op, filter, inputRange, extension) \
3136         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3137         { \
3138                 int16Tests[ndx]->createTests((name), (spirvOp), \
3139                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3140                 int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3141                         TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3142         } \
3143
3144 #define MAKE_TEST_SV_I_3(name, spirvOp, op, filter, inputRange, extension) \
3145         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3146                 int32Tests[ndx]->createTests((name), (spirvOp), \
3147                         TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3148
3149 #define MAKE_TEST_SV_I_3_W(name, spirvOp, op, filter, inputRange, extension) \
3150         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3151         for (deUint32 width = 0; width < 9; ++width) \
3152         { \
3153                 int32Tests[ndx]->createTests(string(name + bitFieldTestPostfix[width]).c_str(), (spirvOp), \
3154                         TestMathInt32::test_##op, I32_##filter, inputRange, InputWidth(WIDTH_16_16 + width), (extension)); \
3155         } \
3156
3157 #define MAKE_TEST_S_U_136(name, spirvOp, op, filter, inputRange, extension) \
3158         for (deUint32 ndx = 0; ndx < 1; ++ndx) \
3159         { \
3160                 uint16Tests[ndx]->createTests((name), (spirvOp), \
3161                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3162                 uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3163                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3164                 uint32Tests[ndx]->createTests((name), (spirvOp), \
3165                         TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3166                 uint64Tests[ndx]->createTests((name), (spirvOp), \
3167                         TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3168         } \
3169
3170 #define MAKE_TEST_V_U_136(name, spirvOp, op, filter, inputRange, extension) \
3171         for (deUint32 ndx = 1; ndx < 4; ++ndx) \
3172         { \
3173                 uint16Tests[ndx]->createTests((name), (spirvOp), \
3174                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3175                 uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3176                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3177                 uint32Tests[ndx]->createTests((name), (spirvOp), \
3178                         TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3179                 uint64Tests[ndx]->createTests((name), (spirvOp), \
3180                         TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3181         } \
3182
3183 #define MAKE_TEST_SV_U_136(name, spirvOp, op, filter, inputRange, extension) \
3184         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3185         { \
3186                 uint16Tests[ndx]->createTests((name), (spirvOp), \
3187                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3188                 uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3189                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3190                 uint32Tests[ndx]->createTests((name), (spirvOp), \
3191                         TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3192                 uint64Tests[ndx]->createTests((name), (spirvOp), \
3193                         TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3194         } \
3195
3196 #define MAKE_TEST_SV_U_136_N(name, spirvOp, op, filter, inputRange, extension) \
3197         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3198         { \
3199                 uint16Tests[ndx]->createTests((name), (spirvOp), \
3200                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3201                 uint32Tests[ndx]->createTests((name), (spirvOp), \
3202                         TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3203                 uint64Tests[ndx]->createTests((name), (spirvOp), \
3204                         TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3205         } \
3206
3207 #define MAKE_TEST_SV_U_136_W(name, spirvOp, op, filter, inputRange, extension) \
3208         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3209         for (deUint32 width = 0; width < 3; ++width) \
3210         { \
3211                 uint16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width]).c_str(), (spirvOp), \
3212                         TestMathUint16::test_##op, U16_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension)); \
3213                 uint16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width] + "_test_high_part_zero").c_str(), (spirvOp), \
3214                         TestMathUint16::test_##op, U16_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension), true); \
3215                 uint32Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width]).c_str(), (spirvOp), \
3216                         TestMathUint32::test_##op, U32_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension)); \
3217                 uint64Tests[ndx]->createTests(string(name + bitShiftTestPostfix[width]).c_str(), (spirvOp), \
3218                         TestMathUint64::test_##op, U64_##filter, inputRange, InputWidth(WIDTH_16 + width), (extension)); \
3219         } \
3220
3221 #define MAKE_TEST_SV_U_1(name, spirvOp, op, filter, inputRange, extension) \
3222         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3223         { \
3224                 uint16Tests[ndx]->createTests((name), (spirvOp), \
3225                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3226                 uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3227                         TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3228         } \
3229
3230 #define MAKE_TEST_SV_U_3(name, spirvOp, op, filter, inputRange, extension) \
3231         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3232                 uint32Tests[ndx]->createTests((name), (spirvOp), \
3233                         TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3234
3235 #define MAKE_TEST_SV_U_3_W(name, spirvOp, op, filter, inputRange, extension) \
3236         for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3237         for (deUint32 width = 0; width < 9; ++width) \
3238         { \
3239                 uint32Tests[ndx]->createTests(string(name + bitFieldTestPostfix[width]).c_str(), (spirvOp), \
3240                         TestMathUint32::test_##op, U32_##filter, inputRange, InputWidth(WIDTH_16_16 + width), (extension)); \
3241         } \
3242
3243 tcu::TestCaseGroup* createTypeTests (tcu::TestContext& testCtx)
3244 {
3245         de::MovePtr<tcu::TestCaseGroup>         typeTests                       (new tcu::TestCaseGroup(testCtx, "type", "Test types"));
3246         de::MovePtr<tcu::TestCaseGroup>         typeScalarTests         (new tcu::TestCaseGroup(testCtx, "scalar", "scalar tests"));
3247         de::MovePtr<tcu::TestCaseGroup>         typeVectorTests[3];
3248
3249         de::MovePtr<SpvAsmTypeInt16Tests>       int16Tests[4];
3250         de::MovePtr<SpvAsmTypeInt32Tests>       int32Tests[4];
3251         de::MovePtr<SpvAsmTypeInt64Tests>       int64Tests[4];
3252         de::MovePtr<SpvAsmTypeUint16Tests>      uint16Tests[4];
3253         de::MovePtr<SpvAsmTypeUint32Tests>      uint32Tests[4];
3254         de::MovePtr<SpvAsmTypeUint64Tests>      uint64Tests[4];
3255
3256         for (deUint32 ndx = 0; ndx < 3; ++ndx)
3257         {
3258                 std::string testName = "vec" + numberToString(ndx + 2);
3259                 typeVectorTests[ndx] = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, testName.c_str(), "vector tests"));
3260         }
3261
3262         for (deUint32 ndx = 0; ndx < 4; ++ndx)
3263         {
3264                 int16Tests[ndx]         = de::MovePtr<SpvAsmTypeInt16Tests>(new SpvAsmTypeInt16Tests(testCtx, ndx + 1));
3265                 int32Tests[ndx]         = de::MovePtr<SpvAsmTypeInt32Tests>(new SpvAsmTypeInt32Tests(testCtx, ndx + 1));
3266                 int64Tests[ndx]         = de::MovePtr<SpvAsmTypeInt64Tests>(new SpvAsmTypeInt64Tests(testCtx, ndx + 1));
3267                 uint16Tests[ndx]        = de::MovePtr<SpvAsmTypeUint16Tests>(new SpvAsmTypeUint16Tests(testCtx, ndx + 1));
3268                 uint32Tests[ndx]        = de::MovePtr<SpvAsmTypeUint32Tests>(new SpvAsmTypeUint32Tests(testCtx, ndx + 1));
3269                 uint64Tests[ndx]        = de::MovePtr<SpvAsmTypeUint64Tests>(new SpvAsmTypeUint64Tests(testCtx, ndx + 1));
3270         }
3271
3272         MAKE_TEST_SV_I_136("negate", SpvOpSNegate, negate, FILTER_NONE, RANGE_FULL, DE_NULL);
3273         MAKE_TEST_SV_I_136("add", SpvOpIAdd, add, FILTER_NONE, RANGE_FULL, DE_NULL);
3274         MAKE_TEST_SV_I_136("sub", SpvOpISub, sub, FILTER_NONE, RANGE_FULL, DE_NULL);
3275         MAKE_TEST_SV_I_136("mul", SpvOpIMul, mul, FILTER_NONE, RANGE_FULL, DE_NULL);
3276         MAKE_TEST_SV_I_136("div", SpvOpSDiv, div, FILTER_ZERO, RANGE_FULL, DE_NULL);
3277         MAKE_TEST_SV_U_136("div", SpvOpUDiv, div, FILTER_ZERO, RANGE_FULL, DE_NULL);
3278         MAKE_TEST_SV_I_136("rem", SpvOpSRem, rem, FILTER_NEGATIVES_AND_ZERO, RANGE_FULL, DE_NULL);
3279         MAKE_TEST_SV_I_136("mod", SpvOpSMod, mod, FILTER_NEGATIVES_AND_ZERO, RANGE_FULL, DE_NULL);
3280         MAKE_TEST_SV_U_136("mod", SpvOpUMod, mod, FILTER_ZERO, RANGE_FULL, DE_NULL);
3281         MAKE_TEST_SV_I_136("abs", GLSLstd450SAbs, abs, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3282         MAKE_TEST_SV_I_136("sign", GLSLstd450SSign, sign, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3283         MAKE_TEST_SV_I_136("min", GLSLstd450SMin, min, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3284         MAKE_TEST_SV_U_136("min", GLSLstd450UMin, min, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3285         MAKE_TEST_SV_I_136("max", GLSLstd450SMax, max, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3286         MAKE_TEST_SV_U_136("max", GLSLstd450UMax, max, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3287         MAKE_TEST_SV_I_136("clamp", GLSLstd450SClamp, clamp, FILTER_MIN_GT_MAX, RANGE_FULL, "GLSL.std.450");
3288         MAKE_TEST_SV_U_136("clamp", GLSLstd450UClamp, clamp, FILTER_MIN_GT_MAX, RANGE_FULL, "GLSL.std.450");
3289         MAKE_TEST_SV_I_3("find_lsb", GLSLstd450FindILsb, lsb, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3290         MAKE_TEST_SV_I_3("find_msb", GLSLstd450FindSMsb, msb, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3291         MAKE_TEST_SV_U_3("find_msb", GLSLstd450FindUMsb, msb, FILTER_NONE, RANGE_FULL, "GLSL.std.450");
3292         MAKE_TEST_SV_I_1("mul_sdiv", DE_NULL, mul_div, FILTER_ZERO, RANGE_FULL, DE_NULL);
3293         MAKE_TEST_SV_U_1("mul_udiv", DE_NULL, mul_div, FILTER_ZERO, RANGE_FULL, DE_NULL);
3294
3295         MAKE_TEST_SV_U_136_W("shift_right_logical", SpvOpShiftRightLogical, lsr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL);
3296         MAKE_TEST_SV_I_136_W("shift_right_logical", SpvOpShiftRightLogical, lsr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL);
3297         MAKE_TEST_SV_U_136_W("shift_right_arithmetic", SpvOpShiftRightArithmetic, asr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL);
3298         MAKE_TEST_SV_I_136_W("shift_right_arithmetic", SpvOpShiftRightArithmetic, asr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL);
3299         MAKE_TEST_SV_U_136_W("shift_left_logical", SpvOpShiftLeftLogical, lsl, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL);
3300         MAKE_TEST_SV_I_136_W("shift_left_logical", SpvOpShiftLeftLogical, lsl, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL);
3301
3302         MAKE_TEST_SV_U_136("bitwise_or", SpvOpBitwiseOr, bitwise_or, FILTER_NONE, RANGE_FULL, DE_NULL);
3303         MAKE_TEST_SV_I_136("bitwise_or", SpvOpBitwiseOr, bitwise_or , FILTER_NONE, RANGE_FULL, DE_NULL);
3304         MAKE_TEST_SV_U_136("bitwise_xor", SpvOpBitwiseXor, bitwise_xor, FILTER_NONE, RANGE_FULL, DE_NULL);
3305         MAKE_TEST_SV_I_136("bitwise_xor", SpvOpBitwiseXor, bitwise_xor, FILTER_NONE, RANGE_FULL, DE_NULL);
3306         MAKE_TEST_SV_U_136("bitwise_and", SpvOpBitwiseAnd, bitwise_and, FILTER_NONE, RANGE_FULL, DE_NULL);
3307         MAKE_TEST_SV_I_136("bitwise_and", SpvOpBitwiseAnd, bitwise_and, FILTER_NONE, RANGE_FULL, DE_NULL);
3308         MAKE_TEST_SV_U_136("not", SpvOpNot, not, FILTER_NONE, RANGE_FULL, DE_NULL);
3309         MAKE_TEST_SV_I_136("not", SpvOpNot, not, FILTER_NONE, RANGE_FULL, DE_NULL);
3310
3311         MAKE_TEST_SV_U_136_N("iequal", SpvOpIEqual, iequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3312         MAKE_TEST_SV_I_136_N("iequal", SpvOpIEqual, iequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3313         MAKE_TEST_SV_U_136_N("inotequal", SpvOpINotEqual, inotequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3314         MAKE_TEST_SV_I_136_N("inotequal", SpvOpINotEqual, inotequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3315         MAKE_TEST_SV_U_136_N("ugreaterthan", SpvOpUGreaterThan, ugreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3316         MAKE_TEST_SV_I_136_N("ugreaterthan", SpvOpUGreaterThan, ugreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3317         MAKE_TEST_SV_U_136_N("sgreaterthan", SpvOpSGreaterThan, sgreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3318         MAKE_TEST_SV_I_136_N("sgreaterthan", SpvOpSGreaterThan, sgreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3319         MAKE_TEST_SV_U_136_N("ugreaterthanequal", SpvOpUGreaterThanEqual, ugreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3320         MAKE_TEST_SV_I_136_N("ugreaterthanequal", SpvOpUGreaterThanEqual, ugreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3321         MAKE_TEST_SV_U_136_N("sgreaterthanequal", SpvOpSGreaterThanEqual, sgreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3322         MAKE_TEST_SV_I_136_N("sgreaterthanequal", SpvOpSGreaterThanEqual, sgreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3323         MAKE_TEST_SV_U_136_N("ulessthan", SpvOpULessThan, ulessthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3324         MAKE_TEST_SV_I_136_N("ulessthan", SpvOpULessThan, ulessthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3325         MAKE_TEST_SV_U_136_N("slessthan", SpvOpSLessThan, slessthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3326         MAKE_TEST_SV_I_136_N("slessthan", SpvOpSLessThan, slessthan, FILTER_NONE, RANGE_FULL, DE_NULL);
3327         MAKE_TEST_SV_U_136_N("ulessthanequal", SpvOpULessThanEqual, ulessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3328         MAKE_TEST_SV_I_136_N("ulessthanequal", SpvOpULessThanEqual, ulessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3329         MAKE_TEST_SV_U_136_N("slessthanequal", SpvOpSLessThanEqual, slessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3330         MAKE_TEST_SV_I_136_N("slessthanequal", SpvOpSLessThanEqual, slessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL);
3331
3332         MAKE_TEST_SV_U_3_W("bit_field_insert", SpvOpBitFieldInsert, bitFieldInsert, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL);
3333         MAKE_TEST_SV_I_3_W("bit_field_insert", SpvOpBitFieldInsert, bitFieldInsert, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL);
3334         MAKE_TEST_SV_U_3_W("bit_field_s_extract", SpvOpBitFieldSExtract, bitFieldSExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL);
3335         MAKE_TEST_SV_I_3_W("bit_field_s_extract", SpvOpBitFieldSExtract, bitFieldSExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL);
3336         MAKE_TEST_SV_U_3_W("bit_field_u_extract", SpvOpBitFieldUExtract, bitFieldUExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL);
3337         MAKE_TEST_SV_I_3_W("bit_field_u_extract", SpvOpBitFieldUExtract, bitFieldUExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL);
3338         MAKE_TEST_SV_U_3("bit_reverse", SpvOpBitReverse, bitReverse, FILTER_NONE, RANGE_FULL, DE_NULL);
3339         MAKE_TEST_SV_I_3("bit_reverse", SpvOpBitReverse, bitReverse, FILTER_NONE, RANGE_FULL, DE_NULL);
3340         MAKE_TEST_SV_U_3("bit_count", SpvOpBitCount, bitCount, FILTER_NONE, RANGE_FULL, DE_NULL);
3341         MAKE_TEST_SV_I_3("bit_count", SpvOpBitCount, bitCount, FILTER_NONE, RANGE_FULL, DE_NULL);
3342
3343         MAKE_TEST_S_U_136("constant", SpvOpConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3344         MAKE_TEST_S_I_136("constant", SpvOpConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3345         MAKE_TEST_V_U_136("constant_composite", SpvOpConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3346         MAKE_TEST_V_I_136("constant_composite", SpvOpConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3347         MAKE_TEST_V_U_136("constant_null", SpvOpConstantNull, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3348         MAKE_TEST_V_I_136("constant_null", SpvOpConstantNull, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3349         MAKE_TEST_SV_U_136("variable_initializer", SpvOpVariable, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3350         MAKE_TEST_SV_I_136("variable_initializer", SpvOpVariable, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3351         MAKE_TEST_S_U_136("spec_constant_initializer", SpvOpSpecConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3352         MAKE_TEST_S_I_136("spec_constant_initializer", SpvOpSpecConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3353         MAKE_TEST_V_U_136("spec_constant_composite_initializer", SpvOpSpecConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3354         MAKE_TEST_V_I_136("spec_constant_composite_initializer", SpvOpSpecConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL);
3355
3356         int16Tests[0]->createSwitchTests();
3357         int32Tests[0]->createSwitchTests();
3358         int64Tests[0]->createSwitchTests();
3359         uint16Tests[0]->createSwitchTests();
3360         uint32Tests[0]->createSwitchTests();
3361         uint64Tests[0]->createSwitchTests();
3362
3363         typeScalarTests->addChild(int16Tests[0].release());
3364         typeScalarTests->addChild(int32Tests[0].release());
3365         typeScalarTests->addChild(int64Tests[0].release());
3366         typeScalarTests->addChild(uint16Tests[0].release());
3367         typeScalarTests->addChild(uint32Tests[0].release());
3368         typeScalarTests->addChild(uint64Tests[0].release());
3369
3370         typeTests->addChild(typeScalarTests.release());
3371
3372         for (deUint32 ndx = 0; ndx < 3; ++ndx)
3373         {
3374                 typeVectorTests[ndx]->addChild(int16Tests[ndx + 1].release());
3375                 typeVectorTests[ndx]->addChild(int32Tests[ndx + 1].release());
3376                 typeVectorTests[ndx]->addChild(int64Tests[ndx + 1].release());
3377                 typeVectorTests[ndx]->addChild(uint16Tests[ndx + 1].release());
3378                 typeVectorTests[ndx]->addChild(uint32Tests[ndx + 1].release());
3379                 typeVectorTests[ndx]->addChild(uint64Tests[ndx + 1].release());
3380
3381                 typeTests->addChild(typeVectorTests[ndx].release());
3382         }
3383
3384         return typeTests.release();
3385 }
3386
3387 } // SpirVAssembly
3388 } // vkt