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