• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 Arm Limited.
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 Functional integer dot product tests
22  *//*--------------------------------------------------------------------*/
23 
24 
25 #include "tcuTestLog.hpp"
26 #include "tcuVectorUtil.hpp"
27 
28 #include "deRandom.hpp"
29 
30 #include "vktSpvAsmComputeShaderCase.hpp"
31 #include "vktSpvAsmComputeShaderTestUtil.hpp"
32 #include "vktSpvAsmIntegerDotProductTests.hpp"
33 
34 #include <limits>
35 #include <string>
36 
37 // VK_KHR_shader_integer_dot_product tests
38 
39 // Note: these tests make use of the following extensions that are not
40 // required by the VK_KHR_shader_integer_dot_product extension itself:
41 //    * VK_KHR_8bit_storage (VkPhysicalDevice8BitStorageFeatures) for shaderInt8
42 //    * VK_KHR_16bit_storage (VkPhysicalDevice16BitStorageFeatures) for shaderInt16
43 
44 namespace vkt
45 {
46 namespace SpirVAssembly
47 {
48 
49 using namespace vk;
50 using std::string;
51 
52 namespace
53 {
54 using std::vector;
55 using tcu::IVec3;
56 using tcu::TestLog;
57 
58 template<typename T>
fillRandomScalars(de::Random & rnd,T minValue,T maxValue,void * dst,int numValues,int offset=0)59 static void fillRandomScalars(de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
60 {
61 	T* const typedPtr = (T*)dst;
62 	for (int ndx = 0; ndx < numValues; ndx++)
63 		typedPtr[offset + ndx] = de::randomScalar<T>(rnd, minValue, maxValue);
64 }
65 
getEqualValue(T v1,T v2)66 template <typename T> T getEqualValue(T v1, T v2)
67 {
68 	DE_ASSERT(v1 == v2);
69 	(void)v2;
70 	return v1;
71 }
72 
73 template <class T>
withinLimits(deInt64 val)74 bool withinLimits(deInt64 val)
75 {
76 	return static_cast<deInt64>(std::numeric_limits<T>::min()) <= val
77 		   && val <= static_cast<deInt64>(std::numeric_limits<T>::max());
78 }
79 
80 template <class T, class LHSOperandT, class RHSOperandT>
dotProduct(vector<LHSOperandT> lhs,vector<RHSOperandT> rhs)81 static T dotProduct(vector<LHSOperandT> lhs, vector<RHSOperandT> rhs)
82 {
83 	uint64_t	res		= 0u;
84 	size_t		size	= getEqualValue(lhs.size(), rhs.size());
85 
86 	for (size_t i = 0; i < size; ++i)
87 		res += static_cast<uint64_t>(lhs[i]) * static_cast<uint64_t>(rhs[i]);
88 
89 	int64_t signedRes;
90 	deMemcpy(&signedRes, &res, sizeof(res));
91 	return static_cast<T>(signedRes);
92 }
93 
94 template <class AddendT, class LHSOperandT, class RHSOperandT>
compareDotProductAccSat(const std::vector<Resource> & inputs,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> &,TestLog &)95 bool compareDotProductAccSat(const std::vector<Resource> &inputs, const vector<AllocationSp>& outputAllocs,
96 							 const std::vector<Resource>&, TestLog&)
97 {
98 	if (inputs.size() != 3 || outputAllocs.size() != 1)
99 		return false;
100 
101 	vector<deUint8>	lhsBytes;
102 	vector<deUint8>	rhsBytes;
103 	vector<deUint8>	addendBytes;
104 
105 	inputs[0].getBytes(lhsBytes);
106 	inputs[1].getBytes(rhsBytes);
107 	inputs[2].getBytes(addendBytes);
108 
109 	const AddendT* const	output	= static_cast<AddendT* const>(outputAllocs[0]->getHostPtr());
110 	const AddendT* const	addends	= reinterpret_cast<AddendT* const>(&addendBytes.front());
111 	const LHSOperandT* const	lhsInts = reinterpret_cast<LHSOperandT* const>(&lhsBytes.front());
112 	const RHSOperandT* const	rhsInts = reinterpret_cast<RHSOperandT* const>(&rhsBytes.front());
113 
114 	for (size_t idx = 0; idx < inputs[2].getByteSize() / sizeof(AddendT); ++idx)
115 	{
116 		size_t vecLen = (inputs[0].getByteSize() / sizeof(LHSOperandT)) / (inputs[2].getByteSize() / sizeof(AddendT));
117 
118 		std::vector<LHSOperandT> inputVec1Pos;
119 		std::vector<RHSOperandT> inputVec2Pos;
120 		inputVec1Pos.reserve(vecLen);
121 		inputVec2Pos.reserve(vecLen);
122 
123 		std::vector<LHSOperandT> inputVec1Neg;
124 		std::vector<RHSOperandT> inputVec2Neg;
125 		inputVec1Neg.reserve(vecLen);
126 		inputVec2Neg.reserve(vecLen);
127 
128 		for (unsigned int vecElem = 0; vecElem < vecLen; ++vecElem)
129 		{
130 			LHSOperandT elem1 = lhsInts[idx * vecLen + vecElem];
131 			RHSOperandT elem2 = rhsInts[idx * vecLen + vecElem];
132 
133 			// Note: ordering of components does not matter, provided
134 			// that it is consistent between lhs and rhs.
135 			if ((elem1 < 0) == (elem2 < 0))
136 			{
137 				inputVec1Pos.push_back(elem1);
138 				inputVec2Pos.push_back(elem2);
139 				inputVec1Neg.push_back(0);
140 				inputVec2Neg.push_back(0);
141 			}
142 			else
143 			{
144 				inputVec1Pos.push_back(0);
145 				inputVec2Pos.push_back(0);
146 				inputVec1Neg.push_back(elem1);
147 				inputVec2Neg.push_back(elem2);
148 			}
149 		}
150 
151 		deInt64 PosProduct = dotProduct<deInt64>(inputVec1Pos, inputVec2Pos);
152 		deInt64 NegProduct = dotProduct<deInt64>(inputVec1Neg, inputVec2Neg);
153 		bool outputOverflow = (!withinLimits<AddendT>(PosProduct) || !withinLimits<AddendT>(NegProduct));
154 
155 		if (!outputOverflow)
156 		{
157 			AddendT expectedOutput = static_cast<AddendT>(PosProduct + NegProduct);
158 			const auto& addend = addends[idx];
159 
160 			if (addend < 0)
161 			{
162 				if (expectedOutput < std::numeric_limits<AddendT>::min() - addend)
163 					expectedOutput = std::numeric_limits<AddendT>::min();
164 				else
165 					expectedOutput = static_cast<AddendT>(expectedOutput + addend);
166 			}
167 			else
168 			{
169 				if (expectedOutput > std::numeric_limits<AddendT>::max() - addend)
170 					expectedOutput = std::numeric_limits<AddendT>::max();
171 				else
172 					expectedOutput = static_cast<AddendT>(expectedOutput + addend);
173 			}
174 
175 			if (output[idx] != expectedOutput)
176 			{
177 				return false;
178 			}
179 		}
180 	}
181 
182 	return true;
183 }
184 
185 struct DotProductPackingInfo
186 {
187 	bool packed;
188 	bool signedLHS;
189 	bool signedRHS;
190 };
191 
192 struct DotProductVectorInfo
193 {
194 	size_t vecElementSize;
195 	unsigned int vecLen;
196 };
197 
addDotProductExtensionAndFeatures(ComputeShaderSpec & spec,const struct DotProductPackingInfo & packingInfo,size_t elementSize,size_t outSize)198 void addDotProductExtensionAndFeatures(ComputeShaderSpec &spec,
199 									   const struct DotProductPackingInfo &packingInfo,
200 									   size_t elementSize, size_t outSize)
201 {
202 	spec.extensions.push_back("VK_KHR_shader_integer_dot_product");
203 	spec.requestedVulkanFeatures.extIntegerDotProduct.shaderIntegerDotProduct = VK_TRUE;
204 
205 	DE_ASSERT(!packingInfo.packed || elementSize == 8);
206 	if ((!packingInfo.packed && elementSize == 8) || outSize == 8)
207 	{
208 		spec.requestedVulkanFeatures.extFloat16Int8.shaderInt8 = true;
209 		spec.requestedVulkanFeatures.ext8BitStorage.storageBuffer8BitAccess = true;
210 		spec.extensions.push_back("VK_KHR_8bit_storage");
211 	}
212 
213 	if (elementSize == 16 || outSize == 16)
214 	{
215 		spec.requestedVulkanFeatures.coreFeatures.shaderInt16 = true;
216 		spec.requestedVulkanFeatures.ext16BitStorage.storageBuffer16BitAccess = true;
217 		spec.extensions.push_back("VK_KHR_16bit_storage");
218 	}
219 }
220 
221 const struct DotProductPackingInfo dotProductPacking[] = {
222 	{ false, false, false },
223 	{ false, false, true  },
224 	{ false, true,  false },
225 	{ false, true,  true  },
226 	{ true,  true,  true  },
227 	{ true,  true,  false },
228 	{ true,  false, true  },
229 	{ true,  false, false },
230 };
231 
232 const struct DotProductVectorInfo dotProductVector8[] = {
233 	{ 8, 2 },
234 	{ 8, 3 },
235 	{ 8, 4 },
236 };
237 
238 const struct DotProductVectorInfo dotProductVector16[] = {
239 	{ 16, 2 },
240 	{ 16, 3 },
241 	{ 16, 4 },
242 };
243 
244 const struct DotProductVectorInfo dotProductVector32[] = {
245 	{ 32, 2 },
246 	{ 32, 3 },
247 	{ 32, 4 },
248 };
249 
getAlignedVecLen(const DotProductVectorInfo & vectorInfo)250 unsigned int getAlignedVecLen(const DotProductVectorInfo& vectorInfo)
251 {
252 	return (vectorInfo.vecLen == 3 ? 4 : vectorInfo.vecLen);
253 }
254 
generateIntegerDotProductTypeDeclsAndStrideDecors(std::ostringstream & typeDeclsStream,std::ostringstream & strideDecorsStream,const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo,size_t outSize,bool signedLHSAndResult,bool signedRHS)255 void generateIntegerDotProductTypeDeclsAndStrideDecors(std::ostringstream &typeDeclsStream, std::ostringstream &strideDecorsStream,
256 													   const struct DotProductPackingInfo &packingInfo,
257 													   const struct DotProductVectorInfo &vectorInfo, size_t outSize,
258 													   bool signedLHSAndResult, bool signedRHS)
259 {
260 	size_t signedScalarArraysMask = 0;
261 	size_t unsignedScalarArraysMask = 0;
262 	bool signedIntVectorNeeded = false;
263 	bool unsignedIntVectorNeeded = false;
264 
265 	if (signedLHSAndResult)
266 		signedScalarArraysMask |= static_cast<int>(outSize);
267 	else
268 		unsignedScalarArraysMask |= static_cast<int>(outSize);
269 
270 	if (packingInfo.packed)
271 	{
272 		if (packingInfo.signedLHS || packingInfo.signedRHS)
273 			signedScalarArraysMask |= vectorInfo.vecElementSize * vectorInfo.vecLen;
274 		if (!packingInfo.signedLHS || !packingInfo.signedRHS)
275 			unsignedScalarArraysMask |= vectorInfo.vecElementSize * vectorInfo.vecLen;
276 	}
277 	else
278 	{
279 		if (signedLHSAndResult)
280 		{
281 			signedIntVectorNeeded = true;
282 			signedScalarArraysMask |= vectorInfo.vecElementSize;
283 		}
284 		if (!signedRHS)
285 		{
286 			unsignedIntVectorNeeded = true;
287 			unsignedScalarArraysMask |= vectorInfo.vecElementSize;
288 		}
289 	}
290 
291 	size_t signedScalarTypesMask = signedScalarArraysMask;
292 	size_t unsignedScalarTypesMask = unsignedScalarArraysMask;
293 
294 	for (unsigned int size = 8; size <= 64; size *= 2)
295 	{
296 		if (size != 32)
297 		{
298 			string sizeStr(de::toString(size));
299 			if ((signedScalarTypesMask & size))
300 				typeDeclsStream << "%i" << sizeStr << " = OpTypeInt " << sizeStr << " 1\n";
301 			if ((unsignedScalarTypesMask & size))
302 				typeDeclsStream << "%u" << sizeStr << " = OpTypeInt " << sizeStr << " 0\n";
303 		}
304 	}
305 
306 	for (unsigned int size = 8; size <= 64; size *= 2)
307 	{
308 		string sizeStr = de::toString(size);
309 		if ((signedScalarArraysMask & size))
310 		{
311 			if (size != 32)
312 				typeDeclsStream << "%i" << sizeStr << "ptr = OpTypePointer Uniform %i" << sizeStr << "\n"
313 								   "%i" << sizeStr << "arr = OpTypeRuntimeArray %i" << sizeStr << "\n";
314 			strideDecorsStream << "OpDecorate %i" << sizeStr << "arr ArrayStride " << de::toString(size / 8) << "\n";
315 		}
316 		if ((unsignedScalarArraysMask & size))
317 		{
318 			typeDeclsStream << "%u" << sizeStr << "ptr = OpTypePointer Uniform %u" << sizeStr << "\n"
319 							   "%u" << sizeStr << "arr = OpTypeRuntimeArray %u" << sizeStr << "\n";
320 			strideDecorsStream << "OpDecorate %u" << sizeStr << "arr ArrayStride " << de::toString(size / 8) << "\n";
321 		}
322 	}
323 
324 	if (signedIntVectorNeeded)
325 	{
326 		string vecType = "%i" + de::toString(vectorInfo.vecElementSize) + "vec" + de::toString(vectorInfo.vecLen);
327 		typeDeclsStream << vecType << " = OpTypeVector %i" << vectorInfo.vecElementSize << " " << vectorInfo.vecLen << "\n"
328 						<< vecType << "ptr = OpTypePointer Uniform " << vecType << "\n"
329 						<< vecType << "arr = OpTypeRuntimeArray " << vecType << "\n";
330 		strideDecorsStream << "OpDecorate " << vecType << "arr ArrayStride "
331 						   << (vectorInfo.vecLen == 3 ? 4 : vectorInfo.vecLen) * (vectorInfo.vecElementSize / 8) << "\n";
332 	}
333 
334 
335 	if (unsignedIntVectorNeeded)
336 	{
337 		string vecType = "%u" + de::toString(vectorInfo.vecElementSize) + "vec" + de::toString(vectorInfo.vecLen);
338 		bool changeTypeName = false;
339 		if (vectorInfo.vecElementSize == 32 && vectorInfo.vecLen == 3)
340 			changeTypeName = true;
341 		else
342 			typeDeclsStream << vecType << " = OpTypeVector %u" << vectorInfo.vecElementSize << " " << vectorInfo.vecLen << "\n";
343 
344 		typeDeclsStream << vecType << "ptr = OpTypePointer Uniform " << (changeTypeName ? "%uvec3" : vecType) << "\n"
345 						<< vecType << "arr = OpTypeRuntimeArray " << (changeTypeName ? "%uvec3" : vecType) << "\n";
346 		strideDecorsStream << "OpDecorate " << vecType << "arr ArrayStride "
347 						   << (vectorInfo.vecLen == 3 ? 4 : vectorInfo.vecLen) * (vectorInfo.vecElementSize / 8) << "\n";
348 	}
349 }
350 
generateIntegerDotProductCode(const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo,size_t outSize,bool signedLHSAndResult,bool signedRHS,bool acc)351 string generateIntegerDotProductCode(const struct DotProductPackingInfo &packingInfo, const struct DotProductVectorInfo &vectorInfo,
352 									 size_t outSize, bool signedLHSAndResult, bool signedRHS, bool acc)
353 {
354 	DE_ASSERT(signedLHSAndResult || !signedRHS);
355 
356 	const string insnSignedness(signedLHSAndResult ? (signedRHS ? "S" : "SU") : "U");
357 	const string insnName(string("Op") + insnSignedness + "Dot" + (acc ? "AccSat" : "") + "KHR");
358 
359 	const string outputCapability(outSize != 32 ?
360 		"OpCapability Int" + de::toString(outSize) + "\n" : "");
361 	const string elementCapability(!packingInfo.packed && outSize != vectorInfo.vecElementSize && vectorInfo.vecElementSize != 32 ?
362 		"OpCapability Int" + de::toString(vectorInfo.vecElementSize) + "\n" : "");
363 
364 	const string dotProductInputCapabilityName(
365 		packingInfo.packed ? "DotProductInput4x8BitPackedKHR" : (vectorInfo.vecElementSize > 8) ? "DotProductInputAllKHR" : "DotProductInput4x8BitKHR");
366 
367 	const string capabilities(outputCapability +
368 							  elementCapability +
369 							  "OpCapability " + dotProductInputCapabilityName + "\n"
370 							  "OpCapability DotProductKHR\n");
371 	const string extensions("OpExtension \"SPV_KHR_integer_dot_product\"\n");
372 
373 	const string outType((signedLHSAndResult ? "i" : "u") + de::toString(outSize));
374 
375 	std::ostringstream typeDeclsStream;
376 	std::ostringstream strideDecorsStream;
377 	generateIntegerDotProductTypeDeclsAndStrideDecors(typeDeclsStream, strideDecorsStream,
378 													  packingInfo, vectorInfo, outSize, signedLHSAndResult, signedRHS);
379 	string typeDecls(typeDeclsStream.str());
380 	string strideDecors(strideDecorsStream.str());
381 
382 	const string lhsVecType(packingInfo.packed
383 							? string(packingInfo.signedLHS ? "i" : "u") + de::toString(vectorInfo.vecElementSize * vectorInfo.vecLen)
384 							: (signedLHSAndResult ? "i" : "u") + ((!signedLHSAndResult && vectorInfo.vecElementSize == 32 && vectorInfo.vecLen == 3) ? "" : de::toString(vectorInfo.vecElementSize)) + "vec" + de::toString(vectorInfo.vecLen));
385 	const string rhsVecType(packingInfo.packed
386 							? string(packingInfo.signedRHS ? "i" : "u") + de::toString(vectorInfo.vecElementSize * vectorInfo.vecLen)
387 							: (signedRHS ? "i" : "u") + ((!signedRHS && vectorInfo.vecElementSize == 32 && vectorInfo.vecLen == 3) ? "" : de::toString(vectorInfo.vecElementSize)) + "vec" + de::toString(vectorInfo.vecLen));
388 	const string lhsVecTypeBase(packingInfo.packed
389 								? string(packingInfo.signedLHS ? "i" : "u") + de::toString(vectorInfo.vecElementSize * vectorInfo.vecLen)
390 								: (signedLHSAndResult ? "i" : "u") + de::toString(vectorInfo.vecElementSize) + "vec" + de::toString(vectorInfo.vecLen));
391 	const string rhsVecTypeBase(packingInfo.packed
392 								? string(packingInfo.signedRHS ? "i" : "u") + de::toString(vectorInfo.vecElementSize * vectorInfo.vecLen)
393 								: (signedRHS ? "i" : "u") + de::toString(vectorInfo.vecElementSize) + "vec" + de::toString(vectorInfo.vecLen));
394 
395 	const string optFormatParam(packingInfo.packed ? " PackedVectorFormat4x8BitKHR" : "");
396 
397 	bool bufferSignednessMatches = (packingInfo.packed
398 									? (packingInfo.signedLHS == packingInfo.signedRHS)
399 									: (signedLHSAndResult == signedRHS));
400 
401 	return string(getComputeAsmShaderPreamble(capabilities, extensions)) +
402 
403 		"OpName %main           \"main\"\n"
404 		"OpName %id             \"gl_GlobalInvocationID\"\n"
405 
406 		"OpDecorate %id BuiltIn GlobalInvocationId\n"
407 		+ (bufferSignednessMatches
408 		   ? "OpDecorate %bufin BufferBlock\n"
409 		   : "OpDecorate %buflhs BufferBlock\n"
410 			 "OpDecorate %bufrhs BufferBlock\n") +
411 		"OpDecorate %bufout BufferBlock\n"
412 		"OpDecorate %indatalhs DescriptorSet 0\n"
413 		"OpDecorate %indatalhs Binding 0\n"
414 		"OpDecorate %indatarhs DescriptorSet 0\n"
415 		"OpDecorate %indatarhs Binding 1\n"
416 		+ (acc
417 		   ? "OpDecorate %indataacc DescriptorSet 0\n"
418 			 "OpDecorate %indataacc Binding 2\n"
419 		   : "") +
420 		"OpDecorate %outdata DescriptorSet 0\n"
421 		"OpDecorate %outdata Binding " + (acc ? "3" : "2") + "\n"
422 		+ strideDecors
423 
424 		+ (bufferSignednessMatches
425 		   ? "OpMemberDecorate %bufin 0 Offset 0\n"
426 		   : "OpMemberDecorate %buflhs 0 Offset 0\n"
427 			 "OpMemberDecorate %bufrhs 0 Offset 0\n") +
428 		"OpMemberDecorate %bufout 0 Offset 0\n"
429 
430 		+ getComputeAsmCommonTypes()
431 		+ typeDecls
432 
433 		+ (bufferSignednessMatches
434 		   ? "%bufin     = OpTypeStruct %" + lhsVecTypeBase + "arr\n"
435 			 "%bufinptr  = OpTypePointer Uniform %bufin\n"
436 		   : "%buflhs    = OpTypeStruct %" + lhsVecTypeBase + "arr\n"
437 			 "%buflhsptr = OpTypePointer Uniform %buflhs\n"
438 			 "%bufrhs    = OpTypeStruct %" + rhsVecTypeBase + "arr\n"
439 			 "%bufrhsptr = OpTypePointer Uniform %bufrhs\n") +
440 		"%bufout    = OpTypeStruct %" + outType + "arr\n"
441 		"%bufoutptr = OpTypePointer Uniform %bufout\n"
442 		"%indatalhs = OpVariable " + (bufferSignednessMatches ? "%bufinptr" : "%buflhsptr") + " Uniform\n"
443 		"%indatarhs = OpVariable " + (bufferSignednessMatches ? "%bufinptr" : "%bufrhsptr") + " Uniform\n"
444 		+ (acc ? "%indataacc = OpVariable %bufoutptr Uniform\n" : "") +
445 		"%outdata   = OpVariable %bufoutptr Uniform\n"
446 
447 		"%id        = OpVariable %uvec3ptr Input\n"
448 		"%zero      = OpConstant %i32 0\n"
449 
450 		"%main      = OpFunction %void None %voidf\n"
451 		"%label     = OpLabel\n"
452 		"%idval     = OpLoad %uvec3 %id\n"
453 		"%x         = OpCompositeExtract %u32 %idval 0\n"
454 		"%inloclhs  = OpAccessChain %" + lhsVecTypeBase + "ptr %indatalhs %zero %x\n"
455 		"%invallhs  = OpLoad %" + lhsVecType + " %inloclhs\n"
456 		"%inlocrhs  = OpAccessChain %" + rhsVecTypeBase + "ptr %indatarhs %zero %x\n"
457 		"%invalrhs  = OpLoad %" + rhsVecType + " %inlocrhs\n"
458 		+ (acc
459 		   ? "%inlocacc  = OpAccessChain %" + outType + "ptr %indataacc %zero %x\n"
460 			 "%invalacc  = OpLoad %" + outType + " %inlocacc\n"
461 		   : ""
462 		  ) +
463 		"%res       = " + insnName + " %" + outType + " %invallhs %invalrhs" + (acc ? " %invalacc" : "") + optFormatParam + "\n"
464 		"%outloc    = OpAccessChain %" + outType + "ptr %outdata %zero %x\n"
465 		"             OpStore %outloc %res\n"
466 		"             OpReturn\n"
467 		"             OpFunctionEnd\n";
468 }
469 
470 struct DotProductInputInfo
471 {
472 	string			name;
473 	unsigned int	vecLen;
474 	size_t			vecElemSize;
475 };
476 
477 template <class OutputT, class LHSOperandT, class RHSOperandT>
fillDotProductOutputs(int numElements,vector<LHSOperandT> & inputInts1,vector<RHSOperandT> & inputInts2,vector<OutputT> & outputInts,const struct DotProductInputInfo & inputInfo)478 void fillDotProductOutputs(int numElements, vector<LHSOperandT> &inputInts1, vector<RHSOperandT> &inputInts2,
479 						   vector<OutputT> &outputInts, const struct DotProductInputInfo &inputInfo)
480 {
481 	unsigned int alignedVecLen = inputInfo.vecLen == 3 ? 4 : inputInfo.vecLen;
482 	for (int ndx = 0; ndx < numElements; ++ndx)
483 	{
484 		std::vector<LHSOperandT> inputVec1;
485 		std::vector<RHSOperandT> inputVec2;
486 		inputVec1.reserve(alignedVecLen);
487 		inputVec2.reserve(alignedVecLen);
488 
489 		for (unsigned int vecElem = 0; vecElem < alignedVecLen; ++vecElem)
490 		{
491 			// Note: ordering of components does not matter, provided
492 			// that it is consistent between lhs and rhs.
493 			inputVec1.push_back(inputInts1[ndx * alignedVecLen + vecElem]);
494 			inputVec2.push_back(inputInts2[ndx * alignedVecLen + vecElem]);
495 		}
496 
497 		outputInts[ndx] = dotProduct<OutputT>(inputVec1, inputVec2);
498 	}
499 }
500 
getDotProductTestName(const struct DotProductInputInfo & inputInfo,const struct DotProductPackingInfo & packingInfo,size_t outSize)501 string getDotProductTestName(const struct DotProductInputInfo &inputInfo,
502 							 const struct DotProductPackingInfo &packingInfo, size_t outSize)
503 {
504 	return inputInfo.name
505 		+ (packingInfo.packed ? string("_packed_") : "_")
506 		+ (packingInfo.signedLHS ? "s" : "u") + (packingInfo.signedRHS ? "s" : "u") +
507 		"_v" + de::toString(inputInfo.vecLen) + "i" + de::toString(inputInfo.vecElemSize) +
508 		"_out" + de::toString(outSize);
509 }
510 
511 template <class InBufferT, class OutBufferT, class OutputT, class OperandT>
addOpSDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,int numElements,vector<OperandT> & inputInts1,vector<OperandT> & inputInts2,const struct DotProductInputInfo & inputInfo,const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo)512 void addOpSDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group,
513 							  int numElements, vector<OperandT> &inputInts1, vector<OperandT> &inputInts2,
514 							  const struct DotProductInputInfo &inputInfo, const struct DotProductPackingInfo &packingInfo,
515 							  const struct DotProductVectorInfo &vectorInfo)
516 {
517 	ComputeShaderSpec	spec;
518 	size_t				outSize = sizeof(OutputT) * 8;
519 	vector<OutputT>		outputInts	(numElements, 0);
520 
521 	fillDotProductOutputs(numElements, inputInts1, inputInts2, outputInts, inputInfo);
522 
523 	spec.assembly = generateIntegerDotProductCode(packingInfo, vectorInfo, outSize, true, true, false);
524 	addDotProductExtensionAndFeatures(spec, packingInfo, vectorInfo.vecElementSize, outSize);
525 
526 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts1)));
527 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts2)));
528 	spec.outputs.push_back	(BufferSp(new OutBufferT(outputInts)));
529 	spec.numWorkGroups		= IVec3(numElements, 1, 1);
530 	spec.failResult			= QP_TEST_RESULT_FAIL;
531 	spec.failMessage		= "Output doesn't match with expected";
532 
533 	string qualTestName(getDotProductTestName(inputInfo, packingInfo, outSize));
534 
535 	group->addChild(new SpvAsmComputeShaderCase(testCtx, qualTestName.data(), spec));
536 }
537 
538 template <class InBufferT, class T>
addOpSDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,const struct DotProductPackingInfo dotProductPackingInfo[],unsigned dotProductPackingInfoSize,const struct DotProductVectorInfo dotProductVectorInfo[],unsigned dotProductVectorInfoSize,T vecMin,T vecMax)539 void addOpSDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name,
540 							  const struct DotProductPackingInfo dotProductPackingInfo[], unsigned dotProductPackingInfoSize,
541 							  const struct DotProductVectorInfo dotProductVectorInfo[], unsigned dotProductVectorInfoSize,
542 							  T vecMin, T vecMax)
543 {
544 	const int		numElements	= 200;
545 	// Note: this test does not currently cover 64-bit integer results
546 	for (unsigned int j = 0; j < dotProductVectorInfoSize; j++)
547 	{
548 		const struct DotProductVectorInfo &vectorInfo = dotProductVectorInfo[j];
549 		unsigned int alignedVecLen = getAlignedVecLen(vectorInfo);
550 		struct DotProductInputInfo inputInfo = { name, vectorInfo.vecLen, vectorInfo.vecElementSize };
551 		vector<T>		inputInts1	(numElements * alignedVecLen, 0);
552 		vector<T>		inputInts2	(numElements * alignedVecLen, 0);
553 
554 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts1[0], numElements * alignedVecLen);
555 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts2[0], numElements * alignedVecLen);
556 
557 		if (vectorInfo.vecLen == 3)
558 			for (unsigned int ndx = 0; ndx < numElements; ++ndx)
559 				inputInts1[ndx*4+3] = inputInts2[ndx*4+3] = 0;
560 
561 		for (unsigned int i = 0; i < dotProductPackingInfoSize; i++)
562 		{
563 			const struct DotProductPackingInfo &packingInfo = dotProductPackingInfo[i];
564 			if (packingInfo.packed && (vectorInfo.vecElementSize != 8 || vectorInfo.vecLen != 4))
565 				continue;
566 
567 			if (vectorInfo.vecElementSize <= 32)
568 				addOpSDotKHRComputeTests<InBufferT, Int32Buffer, deInt32>(testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
569 			if (vectorInfo.vecElementSize <= 16)
570 				addOpSDotKHRComputeTests<InBufferT, Int16Buffer, deInt16>(testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
571 			if (vectorInfo.vecElementSize <= 8)
572 				addOpSDotKHRComputeTests<InBufferT, Int8Buffer,  deInt8> (testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
573 		}
574 	}
575 }
576 
577 template <class T>
add32bitOpSDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax)578 void add32bitOpSDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax)
579 {
580 	addOpSDotKHRComputeTests<Int32Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
581 										  dotProductVector32, DE_LENGTH_OF_ARRAY(dotProductVector32), vecMin, vecMax);
582 }
583 
584 template <class T>
add16bitOpSDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax)585 void add16bitOpSDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax)
586 {
587 	addOpSDotKHRComputeTests<Int16Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
588 										  dotProductVector16, DE_LENGTH_OF_ARRAY(dotProductVector16), vecMin, vecMax);
589 }
590 
591 template <class T>
add8bitOpSDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax)592 void add8bitOpSDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax)
593 {
594 	addOpSDotKHRComputeTests<Int8Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
595 										 dotProductVector8, DE_LENGTH_OF_ARRAY(dotProductVector8), vecMin, vecMax);
596 }
597 
598 template <class InBufferT, class OutBufferT, class OutputT, class OperandT>
addOpUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,int numElements,vector<OperandT> & inputInts1,vector<OperandT> & inputInts2,const struct DotProductInputInfo & inputInfo,const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo)599 void addOpUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group,
600 							  int numElements, vector<OperandT> &inputInts1, vector<OperandT> &inputInts2,
601 							  const struct DotProductInputInfo &inputInfo, const struct DotProductPackingInfo &packingInfo,
602 							  const struct DotProductVectorInfo &vectorInfo)
603 {
604 	ComputeShaderSpec	spec;
605 	size_t				outSize = sizeof(OutputT) * 8;
606 	vector<OutputT>		outputInts	(numElements, 0);
607 
608 	fillDotProductOutputs(numElements, inputInts1, inputInts2, outputInts, inputInfo);
609 
610 	spec.assembly = generateIntegerDotProductCode(packingInfo, vectorInfo, outSize, false, false, false);
611 
612 	addDotProductExtensionAndFeatures(spec, packingInfo, vectorInfo.vecElementSize, outSize);
613 
614 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts1)));
615 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts2)));
616 	spec.outputs.push_back	(BufferSp(new OutBufferT(outputInts)));
617 	spec.numWorkGroups		= IVec3(numElements, 1, 1);
618 	spec.failResult			= QP_TEST_RESULT_FAIL;
619 	spec.failMessage		= "Output doesn't match with expected";
620 
621 	string qualTestName(getDotProductTestName(inputInfo, packingInfo, outSize));
622 
623 	group->addChild(new SpvAsmComputeShaderCase(testCtx, qualTestName.data(), spec));
624 }
625 
626 template <class InBufferT, class T>
addOpUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,const struct DotProductPackingInfo dotProductPackingInfo[],unsigned dotProductPackingInfoSize,const struct DotProductVectorInfo dotProductVectorInfo[],unsigned dotProductVectorInfoSize,T vecMin,T vecMax)627 void addOpUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name,
628 							  const struct DotProductPackingInfo dotProductPackingInfo[], unsigned dotProductPackingInfoSize,
629 							  const struct DotProductVectorInfo dotProductVectorInfo[], unsigned dotProductVectorInfoSize,
630 							  T vecMin, T vecMax)
631 {
632 	const int		numElements	= 200;
633 
634 	for (unsigned int j = 0; j < dotProductVectorInfoSize; j++)
635 	{
636 		const struct DotProductVectorInfo &vectorInfo = dotProductVectorInfo[j];
637 		unsigned int alignedVecLen = getAlignedVecLen(vectorInfo);
638 		struct DotProductInputInfo inputInfo = { name, vectorInfo.vecLen, vectorInfo.vecElementSize };
639 		vector<T>		inputInts1	(numElements * alignedVecLen, 0);
640 		vector<T>		inputInts2	(numElements * alignedVecLen, 0);
641 
642 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts1[0], numElements * alignedVecLen);
643 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts2[0], numElements * alignedVecLen);
644 
645 		if (vectorInfo.vecLen == 3)
646 			for (unsigned int ndx = 0; ndx < numElements; ++ndx)
647 				inputInts1[ndx*4+3] = inputInts2[ndx*4+3] = 0;
648 
649 		for (unsigned int i = 0; i < dotProductPackingInfoSize; i++)
650 		{
651 			const struct DotProductPackingInfo &packingInfo = dotProductPackingInfo[i];
652 			if (packingInfo.packed && (vectorInfo.vecElementSize != 8 || vectorInfo.vecLen != 4))
653 				continue;
654 
655 			if (vectorInfo.vecElementSize <= 32)
656 				addOpUDotKHRComputeTests<InBufferT, Uint32Buffer, deUint32>(testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
657 			if (vectorInfo.vecElementSize <= 16)
658 				addOpUDotKHRComputeTests<InBufferT, Uint16Buffer, deUint16>(testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
659 			if (vectorInfo.vecElementSize <= 8)
660 				addOpUDotKHRComputeTests<InBufferT, Uint8Buffer,  deUint8> (testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
661 		}
662 	}
663 }
664 
665 template <class T>
add32bitOpUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax)666 void add32bitOpUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax)
667 {
668 	addOpUDotKHRComputeTests<Uint32Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
669 										   dotProductVector32, DE_LENGTH_OF_ARRAY(dotProductVector32), vecMin, vecMax);
670 }
671 
672 template <class T>
add16bitOpUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax)673 void add16bitOpUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax)
674 {
675 	addOpUDotKHRComputeTests<Uint16Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
676 										   dotProductVector16, DE_LENGTH_OF_ARRAY(dotProductVector16), vecMin, vecMax);
677 }
678 
679 template <class T>
add8bitOpUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax)680 void add8bitOpUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax)
681 {
682 	addOpUDotKHRComputeTests<Uint8Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
683 										  dotProductVector8, DE_LENGTH_OF_ARRAY(dotProductVector8), vecMin, vecMax);
684 }
685 
686 template <class LHSBufferT, class RHSBufferT, class OutBufferT, class OutputT, class LHSOperandT, class RHSOperandT>
addOpSUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,int numElements,vector<LHSOperandT> & inputInts1,vector<RHSOperandT> & inputInts2,const struct DotProductInputInfo & inputInfo,const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo)687 void addOpSUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group,
688 							   int numElements, vector<LHSOperandT> &inputInts1, vector<RHSOperandT> &inputInts2,
689 							   const struct DotProductInputInfo &inputInfo, const struct DotProductPackingInfo &packingInfo,
690 							   const struct DotProductVectorInfo &vectorInfo)
691 {
692 	ComputeShaderSpec	spec;
693 	size_t				outSize = sizeof(OutputT) * 8;
694 	vector<OutputT>		outputInts	(numElements, 0);
695 
696 	fillDotProductOutputs(numElements, inputInts1, inputInts2, outputInts, inputInfo);
697 
698 	spec.assembly = generateIntegerDotProductCode(packingInfo, vectorInfo, outSize, true, false, false);
699 	addDotProductExtensionAndFeatures(spec, packingInfo, vectorInfo.vecElementSize, outSize);
700 
701 	spec.inputs.push_back	(BufferSp(new LHSBufferT(inputInts1)));
702 	spec.inputs.push_back	(BufferSp(new RHSBufferT(inputInts2)));
703 	spec.outputs.push_back	(BufferSp(new OutBufferT(outputInts)));
704 	spec.numWorkGroups		= IVec3(numElements, 1, 1);
705 	spec.failResult			= QP_TEST_RESULT_FAIL;
706 	spec.failMessage		= "Output doesn't match with expected";
707 
708 	string qualTestName(getDotProductTestName(inputInfo, packingInfo, outSize));
709 
710 	group->addChild(new SpvAsmComputeShaderCase(testCtx, qualTestName.data(), spec));
711 }
712 
713 template <class LHSBufferT, class RHSBufferT, class LHSOperandT, class RHSOperandT>
addOpSUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,const struct DotProductPackingInfo dotProductPackingInfo[],unsigned dotProductPackingInfoSize,const struct DotProductVectorInfo dotProductVectorInfo[],unsigned dotProductVectorInfoSize,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax)714 void addOpSUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name,
715 							   const struct DotProductPackingInfo dotProductPackingInfo[], unsigned dotProductPackingInfoSize,
716 							   const struct DotProductVectorInfo dotProductVectorInfo[], unsigned dotProductVectorInfoSize,
717 							   LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax)
718 {
719 	const int		numElements	= 200;
720 	// Note: this test does not currently cover 64-bit integer results
721 	for (unsigned int j = 0; j < dotProductVectorInfoSize; j++)
722 	{
723 		const struct DotProductVectorInfo &vectorInfo = dotProductVectorInfo[j];
724 		unsigned int alignedVecLen = getAlignedVecLen(vectorInfo);
725 		struct DotProductInputInfo inputInfo = { name, vectorInfo.vecLen, vectorInfo.vecElementSize };
726 		vector<LHSOperandT>	inputInts1	(numElements * alignedVecLen, 0);
727 		vector<RHSOperandT>	inputInts2	(numElements * alignedVecLen, 0);
728 
729 		fillRandomScalars(rnd, lhsVecMin, lhsVecMax, &inputInts1[0], numElements * alignedVecLen);
730 		fillRandomScalars(rnd, rhsVecMin, rhsVecMax, &inputInts2[0], numElements * alignedVecLen);
731 
732 		if (vectorInfo.vecLen == 3)
733 			for (unsigned int ndx = 0; ndx < numElements; ++ndx)
734 				inputInts1[ndx*4+3] = inputInts2[ndx*4+3] = 0;
735 
736 
737 		for (unsigned int i = 0; i < dotProductPackingInfoSize; i++)
738 		{
739 			const struct DotProductPackingInfo &packingInfo = dotProductPackingInfo[i];
740 			if (packingInfo.packed && (vectorInfo.vecElementSize != 8 || vectorInfo.vecLen != 4))
741 				continue;
742 
743 			if (vectorInfo.vecElementSize <= 32)
744 				addOpSUDotKHRComputeTests<LHSBufferT, RHSBufferT, Int32Buffer, deInt32>(testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
745 			if (vectorInfo.vecElementSize <= 16)
746 				addOpSUDotKHRComputeTests<LHSBufferT, RHSBufferT, Int16Buffer, deInt16>(testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
747 			if (vectorInfo.vecElementSize <= 8)
748 				addOpSUDotKHRComputeTests<LHSBufferT, RHSBufferT, Int8Buffer,  deInt8> (testCtx, group, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo);
749 		}
750 	}
751 }
752 
753 template <class LHSOperandT, class RHSOperandT>
add32bitOpSUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax)754 void add32bitOpSUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax)
755 {
756 	addOpSUDotKHRComputeTests<Int32Buffer, Uint32Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
757 														 dotProductVector32, DE_LENGTH_OF_ARRAY(dotProductVector32), lhsVecMin, lhsVecMax, rhsVecMin, rhsVecMax);
758 }
759 
760 template <class LHSOperandT, class RHSOperandT>
add16bitOpSUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax)761 void add16bitOpSUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax)
762 {
763 	addOpSUDotKHRComputeTests<Int16Buffer, Uint16Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
764 														 dotProductVector16, DE_LENGTH_OF_ARRAY(dotProductVector16), lhsVecMin, lhsVecMax, rhsVecMin, rhsVecMax);
765 }
766 
767 template <class LHSOperandT, class RHSOperandT>
add8bitOpSUDotKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax)768 void add8bitOpSUDotKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax)
769 {
770 	addOpSUDotKHRComputeTests<Int8Buffer, Uint8Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
771 													   dotProductVector8, DE_LENGTH_OF_ARRAY(dotProductVector8), lhsVecMin, lhsVecMax, rhsVecMin, rhsVecMax);
772 }
773 
774 template <class InBufferT, class AddendBufferT, class AddendT, class OperandT>
addOpSDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,int numElements,vector<OperandT> & inputInts1,vector<OperandT> & inputInts2,const struct DotProductInputInfo & inputInfo,const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo,bool useMaxAddend)775 void addOpSDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd,
776 									int numElements, vector<OperandT> &inputInts1, vector<OperandT> &inputInts2,
777 									const struct DotProductInputInfo &inputInfo, const struct DotProductPackingInfo &packingInfo,
778 									const struct DotProductVectorInfo &vectorInfo, bool useMaxAddend)
779 {
780 	ComputeShaderSpec	spec;
781 	size_t				addendSize = sizeof(AddendT) * 8;
782 	vector<AddendT>		inputInts3	(numElements, 0);
783 	vector<AddendT>		outputInts	(numElements, 0);
784 
785 	if (useMaxAddend)
786 		fillRandomScalars(rnd, (AddendT)(std::numeric_limits<AddendT>::max()-20), (AddendT)(std::numeric_limits<AddendT>::max()),
787 					  &inputInts3[0], numElements);
788 	else
789 		fillRandomScalars(rnd, (AddendT)(std::numeric_limits<AddendT>::min()), (AddendT)(std::numeric_limits<AddendT>::min()+20),
790 					  &inputInts3[0], numElements);
791 
792 	spec.assembly = generateIntegerDotProductCode(packingInfo, vectorInfo, addendSize, true, true, true);
793 
794 	addDotProductExtensionAndFeatures(spec, packingInfo, vectorInfo.vecElementSize, addendSize);
795 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts1)));
796 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts2)));
797 	spec.inputs.push_back	(BufferSp(new AddendBufferT(inputInts3)));
798 	spec.outputs.push_back	(BufferSp(new AddendBufferT(outputInts)));
799 	spec.numWorkGroups		= IVec3(numElements, 1, 1);
800 	spec.verifyIO			= &compareDotProductAccSat<AddendT, OperandT, OperandT>;
801 	spec.failResult			= QP_TEST_RESULT_FAIL;
802 	spec.failMessage		= "Output doesn't match with expected";
803 
804 	string qualTestName(getDotProductTestName(inputInfo, packingInfo, addendSize));
805 
806 	group->addChild(new SpvAsmComputeShaderCase(testCtx, qualTestName.data(), spec));
807 }
808 
809 template <class InBufferT, class T>
addOpSDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,const struct DotProductPackingInfo dotProductPackingInfo[],unsigned dotProductPackingInfoSize,const struct DotProductVectorInfo dotProductVectorInfo[],unsigned dotProductVectorInfoSize,T vecMin,T vecMax,bool useMaxAddend)810 void addOpSDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name,
811 									const struct DotProductPackingInfo dotProductPackingInfo[], unsigned dotProductPackingInfoSize,
812 									const struct DotProductVectorInfo dotProductVectorInfo[], unsigned dotProductVectorInfoSize,
813 									T vecMin, T vecMax, bool useMaxAddend)
814 {
815 	const int		numElements	= 200;
816 	// Note: this test does not currently cover 64-bit integer results
817 	for (unsigned int j = 0 ; j < dotProductVectorInfoSize; j++)
818 	{
819 		const struct DotProductVectorInfo &vectorInfo = dotProductVectorInfo[j];
820 		unsigned int alignedVecLen = getAlignedVecLen(vectorInfo);
821 		struct DotProductInputInfo inputInfo = { name, vectorInfo.vecLen, vectorInfo.vecElementSize };
822 		vector<T>		inputInts1	(numElements * alignedVecLen, 0);
823 		vector<T>		inputInts2	(numElements * alignedVecLen, 0);
824 
825 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts1[0], numElements * alignedVecLen);
826 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts2[0], numElements * alignedVecLen);
827 
828 		if (vectorInfo.vecLen == 3)
829 			for (unsigned int ndx = 0; ndx < numElements; ++ndx)
830 				inputInts1[ndx*4+3] = inputInts2[ndx*4+3] = 0;
831 
832 
833 		for (unsigned int i = 0; i < dotProductPackingInfoSize; i++)
834 		{
835 			const struct DotProductPackingInfo &packingInfo = dotProductPackingInfo[i];
836 			if (packingInfo.packed && (vectorInfo.vecElementSize != 8 || vectorInfo.vecLen != 4))
837 				continue;
838 
839 			if (vectorInfo.vecElementSize <= 32)
840 				addOpSDotAccSatKHRComputeTests<InBufferT, Int32Buffer, deInt32>(testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
841 			if (vectorInfo.vecElementSize <= 16)
842 				addOpSDotAccSatKHRComputeTests<InBufferT, Int16Buffer, deInt16>(testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
843 			if (vectorInfo.vecElementSize <= 8)
844 				addOpSDotAccSatKHRComputeTests<InBufferT, Int8Buffer,  deInt8> (testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
845 		}
846 	}
847 }
848 
849 template <class T>
add32bitOpSDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax,bool useMaxAddend=true)850 void add32bitOpSDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax, bool useMaxAddend = true)
851 {
852 	addOpSDotAccSatKHRComputeTests<Int32Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
853 												dotProductVector32, DE_LENGTH_OF_ARRAY(dotProductVector32), vecMin, vecMax, useMaxAddend);
854 }
855 
856 template <class T>
add16bitOpSDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax,bool useMaxAddend=true)857 void add16bitOpSDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax, bool useMaxAddend = true)
858 {
859 	addOpSDotAccSatKHRComputeTests<Int16Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
860 												dotProductVector16, DE_LENGTH_OF_ARRAY(dotProductVector16), vecMin, vecMax, useMaxAddend);
861 }
862 
863 template <class T>
add8bitOpSDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax,bool useMaxAddend=true)864 void add8bitOpSDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax, bool useMaxAddend = true)
865 {
866 	addOpSDotAccSatKHRComputeTests<Int8Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
867 											   dotProductVector8, DE_LENGTH_OF_ARRAY(dotProductVector8), vecMin, vecMax, useMaxAddend);
868 }
869 
870 template <class InBufferT, class AddendBufferT, class AddendT, class OperandT>
addOpUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,int numElements,vector<OperandT> & inputInts1,vector<OperandT> & inputInts2,const struct DotProductInputInfo & inputInfo,const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo,bool useMaxAddend)871 void addOpUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd,
872 									int numElements, vector<OperandT> &inputInts1, vector<OperandT> &inputInts2,
873 									const struct DotProductInputInfo &inputInfo, const struct DotProductPackingInfo &packingInfo,
874 									const struct DotProductVectorInfo &vectorInfo, bool useMaxAddend)
875 {
876 	ComputeShaderSpec	spec;
877 	size_t				addendSize = sizeof(AddendT) * 8;
878 	vector<AddendT>		inputInts3	(numElements, 0);
879 	vector<AddendT>		outputInts	(numElements, 0);
880 
881 	if (useMaxAddend)
882 		fillRandomScalars(rnd, (AddendT)(std::numeric_limits<AddendT>::max()-20), (AddendT)(std::numeric_limits<AddendT>::max()),
883 					&inputInts3[0], numElements);
884 	else
885 		fillRandomScalars(rnd, (AddendT)(std::numeric_limits<AddendT>::min()), (AddendT)(std::numeric_limits<AddendT>::min()+20),
886 					&inputInts3[0], numElements);
887 
888 	spec.assembly = generateIntegerDotProductCode(packingInfo, vectorInfo, addendSize, false, false, true);
889 
890 	addDotProductExtensionAndFeatures(spec, packingInfo, vectorInfo.vecElementSize, addendSize);
891 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts1)));
892 	spec.inputs.push_back	(BufferSp(new InBufferT(inputInts2)));
893 	spec.inputs.push_back	(BufferSp(new AddendBufferT(inputInts3)));
894 	spec.outputs.push_back	(BufferSp(new AddendBufferT(outputInts)));
895 	spec.numWorkGroups		= IVec3(numElements, 1, 1);
896 	spec.verifyIO			= &compareDotProductAccSat<AddendT, OperandT, OperandT>;
897 	spec.failResult			= QP_TEST_RESULT_FAIL;
898 	spec.failMessage		= "Output doesn't match with expected";
899 
900 	string qualTestName(getDotProductTestName(inputInfo, packingInfo, addendSize));
901 
902 	group->addChild(new SpvAsmComputeShaderCase(testCtx, qualTestName.data(), spec));
903 }
904 
905 template <class InBufferT, class T>
addOpUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,const struct DotProductPackingInfo dotProductPackingInfo[],unsigned dotProductPackingInfoSize,const struct DotProductVectorInfo dotProductVectorInfo[],unsigned dotProductVectorInfoSize,T vecMin,T vecMax,bool useMaxAddend)906 void addOpUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name,
907 									const struct DotProductPackingInfo dotProductPackingInfo[], unsigned dotProductPackingInfoSize,
908 									const struct DotProductVectorInfo dotProductVectorInfo[], unsigned dotProductVectorInfoSize,
909 									T vecMin, T vecMax, bool useMaxAddend)
910 {
911 	const int		numElements	= 200;
912 	// Note: this test does not currently cover 64-bit integer results
913 
914 	for (unsigned int j = 0 ; j < dotProductVectorInfoSize; j++)
915 	{
916 		const struct DotProductVectorInfo &vectorInfo = dotProductVectorInfo[j];
917 		unsigned int alignedVecLen = getAlignedVecLen(vectorInfo);
918 		struct DotProductInputInfo inputInfo = { name, vectorInfo.vecLen, vectorInfo.vecElementSize };
919 		vector<T>		inputInts1	(numElements * alignedVecLen, 0);
920 		vector<T>		inputInts2	(numElements * alignedVecLen, 0);
921 
922 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts1[0], numElements * alignedVecLen);
923 		fillRandomScalars(rnd, vecMin, vecMax, &inputInts2[0], numElements * alignedVecLen);
924 
925 		if (vectorInfo.vecLen == 3)
926 			for (unsigned int ndx = 0; ndx < numElements; ++ndx)
927 				inputInts1[ndx*4+3] = inputInts2[ndx*4+3] = 0;
928 
929 		for (unsigned int i = 0; i < dotProductPackingInfoSize; i++)
930 		{
931 			const struct DotProductPackingInfo &packingInfo = dotProductPackingInfo[i];
932 			if (packingInfo.packed && (vectorInfo.vecElementSize != 8 || vectorInfo.vecLen != 4))
933 				continue;
934 
935 			if (vectorInfo.vecElementSize <= 32)
936 				addOpUDotAccSatKHRComputeTests<InBufferT, Uint32Buffer, deUint32>(testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
937 			if (vectorInfo.vecElementSize <= 16)
938 				addOpUDotAccSatKHRComputeTests<InBufferT, Uint16Buffer, deUint16>(testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
939 			if (vectorInfo.vecElementSize <= 8)
940 				addOpUDotAccSatKHRComputeTests<InBufferT, Uint8Buffer,  deUint8> (testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
941 		}
942 	}
943 }
944 
945 template <class T>
add32bitOpUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax,bool useMaxAddend=true)946 void add32bitOpUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax, bool useMaxAddend = true)
947 {
948 	addOpUDotAccSatKHRComputeTests<Uint32Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
949 												 dotProductVector32, DE_LENGTH_OF_ARRAY(dotProductVector32), vecMin, vecMax, useMaxAddend);
950 }
951 
952 template <class T>
add16bitOpUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax,bool useMaxAddend=true)953 void add16bitOpUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax, bool useMaxAddend = true)
954 {
955 	addOpUDotAccSatKHRComputeTests<Uint16Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
956 												 dotProductVector16, DE_LENGTH_OF_ARRAY(dotProductVector16), vecMin, vecMax, useMaxAddend);
957 }
958 
959 template <class T>
add8bitOpUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,T vecMin,T vecMax,bool useMaxAddend=true)960 void add8bitOpUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, T vecMin, T vecMax, bool useMaxAddend = true)
961 {
962 	addOpUDotAccSatKHRComputeTests<Uint8Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
963 												dotProductVector8, DE_LENGTH_OF_ARRAY(dotProductVector8), vecMin, vecMax, useMaxAddend);
964 }
965 
966 template <class LHSBufferT, class RHSBufferT, class AddendBufferT, class AddendT, class LHSOperandT, class RHSOperandT>
addOpSUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,int numElements,vector<LHSOperandT> & inputInts1,vector<RHSOperandT> & inputInts2,const struct DotProductInputInfo & inputInfo,const struct DotProductPackingInfo & packingInfo,const struct DotProductVectorInfo & vectorInfo,bool useMaxAddend)967 void addOpSUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd,
968 									 int numElements, vector<LHSOperandT> &inputInts1, vector<RHSOperandT> &inputInts2,
969 									 const struct DotProductInputInfo &inputInfo, const struct DotProductPackingInfo &packingInfo,
970 									 const struct DotProductVectorInfo &vectorInfo, bool useMaxAddend)
971 {
972 	ComputeShaderSpec	spec;
973 	size_t				addendSize = sizeof(AddendT) * 8;
974 	vector<AddendT>		inputInts3	(numElements, 0);
975 	vector<AddendT>		outputInts	(numElements, 0);
976 
977 	// Populate the accumulation buffer with large values to attempt to guarantee saturation
978 	if (useMaxAddend)
979 		fillRandomScalars(rnd, (AddendT)(std::numeric_limits<AddendT>::max()-20), (AddendT)(std::numeric_limits<AddendT>::max()),
980 					&inputInts3[0], numElements);
981 	else
982 		fillRandomScalars(rnd, (AddendT)(std::numeric_limits<AddendT>::min()), (AddendT)(std::numeric_limits<AddendT>::min()+20),
983 					&inputInts3[0], numElements);
984 
985 	spec.assembly = generateIntegerDotProductCode(packingInfo, vectorInfo, addendSize, true, false, true);
986 	addDotProductExtensionAndFeatures(spec, packingInfo, vectorInfo.vecElementSize, addendSize);
987 	spec.inputs.push_back	(BufferSp(new LHSBufferT(inputInts1)));
988 	spec.inputs.push_back	(BufferSp(new RHSBufferT(inputInts2)));
989 	spec.inputs.push_back	(BufferSp(new AddendBufferT(inputInts3)));
990 	spec.outputs.push_back	(BufferSp(new AddendBufferT(outputInts)));
991 	spec.numWorkGroups		= IVec3(numElements, 1, 1);
992 	spec.verifyIO			= &compareDotProductAccSat<AddendT, LHSOperandT, RHSOperandT>;
993 	spec.failResult			= QP_TEST_RESULT_FAIL;
994 	spec.failMessage		= "Output doesn't match with expected";
995 
996 	string qualTestName(getDotProductTestName(inputInfo, packingInfo, addendSize));
997 
998 	group->addChild(new SpvAsmComputeShaderCase(testCtx, qualTestName.data(), spec));
999 }
1000 
1001 template <class LHSBufferT, class RHSBufferT, class LHSOperandT, class RHSOperandT>
addOpSUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,const struct DotProductPackingInfo dotProductPackingInfo[],unsigned dotProductPackingInfoSize,const struct DotProductVectorInfo dotProductVectorInfo[],unsigned dotProductVectorInfoSize,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax,bool useMaxAddend)1002 void addOpSUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name,
1003 									 const struct DotProductPackingInfo dotProductPackingInfo[], unsigned dotProductPackingInfoSize,
1004 									 const struct DotProductVectorInfo dotProductVectorInfo[], unsigned dotProductVectorInfoSize,
1005 									 LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax, bool useMaxAddend)
1006 {
1007 	const int	numElements	= 200;
1008 	// Note: this test does not currently cover 64-bit integer results
1009 
1010 	for (unsigned int j = 0; j < dotProductVectorInfoSize; j++)
1011 	{
1012 		const struct DotProductVectorInfo &vectorInfo = dotProductVectorInfo[j];
1013 		unsigned int alignedVecLen = getAlignedVecLen(vectorInfo);
1014 		struct DotProductInputInfo inputInfo = { name, vectorInfo.vecLen, vectorInfo.vecElementSize };
1015 		vector<LHSOperandT>	inputInts1	(numElements * alignedVecLen, 0);
1016 		vector<RHSOperandT>	inputInts2	(numElements * alignedVecLen, 0);
1017 
1018 		fillRandomScalars(rnd, lhsVecMin, lhsVecMax, &inputInts1[0], numElements * alignedVecLen);
1019 		fillRandomScalars(rnd, rhsVecMin, rhsVecMax, &inputInts2[0], numElements * alignedVecLen);
1020 
1021 		if (vectorInfo.vecLen == 3)
1022 			for (unsigned int ndx = 0; ndx < numElements; ++ndx)
1023 				inputInts1[ndx*4+3] = inputInts2[ndx*4+3] = 0;
1024 
1025 		for (unsigned int i = 0; i < dotProductPackingInfoSize; i++)
1026 		{
1027 			const struct DotProductPackingInfo &packingInfo = dotProductPackingInfo[i];
1028 			if (packingInfo.packed && (vectorInfo.vecElementSize != 8 || vectorInfo.vecLen != 4))
1029 				continue;
1030 
1031 			if (vectorInfo.vecElementSize <= 32)
1032 				addOpSUDotAccSatKHRComputeTests<LHSBufferT, RHSBufferT, Int32Buffer, deInt32>(testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
1033 			if (vectorInfo.vecElementSize <= 16)
1034 				addOpSUDotAccSatKHRComputeTests<LHSBufferT, RHSBufferT, Int16Buffer, deInt16>(testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
1035 			if (vectorInfo.vecElementSize <= 8)
1036 				addOpSUDotAccSatKHRComputeTests<LHSBufferT, RHSBufferT, Int8Buffer,  deInt8> (testCtx, group, rnd, numElements, inputInts1, inputInts2, inputInfo, packingInfo, vectorInfo, useMaxAddend);
1037 		}
1038 	}
1039 }
1040 
1041 template <class LHSOperandT, class RHSOperandT>
add32bitOpSUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax,bool useMaxAddend=true)1042 void add32bitOpSUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax, bool useMaxAddend = true)
1043 {
1044     addOpSUDotAccSatKHRComputeTests<Int32Buffer, Uint32Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
1045 															   dotProductVector32, DE_LENGTH_OF_ARRAY(dotProductVector32), lhsVecMin, lhsVecMax, rhsVecMin, rhsVecMax, useMaxAddend);
1046 }
1047 
1048 template <class LHSOperandT, class RHSOperandT>
add16bitOpSUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax,bool useMaxAddend=true)1049 void add16bitOpSUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax, bool useMaxAddend = true)
1050 {
1051 	addOpSUDotAccSatKHRComputeTests<Int16Buffer, Uint16Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
1052 															   dotProductVector16, DE_LENGTH_OF_ARRAY(dotProductVector16), lhsVecMin, lhsVecMax, rhsVecMin, rhsVecMax, useMaxAddend);
1053 }
1054 
1055 template <class LHSOperandT, class RHSOperandT>
add8bitOpSUDotAccSatKHRComputeTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * group,de::Random & rnd,string name,LHSOperandT lhsVecMin,LHSOperandT lhsVecMax,RHSOperandT rhsVecMin,RHSOperandT rhsVecMax,bool useMaxAddend=true)1056 void add8bitOpSUDotAccSatKHRComputeTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *group, de::Random &rnd, string name, LHSOperandT lhsVecMin, LHSOperandT lhsVecMax, RHSOperandT rhsVecMin, RHSOperandT rhsVecMax, bool useMaxAddend = true)
1057 {
1058 	addOpSUDotAccSatKHRComputeTests<Int8Buffer, Uint8Buffer>(testCtx, group, rnd, name, dotProductPacking, DE_LENGTH_OF_ARRAY(dotProductPacking),
1059 															 dotProductVector8, DE_LENGTH_OF_ARRAY(dotProductVector8), lhsVecMin, lhsVecMax, rhsVecMin, rhsVecMax, useMaxAddend);
1060 }
1061 
1062 } // anon namespace
1063 
createOpSDotKHRComputeGroup(tcu::TestContext & testCtx)1064 tcu::TestCaseGroup* createOpSDotKHRComputeGroup(tcu::TestContext& testCtx)
1065 {
1066 	// Test the OpSDotKHR instruction
1067 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "opsdotkhr"));
1068 	de::Random						rnd		(deStringHash(group->getName()));
1069 
1070 	add8bitOpSDotKHRComputeTests(testCtx, group.get(), rnd, string("all"),   std::numeric_limits<deInt8>::min(), std::numeric_limits<deInt8>::max());
1071 	add8bitOpSDotKHRComputeTests(testCtx, group.get(), rnd, string("small"), (deInt8)-20,  (deInt8)20);
1072 	add16bitOpSDotKHRComputeTests(testCtx, group.get(), rnd, string("all"), std::numeric_limits<deInt16>::min(), std::numeric_limits<deInt16>::max());
1073 	add32bitOpSDotKHRComputeTests(testCtx, group.get(), rnd, string("all"), std::numeric_limits<deInt32>::min(), std::numeric_limits<deInt32>::max());
1074 
1075 	return group.release();
1076 }
1077 
createOpUDotKHRComputeGroup(tcu::TestContext & testCtx)1078 tcu::TestCaseGroup* createOpUDotKHRComputeGroup(tcu::TestContext& testCtx)
1079 {
1080 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "opudotkhr", "Test the OpUDotKHR instruction"));
1081 	de::Random						rnd		(deStringHash(group->getName()));
1082 
1083 	add8bitOpUDotKHRComputeTests(testCtx, group.get(), rnd, string("all"),   std::numeric_limits<deUint8>::min(), std::numeric_limits<deUint8>::max());
1084 	add8bitOpUDotKHRComputeTests(testCtx, group.get(), rnd, string("small"), (deUint8)0,  (deUint8)20);
1085 	add16bitOpUDotKHRComputeTests(testCtx, group.get(), rnd, string("all"), std::numeric_limits<deUint16>::min(), std::numeric_limits<deUint16>::max());
1086 	add32bitOpUDotKHRComputeTests(testCtx, group.get(), rnd, string("all"), std::numeric_limits<deUint32>::min(), std::numeric_limits<deUint32>::max());
1087 
1088 	return group.release();
1089 }
1090 
createOpSUDotKHRComputeGroup(tcu::TestContext & testCtx)1091 tcu::TestCaseGroup* createOpSUDotKHRComputeGroup(tcu::TestContext& testCtx)
1092 {
1093 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "opsudotkhr", "Test the OpSUDotKHR instruction"));
1094 	de::Random						rnd		(deStringHash(group->getName()));
1095 
1096 	add8bitOpSUDotKHRComputeTests(testCtx, group.get(), rnd, string("all"),   std::numeric_limits<deInt8>::min(), std::numeric_limits<deInt8>::max(), std::numeric_limits<deUint8>::min(), std::numeric_limits<deUint8>::max());
1097 	add8bitOpSUDotKHRComputeTests(testCtx, group.get(), rnd, string("small"), (deInt8)-20,  (deInt8)20,  (deUint8)0, (deUint8)20);
1098 	add16bitOpSUDotKHRComputeTests(testCtx, group.get(), rnd, string("all"), std::numeric_limits<deInt16>::min(), std::numeric_limits<deInt16>::max(),  std::numeric_limits<deUint16>::min(), std::numeric_limits<deUint16>::max());
1099 	add32bitOpSUDotKHRComputeTests(testCtx, group.get(), rnd, string("all"), std::numeric_limits<deInt32>::min(), std::numeric_limits<deInt32>::max(),  std::numeric_limits<deUint32>::min(), std::numeric_limits<deUint32>::max());
1100 
1101 	return group.release();
1102 }
1103 
createOpSDotAccSatKHRComputeGroup(tcu::TestContext & testCtx)1104 tcu::TestCaseGroup* createOpSDotAccSatKHRComputeGroup(tcu::TestContext& testCtx)
1105 {
1106 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "opsdotaccsatkhr", "Test the OpSDotAccSatKHR instruction"));
1107 	de::Random						rnd		(deStringHash(group->getName()));
1108 
1109 	add8bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),         std::numeric_limits<deInt8>::min(), std::numeric_limits<deInt8>::max());
1110 	add8bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),      (deInt8)(12), (deInt8)(20));
1111 	add8bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits-neg"),  (deInt8)(-20), (deInt8)(-12), false);
1112 	add8bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("small"),       (deInt8)-4,  (deInt8)4);
1113 	add8bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("small-neg"),   (deInt8)-4,  (deInt8)4, false);
1114 	add16bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),        std::numeric_limits<deInt16>::min(), std::numeric_limits<deInt16>::max());
1115 	add16bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),     (deInt16)(-20), (deInt16)(20));
1116 	add16bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits-neg"), (deInt16)(-20), (deInt16)(20), false);
1117 	add32bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),        std::numeric_limits<deInt32>::min(), std::numeric_limits<deInt32>::max());
1118 	add32bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),     (deInt32)(std::numeric_limits<deInt8>::min()), (deInt32)(std::numeric_limits<deInt8>::max()));
1119 	add32bitOpSDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits-neg"), (deInt32)(std::numeric_limits<deInt8>::min()), (deInt32)(std::numeric_limits<deInt8>::max()), false);
1120 
1121 	return group.release();
1122 }
1123 
createOpUDotAccSatKHRComputeGroup(tcu::TestContext & testCtx)1124 tcu::TestCaseGroup* createOpUDotAccSatKHRComputeGroup(tcu::TestContext& testCtx)
1125 {
1126 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "opudotaccsatkhr", "Test the OpUDotAccSatKHR instruction"));
1127 	de::Random						rnd		(deStringHash(group->getName()));
1128 
1129 	add8bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),         std::numeric_limits<deUint8>::min(), std::numeric_limits<deUint8>::max());
1130 	add8bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),      (deUint8)(12), (deUint8)(20));
1131 	add8bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("small"),       (deUint8)1,  (deUint8)8);
1132 	add8bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("small-nosat"), (deUint8)1,  (deUint8)8, false);
1133 	add16bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),        std::numeric_limits<deUint16>::min(), std::numeric_limits<deUint16>::max());
1134 	add16bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),     (deUint16)(12), (deUint16)(20));
1135 	add16bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("nosat"),      (deUint16)(12), (deUint16)(20), false);
1136 	add32bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),        std::numeric_limits<deUint32>::min(), std::numeric_limits<deUint32>::max());
1137 	add32bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),     (deUint32)(std::numeric_limits<deUint8>::max()-40), (deUint32)(std::numeric_limits<deUint8>::max()-20));
1138 	add32bitOpUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("nosat"),      (deUint32)(std::numeric_limits<deUint8>::max()-40), (deUint32)(std::numeric_limits<deUint8>::max()-20), false);
1139 
1140 	return group.release();
1141 }
1142 
createOpSUDotAccSatKHRComputeGroup(tcu::TestContext & testCtx)1143 tcu::TestCaseGroup* createOpSUDotAccSatKHRComputeGroup(tcu::TestContext& testCtx)
1144 {
1145 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "opsudotaccsatkhr", "Test the OpSUDotAccSatKHR instruction"));
1146 	de::Random						rnd		(deStringHash(group->getName()));
1147 
1148 	add8bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),         std::numeric_limits<deInt8>::min(), std::numeric_limits<deInt8>::max(), std::numeric_limits<deUint8>::min(), std::numeric_limits<deUint8>::max());
1149 	add8bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),      (deInt8)(12), (deInt8)(20), (deUint8)(12), (deUint8)(20));
1150 	add8bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits-neg"),  (deInt8)(-20), (deInt8)(-12), (deUint8)(12), (deUint8)(20), false);
1151 	add8bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("small"),       (deInt8)-4,  (deInt8)4,  (deUint8)1, (deUint8)8);
1152 	add8bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("small-neg"),   (deInt8)-4,  (deInt8)4,  (deUint8)1, (deUint8)8, false);
1153 	add16bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),        std::numeric_limits<deInt16>::min(), std::numeric_limits<deInt16>::max(),  std::numeric_limits<deUint16>::min(), std::numeric_limits<deUint16>::max());
1154 	add16bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),     (deInt16)(-20), (deInt16)(20), (deUint16)(12), (deUint16)(20));
1155 	add16bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits-neg"), (deInt16)(-20), (deInt16)(20), (deUint16)(12), (deUint16)(20), false);
1156 	add32bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("all"),        std::numeric_limits<deInt32>::min(), std::numeric_limits<deInt32>::max(),  std::numeric_limits<deUint32>::min(), std::numeric_limits<deUint32>::max());
1157 	add32bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits"),     (deInt32)(std::numeric_limits<deInt8>::min()), (deInt32)(std::numeric_limits<deInt8>::max()), (deUint32)(std::numeric_limits<deUint8>::min()), (deUint32)(std::numeric_limits<deUint8>::max()));
1158 	add32bitOpSUDotAccSatKHRComputeTests(testCtx, group.get(), rnd, string("limits-neg"), (deInt32)(std::numeric_limits<deInt8>::min()), (deInt32)(std::numeric_limits<deInt8>::max()), (deUint32)(std::numeric_limits<deUint8>::max()), (deUint32)(std::numeric_limits<deUint8>::max()), false);
1159 
1160 	return group.release();
1161 }
1162 
1163 } // SpirVAssembly
1164 } // vkt
1165