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