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