• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.shaderInt8 = true;
1556 	}
1557 
1558 	if (m_inputType == TYPE_I8 || m_inputType == TYPE_U8)
1559 	{
1560 		requiredFeatures.ext8BitStorage.storageBuffer8BitAccess = true;
1561 		spirvExtensions					+= "OpExtension \"SPV_KHR_8bit_storage\"\n";
1562 	}
1563 
1564 	if (m_inputType == TYPE_I16 || m_inputType == TYPE_U16)
1565 	{
1566 		requiredFeatures.ext16BitStorage.storageBuffer16BitAccess = true;
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 
1635 	createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, noExtensions, this, requiredFeatures);
1636 
1637 	computeResources.requestedVulkanFeatures = requiredFeatures;
1638 	computeResources.requestedVulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = false;
1639 	computeResources.requestedVulkanFeatures.coreFeatures.fragmentStoresAndAtomics = false;
1640 
1641 	createComputeTest(computeResources, computeShaderTemplate, fragments, *this, testName);
1642 }
1643 
1644 template <class T>
valueToStr(const T v)1645 std::string valueToStr(const T v)
1646 {
1647 	std::stringstream s;
1648 	s << v;
1649 	return s.str();
1650 }
1651 
1652 template <>
valueToStr(const deUint8 v)1653 std::string valueToStr<deUint8> (const deUint8 v)
1654 {
1655 	std::stringstream s;
1656 	s << (deUint16)v;
1657 	return s.str();
1658 }
1659 
1660 template <>
valueToStr(const deInt8 v)1661 std::string valueToStr<deInt8> ( const deInt8 v)
1662 {
1663 	std::stringstream s;
1664 	s << (deInt16)v;
1665 	return s.str();
1666 }
1667 
1668 template <class T>
verifyResult(const vector<Resource> & inputs,const vector<AllocationSp> & outputAllocations,const vector<Resource> & expectedOutputs,deUint32 skip,tcu::TestLog & log)1669 bool SpvAsmTypeTests<T>::verifyResult (const vector<Resource>&		inputs,
1670 									   const vector<AllocationSp>&	outputAllocations,
1671 									   const vector<Resource>&		expectedOutputs,
1672 									   deUint32						skip,
1673 									   tcu::TestLog&				log)
1674 {
1675 	DE_ASSERT(outputAllocations.size() == 1);
1676 	DE_ASSERT(inputs.size() > 0 && inputs.size() < 5);
1677 
1678 	const T*		input[4]		= { DE_NULL };
1679 	vector<deUint8>	inputBytes[4];
1680 	vector<deUint8>	expectedBytes;
1681 
1682 	expectedOutputs[0].getBytes(expectedBytes);
1683 	const deUint32 count	= static_cast<deUint32>(expectedBytes.size() / sizeof(T));
1684 	const T* obtained		= static_cast<const T *>(outputAllocations[0]->getHostPtr());
1685 	const T* expected		= reinterpret_cast<const T*>(&expectedBytes.front());
1686 
1687 	for (deUint32 ndxCount = 0; ndxCount < inputs.size(); ndxCount++)
1688 	{
1689 		inputs[ndxCount].getBytes(inputBytes[ndxCount]);
1690 		input[ndxCount]	= reinterpret_cast<const T*>(&inputBytes[ndxCount].front());
1691 	}
1692 
1693 	for (deUint32 ndxCount = 0 ; ndxCount < count; ++ndxCount)
1694 	{
1695 		/* Skip padding */
1696 		if (((ndxCount + 1) % skip) == 0)
1697 			continue;
1698 
1699 		if (obtained[ndxCount] != expected[ndxCount])
1700 		{
1701 			std::stringstream inputStream;
1702 			inputStream << "(";
1703 			for (deUint32 ndxIndex = 0 ; ndxIndex < inputs.size(); ++ndxIndex)
1704 			{
1705 				inputStream << valueToStr(input[ndxIndex][ndxCount]);
1706 				if (ndxIndex < inputs.size() - 1)
1707 					inputStream << ",";
1708 			}
1709 			inputStream << ")";
1710 			log << tcu::TestLog::Message
1711 				<< "Error: found unexpected result for inputs " << inputStream.str()
1712 				<< ": expected " << valueToStr(expected[ndxCount]) << ", obtained "
1713 				<< valueToStr(obtained[ndxCount]) << tcu::TestLog::EndMessage;
1714 			return false;
1715 		}
1716 	}
1717 
1718 	return true;
1719 }
1720 
1721 template <class T>
verifyDefaultResult(const vector<Resource> & inputs,const vector<AllocationSp> & outputAllocations,const vector<Resource> & expectedOutputs,tcu::TestLog & log)1722 bool SpvAsmTypeTests<T>::verifyDefaultResult (const vector<Resource>&		inputs,
1723 											  const vector<AllocationSp>&	outputAllocations,
1724 											  const vector<Resource>&		expectedOutputs,
1725 											  tcu::TestLog&					log)
1726 {
1727 	return verifyResult(inputs, outputAllocations, expectedOutputs, ~0, log);
1728 }
1729 
1730 template <class T>
verifyVec3Result(const vector<Resource> & inputs,const vector<AllocationSp> & outputAllocations,const vector<Resource> & expectedOutputs,tcu::TestLog & log)1731 bool SpvAsmTypeTests<T>::verifyVec3Result (const vector<Resource>&		inputs,
1732 										   const vector<AllocationSp>&	outputAllocations,
1733 										   const vector<Resource>&		expectedOutputs,
1734 										   tcu::TestLog&				log)
1735 {
1736 	return verifyResult(inputs, outputAllocations, expectedOutputs, 4, log);
1737 }
1738 
1739 template <class T>
createConstantDeclaration(vector<T> & dataset,deUint32 spirvOperation)1740 string SpvAsmTypeTests<T>::createConstantDeclaration (vector<T>& dataset, deUint32 spirvOperation)
1741 {
1742 	const bool		isVariableTest				= (SpvOpVariable == spirvOperation);
1743 	const bool		isConstantNullTest			= (SpvOpConstantNull == spirvOperation) || isVariableTest;
1744 	const bool		isConstantCompositeTest		= (SpvOpConstantComposite == spirvOperation) || (isConstantNullTest && m_vectorSize > 1);
1745 	const bool		isConstantTest				= (SpvOpConstant == spirvOperation) || isConstantCompositeTest || isConstantNullTest;
1746 	const bool		isSpecConstantTest			= (SpvOpSpecConstant == spirvOperation);
1747 	const bool		isSpecConstantCompositeTest	= (SpvOpSpecConstantComposite == spirvOperation);
1748 
1749 	const string	testScalarType				= (m_inputType == TYPE_I32) ? "i32"
1750 												: (m_inputType == TYPE_U32) ? "u32"
1751 												: "scalartype";
1752 	const string	constantType				= (m_vectorSize > 1) ? testScalarType : m_spirvTestType;
1753 	const string	constantName				= (m_vectorSize > 1) ? "%c_constituent_" : "%c_testtype_";
1754 
1755 	string			str							= "";
1756 
1757 	// Declare scalar specialization constants
1758 	if (isSpecConstantTest)
1759 	{
1760 		for (size_t constantNdx = 0u; constantNdx < dataset.size(); constantNdx++)
1761 			str += constantName + de::toString(constantNdx) + " = OpSpecConstant %" + constantType + " " + de::toString(dataset[constantNdx]) + "\n";
1762 	}
1763 
1764 	// Declare specialization constant composites
1765 	if (isSpecConstantCompositeTest)
1766 	{
1767 		// Constituents are a mix of OpConstantNull, OpConstants and OpSpecializationConstants
1768 		for (size_t constantNdx = 0u; constantNdx < dataset.size(); constantNdx++)
1769 		{
1770 			const char* constantOp[] =
1771 			{
1772 				"OpConstant",
1773 				"OpSpecConstant"
1774 			};
1775 
1776 			if (constantNdx == 0u)
1777 				str += constantName + de::toString(constantNdx) + " = OpConstantNull %" + constantType + "\n";
1778 			else
1779 				str += constantName + de::toString(constantNdx) + " = " + constantOp[constantNdx % 2] + " %" + constantType + " " + de::toString(dataset[constantNdx]) + "\n";
1780 		}
1781 
1782 		for (deUint32 compositeNdx = 0u; compositeNdx < (deUint32)dataset.size(); compositeNdx++)
1783 		{
1784 			str += "%c_testtype_" + de::toString(compositeNdx) + " = OpSpecConstantComposite %" + m_spirvTestType;
1785 
1786 			for (deUint32 componentNdx = 0u; componentNdx < m_vectorSize; componentNdx++)
1787 				str += " %c_constituent_" + de::toString(getConstituentIndex(compositeNdx * m_vectorSize + componentNdx, m_vectorSize));
1788 
1789 			str += "\n";
1790 		}
1791 	}
1792 
1793 	// Declare scalar constants
1794 	if (isConstantTest || isVariableTest)
1795 	{
1796 		for (size_t constantNdx = 0u; constantNdx < dataset.size(); constantNdx++)
1797 		{
1798 			if (isConstantNullTest && constantNdx == 0u)
1799 				str += constantName + de::toString(constantNdx) + " = OpConstantNull %" + constantType + "\n";
1800 			else
1801 				str += constantName + de::toString(constantNdx) + " = OpConstant %" + constantType + " " + de::toString(dataset[constantNdx]) + "\n";
1802 		}
1803 	}
1804 
1805 	// Declare constant composites
1806 	if (isConstantCompositeTest)
1807 	{
1808 		for (deUint32 compositeNdx = 0u; compositeNdx < (deUint32)dataset.size(); compositeNdx++)
1809 		{
1810 			str += "%c_testtype_" + de::toString(compositeNdx) + " = OpConstantComposite %" + m_spirvTestType;
1811 
1812 			for (deUint32 componentNdx = 0u; componentNdx < m_vectorSize; componentNdx++)
1813 				str += " %c_constituent_" + de::toString(getConstituentIndex(compositeNdx * m_vectorSize + componentNdx, m_vectorSize));
1814 
1815 			str += "\n";
1816 		}
1817 	}
1818 
1819 	return str;
1820 }
1821 
1822 template <class T>
getVariableStr(vector<T> & dataset,const char * spirvType,deUint32 spirvOperation)1823 string getVariableStr (vector<T>& dataset, const char* spirvType, deUint32 spirvOperation)
1824 {
1825 	const bool		isVariableTest = (SpvOpVariable == spirvOperation);
1826 	string			str = "";
1827 
1828 	// Declare variables with initializers
1829 	if (isVariableTest)
1830 		for (size_t i = 0u; i < dataset.size(); i++)
1831 			str += "%testvariable_" + de::toString(i) + " = OpVariable %fp_" + spirvType + " Function %c_testtype_" + de::toString(i) + "\n";
1832 
1833 	return str;
1834 }
1835 
1836 template <class T>
createTests(const char * testName,deUint32 spirvOperation,OpUnaryFuncType operation,UnaryFilterFuncType filter,InputRange inputRange,InputWidth inputWidth,const char * spirvExtension,const bool returnHighPart)1837 void SpvAsmTypeTests<T>::createTests (const char*			testName,
1838 									  deUint32				spirvOperation,
1839 									  OpUnaryFuncType		operation,
1840 									  UnaryFilterFuncType	filter,
1841 									  InputRange			inputRange,
1842 									  InputWidth			inputWidth,
1843 									  const char*			spirvExtension,
1844 									  const bool			returnHighPart)
1845 {
1846 	DE_ASSERT(!isBooleanResultTest(spirvOperation));
1847 
1848 	const string		resultName	= returnHighPart ? "%op_result_pre" : "%op_result";
1849 	OpUnaryFuncType		zeroFunc	= &zero;
1850 	vector<T>			dataset;
1851 	vector<string>		decorations;
1852 	vector<string>		pre_mains;
1853 	vector<string>		testfuns;
1854 	GraphicsResources	resources;
1855 	ComputeShaderSpec	computeResources;
1856 	map<string, string>	fragments;
1857 	map<string, string>	specs;
1858 
1859 	if (isConstantOrVariableTest(spirvOperation))
1860 	{
1861 		DE_ASSERT(!spirvExtension);
1862 
1863 		const deUint32		inputSize		= TEST_DATASET_SIZE;
1864 		const deUint32		outputSize		= TEST_DATASET_SIZE * m_vectorSize;
1865 		vector<T>			inputDataset;
1866 
1867 		inputDataset.reserve(inputSize);
1868 		dataset.reserve(outputSize);
1869 
1870 		getDataset(inputDataset, inputSize);
1871 		getConstantDataset(inputDataset, dataset, spirvOperation);
1872 
1873 		const deUint32		totalElements	= combine(resources, computeResources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1874 
1875 		pre_mains.reserve(1);
1876 		pre_mains.push_back(createConstantDeclaration(inputDataset, spirvOperation));
1877 
1878 		string				fullOperation	= "OpBranch %switchStart\n"
1879 											  "%switchStart = OpLabel\n"
1880 											  "OpSelectionMerge %switchEnd None\n"
1881 											  "OpSwitch %counter_val %caseDefault";
1882 
1883 		for (deUint32 caseNdx = 0u; caseNdx < inputSize; caseNdx++)
1884 			fullOperation += " " + de::toString(caseNdx) + " " + "%case" + de::toString(caseNdx);
1885 
1886 		fullOperation += "\n";
1887 
1888 		const string		funVariables	= getVariableStr(inputDataset, m_spirvTestType.c_str(), spirvOperation);
1889 
1890 		if (SpvOpVariable == spirvOperation)
1891 		{
1892 			for (deUint32 caseNdx = 0u; caseNdx < inputSize; caseNdx++)
1893 				fullOperation +=	"%case" + de::toString(caseNdx) + " = OpLabel\n"
1894 									"%temp_" + de::toString(caseNdx) + " = OpLoad %" + m_spirvTestType + " %testvariable_" + de::toString(caseNdx) + "\n"
1895 									"OpStore %op_constant %temp_" + de::toString(caseNdx) + "\n"
1896 									"OpBranch %switchEnd\n";
1897 		}
1898 		else
1899 		{
1900 			for (deUint32 caseNdx = 0u; caseNdx < inputSize; caseNdx++)
1901 				fullOperation +=	"%case" + de::toString(caseNdx) + " = OpLabel\n"
1902 									"OpStore %op_constant %c_testtype_" + de::toString(caseNdx) + "\n"
1903 									"OpBranch %switchEnd\n";
1904 		}
1905 
1906 		fullOperation +=	"%caseDefault = OpLabel\n"
1907 							"OpBranch %switchEnd\n"
1908 							"%switchEnd = OpLabel\n"
1909 							+ resultName + " = OpLoad %" + m_spirvTestType + " %op_constant\n";
1910 
1911 
1912 		finalizeFullOperation(fullOperation, resultName, returnHighPart, false);
1913 
1914 		createStageTests(testName, resources, computeResources, totalElements, decorations,
1915 						 pre_mains, testfuns, fullOperation, inputWidth, funVariables.c_str(), spirvExtension);
1916 	}
1917 	else
1918 	{
1919 		dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
1920 		getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
1921 		const deUint32	totalElements	= combine(resources, computeResources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1922 
1923 		decorations.reserve(1);
1924 		pre_mains.reserve(1);
1925 		testfuns.reserve(1);
1926 
1927 		decorations.push_back(createInputDecoration(0));
1928 		pre_mains.push_back(createInputPreMain(0, spirvOperation));
1929 		testfuns.push_back(createInputTestfun(0, spirvOperation));
1930 
1931 		string			full_operation	(spirvExtension ? resultName + " = OpExtInst %" + m_spirvTestType + " %ext1 " + getGLSLstd450OperationStr(spirvOperation) + " %input0_val\n"
1932 										: resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + m_spirvTestType + " %input0_val\n");
1933 
1934 		finalizeFullOperation(full_operation, resultName, returnHighPart, false);
1935 
1936 		createStageTests(testName, resources, computeResources, totalElements, decorations,
1937 						 pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
1938 	}
1939 }
1940 
1941 template <class T>
createTests(const char * testName,deUint32 spirvOperation,OpBinaryFuncType operation,BinaryFilterFuncType filter,InputRange inputRange,InputWidth inputWidth,const char * spirvExtension,const bool returnHighPart)1942 void SpvAsmTypeTests<T>::createTests (const char*			testName,
1943 									  deUint32				spirvOperation,
1944 									  OpBinaryFuncType		operation,
1945 									  BinaryFilterFuncType	filter,
1946 									  InputRange			inputRange,
1947 									  InputWidth			inputWidth,
1948 									  const char*			spirvExtension,
1949 									  const bool			returnHighPart)
1950 {
1951 	const bool			isBoolean		= isBooleanResultTest(spirvOperation);
1952 	const string		resultName		= (returnHighPart || isBoolean) ? "%op_result_pre" : "%op_result";
1953 	const string		resultType		= isBoolean ? getBooleanResultType(m_vectorSize) : m_spirvTestType;
1954 	OpBinaryFuncType	zeroFunc		= &zero;
1955 	vector<T>			dataset;
1956 	vector<string>		decorations;
1957 	vector<string>		pre_mains;
1958 	vector<string>		testfuns;
1959 	GraphicsResources	resources;
1960 	ComputeShaderSpec	computeResources;
1961 	map<string, string>	fragments;
1962 	map<string, string>	specs;
1963 	string				full_operation;
1964 
1965 	dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
1966 	getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
1967 	const deUint32		totalElements	= combine(resources, computeResources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
1968 
1969 	decorations.reserve(2);
1970 	pre_mains.reserve(2);
1971 	testfuns.reserve(2);
1972 
1973 	for (deUint32 elemNdx = 0; elemNdx < 2; ++elemNdx)
1974 	{
1975 		decorations.push_back(createInputDecoration(elemNdx));
1976 		pre_mains.push_back(createInputPreMain(elemNdx, spirvOperation));
1977 		testfuns.push_back(createInputTestfun(elemNdx, spirvOperation));
1978 	}
1979 
1980 	if (spirvOperation != DE_NULL)
1981 	{
1982 		if (inputWidth == WIDTH_DEFAULT)
1983 			full_operation = spirvExtension	? resultName + " = OpExtInst %" + resultType + " %ext1 " + getGLSLstd450OperationStr(spirvOperation) + " %input0_val %input1_val\n"
1984 											: resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + resultType + " %input0_val %input1_val\n";
1985 		else
1986 			full_operation = getBinaryFullOperationWithInputWidthStr(resultName, getSpvOperationStr(spirvOperation), m_inputType, m_spirvTestType, m_vectorSize, inputWidth);
1987 	}
1988 	else
1989 	{
1990 		if (deStringBeginsWith(testName, "mul_sdiv"))
1991 		{
1992 			DE_ASSERT(spirvExtension == DE_NULL);
1993 			full_operation = "%op_result2 = OpIMul %" + m_spirvTestType + " %input0_val %input1_val\n";
1994 			full_operation += resultName + " = OpSDiv %" + m_spirvTestType + " %op_result2 %input1_val\n";
1995 		}
1996 		if (deStringBeginsWith(testName, "mul_udiv"))
1997 		{
1998 			DE_ASSERT(spirvExtension == DE_NULL);
1999 			full_operation = "%op_result2 = OpIMul %" + m_spirvTestType + " %input0_val %input1_val\n";
2000 			full_operation += resultName + " = OpUDiv %" + m_spirvTestType + " %op_result2 %input1_val\n";
2001 		}
2002 	}
2003 
2004 	finalizeFullOperation(full_operation, resultName, returnHighPart, isBoolean);
2005 
2006 	createStageTests(testName, resources, computeResources, totalElements, decorations,
2007 					 pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
2008 }
2009 
2010 template <class T>
createTests(const char * testName,deUint32 spirvOperation,OpTernaryFuncType operation,TernaryFilterFuncType filter,InputRange inputRange,InputWidth inputWidth,const char * spirvExtension,const bool returnHighPart)2011 void SpvAsmTypeTests<T>::createTests (const char*			testName,
2012 									  deUint32				spirvOperation,
2013 									  OpTernaryFuncType		operation,
2014 									  TernaryFilterFuncType	filter,
2015 									  InputRange			inputRange,
2016 									  InputWidth			inputWidth,
2017 									  const char*			spirvExtension,
2018 									  const bool			returnHighPart)
2019 {
2020 	DE_ASSERT(!isBooleanResultTest(spirvOperation));
2021 
2022 	const string		resultName		= returnHighPart ? "%op_result_pre" : "%op_result";
2023 	OpTernaryFuncType	zeroFunc		= &zero;
2024 	vector<T>			dataset;
2025 	vector<string>		decorations;
2026 	vector<string>		pre_mains;
2027 	vector<string>		testfuns;
2028 	GraphicsResources	resources;
2029 	ComputeShaderSpec	computeResources;
2030 	map<string, string>	fragments;
2031 	map<string, string>	specs;
2032 
2033 	dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
2034 	getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
2035 	const deUint32		totalElements	= combine(resources, computeResources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
2036 
2037 	decorations.reserve(3);
2038 	pre_mains.reserve(3);
2039 	testfuns.reserve(3);
2040 
2041 	for (deUint32 elemNdx = 0; elemNdx < 3; ++elemNdx)
2042 	{
2043 		decorations.push_back(createInputDecoration(elemNdx));
2044 		pre_mains.push_back(createInputPreMain(elemNdx, spirvOperation));
2045 		testfuns.push_back(createInputTestfun(elemNdx, spirvOperation));
2046 	}
2047 
2048 	string				full_operation	= "";
2049 
2050 	if (inputWidth == WIDTH_DEFAULT)
2051 		full_operation = (spirvExtension ? resultName + " = OpExtInst %" + m_spirvTestType + " %ext1 " + getGLSLstd450OperationStr(spirvOperation) + " %input0_val %input1_val %input2_val\n"
2052 										 : resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + m_spirvTestType + " %input0_val %input1_val %input2_val\n");
2053 	else
2054 		full_operation = getFullOperationWithDifferentInputWidthStr(resultName, getSpvOperationStr(spirvOperation), m_inputType, m_spirvTestType, inputWidth, false);
2055 
2056 	finalizeFullOperation(full_operation, resultName, returnHighPart, false);
2057 
2058 	createStageTests(testName, resources, computeResources, totalElements, decorations,
2059 					 pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
2060 }
2061 
2062 template <class T>
createTests(const char * testName,deUint32 spirvOperation,OpQuaternaryFuncType operation,QuaternaryFilterFuncType filter,InputRange inputRange,InputWidth inputWidth,const char * spirvExtension,const bool returnHighPart)2063 void SpvAsmTypeTests<T>::createTests (const char*				testName,
2064 									  deUint32					spirvOperation,
2065 									  OpQuaternaryFuncType		operation,
2066 									  QuaternaryFilterFuncType	filter,
2067 									  InputRange				inputRange,
2068 									  InputWidth				inputWidth,
2069 									  const char*				spirvExtension,
2070 									  const bool				returnHighPart)
2071 {
2072 	DE_ASSERT(!spirvExtension);
2073 	DE_ASSERT(!isBooleanResultTest(spirvOperation));
2074 
2075 	const string			resultName		= returnHighPart ? "%op_result_pre" : "%op_result";
2076 	OpQuaternaryFuncType	zeroFunc		= &zero;
2077 	vector<T>				dataset;
2078 	vector<string>			decorations;
2079 	vector<string>			pre_mains;
2080 	vector<string>			testfuns;
2081 	GraphicsResources		resources;
2082 	ComputeShaderSpec		computeResources;
2083 	map<string, string>		fragments;
2084 	map<string, string>		specs;
2085 	string					full_operation;
2086 
2087 	dataset.reserve(TEST_DATASET_SIZE * m_vectorSize);
2088 	getDataset(dataset, TEST_DATASET_SIZE * m_vectorSize);
2089 	const deUint32			totalElements	= combine(resources, computeResources, dataset, (returnHighPart ? zeroFunc : operation), filter, inputRange);
2090 
2091 	decorations.reserve(4);
2092 	pre_mains.reserve(4);
2093 	testfuns.reserve(4);
2094 
2095 	for (deUint32 elemNdx = 0; elemNdx < 4; ++elemNdx)
2096 	{
2097 		decorations.push_back(createInputDecoration(elemNdx));
2098 		pre_mains.push_back(createInputPreMain(elemNdx, spirvOperation));
2099 		testfuns.push_back(createInputTestfun(elemNdx, spirvOperation));
2100 	}
2101 
2102 	if (inputWidth == WIDTH_DEFAULT)
2103 		full_operation	= resultName + " = " + getSpvOperationStr(spirvOperation) + " %" + m_spirvTestType + " %input0_val %input1_val %input2_val %input3_val\n";
2104 	else
2105 		full_operation = getFullOperationWithDifferentInputWidthStr(resultName, getSpvOperationStr(spirvOperation), m_inputType, m_spirvTestType, inputWidth, true);
2106 
2107 	finalizeFullOperation(full_operation, resultName, returnHighPart, false);
2108 
2109 	createStageTests(testName, resources, computeResources, totalElements, decorations,
2110 					 pre_mains, testfuns, full_operation, inputWidth, "", spirvExtension);
2111 }
2112 
2113 template <class T>
createSwitchTests(void)2114 void SpvAsmTypeTests<T>::createSwitchTests (void)
2115 {
2116 	// The switch case test function is a bit different from the normal one. It uses two input buffers for input data and expected
2117 	// results. The shader itself will calculate results based on input data and compare them to the expected results in the second
2118 	// buffer, instead of verifying results on the CPU.
2119 	//
2120 	// The test function will return the color passed to it if the obtained results match the expected results, and will return (0.5,
2121 	// 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
2122 	// image as usual with the graphics shader test utils. For compute shaders, this does not work.
2123 	//
2124 	// 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
2125 	// single integer in an output storage buffer as a boolean value indicating if the returned color matches the input color, to be
2126 	// checked after the shader runs. Roughly equivalent to the following GLSL code:
2127 	//
2128 	//      layout(binding = 2) buffer BlockType { int values[]; } block;
2129 	//
2130 	//      vec4 testfun(in vec4 param);
2131 	//
2132 	//      void main()
2133 	//      {
2134 	//              vec4 in_color   = vec4(0.0, 0.0, 0.0, 1.0);
2135 	//              vec4 out_color  = testfun(in_color);
2136 	//              block.values[0] = int(all(equal(in_color, out_color)));
2137 	//      }
2138 	const tcu::StringTemplate computeShaderSwitchTemplate(R"(
2139 					OpCapability Shader
2140 					${capability:opt}
2141 					${extension:opt}
2142 					OpMemoryModel Logical GLSL450
2143 					OpEntryPoint GLCompute %BP_main "main"
2144 					OpExecutionMode %BP_main LocalSize 1 1 1
2145 					${execution_mode:opt}
2146 					${debug:opt}
2147 					${moduleprocessed:opt}
2148 					${IF_decoration:opt}
2149 					${decoration:opt}
2150 					OpDecorate %rta_i32 ArrayStride 4
2151 					OpMemberDecorate %BlockType 0 Offset 0
2152 					OpDecorate %BlockType BufferBlock
2153 					OpDecorate %block DescriptorSet 0
2154 					OpDecorate %block Binding 2
2155 	)"
2156 					SPIRV_ASSEMBLY_TYPES
2157 					SPIRV_ASSEMBLY_CONSTANTS
2158 					SPIRV_ASSEMBLY_ARRAYS
2159 	R"(
2160 		 %rta_i32 = OpTypeRuntimeArray %i32
2161 	   %BlockType = OpTypeStruct %rta_i32
2162 	%up_BlockType = OpTypePointer Uniform %BlockType
2163 		   %block = OpVariable %up_BlockType Uniform
2164 		%BP_color = OpConstantComposite %v4f32 %c_f32_0 %c_f32_0 %c_f32_0 %c_f32_1
2165 					${pre_main:opt}
2166 					${IF_variable:opt}
2167 		  %up_i32 = OpTypePointer Uniform %i32
2168 		 %BP_main = OpFunction %void None %voidf
2169    %BP_label_main = OpLabel
2170 					${IF_carryforward:opt}
2171 					${post_interface_op_comp:opt}
2172 	 %BP_in_color = OpVariable %fp_v4f32 Function
2173 	%BP_out_color = OpVariable %fp_v4f32 Function
2174 					OpStore %BP_in_color %BP_color
2175 		 %BP_tmp1 = OpLoad %v4f32 %BP_in_color
2176 		 %BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1
2177 					OpStore %BP_out_color %BP_tmp2
2178 
2179 		 %BP_tmp3 = OpLoad %v4f32 %BP_in_color
2180 		 %BP_tmp4 = OpLoad %v4f32 %BP_out_color
2181 		 %BP_tmp5 = OpFOrdEqual %v4bool %BP_tmp3 %BP_tmp4
2182 		 %BP_tmp6 = OpAll %bool %BP_tmp5
2183 		 %BP_tmp7 = OpSelect %i32 %BP_tmp6 %c_i32_1 %c_i32_0
2184 		 %BP_tmp8 = OpAccessChain %up_i32 %block %c_i32_0 %c_i32_0
2185 					OpStore %BP_tmp8 %BP_tmp7
2186 
2187 					OpReturn
2188 					OpFunctionEnd
2189 
2190 					${testfun}
2191 	)");
2192 
2193 	const StringTemplate	decoration		("OpDecorate %input DescriptorSet 0\n"
2194 											 "OpDecorate %input Binding 0\n"
2195 											 "OpDecorate %input NonWritable\n"
2196 											 "OpDecorate %expectedOutput DescriptorSet 0\n"
2197 											 "OpDecorate %expectedOutput Binding 1\n"
2198 											 "OpDecorate %expectedOutput NonWritable\n"
2199 											 "OpDecorate %a${num_elements}testtype ArrayStride ${typesize}\n"
2200 											 "OpDecorate %buf BufferBlock\n"
2201 											 "OpMemberDecorate %buf 0 Offset 0\n");
2202 
2203 	const StringTemplate	pre_pre_main	("%fp_bool = OpTypePointer Function %bool\n"
2204 											 "%c_u32_${num_elements} = OpConstant %u32 ${num_elements}\n"
2205 											 "%c_i32_${num_elements} = OpConstant %i32 ${num_elements}\n");
2206 
2207 	const StringTemplate	scalar_pre_main	("%testtype = ${scalartype}\n");
2208 
2209 	const StringTemplate	post_pre_main	("%c_casedefault = OpConstant %${testtype} 10\n"
2210 											 "%c_case0 = OpConstant %${testtype} 100\n"
2211 											 "%c_case1 = OpConstant %${testtype} 110\n"
2212 											 "%c_case2 = OpConstant %${testtype} 120\n"
2213 											 "%fail_color = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_1\n"
2214 											 "%a${num_elements}testtype = OpTypeArray %${testtype} %c_u32_${num_elements}\n"
2215 											 "%up_testtype = OpTypePointer Uniform %${testtype}\n"
2216 											 "%buf = OpTypeStruct %a${num_elements}testtype\n"
2217 											 "%bufptr = OpTypePointer Uniform %buf\n"
2218 											 "%input = OpVariable %bufptr Uniform\n"
2219 											 "%expectedOutput = OpVariable %bufptr Uniform\n");
2220 
2221 	const StringTemplate	testfun			("%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
2222 											 "%param = OpFunctionParameter %v4f32\n"
2223 
2224 											 "%entry = OpLabel\n"
2225 											 "%counter = OpVariable %fp_i32 Function\n"
2226 											 "%return = OpVariable %fp_v4f32 Function\n"
2227 											 "%works = OpVariable %fp_bool Function\n"
2228 											 "OpStore %counter %c_i32_0\n"
2229 											 "OpStore %return %param\n"
2230 											 "OpBranch %loop\n"
2231 
2232 											 "%loop = OpLabel\n"
2233 											 "%counter_val = OpLoad %i32 %counter\n"
2234 											 "%lt = OpSLessThan %bool %counter_val %c_i32_${num_elements}\n"
2235 											 "OpLoopMerge %loop_exit %inc None\n"
2236 											 "OpBranchConditional %lt %load %loop_exit\n"
2237 
2238 											 "%load = OpLabel\n"
2239 											 "%input_loc = OpAccessChain %up_testtype %input %c_i32_0 %counter_val\n"
2240 											 "%input_val = OpLoad %${testtype} %input_loc\n"
2241 											 "%expectedOutput_loc = OpAccessChain %up_testtype %expectedOutput %c_i32_0 %counter_val\n"
2242 											 "%expectedOutput_val = OpLoad %${testtype} %expectedOutput_loc\n"
2243 
2244 											 "OpSelectionMerge %switch_exit None\n"
2245 											 "OpSwitch %input_val %default ${case0} %case0 ${case1} %case1 ${case2} %case2\n"
2246 
2247 											 "%default = OpLabel\n"
2248 											 "%is_default = OpIEqual %bool %expectedOutput_val %c_casedefault\n"
2249 											 "OpBranch %switch_exit\n"
2250 
2251 											 "%case0 = OpLabel\n"
2252 											 "%is_case0 = OpIEqual %bool %expectedOutput_val %c_case0\n"
2253 											 "OpBranch %switch_exit\n"
2254 
2255 											 "%case1 = OpLabel\n"
2256 											 "%is_case1 = OpIEqual %bool %expectedOutput_val %c_case1\n"
2257 											 "OpBranch %switch_exit\n"
2258 
2259 											 "%case2 = OpLabel\n"
2260 											 "%is_case2 = OpIEqual %bool %expectedOutput_val %c_case2\n"
2261 											 "OpBranch %switch_exit\n"
2262 
2263 											 "%switch_exit = OpLabel\n"
2264 											 "%case_result = OpPhi %bool %is_default %default %is_case0 %case0 %is_case1 %case1 %is_case2 %case2\n"
2265 											 "OpSelectionMerge %result_end None\n"
2266 											 "OpBranchConditional %case_result %result_correct %result_incorrect\n"
2267 
2268 											 "%result_correct = OpLabel\n"
2269 											 "OpBranch %result_end\n"
2270 
2271 											 "%result_incorrect = OpLabel\n"
2272 											 "%counter_val_end = OpIAdd %i32 %counter_val %c_i32_${num_elements}\n"
2273 											 "OpStore %counter %counter_val_end\n"
2274 											 "OpStore %return %fail_color\n"
2275 											 "OpBranch %result_end\n"
2276 
2277 											 "%result_end = OpLabel\n"
2278 											 "OpBranch %inc\n"
2279 
2280 											 "%inc = OpLabel\n"
2281 											 "%counter_val_next = OpIAdd %i32 %counter_val %c_i32_1\n"
2282 											 "OpStore %counter %counter_val_next\n"
2283 											 "OpBranch %loop\n"
2284 
2285 											 "%loop_exit = OpLabel\n"
2286 											 "%return_val = OpLoad %v4f32 %return\n"
2287 											 "OpReturnValue %return_val\n"
2288 
2289 											 "OpFunctionEnd\n");
2290 
2291 	const bool				uses8bit		(m_inputType == TYPE_I8 || m_inputType == TYPE_U8);
2292 
2293 	GraphicsResources		resources;
2294 	ComputeShaderSpec		computeResources;
2295 	RGBA					defaultColors[4];
2296 	map<string, string>		fragments;
2297 	map<string, string>		specs;
2298 	std::vector<string>		noExtensions;
2299 	std::vector<string>		features;
2300 	VulkanFeatures			requiredFeatures;
2301 	vector<T>				dataset;
2302 	deUint32				numElements;
2303 	std::string				spirvExtensions;
2304 	std::string				spirvCapabilities;
2305 
2306 	getDefaultColors(defaultColors);
2307 
2308 	dataset.reserve(TEST_DATASET_SIZE);
2309 	getDataset(dataset, TEST_DATASET_SIZE);
2310 	numElements = fillResources(resources, computeResources, dataset);
2311 
2312 	if (m_deviceFeature)
2313 		features.insert(features.begin(), m_deviceFeature);
2314 
2315 	if (uses8bit)
2316 	{
2317 		requiredFeatures.extFloat16Int8.shaderInt8 = true;
2318 	}
2319 
2320 	if (m_inputType == TYPE_I8 || m_inputType == TYPE_U8)
2321 	{
2322 		requiredFeatures.ext8BitStorage.storageBuffer8BitAccess = true;
2323 		spirvExtensions						+= "OpExtension \"SPV_KHR_8bit_storage\"\n";
2324 	}
2325 
2326 	if (m_inputType == TYPE_I16 || m_inputType == TYPE_U16)
2327 	{
2328 		requiredFeatures.ext16BitStorage.storageBuffer16BitAccess = true;
2329 		spirvExtensions						+= "OpExtension \"SPV_KHR_16bit_storage\"\n";
2330 	}
2331 
2332 	specs["testtype"] = m_spirvTestType;
2333 	specs["scalartype"] = m_spirvType;
2334 	specs["typesize"] = de::toString(m_typeSize / 8);
2335 	specs["num_elements"] = de::toString(numElements);
2336 	specs["case0"] = de::toString(m_cases[0]);
2337 	specs["case1"] = de::toString(m_cases[1]);
2338 	specs["case2"] = de::toString(m_cases[2]);
2339 
2340 	fragments["decoration"] = decoration.specialize(specs);
2341 
2342 	fragments["pre_main"] = pre_pre_main.specialize(specs);
2343 	if (specs["testtype"].compare(UNDEFINED_SPIRV_TEST_TYPE) == 0)
2344 		fragments["pre_main"] += scalar_pre_main.specialize(specs);
2345 	fragments["pre_main"] += post_pre_main.specialize(specs);
2346 
2347 	fragments["testfun"] = testfun.specialize(specs);
2348 
2349 	spirvCapabilities += getSpirvCapabilityStr(m_spirvCapability, WIDTH_DEFAULT);
2350 
2351 	fragments["extension"]	= spirvExtensions;
2352 	fragments["capability"]	= spirvCapabilities;
2353 
2354 	requiredFeaturesFromStrings(features, requiredFeatures);
2355 	computeResources.requestedVulkanFeatures = requiredFeatures;
2356 
2357 	const string testName = "switch";
2358 
2359 	createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, noExtensions, this, requiredFeatures);
2360 	createComputeTest(computeResources, computeShaderSwitchTemplate, fragments, *this, testName);
2361 }
2362 
2363 template <class T>
getConstantDataset(vector<T> inputDataset,vector<T> & outputDataset,deUint32 spirvOperation)2364 void SpvAsmTypeTests<T>::getConstantDataset (vector<T> inputDataset, vector<T>& outputDataset, deUint32 spirvOperation)
2365 {
2366 	const deUint32 numElements = (deUint32)inputDataset.size();
2367 
2368 	if ((SpvOpConstant == spirvOperation) || (SpvOpSpecConstant == spirvOperation))
2369 	{
2370 		for (deUint32 elementNdx = 0u; elementNdx < numElements; elementNdx++)
2371 			outputDataset.push_back(inputDataset[elementNdx]);
2372 	}
2373 	else
2374 	{
2375 		for (deUint32 elementNdx = 0; elementNdx < numElements * m_vectorSize; elementNdx++)
2376 			outputDataset.push_back(inputDataset[getConstituentIndex(elementNdx, m_vectorSize)]);
2377 	}
2378 }
2379 
2380 template <class T>
finalizeFullOperation(string & fullOperation,const string & resultName,const bool returnHighPart,const bool isBooleanResult)2381 void SpvAsmTypeTests<T>::finalizeFullOperation (string&			fullOperation,
2382 												const string&	resultName,
2383 												const bool		returnHighPart,
2384 												const bool		isBooleanResult)
2385 {
2386 	DE_ASSERT(!fullOperation.empty());
2387 
2388 	if (returnHighPart)
2389 	{
2390 		DE_ASSERT(sizeof(T) == sizeof(deInt16));
2391 		DE_ASSERT((m_inputType == TYPE_I16) || (m_inputType == TYPE_U16));
2392 
2393 		const bool		signedness		= (m_inputType == TYPE_I16);
2394 		const string	convertOp		= signedness ? "OpSConvert" : "OpUConvert";
2395 		const string	convertPrefix	= (m_vectorSize == 1) ? "" : "v" + de::toString(m_vectorSize);
2396 		const string	convertType		= convertPrefix + "u32";
2397 
2398 		// Zero extend value to double-width value, then return high part
2399 		fullOperation += "%op_result_a = OpUConvert %" + convertType + " " + resultName + "\n";
2400 		fullOperation += "%op_result_b = OpShiftRightLogical %" + convertType + " %op_result_a %c_shift\n";
2401 		fullOperation += "%op_result   = " + convertOp + " %" + m_spirvTestType + " %op_result_b\n";
2402 	}
2403 	else if (isBooleanResult)
2404 	{
2405 		const string selectType = (m_vectorSize == 1) ? ("u32") : ("v" + de::toString(m_vectorSize) + "u32");
2406 
2407 		// Convert boolean values to result format
2408 		if (m_inputType == TYPE_U32)
2409 		{
2410 			fullOperation += "%op_result     = OpSelect %" + selectType + " %op_result_pre %c_one %c_zero\n";
2411 		}
2412 		else
2413 		{
2414 			fullOperation += "%op_result_u32 = OpSelect %" + selectType + " %op_result_pre %c_one %c_zero\n";
2415 
2416 			if (m_typeSize == 32)
2417 				fullOperation += "%op_result     = OpBitcast %" + m_spirvTestType + " %op_result_u32\n";
2418 			else
2419 				fullOperation += "%op_result     = OpSConvert %" + m_spirvTestType + " %op_result_u32\n";
2420 		}
2421 	}
2422 	else
2423 	{
2424 		DE_ASSERT(resultName == "%op_result");
2425 	}
2426 }
2427 
2428 template <class T>
filterNone(T)2429 bool SpvAsmTypeTests<T>::filterNone	(T)
2430 {
2431 	return true;
2432 }
2433 
2434 template <class T>
filterNone(T,T)2435 bool SpvAsmTypeTests<T>::filterNone (T, T)
2436 {
2437 	return true;
2438 }
2439 
2440 template <class T>
filterNone(T,T,T)2441 bool SpvAsmTypeTests<T>::filterNone (T, T, T)
2442 {
2443 	return true;
2444 }
2445 
2446 template <class T>
filterNone(T,T,T,T)2447 bool SpvAsmTypeTests<T>::filterNone (T, T, T, T)
2448 {
2449 	return true;
2450 }
2451 
2452 template <class T>
filterZero(T,T b)2453 bool SpvAsmTypeTests<T>::filterZero	(T, T b)
2454 {
2455 	if (b == static_cast<T>(0))
2456 		return false;
2457 	else
2458 		return true;
2459 }
2460 
2461 template <class T>
filterNegativesAndZero(T a,T b)2462 bool SpvAsmTypeTests<T>::filterNegativesAndZero	(T a, T b)
2463 {
2464 	if (a < static_cast<T>(0) || b <= static_cast<T>(0))
2465 		return false;
2466 	else
2467 		return true;
2468 }
2469 
2470 template <class T>
filterMinGtMax(T,T a,T b)2471 bool SpvAsmTypeTests<T>::filterMinGtMax	(T, T a, T b)
2472 {
2473 	if (a > b)
2474 		return false;
2475 	else
2476 		return true;
2477 }
2478 
2479 template <class T>
zero(T)2480 T SpvAsmTypeTests<T>::zero (T)
2481 {
2482 	return static_cast<T>(0.0);
2483 }
2484 
2485 template <class T>
zero(T,T)2486 T SpvAsmTypeTests<T>::zero (T, T)
2487 {
2488 	return static_cast<T>(0.0);
2489 }
2490 
2491 template <class T>
zero(T,T,T)2492 T SpvAsmTypeTests<T>::zero (T, T, T)
2493 {
2494 	return static_cast<T>(0.0);
2495 }
2496 
2497 template <class T>
zero(T,T,T,T)2498 T SpvAsmTypeTests<T>::zero (T, T, T, T)
2499 {
2500 	return static_cast<T>(0.0);
2501 }
2502 
2503 template <class T>
replicate(const std::string & replicant,const deUint32 count)2504 std::string	SpvAsmTypeTests<T>::replicate (const std::string&	replicant,
2505 										   const deUint32		count)
2506 {
2507 	std::string result;
2508 
2509 	for (deUint32 i = 0; i < count; ++i)
2510 		result += replicant;
2511 
2512 	return result;
2513 }
2514 
2515 class SpvAsmTypeInt8Tests : public SpvAsmTypeTests<deInt8>
2516 {
2517 public:
2518 				SpvAsmTypeInt8Tests		(tcu::TestContext&		testCtx,
2519 										 deUint32				vectorSize);
2520 				~SpvAsmTypeInt8Tests	(void);
2521 	void		getDataset				(vector<deInt8>&		input,
2522 										 deUint32				numElements);
2523 	void		pushResource			(vector<Resource>&		resource,
2524 										 const vector<deInt8>&	data);
2525 };
2526 
SpvAsmTypeInt8Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2527 SpvAsmTypeInt8Tests::SpvAsmTypeInt8Tests	(tcu::TestContext&	testCtx,
2528 											 deUint32			vectorSize)
2529 	: SpvAsmTypeTests	(testCtx, "i8", "int8 tests", DE_NULL, "Int8", "OpTypeInt 8 1", TYPE_I8, 8, vectorSize)
2530 {
2531 	m_cases[0] = -42;
2532 	m_cases[1] = 73;
2533 	m_cases[2] = 121;
2534 }
2535 
~SpvAsmTypeInt8Tests(void)2536 SpvAsmTypeInt8Tests::~SpvAsmTypeInt8Tests (void)
2537 {
2538 }
2539 
getDataset(vector<deInt8> & input,deUint32 numElements)2540 void SpvAsmTypeInt8Tests::getDataset (vector<deInt8>&	input,
2541 									  deUint32			numElements)
2542 {
2543 	// Push first special cases
2544 	input.push_back(0);
2545 	input.push_back(static_cast<deInt8>(deIntMinValue32(8)));// A 8-bit negative number
2546 	input.push_back(static_cast<deInt8>(deIntMaxValue32(8)));// A 8-bit positive number
2547 
2548 	// Push switch cases
2549 	input.push_back(m_cases[0]);
2550 	input.push_back(m_cases[1]);
2551 	input.push_back(m_cases[2]);
2552 
2553 	numElements -= static_cast<deUint32>(input.size());
2554 
2555 	// Random values
2556 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2557 		input.push_back(static_cast<deInt8>(m_rnd.getUint8()));
2558 }
2559 
pushResource(vector<Resource> & resource,const vector<deInt8> & data)2560 void SpvAsmTypeInt8Tests::pushResource (vector<Resource>&		resource,
2561 										const vector<deInt8>&	data)
2562 {
2563 	resource.push_back(Resource(BufferSp(new Int8Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2564 }
2565 
2566 class SpvAsmTypeInt16Tests : public SpvAsmTypeTests<deInt16>
2567 {
2568 public:
2569 				SpvAsmTypeInt16Tests	(tcu::TestContext&		testCtx,
2570 										 deUint32				vectorSize);
2571 				~SpvAsmTypeInt16Tests	(void);
2572 	void		getDataset				(vector<deInt16>&		input,
2573 										 deUint32				numElements);
2574 	void		pushResource			(vector<Resource>&		resource,
2575 										 const vector<deInt16>&	data);
2576 };
2577 
SpvAsmTypeInt16Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2578 SpvAsmTypeInt16Tests::SpvAsmTypeInt16Tests	(tcu::TestContext&	testCtx,
2579 											 deUint32			vectorSize)
2580 	: SpvAsmTypeTests	(testCtx, "i16", "int16 tests", "shaderInt16", "Int16", "OpTypeInt 16 1", TYPE_I16, 16, vectorSize)
2581 {
2582 	m_cases[0] = -3221;
2583 	m_cases[1] = 3210;
2584 	m_cases[2] = 19597;
2585 }
2586 
~SpvAsmTypeInt16Tests(void)2587 SpvAsmTypeInt16Tests::~SpvAsmTypeInt16Tests (void)
2588 {
2589 }
2590 
getDataset(vector<deInt16> & input,deUint32 numElements)2591 void SpvAsmTypeInt16Tests::getDataset (vector<deInt16>&	input,
2592 									   deUint32			numElements)
2593 {
2594 	// Push first special cases
2595 	input.push_back(0);
2596 	input.push_back(static_cast<deInt16>(deIntMinValue32(16)));// A 16-bit negative number
2597 	input.push_back(static_cast<deInt16>(deIntMaxValue32(16)));// A 16-bit positive number
2598 
2599 	// Push switch cases
2600 	input.push_back(m_cases[0]);
2601 	input.push_back(m_cases[1]);
2602 	input.push_back(m_cases[2]);
2603 
2604 	numElements -= static_cast<deUint32>(input.size());
2605 
2606 	// Random values
2607 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2608 		input.push_back(static_cast<deInt16>(m_rnd.getUint16()));
2609 }
2610 
pushResource(vector<Resource> & resource,const vector<deInt16> & data)2611 void SpvAsmTypeInt16Tests::pushResource (vector<Resource>&		resource,
2612 										 const vector<deInt16>&	data)
2613 {
2614 	resource.push_back(Resource(BufferSp(new Int16Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2615 }
2616 
2617 class SpvAsmTypeInt32Tests : public SpvAsmTypeTests<deInt32>
2618 {
2619 public:
2620 				SpvAsmTypeInt32Tests	(tcu::TestContext&		testCtx,
2621 										 deUint32				vectorSize);
2622 				~SpvAsmTypeInt32Tests	(void);
2623 	void		getDataset				(vector<deInt32>&		input,
2624 										 deUint32				numElements);
2625 	void		pushResource			(vector<Resource>&		resource,
2626 										 const vector<deInt32>&	data);
2627 };
2628 
SpvAsmTypeInt32Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2629 SpvAsmTypeInt32Tests::SpvAsmTypeInt32Tests (tcu::TestContext&	testCtx,
2630 											deUint32			vectorSize)
2631 	: SpvAsmTypeTests	(testCtx, "i32", "int32 tests", DE_NULL, DE_NULL, "OpTypeInt 32 1", TYPE_I32, 32, vectorSize)
2632 {
2633 	m_cases[0] = -3221;
2634 	m_cases[1] = 3210;
2635 	m_cases[2] = 268438669;
2636 }
2637 
~SpvAsmTypeInt32Tests(void)2638 SpvAsmTypeInt32Tests::~SpvAsmTypeInt32Tests (void)
2639 {
2640 }
2641 
getDataset(vector<deInt32> & input,deUint32 numElements)2642 void SpvAsmTypeInt32Tests::getDataset (vector<deInt32>&	input,
2643 									   deUint32			numElements)
2644 {
2645 	// Push first special cases
2646 	input.push_back(0);
2647 	input.push_back(deIntMinValue32(32) + 1); // So MIN = -MAX
2648 	input.push_back(deIntMaxValue32(32));
2649 
2650 	// Push switch cases
2651 	input.push_back(m_cases[0]);
2652 	input.push_back(m_cases[1]);
2653 	input.push_back(m_cases[2]);
2654 
2655 	numElements -= static_cast<deUint32>(input.size());
2656 
2657 	// Random values
2658 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2659 		input.push_back(static_cast<deInt32>(m_rnd.getUint32()));
2660 }
2661 
pushResource(vector<Resource> & resource,const vector<deInt32> & data)2662 void SpvAsmTypeInt32Tests::pushResource (vector<Resource>&		resource,
2663 										 const vector<deInt32>&	data)
2664 {
2665 	resource.push_back(Resource(BufferSp(new Int32Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2666 }
2667 
2668 class SpvAsmTypeInt64Tests : public SpvAsmTypeTests<deInt64>
2669 {
2670 public:
2671 				SpvAsmTypeInt64Tests	(tcu::TestContext&		testCtx,
2672 										 deUint32				vectorSize);
2673 				~SpvAsmTypeInt64Tests	(void);
2674 	void		getDataset				(vector<deInt64>&		input,
2675 										 deUint32				numElements);
2676 	void		pushResource			(vector<Resource>&		resource,
2677 										 const vector<deInt64>&	data);
2678 };
2679 
SpvAsmTypeInt64Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2680 SpvAsmTypeInt64Tests::SpvAsmTypeInt64Tests (tcu::TestContext&	testCtx,
2681 											deUint32			vectorSize)
2682 	: SpvAsmTypeTests	(testCtx, "i64", "int64 tests", "shaderInt64", "Int64", "OpTypeInt 64 1", TYPE_I64, 64, vectorSize)
2683 {
2684 	m_cases[0] = 3210;
2685 	m_cases[1] = -268438669;
2686 	m_cases[2] = 26843866939192872;
2687 }
2688 
~SpvAsmTypeInt64Tests(void)2689 SpvAsmTypeInt64Tests::~SpvAsmTypeInt64Tests (void)
2690 {
2691 }
2692 
getDataset(vector<deInt64> & input,deUint32 numElements)2693 void SpvAsmTypeInt64Tests::getDataset (vector<deInt64>&	input,
2694 									   deUint32			numElements)
2695 {
2696 	// Push first special cases
2697 	input.push_back(0);
2698 	input.push_back(0xFFFF859A3BF78592);// A 64-bit negative number
2699 	input.push_back(0x7FFF859A3BF78592);// A 64-bit positive number
2700 
2701 	// Push switch cases
2702 	input.push_back(m_cases[0]);
2703 	input.push_back(m_cases[1]);
2704 	input.push_back(m_cases[2]);
2705 
2706 	numElements -= static_cast<deUint32>(input.size());
2707 
2708 	// Random values
2709 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2710 		input.push_back(static_cast<deInt64>(m_rnd.getUint64()));
2711 }
2712 
pushResource(vector<Resource> & resource,const vector<deInt64> & data)2713 void SpvAsmTypeInt64Tests::pushResource	(vector<Resource>&		resource,
2714 										 const vector<deInt64>&	data)
2715 {
2716 	resource.push_back(Resource(BufferSp(new Int64Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2717 }
2718 
2719 class SpvAsmTypeUint8Tests : public SpvAsmTypeTests<deUint8>
2720 {
2721 public:
2722 				SpvAsmTypeUint8Tests	(tcu::TestContext&		testCtx,
2723 										 deUint32				vectorSize);
2724 				~SpvAsmTypeUint8Tests	(void);
2725 	void		getDataset				(vector<deUint8>&		input,
2726 										 deUint32				numElements);
2727 	void		pushResource			(vector<Resource>&		resource,
2728 										 const vector<deUint8>&	data);
2729 };
2730 
SpvAsmTypeUint8Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2731 SpvAsmTypeUint8Tests::SpvAsmTypeUint8Tests	(tcu::TestContext&	testCtx,
2732 											 deUint32			vectorSize)
2733 	: SpvAsmTypeTests	(testCtx, "u8", "uint8 tests", DE_NULL, "Int8", "OpTypeInt 8 0", TYPE_U8, 8, vectorSize)
2734 {
2735 	m_cases[0] = 0;
2736 	m_cases[1] = 73;
2737 	m_cases[2] = 193;
2738 }
2739 
~SpvAsmTypeUint8Tests(void)2740 SpvAsmTypeUint8Tests::~SpvAsmTypeUint8Tests (void)
2741 {
2742 }
2743 
getDataset(vector<deUint8> & input,deUint32 numElements)2744 void SpvAsmTypeUint8Tests::getDataset (vector<deUint8>&	input,
2745 									   deUint32			numElements)
2746 {
2747 	// Push first special cases
2748 	input.push_back(0);  // Min value
2749 	input.push_back(~0); // Max value
2750 
2751 	//Push switch cases
2752 	input.push_back(m_cases[0]);
2753 	input.push_back(m_cases[1]);
2754 	input.push_back(m_cases[2]);
2755 
2756 	numElements -= static_cast<deUint32>(input.size());
2757 
2758 	// Random values
2759 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2760 		input.push_back(m_rnd.getUint8());
2761 }
2762 
pushResource(vector<Resource> & resource,const vector<deUint8> & data)2763 void SpvAsmTypeUint8Tests::pushResource (vector<Resource>&		resource,
2764 										 const vector<deUint8>&	data)
2765 {
2766 	resource.push_back(Resource(BufferSp(new Uint8Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2767 }
2768 
2769 class SpvAsmTypeUint16Tests : public SpvAsmTypeTests<deUint16>
2770 {
2771 public:
2772 				SpvAsmTypeUint16Tests	(tcu::TestContext&			testCtx,
2773 										 deUint32					vectorSize);
2774 				~SpvAsmTypeUint16Tests	(void);
2775 	void		getDataset				(vector<deUint16>&			input,
2776 										 deUint32					numElements);
2777 	void		pushResource			(vector<Resource>&			resource,
2778 										 const vector<deUint16>&	data);
2779 };
2780 
SpvAsmTypeUint16Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2781 SpvAsmTypeUint16Tests::SpvAsmTypeUint16Tests	(tcu::TestContext&	testCtx,
2782 												 deUint32			vectorSize)
2783 	: SpvAsmTypeTests	(testCtx, "u16", "uint16 tests", "shaderInt16", "Int16", "OpTypeInt 16 0", TYPE_U16, 16, vectorSize)
2784 {
2785 	m_cases[0] = 0;
2786 	m_cases[1] = 3210;
2787 	m_cases[2] = 19597;
2788 }
2789 
~SpvAsmTypeUint16Tests(void)2790 SpvAsmTypeUint16Tests::~SpvAsmTypeUint16Tests (void)
2791 {
2792 }
2793 
getDataset(vector<deUint16> & input,deUint32 numElements)2794 void SpvAsmTypeUint16Tests::getDataset (vector<deUint16>&	input,
2795 										deUint32			numElements)
2796 {
2797 	// Push first special cases
2798 	input.push_back(0);  // Min value
2799 	input.push_back(~0); // Max value
2800 
2801 	//Push switch cases
2802 	input.push_back(m_cases[0]);
2803 	input.push_back(m_cases[1]);
2804 	input.push_back(m_cases[2]);
2805 
2806 	numElements -= static_cast<deUint32>(input.size());
2807 
2808 	// Random values
2809 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2810 		input.push_back(m_rnd.getUint16());
2811 }
2812 
pushResource(vector<Resource> & resource,const vector<deUint16> & data)2813 void SpvAsmTypeUint16Tests::pushResource (vector<Resource>&			resource,
2814 										  const vector<deUint16>&	data)
2815 {
2816 	resource.push_back(Resource(BufferSp(new Uint16Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2817 }
2818 
2819 class SpvAsmTypeUint32Tests : public SpvAsmTypeTests<deUint32>
2820 {
2821 public:
2822 				SpvAsmTypeUint32Tests	(tcu::TestContext&			testCtx,
2823 										 deUint32					vectorSize);
2824 				~SpvAsmTypeUint32Tests	(void);
2825 	void		getDataset				(vector<deUint32>&			input,
2826 										 deUint32					numElements);
2827 	void		pushResource			(vector<Resource>&			resource,
2828 										 const vector<deUint32>&	data);
2829 };
2830 
SpvAsmTypeUint32Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2831 SpvAsmTypeUint32Tests::SpvAsmTypeUint32Tests (tcu::TestContext&	testCtx,
2832 											  deUint32			vectorSize)
2833 	: SpvAsmTypeTests	(testCtx, "u32", "uint32 tests", DE_NULL, DE_NULL, "OpTypeInt 32 0", TYPE_U32, 32, vectorSize)
2834 {
2835 	m_cases[0] = 0;
2836 	m_cases[1] = 3210;
2837 	m_cases[2] = 268438669;
2838 }
2839 
~SpvAsmTypeUint32Tests(void)2840 SpvAsmTypeUint32Tests::~SpvAsmTypeUint32Tests (void)
2841 {
2842 }
2843 
getDataset(vector<deUint32> & input,deUint32 numElements)2844 void SpvAsmTypeUint32Tests::getDataset (vector<deUint32>&	input,
2845 										deUint32			numElements)
2846 {
2847 	// Push first special cases
2848 	input.push_back(0);  // Min value
2849 	input.push_back(~0); // Max value
2850 
2851 	// Push switch cases
2852 	input.push_back(m_cases[0]);
2853 	input.push_back(m_cases[1]);
2854 	input.push_back(m_cases[2]);
2855 
2856 	numElements -= static_cast<deUint32>(input.size());
2857 
2858 	// Random values
2859 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2860 		input.push_back(m_rnd.getUint32());
2861 }
2862 
pushResource(vector<Resource> & resource,const vector<deUint32> & data)2863 void SpvAsmTypeUint32Tests::pushResource (vector<Resource>&			resource,
2864 										  const vector<deUint32>&	data)
2865 {
2866 	resource.push_back(Resource(BufferSp(new Uint32Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2867 }
2868 
2869 class SpvAsmTypeUint64Tests : public SpvAsmTypeTests<deUint64>
2870 {
2871 public:
2872 				SpvAsmTypeUint64Tests	(tcu::TestContext&			testCtx,
2873 										 deUint32					vectorSize);
2874 				~SpvAsmTypeUint64Tests	(void);
2875 	void		getDataset				(vector<deUint64>&			input,
2876 										 deUint32					numElements);
2877 	void		pushResource			(vector<Resource>&			resource,
2878 										 const vector<deUint64>&	data);
2879 };
2880 
SpvAsmTypeUint64Tests(tcu::TestContext & testCtx,deUint32 vectorSize)2881 SpvAsmTypeUint64Tests::SpvAsmTypeUint64Tests (tcu::TestContext&	testCtx,
2882 											  deUint32			vectorSize)
2883 	: SpvAsmTypeTests	(testCtx, "u64", "uint64 tests", "shaderInt64", "Int64", "OpTypeInt 64 0", TYPE_U64, 64, vectorSize)
2884 {
2885 	m_cases[0] = 3210;
2886 	m_cases[1] = 268438669;
2887 	m_cases[2] = 26843866939192872;
2888 }
2889 
~SpvAsmTypeUint64Tests(void)2890 SpvAsmTypeUint64Tests::~SpvAsmTypeUint64Tests (void)
2891 {
2892 }
2893 
getDataset(vector<deUint64> & input,deUint32 numElements)2894 void SpvAsmTypeUint64Tests::getDataset (vector<deUint64>&	input,
2895 										deUint32			numElements)
2896 {
2897 	// Push first special cases
2898 	input.push_back(0);  // Min value
2899 	input.push_back(~0); // Max value
2900 
2901 	// Push switch cases
2902 	input.push_back(m_cases[0]);
2903 	input.push_back(m_cases[1]);
2904 	input.push_back(m_cases[2]);
2905 
2906 	numElements -= static_cast<deUint32>(input.size());
2907 
2908 	// Random values
2909 	for (deUint32 elemNdx = 0; elemNdx < numElements; ++elemNdx)
2910 		input.push_back(m_rnd.getUint64());
2911 }
2912 
pushResource(vector<Resource> & resource,const vector<deUint64> & data)2913 void SpvAsmTypeUint64Tests::pushResource (vector<Resource>&			resource,
2914 										  const vector<deUint64>&	data)
2915 {
2916 	resource.push_back(Resource(BufferSp(new Uint64Buffer(data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2917 }
2918 
2919 template <class T>
2920 class TestMath
2921 {
2922 public:
test_abs(T x)2923 	static inline T test_abs (T x)
2924 	{
2925 		T t0 = static_cast<T>(0.0);
2926 
2927 		if (x >= t0)
2928 			return x;
2929 		else
2930 			return test_negate(x);
2931 	}
2932 
test_add(T x,T y)2933 	static inline T test_add (T x, T y)
2934 	{
2935 		return static_cast<T>(x + y);
2936 	}
2937 
test_clamp(T x,T minVal,T maxVal)2938 	static inline T test_clamp (T x, T minVal, T maxVal)
2939 	{
2940 		return test_min(test_max(x, minVal), maxVal);
2941 	}
2942 
test_div(T x,T y)2943 	static inline T test_div (T x, T y)
2944 	{
2945 		// In SPIR-V, if "y" is 0, then the result is undefined. In our case,
2946 		// let's return 0
2947 		if (y == static_cast<T>(0))
2948 			return 0;
2949 		else
2950 			return static_cast<T>(x / y);
2951 	}
2952 
test_lsb(T x)2953 	static inline T test_lsb (T x)
2954 	{
2955 		for (deUint32 i = 0; i < 8 * sizeof(T); i++)
2956 		{
2957 			if (x & (1u << i))
2958 				return static_cast<T>(i);
2959 		}
2960 
2961 		return static_cast<T>(-1.0);
2962 	}
2963 
test_max(T x,T y)2964 	static inline T test_max (T x, T y)
2965 	{
2966 		if (x < y)
2967 			return y;
2968 		else
2969 			return x;
2970 	}
2971 
test_min(T x,T y)2972 	static inline T test_min (T x, T y)
2973 	{
2974 		if (y < x)
2975 			return y;
2976 		else
2977 			return x;
2978 	}
2979 
test_mod(T x,T y)2980 	static inline T test_mod (T x, T y)
2981 	{
2982 		T sign_x, sign_y;
2983 
2984 		// In SPIR-V, if "y" is 0, then the result is undefined. In our case,
2985 		// let's return 0
2986 		if (y == static_cast<T>(0))
2987 			return 0;
2988 
2989 		if (x >= static_cast<T>(0))
2990 			sign_x = 1;
2991 		else
2992 			sign_x = -1;
2993 
2994 		if (y >= static_cast<T>(0))
2995 			sign_y = 1;
2996 		else
2997 			sign_y = -1;
2998 
2999 		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));
3000 	}
3001 
test_mul(T x,T y)3002 	static inline T test_mul (T x, T y)
3003 	{
3004 		return static_cast<T>(x * y);
3005 	}
3006 
test_negate(T x)3007 	static inline T test_negate (T x)
3008 	{
3009 		return static_cast<T>(static_cast<T>(0.0) - static_cast<T>(x));
3010 	}
3011 
test_rem(T x,T y)3012 	static inline T test_rem (T x, T y)
3013 	{
3014 		// In SPIR-V, if "y" is 0, then the result is undefined. In our case,
3015 		// let's return 0
3016 		if (y == static_cast<T>(0))
3017 			return 0;
3018 
3019 		return static_cast<T>(x % y);
3020 	}
3021 
test_sign(T x)3022 	static inline T test_sign (T x)
3023 	{
3024 		T t0 = static_cast<T>(0.0);
3025 
3026 		if (x > t0)
3027 			return static_cast<T>(1.0);
3028 		else if (x < t0)
3029 			return static_cast<T>(-1.0);
3030 		else
3031 			return t0;
3032 	}
3033 
test_sub(T x,T y)3034 	static inline T test_sub (T x, T y)
3035 	{
3036 		return static_cast<T>(x - y);
3037 	}
3038 
test_msb(T)3039 	static inline T test_msb (T)
3040 	{
3041 		TCU_THROW(InternalError, "Not implemented");
3042 	}
3043 
test_lsr(T x,T y)3044 	static inline T test_lsr (T x, T y)
3045 	{
3046 		if (x >= static_cast<T>(0) || y == static_cast<T>(0))
3047 		{
3048 			return static_cast<T>(x >> y);
3049 		}
3050 		else
3051 		{
3052 			const T	mask = de::leftZeroMask(y);
3053 			return static_cast<T>((x >> y) & mask);
3054 		}
3055 	}
3056 
test_asr(T x,T y)3057 	static inline T test_asr (T x, T y)
3058 	{
3059 		const T bitmask = static_cast<T>(deUint64(1) << (sizeof(T) * 8u - 1u));
3060 
3061 		if ((x & bitmask) && y > 0)
3062 		{
3063 			const T	mask	= de::leftSetMask(y);
3064 			const T	result	= static_cast<T>((x >> y) | mask);
3065 			return result;
3066 		}
3067 		else
3068 		{
3069 			return static_cast<T>(x >> y);
3070 		}
3071 	}
3072 
test_lsl(T x,T y)3073 	static inline T test_lsl (T x, T y)
3074 	{
3075 		return static_cast<T>(x << y);
3076 	}
3077 
test_bitwise_or(T x,T y)3078 	static inline T test_bitwise_or (T x, T y)
3079 	{
3080 		return static_cast<T>(x | y);
3081 	}
3082 
test_bitwise_xor(T x,T y)3083 	static inline T test_bitwise_xor (T x, T y)
3084 	{
3085 		return static_cast<T>(x ^ y);
3086 	}
3087 
test_bitwise_and(T x,T y)3088 	static inline T test_bitwise_and (T x, T y)
3089 	{
3090 		return static_cast<T>(x & y);
3091 	}
3092 
test_not(T x)3093 	static inline T test_not (T x)
3094 	{
3095 		return static_cast<T>(~x);
3096 	}
3097 
test_iequal(T x,T y)3098 	static inline T test_iequal (T x, T y)
3099 	{
3100 		if (x == y)
3101 			return static_cast<T>(1);
3102 		else
3103 			return static_cast<T>(0);
3104 	}
3105 
test_inotequal(T x,T y)3106 	static inline T test_inotequal (T x, T y)
3107 	{
3108 		if (x != y)
3109 			return static_cast<T>(1);
3110 		else
3111 			return static_cast<T>(0);
3112 	}
3113 
test_ugreaterthan(T x,T y)3114 	static inline T test_ugreaterthan (T x, T y)
3115 	{
3116 		if (x > y)
3117 			return static_cast<T>(1);
3118 		else
3119 			return static_cast<T>(0);
3120 	}
3121 
test_ulessthan(T x,T y)3122 	static inline T test_ulessthan (T x, T y)
3123 	{
3124 		return test_ugreaterthan(y, x);
3125 	}
3126 
test_sgreaterthan(T x,T y)3127 	static inline T test_sgreaterthan (T x, T y)
3128 	{
3129 		if (x > y)
3130 			return static_cast<T>(1);
3131 		else
3132 			return static_cast<T>(0);
3133 	}
3134 
test_slessthan(T x,T y)3135 	static inline T test_slessthan (T x, T y)
3136 	{
3137 		return test_sgreaterthan(y, x);
3138 	}
3139 
test_ugreaterthanequal(T x,T y)3140 	static inline T test_ugreaterthanequal (T x, T y)
3141 	{
3142 		if (x >= y)
3143 			return static_cast<T>(1);
3144 		else
3145 			return static_cast<T>(0);
3146 	}
3147 
test_ulessthanequal(T x,T y)3148 	static inline T test_ulessthanequal (T x, T y)
3149 	{
3150 		return test_ugreaterthanequal(y, x);
3151 	}
3152 
test_sgreaterthanequal(T x,T y)3153 	static inline T test_sgreaterthanequal (T x, T y)
3154 	{
3155 		if (x >= y)
3156 			return static_cast<T>(1);
3157 		else
3158 			return static_cast<T>(0);
3159 	}
3160 
test_slessthanequal(T x,T y)3161 	static inline T test_slessthanequal (T x, T y)
3162 	{
3163 		return test_sgreaterthanequal(y, x);
3164 	}
3165 
test_bitFieldInsert(T base,T insert,T offset,T count)3166 	static inline T test_bitFieldInsert (T base, T insert, T offset, T count)
3167 	{
3168 		const T	insertMask	= de::rightSetMask(count);
3169 
3170 		return static_cast<T>((base & ~(insertMask << offset)) | ((insert & insertMask) << offset));
3171 	}
3172 
test_bitFieldSExtract(T x,T y,T z)3173 	static inline T test_bitFieldSExtract (T x, T y, T z)
3174 	{
3175 		const T allZeros	= static_cast<T>(0);
3176 
3177 		// Count can be 0, in which case the result will be 0
3178 		if (z == allZeros)
3179 			return allZeros;
3180 
3181 		const T extractMask	= de::rightSetMask(z);
3182 		const T signBit		= static_cast<T>(x & (1 << (y + z - 1)));
3183 		const T signMask	= static_cast<T>(signBit ? ~extractMask : allZeros);
3184 
3185 		return static_cast<T>((signMask & ~extractMask) | ((x >> y) & extractMask));
3186 	}
3187 
test_bitFieldUExtract(T x,T y,T z)3188 	static inline T test_bitFieldUExtract (T x, T y, T z)
3189 	{
3190 		const T allZeros	= (static_cast<T>(0));
3191 
3192 		// Count can be 0, in which case the result will be 0
3193 		if (z == allZeros)
3194 			return allZeros;
3195 
3196 		const T extractMask	= de::rightSetMask(z);
3197 
3198 		return static_cast<T>((x >> y) & extractMask);
3199 	}
3200 
test_bitReverse(T x)3201 	static inline T test_bitReverse (T x)
3202 	{
3203 		T		base	= x;
3204 		T		result	= static_cast<T>(0);
3205 
3206 		for (size_t bitNdx = 0u; bitNdx < sizeof(T) * 8u; bitNdx++)
3207 		{
3208 			result = static_cast<T>(result << 1) | (base & 1);
3209 			base >>= 1;
3210 		}
3211 
3212 		return result;
3213 	}
3214 
test_bitCount(T x)3215 	static inline T test_bitCount (T x)
3216 	{
3217 		T count	= static_cast<T>(0);
3218 
3219 		for (deUint32 bitNdx = 0u; bitNdx < (deUint32)sizeof(T) * 8u; bitNdx++)
3220 			if (x & (static_cast<T>(1) << bitNdx))
3221 				count++;
3222 
3223 		return count;
3224 	}
3225 
test_constant(T a)3226 	static inline T test_constant (T a)
3227 	{
3228 		return a;
3229 	}
3230 };
3231 
3232 class TestMathInt8 : public TestMath<deInt8>
3233 {
3234 public:
test_msb(deInt8 x)3235 	static inline deInt8 test_msb (deInt8 x)
3236 	{
3237 		if (x > 0)
3238 			return static_cast<deInt8>(7 - deClz32((deUint32)x));
3239 		else if (x < 0)
3240 			return static_cast<deInt8>(7 - deClz32(~(deUint32)x));
3241 		else
3242 			return -1;
3243 	}
3244 
test_mul_div(deInt8 x,deInt8 y)3245 	static inline deInt8 test_mul_div (deInt8 x, deInt8 y)
3246 	{
3247 		deInt32	x32	= static_cast<deInt32>(x);
3248 		deInt32	y32	= static_cast<deInt32>(y);
3249 
3250 		// In SPIR-V, if "y" is 0, then the result is undefined. In our case, let's return 0
3251 		if (y == static_cast<deInt8>(0))
3252 			return 0;
3253 		else
3254 			return static_cast<deInt8>(static_cast<deInt8>(x32 * y32) / y32);
3255 	}
3256 
test_ugreaterthan(deInt8 x,deInt8 y)3257 	static inline deInt8 test_ugreaterthan (deInt8 x, deInt8 y)
3258 	{
3259 		// Consume signed integers as unsigned integers
3260 		if ((x & 0x80) ^ (y & 0x80))
3261 			std::swap(x,y);
3262 
3263 		if (x > y)
3264 			return static_cast<deInt8>(1);
3265 		else
3266 			return static_cast<deInt8>(0);
3267 	}
3268 
test_ulessthan(deInt8 x,deInt8 y)3269 	static inline deInt8 test_ulessthan (deInt8 x, deInt8 y)
3270 	{
3271 		return test_ugreaterthan(y, x);
3272 	}
3273 
test_ugreaterthanequal(deInt8 x,deInt8 y)3274 	static inline deInt8 test_ugreaterthanequal (deInt8 x, deInt8 y)
3275 	{
3276 		// Consume signed integers as unsigned integers
3277 		if ((x & 0x80) ^ (y & 0x80))
3278 			std::swap(x,y);
3279 
3280 		if (x >= y)
3281 			return static_cast<deInt8>(1);
3282 		else
3283 			return static_cast<deInt8>(0);
3284 	}
3285 
test_ulessthanequal(deInt8 x,deInt8 y)3286 	static inline deInt8 test_ulessthanequal (deInt8 x, deInt8 y)
3287 	{
3288 		return test_ugreaterthanequal(y, x);
3289 	}
3290 };
3291 
3292 class TestMathInt16 : public TestMath<deInt16>
3293 {
3294 public:
test_msb(deInt16 x)3295 	static inline deInt16 test_msb (deInt16 x)
3296 	{
3297 		if (x > 0)
3298 			return static_cast<deInt16>(15 - deClz32((deUint32)x));
3299 		else if (x < 0)
3300 			return static_cast<deInt16>(15 - deClz32(~(deUint32)x));
3301 		else
3302 			return -1;
3303 	}
3304 
test_mul_div(deInt16 x,deInt16 y)3305 	static inline deInt16 test_mul_div (deInt16 x, deInt16 y)
3306 	{
3307 		deInt32	x32	= static_cast<deInt32>(x);
3308 		deInt32	y32	= static_cast<deInt32>(y);
3309 
3310 		// In SPIR-V, if "y" is 0, then the result is undefined. In our case, let's return 0
3311 		if (y == static_cast<deInt16>(0))
3312 			return 0;
3313 		else
3314 			return static_cast<deInt16>(static_cast<deInt16>(x32 * y32) / y32);
3315 	}
3316 
test_ugreaterthan(deInt16 x,deInt16 y)3317 	static inline deInt16 test_ugreaterthan (deInt16 x, deInt16 y)
3318 	{
3319 		// Consume signed integers as unsigned integers
3320 		if ((x & 0x8000) ^ (y & 0x8000))
3321 			std::swap(x,y);
3322 
3323 		if (x > y)
3324 			return static_cast<deInt16>(1);
3325 		else
3326 			return static_cast<deInt16>(0);
3327 	}
3328 
test_ulessthan(deInt16 x,deInt16 y)3329 	static inline deInt16 test_ulessthan (deInt16 x, deInt16 y)
3330 	{
3331 		return test_ugreaterthan(y, x);
3332 	}
3333 
test_ugreaterthanequal(deInt16 x,deInt16 y)3334 	static inline deInt16 test_ugreaterthanequal (deInt16 x, deInt16 y)
3335 	{
3336 		// Consume signed integers as unsigned integers
3337 		if ((x & 0x8000) ^ (y & 0x8000))
3338 			std::swap(x,y);
3339 
3340 		if (x >= y)
3341 			return static_cast<deInt16>(1);
3342 		else
3343 			return static_cast<deInt16>(0);
3344 	}
3345 
test_ulessthanequal(deInt16 x,deInt16 y)3346 	static inline deInt16 test_ulessthanequal (deInt16 x, deInt16 y)
3347 	{
3348 		return test_ugreaterthanequal(y, x);
3349 	}
3350 };
3351 
3352 class TestMathInt32 : public TestMath<deInt32>
3353 {
3354 public:
test_msb(deInt32 x)3355 	static inline deInt32 test_msb (deInt32 x)
3356 	{
3357 		if (x > 0)
3358 			return 31 - deClz32((deUint32)x);
3359 		else if (x < 0)
3360 			return 31 - deClz32(~(deUint32)x);
3361 		else
3362 			return -1;
3363 	}
3364 
test_ugreaterthan(deInt32 x,deInt32 y)3365 	static inline deInt32 test_ugreaterthan (deInt32 x, deInt32 y)
3366 	{
3367 		// Consume signed integers as unsigned integers
3368 		if ((x & 0x80000000) ^ (y & 0x80000000))
3369 			std::swap(x,y);
3370 
3371 		if (x > y)
3372 			return static_cast<deInt32>(1);
3373 		else
3374 			return static_cast<deInt32>(0);
3375 	}
3376 
test_ulessthan(deInt32 x,deInt32 y)3377 	static inline deInt32 test_ulessthan (deInt32 x, deInt32 y)
3378 	{
3379 		return test_ugreaterthan(y, x);
3380 	}
3381 
test_ugreaterthanequal(deInt32 x,deInt32 y)3382 	static inline deInt32 test_ugreaterthanequal (deInt32 x, deInt32 y)
3383 	{
3384 		// Consume signed integers as unsigned integers
3385 		if ((x & 0x80000000) ^ (y & 0x80000000))
3386 			std::swap(x,y);
3387 
3388 		if (x >= y)
3389 			return static_cast<deInt32>(1);
3390 		else
3391 			return static_cast<deInt32>(0);
3392 	}
3393 
test_ulessthanequal(deInt32 x,deInt32 y)3394 	static inline deInt32 test_ulessthanequal (deInt32 x, deInt32 y)
3395 	{
3396 		return test_ugreaterthanequal(y, x);
3397 	}
3398 };
3399 
3400 class TestMathInt64 : public TestMath<deInt64>
3401 {
3402 public:
test_ugreaterthan(deInt64 x,deInt64 y)3403 	static inline deInt64 test_ugreaterthan (deInt64 x, deInt64 y)
3404 	{
3405 		// Consume signed integers as unsigned integers
3406 		if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
3407 			std::swap(x,y);
3408 
3409 		if (x > y)
3410 			return static_cast<deInt64>(1);
3411 		else
3412 			return static_cast<deInt64>(0);
3413 	}
3414 
test_ulessthan(deInt64 x,deInt64 y)3415 	static inline deInt64 test_ulessthan (deInt64 x, deInt64 y)
3416 	{
3417 		return test_ugreaterthan(y, x);
3418 	}
3419 
test_ugreaterthanequal(deInt64 x,deInt64 y)3420 	static inline deInt64 test_ugreaterthanequal (deInt64 x, deInt64 y)
3421 	{
3422 		// Consume signed integers as unsigned integers
3423 		if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
3424 			std::swap(x,y);
3425 
3426 		if (x >= y)
3427 			return static_cast<deInt64>(1);
3428 		else
3429 			return static_cast<deInt64>(0);
3430 	}
3431 
test_ulessthanequal(deInt64 x,deInt64 y)3432 	static inline deInt64 test_ulessthanequal (deInt64 x, deInt64 y)
3433 	{
3434 		return test_ugreaterthanequal(y, x);
3435 	}
3436 };
3437 
3438 class TestMathUint8 : public TestMath<deUint8>
3439 {
3440 public:
test_msb(deUint8 x)3441 	static inline deUint32 test_msb (deUint8 x)
3442 	{
3443 		if (x > 0)
3444 			return 7 - deClz32((deUint32)x);
3445 		else
3446 			return -1;
3447 	}
3448 
test_mul_div(deUint8 x,deUint8 y)3449 	static inline deUint8 test_mul_div (deUint8 x, deUint8 y)
3450 	{
3451 		const deUint32 x32 = static_cast<deUint32>(x);
3452 		const deUint32 y32 = static_cast<deUint32>(y);
3453 
3454 		// In SPIR-V, if "y" is 0, then the result is undefined. In our case, let's return 0
3455 		if (y == static_cast<deUint8>(0))
3456 			return 0;
3457 		else
3458 			return static_cast<deUint8>(static_cast<deUint8>(x32 * y32) / y32);
3459 	}
3460 
test_sgreaterthan(deUint8 x,deUint8 y)3461 	static inline deUint8 test_sgreaterthan (deUint8 x, deUint8 y)
3462 	{
3463 		// Consume unsigned integers as signed integers
3464 		if ((x & 0x80) ^ (y & 0x80))
3465 			std::swap(x,y);
3466 
3467 		if (x > y)
3468 			return static_cast<deUint8>(1);
3469 		else
3470 			return static_cast<deUint8>(0);
3471 	}
3472 
test_slessthan(deUint8 x,deUint8 y)3473 	static inline deUint8 test_slessthan (deUint8 x, deUint8 y)
3474 	{
3475 		return test_sgreaterthan(y, x);
3476 	}
3477 
test_sgreaterthanequal(deUint8 x,deUint8 y)3478 	static inline deUint8 test_sgreaterthanequal (deUint8 x, deUint8 y)
3479 	{
3480 		// Consume unsigned integers as signed integers
3481 		if ((x & 0x80) ^ (y & 0x80))
3482 			std::swap(x,y);
3483 
3484 		if (x >= y)
3485 			return static_cast<deUint8>(1);
3486 		else
3487 			return static_cast<deUint8>(0);
3488 	}
3489 
test_slessthanequal(deUint8 x,deUint8 y)3490 	static inline deUint8 test_slessthanequal (deUint8 x, deUint8 y)
3491 	{
3492 		return test_sgreaterthanequal(y, x);
3493 	}
3494 };
3495 
3496 class TestMathUint16 : public TestMath<deUint16>
3497 {
3498 public:
test_msb(deUint16 x)3499 	static inline deUint32 test_msb (deUint16 x)
3500 	{
3501 		if (x > 0)
3502 			return 15 - deClz32((deUint32)x);
3503 		else
3504 			return -1;
3505 	}
3506 
test_mul_div(deUint16 x,deUint16 y)3507 	static inline deUint16 test_mul_div (deUint16 x, deUint16 y)
3508 	{
3509 		const deUint32 x32 = static_cast<deUint32>(x);
3510 		const deUint32 y32 = static_cast<deUint32>(y);
3511 
3512 		// In SPIR-V, if "y" is 0, then the result is undefined. In our case, let's return 0
3513 		if (y == static_cast<deUint16>(0))
3514 			return 0;
3515 		else
3516 			return static_cast<deUint16>(static_cast<deUint16>(x32 * y32) / y32);
3517 	}
3518 
test_sgreaterthan(deUint16 x,deUint16 y)3519 	static inline deUint16 test_sgreaterthan (deUint16 x, deUint16 y)
3520 	{
3521 		// Consume unsigned integers as signed integers
3522 		if ((x & 0x8000) ^ (y & 0x8000))
3523 			std::swap(x,y);
3524 
3525 		if (x > y)
3526 			return static_cast<deUint16>(1);
3527 		else
3528 			return static_cast<deUint16>(0);
3529 	}
3530 
test_slessthan(deUint16 x,deUint16 y)3531 	static inline deUint16 test_slessthan (deUint16 x, deUint16 y)
3532 	{
3533 		return test_sgreaterthan(y, x);
3534 	}
3535 
test_sgreaterthanequal(deUint16 x,deUint16 y)3536 	static inline deUint16 test_sgreaterthanequal (deUint16 x, deUint16 y)
3537 	{
3538 		// Consume unsigned integers as signed integers
3539 		if ((x & 0x8000) ^ (y & 0x8000))
3540 			std::swap(x,y);
3541 
3542 		if (x >= y)
3543 			return static_cast<deUint16>(1);
3544 		else
3545 			return static_cast<deUint16>(0);
3546 	}
3547 
test_slessthanequal(deUint16 x,deUint16 y)3548 	static inline deUint16 test_slessthanequal (deUint16 x, deUint16 y)
3549 	{
3550 		return test_sgreaterthanequal(y, x);
3551 	}
3552 };
3553 
3554 class TestMathUint32 : public TestMath<deUint32>
3555 {
3556 public:
test_msb(deUint32 x)3557 	static inline deUint32 test_msb (deUint32 x)
3558 	{
3559 		if (x > 0)
3560 			return 31 - deClz32(x);
3561 		else
3562 			return -1;
3563 	}
3564 
test_sgreaterthan(deUint32 x,deUint32 y)3565 	static inline deUint32 test_sgreaterthan (deUint32 x, deUint32 y)
3566 	{
3567 		// Consume unsigned integers as signed integers
3568 		if ((x & 0x80000000) ^ (y & 0x80000000))
3569 			std::swap(x,y);
3570 
3571 		if (x > y)
3572 			return static_cast<deUint32>(1);
3573 		else
3574 			return static_cast<deUint32>(0);
3575 	}
3576 
test_slessthan(deUint32 x,deUint32 y)3577 	static inline deUint32 test_slessthan (deUint32 x, deUint32 y)
3578 	{
3579 		return test_sgreaterthan(y, x);
3580 	}
3581 
test_sgreaterthanequal(deUint32 x,deUint32 y)3582 	static inline deUint32 test_sgreaterthanequal (deUint32 x, deUint32 y)
3583 	{
3584 		// Consume unsigned integers as signed integers
3585 		if ((x & 0x80000000) ^ (y & 0x80000000))
3586 			std::swap(x,y);
3587 
3588 		if (x >= y)
3589 			return static_cast<deUint32>(1);
3590 		else
3591 			return static_cast<deUint32>(0);
3592 	}
3593 
test_slessthanequal(deUint32 x,deUint32 y)3594 	static inline deUint32 test_slessthanequal (deUint32 x, deUint32 y)
3595 	{
3596 		return test_sgreaterthanequal(y, x);
3597 	}
3598 
3599 };
3600 
3601 class TestMathUint64 : public TestMath<deUint64>
3602 {
3603 public:
test_sgreaterthan(deUint64 x,deUint64 y)3604 	static inline deUint64 test_sgreaterthan (deUint64 x, deUint64 y)
3605 	{
3606 		// Consume unsigned integers as signed integers
3607 		if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
3608 			std::swap(x,y);
3609 
3610 		if (x > y)
3611 			return static_cast<deUint64>(1);
3612 		else
3613 			return static_cast<deUint64>(0);
3614 	}
3615 
test_slessthan(deUint64 x,deUint64 y)3616 	static inline deUint64 test_slessthan (deUint64 x, deUint64 y)
3617 	{
3618 		return test_sgreaterthan(y, x);
3619 	}
3620 
test_sgreaterthanequal(deUint64 x,deUint64 y)3621 	static inline deUint64 test_sgreaterthanequal (deUint64 x, deUint64 y)
3622 	{
3623 		// Consume unsigned integers as signed integers
3624 		if ((x & 0x8000000000000000) ^ (y & 0x8000000000000000))
3625 			std::swap(x,y);
3626 
3627 		if (x >= y)
3628 			return static_cast<deUint64>(1);
3629 		else
3630 			return static_cast<deUint64>(0);
3631 	}
3632 
test_slessthanequal(deUint64 x,deUint64 y)3633 	static inline deUint64 test_slessthanequal (deUint64 x, deUint64 y)
3634 	{
3635 		return test_sgreaterthanequal(y, x);
3636 	}
3637 };
3638 
3639 #define I8_FILTER_NONE SpvAsmTypeInt8Tests::filterNone
3640 #define I16_FILTER_NONE SpvAsmTypeInt16Tests::filterNone
3641 #define I32_FILTER_NONE SpvAsmTypeInt32Tests::filterNone
3642 #define I64_FILTER_NONE SpvAsmTypeInt64Tests::filterNone
3643 #define U8_FILTER_NONE SpvAsmTypeUint8Tests::filterNone
3644 #define U16_FILTER_NONE SpvAsmTypeUint16Tests::filterNone
3645 #define U32_FILTER_NONE SpvAsmTypeUint32Tests::filterNone
3646 #define U64_FILTER_NONE SpvAsmTypeUint64Tests::filterNone
3647 
3648 #define I8_FILTER_ZERO SpvAsmTypeInt8Tests::filterZero
3649 #define I16_FILTER_ZERO SpvAsmTypeInt16Tests::filterZero
3650 #define I32_FILTER_ZERO SpvAsmTypeInt32Tests::filterZero
3651 #define I64_FILTER_ZERO SpvAsmTypeInt64Tests::filterZero
3652 #define U8_FILTER_ZERO SpvAsmTypeUint8Tests::filterZero
3653 #define U16_FILTER_ZERO SpvAsmTypeUint16Tests::filterZero
3654 #define U32_FILTER_ZERO SpvAsmTypeUint32Tests::filterZero
3655 #define U64_FILTER_ZERO SpvAsmTypeUint64Tests::filterZero
3656 
3657 #define I8_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeInt8Tests::filterNegativesAndZero
3658 #define I16_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeInt16Tests::filterNegativesAndZero
3659 #define I32_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeInt32Tests::filterNegativesAndZero
3660 #define I64_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeInt64Tests::filterNegativesAndZero
3661 #define U8_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeUint8Tests::filterNegativesAndZero
3662 #define U16_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeUint16Tests::filterNegativesAndZero
3663 #define U32_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeUint32Tests::filterNegativesAndZero
3664 #define U64_FILTER_NEGATIVES_AND_ZERO SpvAsmTypeUint64Tests::filterNegativesAndZero
3665 
3666 #define I8_FILTER_MIN_GT_MAX SpvAsmTypeInt8Tests::filterMinGtMax
3667 #define I16_FILTER_MIN_GT_MAX SpvAsmTypeInt16Tests::filterMinGtMax
3668 #define I32_FILTER_MIN_GT_MAX SpvAsmTypeInt32Tests::filterMinGtMax
3669 #define I64_FILTER_MIN_GT_MAX SpvAsmTypeInt64Tests::filterMinGtMax
3670 #define U8_FILTER_MIN_GT_MAX SpvAsmTypeUint8Tests::filterMinGtMax
3671 #define U16_FILTER_MIN_GT_MAX SpvAsmTypeUint16Tests::filterMinGtMax
3672 #define U32_FILTER_MIN_GT_MAX SpvAsmTypeUint32Tests::filterMinGtMax
3673 #define U64_FILTER_MIN_GT_MAX SpvAsmTypeUint64Tests::filterMinGtMax
3674 
3675 const string bitShiftTestPostfix[] =
3676 {
3677 	"_shift8",
3678 	"_shift16",
3679 	"_shift32",
3680 	"_shift64"
3681 };
3682 
3683 const string bitFieldTestPostfix[] =
3684 {
3685 	"_offset8_count8",
3686 	"_offset8_count16",
3687 	"_offset8_count32",
3688 	"_offset8_count64",
3689 	"_offset16_count8",
3690 	"_offset16_count16",
3691 	"_offset16_count32",
3692 	"_offset16_count64",
3693 	"_offset32_count8",
3694 	"_offset32_count16",
3695 	"_offset32_count32",
3696 	"_offset32_count64",
3697 	"_offset64_count8",
3698 	"_offset64_count16",
3699 	"_offset64_count32",
3700 	"_offset64_count64",
3701 };
3702 
3703 // Macro to create tests.
3704 // Syntax: MAKE_TEST_{S,V}_{I,U}_{8,1,3,6}
3705 //
3706 //  'S': create scalar test
3707 //  'V': create vector test
3708 //
3709 //  'I': create integer test
3710 //  'U': create unsigned integer test
3711 //
3712 //  '8': create 8-bit test
3713 //  '1': create 16-bit test
3714 //  '3': create 32-bit test
3715 //  '6': create 64-bit test
3716 //
3717 //  'W': bit width of some parameters in bit field and shift operations can be different from Result and Base
3718 //  'N': create 16-bit tests without 'test_high_part_zero' variants
3719 
3720 #define MAKE_TEST_S_I_8136(name, spirvOp, op, filter, inputRange, extension) \
3721 	for (deUint32 ndx = 0; ndx < 1; ++ndx) \
3722 	{ \
3723 		int8Tests[ndx]->createTests((name), (spirvOp), \
3724 			TestMathInt8::test_##op, I8_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3725 		int16Tests[ndx]->createTests((name), (spirvOp), \
3726 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3727 		int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3728 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3729 		int32Tests[ndx]->createTests((name), (spirvOp), \
3730 			TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3731 		int64Tests[ndx]->createTests((name), (spirvOp), \
3732 			TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3733 	} \
3734 
3735 #define MAKE_TEST_V_I_8136(name, spirvOp, op, filter, inputRange, extension) \
3736 	for (deUint32 ndx = 1; ndx < 4; ++ndx) \
3737 	{ \
3738 		int8Tests[ndx]->createTests((name), (spirvOp), \
3739 			TestMathInt8::test_##op, I8_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3740 		int16Tests[ndx]->createTests((name), (spirvOp), \
3741 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3742 		int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3743 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3744 		int32Tests[ndx]->createTests((name), (spirvOp), \
3745 			TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3746 		int64Tests[ndx]->createTests((name), (spirvOp), \
3747 			TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3748 	} \
3749 
3750 #define MAKE_TEST_SV_I_8136(name, spirvOp, op, filter, inputRange, extension) \
3751 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3752 	{ \
3753 		int8Tests[ndx]->createTests((name), (spirvOp), \
3754 			TestMathInt8::test_##op, I8_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3755 		int16Tests[ndx]->createTests((name), (spirvOp), \
3756 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3757 		int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3758 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3759 		int32Tests[ndx]->createTests((name), (spirvOp), \
3760 			TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3761 		int64Tests[ndx]->createTests((name), (spirvOp), \
3762 			TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3763 	} \
3764 
3765 #define MAKE_TEST_SV_I_8136_N(name, spirvOp, op, filter, inputRange, extension) \
3766 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3767 	{ \
3768 		int8Tests[ndx]->createTests((name), (spirvOp), \
3769 			TestMathInt8::test_##op, I8_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3770 		int16Tests[ndx]->createTests((name), (spirvOp), \
3771 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3772 		int32Tests[ndx]->createTests((name), (spirvOp), \
3773 			TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3774 		int64Tests[ndx]->createTests((name), (spirvOp), \
3775 			TestMathInt64::test_##op, I64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3776 	} \
3777 
3778 #define MAKE_TEST_SV_I_8136_W(name, spirvOp, op, filter, inputRange, extension) \
3779 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3780 	for (deUint32 widthNdx = 0; widthNdx < DE_LENGTH_OF_ARRAY(bitShiftTestPostfix); ++widthNdx) \
3781 	{ \
3782 		const InputWidth inputWidth = static_cast<InputWidth>(WIDTH_8 + widthNdx); \
3783 		\
3784 		int8Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3785 			TestMathInt8::test_##op, I8_##filter, inputRange, inputWidth, (extension)); \
3786 		int16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3787 			TestMathInt16::test_##op, I16_##filter, inputRange, inputWidth, (extension)); \
3788 		int16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx] + "_test_high_part_zero").c_str(), (spirvOp), \
3789 			TestMathInt16::test_##op, I16_##filter, inputRange, inputWidth, (extension), true); \
3790 		int32Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3791 			TestMathInt32::test_##op, I32_##filter, inputRange, inputWidth, (extension)); \
3792 		int64Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3793 			TestMathInt64::test_##op, I64_##filter, inputRange, inputWidth, (extension)); \
3794 	} \
3795 
3796 #define MAKE_TEST_SV_I_1(name, spirvOp, op, filter, inputRange, extension) \
3797 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3798 	{ \
3799 		int16Tests[ndx]->createTests((name), (spirvOp), \
3800 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3801 		int16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3802 			TestMathInt16::test_##op, I16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3803 	} \
3804 
3805 #define MAKE_TEST_SV_I_3(name, spirvOp, op, filter, inputRange, extension) \
3806 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3807 		int32Tests[ndx]->createTests((name), (spirvOp), \
3808 			TestMathInt32::test_##op, I32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3809 
3810 #define MAKE_TEST_SV_I_3_W(name, spirvOp, op, filter, inputRange, extension) \
3811 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3812 	for (deUint32 width = 0; width < DE_LENGTH_OF_ARRAY(bitFieldTestPostfix); ++width) \
3813 	{ \
3814 		int32Tests[ndx]->createTests(string(name + bitFieldTestPostfix[width]).c_str(), (spirvOp), \
3815 			TestMathInt32::test_##op, I32_##filter, inputRange, InputWidth(WIDTH_8_8 + width), (extension)); \
3816 	} \
3817 
3818 #define MAKE_TEST_S_U_8136(name, spirvOp, op, filter, inputRange, extension) \
3819 	for (deUint32 ndx = 0; ndx < 1; ++ndx) \
3820 	{ \
3821 		uint8Tests[ndx]->createTests((name), (spirvOp), \
3822 			TestMathUint8::test_##op, U8_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3823 		uint16Tests[ndx]->createTests((name), (spirvOp), \
3824 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3825 		uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3826 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3827 		uint32Tests[ndx]->createTests((name), (spirvOp), \
3828 			TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3829 		uint64Tests[ndx]->createTests((name), (spirvOp), \
3830 			TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3831 	} \
3832 
3833 #define MAKE_TEST_V_U_8136(name, spirvOp, op, filter, inputRange, extension) \
3834 	for (deUint32 ndx = 1; ndx < 4; ++ndx) \
3835 	{ \
3836 		uint16Tests[ndx]->createTests((name), (spirvOp), \
3837 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3838 		uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3839 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3840 		uint32Tests[ndx]->createTests((name), (spirvOp), \
3841 			TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3842 		uint64Tests[ndx]->createTests((name), (spirvOp), \
3843 			TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3844 	} \
3845 
3846 #define MAKE_TEST_SV_U_8136(name, spirvOp, op, filter, inputRange, extension) \
3847 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3848 	{ \
3849 		uint8Tests[ndx]->createTests((name), (spirvOp), \
3850 			TestMathUint8::test_##op, U8_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3851 		uint16Tests[ndx]->createTests((name), (spirvOp), \
3852 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3853 		uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3854 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3855 		uint32Tests[ndx]->createTests((name), (spirvOp), \
3856 			TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3857 		uint64Tests[ndx]->createTests((name), (spirvOp), \
3858 			TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3859 	} \
3860 
3861 #define MAKE_TEST_SV_U_8136_N(name, spirvOp, op, filter, inputRange, extension) \
3862 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3863 	{ \
3864 		uint8Tests[ndx]->createTests((name), (spirvOp), \
3865 			TestMathUint8::test_##op, U8_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3866 		uint16Tests[ndx]->createTests((name), (spirvOp), \
3867 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3868 		uint32Tests[ndx]->createTests((name), (spirvOp), \
3869 			TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3870 		uint64Tests[ndx]->createTests((name), (spirvOp), \
3871 			TestMathUint64::test_##op, U64_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3872 	} \
3873 
3874 #define MAKE_TEST_SV_U_8136_W(name, spirvOp, op, filter, inputRange, extension) \
3875 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3876 	for (deUint32 widthNdx = 0; widthNdx < DE_LENGTH_OF_ARRAY(bitShiftTestPostfix); ++widthNdx) \
3877 	{ \
3878 		const InputWidth inputWidth = static_cast<InputWidth>(WIDTH_8 + widthNdx); \
3879 		\
3880 		uint8Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3881 			TestMathUint8::test_##op, U8_##filter, inputRange, inputWidth, (extension)); \
3882 		uint16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3883 			TestMathUint16::test_##op, U16_##filter, inputRange, inputWidth, (extension)); \
3884 		uint16Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx] + "_test_high_part_zero").c_str(), (spirvOp), \
3885 			TestMathUint16::test_##op, U16_##filter, inputRange, inputWidth, (extension), true); \
3886 		uint32Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3887 			TestMathUint32::test_##op, U32_##filter, inputRange, inputWidth, (extension)); \
3888 		uint64Tests[ndx]->createTests(string(name + bitShiftTestPostfix[widthNdx]).c_str(), (spirvOp), \
3889 			TestMathUint64::test_##op, U64_##filter, inputRange, inputWidth, (extension)); \
3890 	} \
3891 
3892 #define MAKE_TEST_SV_U_1(name, spirvOp, op, filter, inputRange, extension) \
3893 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3894 	{ \
3895 		uint16Tests[ndx]->createTests((name), (spirvOp), \
3896 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3897 		uint16Tests[ndx]->createTests((name "_test_high_part_zero"), (spirvOp), \
3898 			TestMathUint16::test_##op, U16_##filter, inputRange, WIDTH_DEFAULT, (extension), true); \
3899 	} \
3900 
3901 #define MAKE_TEST_SV_U_3(name, spirvOp, op, filter, inputRange, extension) \
3902 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3903 		uint32Tests[ndx]->createTests((name), (spirvOp), \
3904 			TestMathUint32::test_##op, U32_##filter, inputRange, WIDTH_DEFAULT, (extension)); \
3905 
3906 #define MAKE_TEST_SV_U_3_W(name, spirvOp, op, filter, inputRange, extension) \
3907 	for (deUint32 ndx = 0; ndx < 4; ++ndx) \
3908 	for (deUint32 width = 0; width < DE_LENGTH_OF_ARRAY(bitFieldTestPostfix); ++width) \
3909 	{ \
3910 		uint32Tests[ndx]->createTests(string(name + bitFieldTestPostfix[width]).c_str(), (spirvOp), \
3911 			TestMathUint32::test_##op, U32_##filter, inputRange, InputWidth(WIDTH_8_8 + width), (extension)); \
3912 	} \
3913 
createTypeTests(tcu::TestContext & testCtx)3914 tcu::TestCaseGroup* createTypeTests (tcu::TestContext& testCtx)
3915 {
3916 	de::MovePtr<tcu::TestCaseGroup>		typeTests			(new tcu::TestCaseGroup(testCtx, "type", "Test types"));
3917 	de::MovePtr<tcu::TestCaseGroup>		typeScalarTests		(new tcu::TestCaseGroup(testCtx, "scalar", "scalar tests"));
3918 	de::MovePtr<tcu::TestCaseGroup>		typeVectorTests[3];
3919 
3920 	de::MovePtr<SpvAsmTypeInt8Tests>	int8Tests[4];
3921 	de::MovePtr<SpvAsmTypeInt16Tests>	int16Tests[4];
3922 	de::MovePtr<SpvAsmTypeInt32Tests>	int32Tests[4];
3923 	de::MovePtr<SpvAsmTypeInt64Tests>	int64Tests[4];
3924 	de::MovePtr<SpvAsmTypeUint8Tests>	uint8Tests[4];
3925 	de::MovePtr<SpvAsmTypeUint16Tests>	uint16Tests[4];
3926 	de::MovePtr<SpvAsmTypeUint32Tests>	uint32Tests[4];
3927 	de::MovePtr<SpvAsmTypeUint64Tests>	uint64Tests[4];
3928 
3929 	for (deUint32 ndx = 0; ndx < 3; ++ndx)
3930 	{
3931 		std::string testName = "vec" + de::toString(ndx + 2);
3932 		typeVectorTests[ndx] = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, testName.c_str(), "vector tests"));
3933 	}
3934 
3935 	for (deUint32 ndx = 0; ndx < 4; ++ndx)
3936 	{
3937 		int8Tests[ndx]		= de::MovePtr<SpvAsmTypeInt8Tests>(new SpvAsmTypeInt8Tests(testCtx, ndx + 1));
3938 		int16Tests[ndx]		= de::MovePtr<SpvAsmTypeInt16Tests>(new SpvAsmTypeInt16Tests(testCtx, ndx + 1));
3939 		int32Tests[ndx]		= de::MovePtr<SpvAsmTypeInt32Tests>(new SpvAsmTypeInt32Tests(testCtx, ndx + 1));
3940 		int64Tests[ndx]		= de::MovePtr<SpvAsmTypeInt64Tests>(new SpvAsmTypeInt64Tests(testCtx, ndx + 1));
3941 		uint8Tests[ndx]		= de::MovePtr<SpvAsmTypeUint8Tests>(new SpvAsmTypeUint8Tests(testCtx, ndx + 1));
3942 		uint16Tests[ndx]	= de::MovePtr<SpvAsmTypeUint16Tests>(new SpvAsmTypeUint16Tests(testCtx, ndx + 1));
3943 		uint32Tests[ndx]	= de::MovePtr<SpvAsmTypeUint32Tests>(new SpvAsmTypeUint32Tests(testCtx, ndx + 1));
3944 		uint64Tests[ndx]	= de::MovePtr<SpvAsmTypeUint64Tests>(new SpvAsmTypeUint64Tests(testCtx, ndx + 1));
3945 	}
3946 
3947 	MAKE_TEST_SV_I_8136("negate", SpvOpSNegate, negate, FILTER_NONE, RANGE_FULL, DE_NULL)
3948 	MAKE_TEST_SV_I_8136("add", SpvOpIAdd, add, FILTER_NONE, RANGE_FULL, DE_NULL)
3949 	MAKE_TEST_SV_I_8136("sub", SpvOpISub, sub, FILTER_NONE, RANGE_FULL, DE_NULL)
3950 	MAKE_TEST_SV_I_8136("mul", SpvOpIMul, mul, FILTER_NONE, RANGE_FULL, DE_NULL)
3951 	MAKE_TEST_SV_I_8136("div", SpvOpSDiv, div, FILTER_ZERO, RANGE_FULL, DE_NULL)
3952 	MAKE_TEST_SV_U_8136("div", SpvOpUDiv, div, FILTER_ZERO, RANGE_FULL, DE_NULL)
3953 	MAKE_TEST_SV_I_8136("rem", SpvOpSRem, rem, FILTER_NEGATIVES_AND_ZERO, RANGE_FULL, DE_NULL)
3954 	MAKE_TEST_SV_I_8136("mod", SpvOpSMod, mod, FILTER_NEGATIVES_AND_ZERO, RANGE_FULL, DE_NULL)
3955 	MAKE_TEST_SV_U_8136("mod", SpvOpUMod, mod, FILTER_ZERO, RANGE_FULL, DE_NULL)
3956 	MAKE_TEST_SV_I_8136("abs", GLSLstd450SAbs, abs, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3957 	MAKE_TEST_SV_I_8136("sign", GLSLstd450SSign, sign, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3958 	MAKE_TEST_SV_I_8136("min", GLSLstd450SMin, min, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3959 	MAKE_TEST_SV_U_8136("min", GLSLstd450UMin, min, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3960 	MAKE_TEST_SV_I_8136("max", GLSLstd450SMax, max, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3961 	MAKE_TEST_SV_U_8136("max", GLSLstd450UMax, max, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3962 	MAKE_TEST_SV_I_8136("clamp", GLSLstd450SClamp, clamp, FILTER_MIN_GT_MAX, RANGE_FULL, "GLSL.std.450")
3963 	MAKE_TEST_SV_U_8136("clamp", GLSLstd450UClamp, clamp, FILTER_MIN_GT_MAX, RANGE_FULL, "GLSL.std.450")
3964 	MAKE_TEST_SV_I_3("find_lsb", GLSLstd450FindILsb, lsb, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3965 	MAKE_TEST_SV_I_3("find_msb", GLSLstd450FindSMsb, msb, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3966 	MAKE_TEST_SV_U_3("find_msb", GLSLstd450FindUMsb, msb, FILTER_NONE, RANGE_FULL, "GLSL.std.450")
3967 	MAKE_TEST_SV_I_1("mul_sdiv", DE_NULL, mul_div, FILTER_ZERO, RANGE_FULL, DE_NULL)
3968 	MAKE_TEST_SV_U_1("mul_udiv", DE_NULL, mul_div, FILTER_ZERO, RANGE_FULL, DE_NULL)
3969 
3970 	MAKE_TEST_SV_U_8136_W("shift_right_logical", SpvOpShiftRightLogical, lsr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL)
3971 	MAKE_TEST_SV_I_8136_W("shift_right_logical", SpvOpShiftRightLogical, lsr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL)
3972 	MAKE_TEST_SV_U_8136_W("shift_right_arithmetic", SpvOpShiftRightArithmetic, asr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL)
3973 	MAKE_TEST_SV_I_8136_W("shift_right_arithmetic", SpvOpShiftRightArithmetic, asr, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL)
3974 	MAKE_TEST_SV_U_8136_W("shift_left_logical", SpvOpShiftLeftLogical, lsl, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL)
3975 	MAKE_TEST_SV_I_8136_W("shift_left_logical", SpvOpShiftLeftLogical, lsl, FILTER_NONE, RANGE_BIT_WIDTH, DE_NULL)
3976 
3977 	MAKE_TEST_SV_U_8136("bitwise_or", SpvOpBitwiseOr, bitwise_or, FILTER_NONE, RANGE_FULL, DE_NULL)
3978 	MAKE_TEST_SV_I_8136("bitwise_or", SpvOpBitwiseOr, bitwise_or , FILTER_NONE, RANGE_FULL, DE_NULL)
3979 	MAKE_TEST_SV_U_8136("bitwise_xor", SpvOpBitwiseXor, bitwise_xor, FILTER_NONE, RANGE_FULL, DE_NULL)
3980 	MAKE_TEST_SV_I_8136("bitwise_xor", SpvOpBitwiseXor, bitwise_xor, FILTER_NONE, RANGE_FULL, DE_NULL)
3981 	MAKE_TEST_SV_U_8136("bitwise_and", SpvOpBitwiseAnd, bitwise_and, FILTER_NONE, RANGE_FULL, DE_NULL)
3982 	MAKE_TEST_SV_I_8136("bitwise_and", SpvOpBitwiseAnd, bitwise_and, FILTER_NONE, RANGE_FULL, DE_NULL)
3983 	MAKE_TEST_SV_U_8136("not", SpvOpNot, not, FILTER_NONE, RANGE_FULL, DE_NULL)
3984 	MAKE_TEST_SV_I_8136("not", SpvOpNot, not, FILTER_NONE, RANGE_FULL, DE_NULL)
3985 
3986 	MAKE_TEST_SV_U_8136_N("iequal", SpvOpIEqual, iequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3987 	MAKE_TEST_SV_I_8136_N("iequal", SpvOpIEqual, iequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3988 	MAKE_TEST_SV_U_8136_N("inotequal", SpvOpINotEqual, inotequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3989 	MAKE_TEST_SV_I_8136_N("inotequal", SpvOpINotEqual, inotequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3990 	MAKE_TEST_SV_U_8136_N("ugreaterthan", SpvOpUGreaterThan, ugreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL)
3991 	MAKE_TEST_SV_I_8136_N("ugreaterthan", SpvOpUGreaterThan, ugreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL)
3992 	MAKE_TEST_SV_U_8136_N("sgreaterthan", SpvOpSGreaterThan, sgreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL)
3993 	MAKE_TEST_SV_I_8136_N("sgreaterthan", SpvOpSGreaterThan, sgreaterthan, FILTER_NONE, RANGE_FULL, DE_NULL)
3994 	MAKE_TEST_SV_U_8136_N("ugreaterthanequal", SpvOpUGreaterThanEqual, ugreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3995 	MAKE_TEST_SV_I_8136_N("ugreaterthanequal", SpvOpUGreaterThanEqual, ugreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3996 	MAKE_TEST_SV_U_8136_N("sgreaterthanequal", SpvOpSGreaterThanEqual, sgreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3997 	MAKE_TEST_SV_I_8136_N("sgreaterthanequal", SpvOpSGreaterThanEqual, sgreaterthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
3998 	MAKE_TEST_SV_U_8136_N("ulessthan", SpvOpULessThan, ulessthan, FILTER_NONE, RANGE_FULL, DE_NULL)
3999 	MAKE_TEST_SV_I_8136_N("ulessthan", SpvOpULessThan, ulessthan, FILTER_NONE, RANGE_FULL, DE_NULL)
4000 	MAKE_TEST_SV_U_8136_N("slessthan", SpvOpSLessThan, slessthan, FILTER_NONE, RANGE_FULL, DE_NULL)
4001 	MAKE_TEST_SV_I_8136_N("slessthan", SpvOpSLessThan, slessthan, FILTER_NONE, RANGE_FULL, DE_NULL)
4002 	MAKE_TEST_SV_U_8136_N("ulessthanequal", SpvOpULessThanEqual, ulessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
4003 	MAKE_TEST_SV_I_8136_N("ulessthanequal", SpvOpULessThanEqual, ulessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
4004 	MAKE_TEST_SV_U_8136_N("slessthanequal", SpvOpSLessThanEqual, slessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
4005 	MAKE_TEST_SV_I_8136_N("slessthanequal", SpvOpSLessThanEqual, slessthanequal, FILTER_NONE, RANGE_FULL, DE_NULL)
4006 
4007 	MAKE_TEST_SV_U_3_W("bit_field_insert", SpvOpBitFieldInsert, bitFieldInsert, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL)
4008 	MAKE_TEST_SV_I_3_W("bit_field_insert", SpvOpBitFieldInsert, bitFieldInsert, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL)
4009 	MAKE_TEST_SV_U_3_W("bit_field_s_extract", SpvOpBitFieldSExtract, bitFieldSExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL)
4010 	MAKE_TEST_SV_I_3_W("bit_field_s_extract", SpvOpBitFieldSExtract, bitFieldSExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL)
4011 	MAKE_TEST_SV_U_3_W("bit_field_u_extract", SpvOpBitFieldUExtract, bitFieldUExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL)
4012 	MAKE_TEST_SV_I_3_W("bit_field_u_extract", SpvOpBitFieldUExtract, bitFieldUExtract, FILTER_NONE, RANGE_BIT_WIDTH_SUM, DE_NULL)
4013 	MAKE_TEST_SV_U_3("bit_reverse", SpvOpBitReverse, bitReverse, FILTER_NONE, RANGE_FULL, DE_NULL)
4014 	MAKE_TEST_SV_I_3("bit_reverse", SpvOpBitReverse, bitReverse, FILTER_NONE, RANGE_FULL, DE_NULL)
4015 	MAKE_TEST_SV_U_3("bit_count", SpvOpBitCount, bitCount, FILTER_NONE, RANGE_FULL, DE_NULL)
4016 	MAKE_TEST_SV_I_3("bit_count", SpvOpBitCount, bitCount, FILTER_NONE, RANGE_FULL, DE_NULL)
4017 
4018 	MAKE_TEST_S_U_8136("constant", SpvOpConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4019 	MAKE_TEST_S_I_8136("constant", SpvOpConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4020 	MAKE_TEST_V_U_8136("constant_composite", SpvOpConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4021 	MAKE_TEST_V_I_8136("constant_composite", SpvOpConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4022 	MAKE_TEST_V_U_8136("constant_null", SpvOpConstantNull, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4023 	MAKE_TEST_V_I_8136("constant_null", SpvOpConstantNull, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4024 	MAKE_TEST_SV_U_8136("variable_initializer", SpvOpVariable, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4025 	MAKE_TEST_SV_I_8136("variable_initializer", SpvOpVariable, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4026 	MAKE_TEST_S_U_8136("spec_constant_initializer", SpvOpSpecConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4027 	MAKE_TEST_S_I_8136("spec_constant_initializer", SpvOpSpecConstant, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4028 	MAKE_TEST_V_U_8136("spec_constant_composite_initializer", SpvOpSpecConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4029 	MAKE_TEST_V_I_8136("spec_constant_composite_initializer", SpvOpSpecConstantComposite, constant, FILTER_NONE, RANGE_FULL, DE_NULL)
4030 
4031 	int8Tests[0]->createSwitchTests();
4032 	int16Tests[0]->createSwitchTests();
4033 	int32Tests[0]->createSwitchTests();
4034 	int64Tests[0]->createSwitchTests();
4035 	uint8Tests[0]->createSwitchTests();
4036 	uint16Tests[0]->createSwitchTests();
4037 	uint32Tests[0]->createSwitchTests();
4038 	uint64Tests[0]->createSwitchTests();
4039 
4040 	typeScalarTests->addChild(int8Tests[0].release());
4041 	typeScalarTests->addChild(int16Tests[0].release());
4042 	typeScalarTests->addChild(int32Tests[0].release());
4043 	typeScalarTests->addChild(int64Tests[0].release());
4044 	typeScalarTests->addChild(uint8Tests[0].release());
4045 	typeScalarTests->addChild(uint16Tests[0].release());
4046 	typeScalarTests->addChild(uint32Tests[0].release());
4047 	typeScalarTests->addChild(uint64Tests[0].release());
4048 
4049 	typeTests->addChild(typeScalarTests.release());
4050 
4051 	for (deUint32 ndx = 0; ndx < 3; ++ndx)
4052 	{
4053 		typeVectorTests[ndx]->addChild(int8Tests[ndx + 1].release());
4054 		typeVectorTests[ndx]->addChild(int16Tests[ndx + 1].release());
4055 		typeVectorTests[ndx]->addChild(int32Tests[ndx + 1].release());
4056 		typeVectorTests[ndx]->addChild(int64Tests[ndx + 1].release());
4057 		typeVectorTests[ndx]->addChild(uint8Tests[ndx + 1].release());
4058 		typeVectorTests[ndx]->addChild(uint16Tests[ndx + 1].release());
4059 		typeVectorTests[ndx]->addChild(uint32Tests[ndx + 1].release());
4060 		typeVectorTests[ndx]->addChild(uint64Tests[ndx + 1].release());
4061 
4062 		typeTests->addChild(typeVectorTests[ndx].release());
4063 	}
4064 
4065 	return typeTests.release();
4066 }
4067 
4068 } // SpirVAssembly
4069 } // vkt
4070