1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Integer built-in function tests.
24 *//*--------------------------------------------------------------------*/
25
26#include "vktShaderIntegerFunctionTests.hpp"
27#include "vktShaderExecutor.hpp"
28#include "tcuTestLog.hpp"
29#include "tcuFormatUtil.hpp"
30#include "tcuFloat.hpp"
31#include "deRandom.hpp"
32#include "deMath.h"
33#include "deString.h"
34#include "deInt32.h"
35#include "deSharedPtr.hpp"
36
37#include <iostream>
38
39namespace vkt
40{
41namespace shaderexecutor
42{
43
44using std::vector;
45using std::string;
46using tcu::TestLog;
47
48using tcu::IVec2;
49using tcu::IVec3;
50using tcu::IVec4;
51using tcu::UVec2;
52using tcu::UVec3;
53using tcu::UVec4;
54
55// Utilities
56
57namespace
58{
59
60struct HexFloat
61{
62	const float value;
63	HexFloat (const float value_) : value(value_) {}
64};
65
66std::ostream& operator<< (std::ostream& str, const HexFloat& v)
67{
68	return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
69}
70
71struct VarValue
72{
73	const glu::VarType&	type;
74	const void*			value;
75
76	VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {}
77};
78
79std::ostream& operator<< (std::ostream& str, const VarValue& varValue)
80{
81	DE_ASSERT(varValue.type.isBasicType());
82
83	const glu::DataType		basicType		= varValue.type.getBasicType();
84	const glu::DataType		scalarType		= glu::getDataTypeScalarType(basicType);
85	const int				numComponents	= glu::getDataTypeScalarSize(basicType);
86
87	if (numComponents > 1)
88		str << glu::getDataTypeName(basicType) << "(";
89
90	for (int compNdx = 0; compNdx < numComponents; compNdx++)
91	{
92		if (compNdx != 0)
93			str << ", ";
94
95		switch (scalarType)
96		{
97			case glu::TYPE_FLOAT:	str << HexFloat(((const float*)varValue.value)[compNdx]);						break;
98			case glu::TYPE_INT:		str << ((const deInt32*)varValue.value)[compNdx];								break;
99			case glu::TYPE_UINT:	str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]);					break;
100			case glu::TYPE_BOOL:	str << (((const deUint32*)varValue.value)[compNdx] != 0 ? "true" : "false");	break;
101
102			default:
103				DE_ASSERT(false);
104		}
105	}
106
107	if (numComponents > 1)
108		str << ")";
109
110	return str;
111}
112
113inline int getShaderUintBitCount (glu::ShaderType shaderType, glu::Precision precision)
114{
115	// \todo [2013-10-31 pyry] Query from GL for vertex and fragment shaders.
116	DE_UNREF(shaderType);
117	const int bitCounts[] = { 9, 16, 32 };
118	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bitCounts) == glu::PRECISION_LAST);
119	return bitCounts[precision];
120}
121
122static inline deUint32 extendSignTo32 (deUint32 integer, deUint32 integerLength)
123{
124	DE_ASSERT(integerLength > 0 && integerLength <= 32);
125
126	return deUint32(0 - deInt32((integer & (1 << (integerLength - 1))) << 1)) | integer;
127}
128
129static inline deUint32 getLowBitMask (int integerLength)
130{
131	DE_ASSERT(integerLength >= 0 && integerLength <= 32);
132
133	// \note: shifting more or equal to 32 => undefined behavior. Avoid it by shifting in two parts (1 << (num-1) << 1)
134	if (integerLength == 0u)
135		return 0u;
136	return ((1u << ((deUint32)integerLength - 1u)) << 1u) - 1u;
137}
138
139static void generateRandomInputData (de::Random& rnd, glu::ShaderType shaderType, glu::DataType dataType, glu::Precision precision, deUint32* dst, int numValues)
140{
141	const int				scalarSize		= glu::getDataTypeScalarSize(dataType);
142	const deUint32			integerLength	= (deUint32)getShaderUintBitCount(shaderType, precision);
143	const deUint32			integerMask		= getLowBitMask(integerLength);
144	const bool				isUnsigned		= glu::isDataTypeUintOrUVec(dataType);
145
146	if (isUnsigned)
147	{
148		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
149			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
150				dst[valueNdx*scalarSize + compNdx] = rnd.getUint32() & integerMask;
151	}
152	else
153	{
154		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
155			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
156				dst[valueNdx*scalarSize + compNdx] = extendSignTo32(rnd.getUint32() & integerMask, integerLength);
157	}
158}
159
160static vector<int> getScalarSizes (const vector<Symbol>& symbols)
161{
162	vector<int> sizes(symbols.size());
163	for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
164		sizes[ndx] = symbols[ndx].varType.getScalarSize();
165	return sizes;
166}
167
168static int computeTotalScalarSize (const vector<Symbol>& symbols)
169{
170	int totalSize = 0;
171	for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
172		totalSize += sym->varType.getScalarSize();
173	return totalSize;
174}
175
176static vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues)
177{
178	vector<void*>	pointers		(symbols.size());
179	int				curScalarOffset	= 0;
180
181	for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
182	{
183		const Symbol&	var				= symbols[varNdx];
184		const int		scalarSize		= var.varType.getScalarSize();
185
186		// Uses planar layout as input/output specs do not support strides.
187		pointers[varNdx] = &data[curScalarOffset];
188		curScalarOffset += scalarSize*numValues;
189	}
190
191	DE_ASSERT(curScalarOffset == (int)data.size());
192
193	return pointers;
194}
195
196static const char* getPrecisionPostfix (glu::Precision precision)
197{
198	static const char* s_postfix[] =
199	{
200		"_lowp",
201		"_mediump",
202		"_highp"
203	};
204	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST);
205	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
206	return s_postfix[precision];
207}
208
209static const char* getShaderTypePostfix (glu::ShaderType shaderType)
210{
211	static const char* s_postfix[] =
212	{
213		"_vertex",
214		"_fragment",
215		"_geometry",
216		"_tess_control",
217		"_tess_eval",
218		"_compute"
219	};
220	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
221	return s_postfix[shaderType];
222}
223
224static std::string getIntegerFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
225{
226	return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
227}
228
229static inline deUint32 reverseBits (deUint32 v)
230{
231	v = (((v & 0xaaaaaaaa) >> 1) | ((v & 0x55555555) << 1));
232	v = (((v & 0xcccccccc) >> 2) | ((v & 0x33333333) << 2));
233	v = (((v & 0xf0f0f0f0) >> 4) | ((v & 0x0f0f0f0f) << 4));
234	v = (((v & 0xff00ff00) >> 8) | ((v & 0x00ff00ff) << 8));
235	return((v >> 16) | (v << 16));
236}
237
238static int findLSB (deUint32 value)
239{
240	for (int i = 0; i < 32; i++)
241	{
242		if (value & (1u<<i))
243			return i;
244	}
245	return -1;
246}
247
248static int findMSB (deInt32 value)
249{
250	if (value > 0)
251		return 31 - deClz32((deUint32)value);
252	else if (value < 0)
253		return 31 - deClz32(~(deUint32)value);
254	else
255		return -1;
256}
257
258static int findMSB (deUint32 value)
259{
260	if (value > 0)
261		return 31 - deClz32(value);
262	else
263		return -1;
264}
265
266static deUint32 toPrecision (deUint32 value, int numIntegerBits)
267{
268	return value & getLowBitMask(numIntegerBits);
269}
270
271static deInt32 toPrecision (deInt32 value, int numIntegerBits)
272{
273	return (deInt32)extendSignTo32((deUint32)value & getLowBitMask(numIntegerBits), numIntegerBits);
274}
275
276template<class TestClass>
277static void addFunctionCases (tcu::TestCaseGroup* parent, const char* functionName, bool intTypes, bool uintTypes, bool allPrec, deUint32 shaderBits)
278{
279	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
280
281	parent->addChild(group);
282	const glu::DataType scalarTypes[] =
283	{
284		glu::TYPE_INT,
285		glu::TYPE_UINT
286	};
287
288	for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
289	{
290		const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
291
292		if ((!intTypes && scalarType == glu::TYPE_INT) || (!uintTypes && scalarType == glu::TYPE_UINT))
293			continue;
294
295		for (int vecSize = 1; vecSize <= 4; vecSize++)
296		{
297			for (int prec = glu::PRECISION_MEDIUMP; prec <= glu::PRECISION_HIGHP; prec++)
298			{
299				if (prec != glu::PRECISION_HIGHP && !allPrec)
300					continue;
301
302				for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
303				{
304					if (shaderBits & (1<<shaderTypeNdx))
305						group->addChild(new TestClass(parent->getTestContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
306				}
307			}
308		}
309	}
310}
311
312} // anonymous
313
314// IntegerFunctionCase
315
316class IntegerFunctionCase : public TestCase
317{
318public:
319										IntegerFunctionCase		(tcu::TestContext& testCtx, const char* name, const char* description, glu::ShaderType shaderType);
320										~IntegerFunctionCase	(void);
321
322	virtual	void						initPrograms			(vk::SourceCollections& programCollection) const
323										{
324											m_executor->setShaderSources(programCollection);
325										}
326
327	virtual TestInstance*				createInstance			(Context& context) const = 0;
328	virtual void						init					(void);
329
330protected:
331										IntegerFunctionCase		(const IntegerFunctionCase& other);
332	IntegerFunctionCase&				operator=				(const IntegerFunctionCase& other);
333
334	const glu::ShaderType				m_shaderType;
335
336	ShaderSpec							m_spec;
337
338	de::MovePtr<ShaderExecutor>			m_executor;
339
340	const int							m_numValues;
341};
342
343IntegerFunctionCase::IntegerFunctionCase (tcu::TestContext& testCtx, const char* name, const char* description, glu::ShaderType shaderType)
344	: TestCase		(testCtx, name, description)
345	, m_shaderType	(shaderType)
346	, m_executor	(DE_NULL)
347	, m_numValues	(100)
348{
349}
350
351IntegerFunctionCase::~IntegerFunctionCase (void)
352{
353}
354
355void IntegerFunctionCase::init (void)
356{
357	DE_ASSERT(!m_executor);
358
359	m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_shaderType, m_spec));
360	m_testCtx.getLog() << *m_executor;
361}
362
363// IntegerFunctionTestInstance
364
365class IntegerFunctionTestInstance : public TestInstance
366{
367public:
368								IntegerFunctionTestInstance		(Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
369									: TestInstance	(context)
370									, m_shaderType	(shaderType)
371									, m_spec		(spec)
372									, m_numValues	(numValues)
373									, m_name		(name)
374									, m_executor	(executor)
375								{
376								}
377	virtual tcu::TestStatus		iterate							(void);
378protected:
379	virtual bool						compare					(const void* const* inputs, const void* const* outputs) = 0;
380
381	virtual void						getInputValues			(int numValues, void* const* values) const = 0;
382
383	const glu::ShaderType				m_shaderType;
384
385	ShaderSpec							m_spec;
386
387	const int							m_numValues;
388
389	const char*							m_name;
390
391	std::ostringstream					m_failMsg;				//!< Comparison failure help message.
392
393	ShaderExecutor&						m_executor;
394};
395
396tcu::TestStatus IntegerFunctionTestInstance::iterate (void)
397{
398	const int				numInputScalars			= computeTotalScalarSize(m_spec.inputs);
399	const int				numOutputScalars		= computeTotalScalarSize(m_spec.outputs);
400	vector<deUint32>		inputData				(numInputScalars * m_numValues);
401	vector<deUint32>		outputData				(numOutputScalars * m_numValues);
402	const vector<void*>		inputPointers			= getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
403	const vector<void*>		outputPointers			= getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
404
405	// Initialize input data.
406	getInputValues(m_numValues, &inputPointers[0]);
407
408	// Execute shader.
409	m_executor.execute(m_context, m_numValues, &inputPointers[0], &outputPointers[0]);
410
411	// Compare results.
412	{
413		const vector<int>		inScalarSizes		= getScalarSizes(m_spec.inputs);
414		const vector<int>		outScalarSizes		= getScalarSizes(m_spec.outputs);
415		vector<void*>			curInputPtr			(inputPointers.size());
416		vector<void*>			curOutputPtr		(outputPointers.size());
417		int						numFailed			= 0;
418		tcu::TestContext&		testCtx				= m_context.getTestContext();
419		for (int valNdx = 0; valNdx < m_numValues; valNdx++)
420		{
421			// Set up pointers for comparison.
422			for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
423				curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx;
424
425			for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
426				curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx;
427
428			if (!compare(&curInputPtr[0], &curOutputPtr[0]))
429			{
430				// \todo [2013-08-08 pyry] We probably want to log reference value as well?
431
432				testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  " << m_failMsg.str() << TestLog::EndMessage;
433
434				testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
435				for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
436					testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
437														   << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
438									   << TestLog::EndMessage;
439
440				testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
441				for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
442					testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
443														   << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
444									   << TestLog::EndMessage;
445
446				m_failMsg.str("");
447				m_failMsg.clear();
448				numFailed += 1;
449			}
450		}
451
452		testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage;
453
454		if (numFailed == 0)
455			return tcu::TestStatus::pass("Pass");
456		else
457			return tcu::TestStatus::fail("Result comparison failed");
458	}
459}
460
461// Test cases
462
463class UaddCarryCaseInstance : public IntegerFunctionTestInstance
464{
465public:
466	UaddCarryCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
467		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
468	{
469	}
470
471	void getInputValues (int numValues, void* const* values) const
472	{
473		de::Random				rnd				(deStringHash(m_name) ^ 0x235facu);
474		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
475		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
476		const int				scalarSize		= glu::getDataTypeScalarSize(type);
477		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
478		const deUint32			integerMask		= getLowBitMask(integerLength);
479		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
480		deUint32*				in0				= (deUint32*)values[0];
481		deUint32*				in1				= (deUint32*)values[1];
482
483		const struct
484		{
485			deUint32	x;
486			deUint32	y;
487		} easyCases[] =
488		{
489			{ 0x00000000u,	0x00000000u },
490			{ 0xfffffffeu,	0x00000001u },
491			{ 0x00000001u,	0xfffffffeu },
492			{ 0xffffffffu,	0x00000001u },
493			{ 0x00000001u,	0xffffffffu },
494			{ 0xfffffffeu,	0x00000002u },
495			{ 0x00000002u,	0xfffffffeu },
496			{ 0xffffffffu,	0xffffffffu }
497		};
498
499		// generate integers with proper bit count
500		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
501		{
502			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
503			{
504				in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
505				in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
506			}
507		}
508
509		// convert to signed
510		if (isSigned)
511		{
512			for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
513			{
514				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
515				{
516					in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
517					in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
518				}
519			}
520		}
521
522		generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
523		generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
524	}
525
526	bool compare (const void* const* inputs, const void* const* outputs)
527	{
528		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
529		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
530		const int				scalarSize		= glu::getDataTypeScalarSize(type);
531		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
532		const deUint32			mask0			= getLowBitMask(integerLength);
533
534		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
535		{
536			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
537			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
538			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
539			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
540			const deUint32	ref0	= in0+in1;
541			const deUint32	ref1	= (deUint64(in0)+deUint64(in1)) > 0xffffffffu ? 1u : 0u;
542
543			if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
544			{
545				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
546				return false;
547			}
548		}
549
550		return true;
551	}
552};
553
554class UaddCarryCase : public IntegerFunctionCase
555{
556public:
557	UaddCarryCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
558		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "uaddCarry", shaderType)
559	{
560		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
561		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
562		m_spec.outputs.push_back(Symbol("sum", glu::VarType(baseType, precision)));
563		m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
564		m_spec.source = "sum = uaddCarry(x, y, carry);";
565		init();
566	}
567
568	TestInstance* createInstance (Context& ctx) const
569	{
570		return new UaddCarryCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
571	}
572};
573
574class UsubBorrowCaseInstance : public IntegerFunctionTestInstance
575{
576public:
577	UsubBorrowCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
578		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
579	{
580	}
581
582	void getInputValues (int numValues, void* const* values) const
583	{
584		de::Random				rnd				(deStringHash(m_name) ^ 0x235facu);
585		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
586		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
587		const int				scalarSize		= glu::getDataTypeScalarSize(type);
588		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
589		const deUint32			integerMask		= getLowBitMask(integerLength);
590		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
591		deUint32*				in0				= (deUint32*)values[0];
592		deUint32*				in1				= (deUint32*)values[1];
593
594		const struct
595		{
596			deUint32	x;
597			deUint32	y;
598		} easyCases[] =
599		{
600			{ 0x00000000u,	0x00000000u },
601			{ 0x00000001u,	0x00000001u },
602			{ 0x00000001u,	0x00000002u },
603			{ 0x00000001u,	0xffffffffu },
604			{ 0xfffffffeu,	0xffffffffu },
605			{ 0xffffffffu,	0xffffffffu },
606		};
607
608		// generate integers with proper bit count
609		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
610		{
611			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
612			{
613				in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
614				in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
615			}
616		}
617
618		// convert to signed
619		if (isSigned)
620		{
621			for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
622			{
623				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
624				{
625					in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
626					in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
627				}
628			}
629		}
630
631		generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
632		generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
633	}
634
635	bool compare (const void* const* inputs, const void* const* outputs)
636	{
637		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
638		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
639		const int				scalarSize		= glu::getDataTypeScalarSize(type);
640		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
641		const deUint32			mask0			= getLowBitMask(integerLength);
642
643		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
644		{
645			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
646			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
647			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
648			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
649			const deUint32	ref0	= in0-in1;
650			const deUint32	ref1	= in0 >= in1 ? 0u : 1u;
651
652			if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
653			{
654				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
655				return false;
656			}
657		}
658
659		return true;
660	}
661};
662
663class UsubBorrowCase : public IntegerFunctionCase
664{
665public:
666	UsubBorrowCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
667		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "usubBorrow", shaderType)
668	{
669		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
670		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
671		m_spec.outputs.push_back(Symbol("diff", glu::VarType(baseType, precision)));
672		m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
673		m_spec.source = "diff = usubBorrow(x, y, carry);";
674		init();
675	}
676
677	TestInstance* createInstance (Context& ctx) const
678	{
679		return new UsubBorrowCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
680	}
681};
682
683class UmulExtendedCaseInstance : public IntegerFunctionTestInstance
684{
685public:
686	UmulExtendedCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
687		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
688	{
689	}
690
691	void getInputValues (int numValues, void* const* values) const
692	{
693		de::Random				rnd			(deStringHash(m_name) ^ 0x235facu);
694		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
695//		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
696		const int				scalarSize	= glu::getDataTypeScalarSize(type);
697		deUint32*				in0			= (deUint32*)values[0];
698		deUint32*				in1			= (deUint32*)values[1];
699		int						valueNdx	= 0;
700
701		const struct
702		{
703			deUint32	x;
704			deUint32	y;
705		} easyCases[] =
706		{
707			{ 0x00000000u,	0x00000000u },
708			{ 0xffffffffu,	0x00000001u },
709			{ 0xffffffffu,	0x00000002u },
710			{ 0x00000001u,	0xffffffffu },
711			{ 0x00000002u,	0xffffffffu },
712			{ 0xffffffffu,	0xffffffffu },
713		};
714
715		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
716		{
717			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
718			{
719				in0[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x;
720				in1[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y;
721			}
722
723			valueNdx += 1;
724		}
725
726		while (valueNdx < numValues)
727		{
728			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
729			{
730				const deUint32	base0	= rnd.getUint32();
731				const deUint32	base1	= rnd.getUint32();
732				const int		adj0	= rnd.getInt(0, 20);
733				const int		adj1	= rnd.getInt(0, 20);
734				in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
735				in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
736			}
737
738			valueNdx += 1;
739		}
740	}
741
742	bool compare (const void* const* inputs, const void* const* outputs)
743	{
744		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
745		const int				scalarSize		= glu::getDataTypeScalarSize(type);
746
747		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
748		{
749			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
750			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
751			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
752			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
753			const deUint64	mul64	= deUint64(in0)*deUint64(in1);
754			const deUint32	ref0	= deUint32(mul64 >> 32);
755			const deUint32	ref1	= deUint32(mul64 & 0xffffffffu);
756
757			if (out0 != ref0 || out1 != ref1)
758			{
759				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
760				return false;
761			}
762		}
763
764		return true;
765	}
766};
767
768class UmulExtendedCase : public IntegerFunctionCase
769{
770public:
771	UmulExtendedCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
772		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "umulExtended", shaderType)
773	{
774		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
775		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
776		m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
777		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
778		m_spec.source = "umulExtended(x, y, msb, lsb);";
779		init();
780	}
781
782	TestInstance* createInstance (Context& ctx) const
783	{
784		return new UmulExtendedCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
785	}
786};
787
788class ImulExtendedCaseInstance : public IntegerFunctionTestInstance
789{
790public:
791	ImulExtendedCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
792		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
793	{
794	}
795
796	void getInputValues (int numValues, void* const* values) const
797	{
798		de::Random				rnd			(deStringHash(m_name) ^ 0x224fa1u);
799		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
800//		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
801		const int				scalarSize	= glu::getDataTypeScalarSize(type);
802		deUint32*				in0			= (deUint32*)values[0];
803		deUint32*				in1			= (deUint32*)values[1];
804		int						valueNdx	= 0;
805
806		const struct
807		{
808			deUint32	x;
809			deUint32	y;
810		} easyCases[] =
811		{
812			{ 0x00000000u,	0x00000000u },
813			{ 0xffffffffu,	0x00000002u },
814			{ 0x7fffffffu,	0x00000001u },
815			{ 0x7fffffffu,	0x00000002u },
816			{ 0x7fffffffu,	0x7fffffffu },
817			{ 0xffffffffu,	0xffffffffu },
818			{ 0x7fffffffu,	0xfffffffeu },
819		};
820
821		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
822		{
823			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
824			{
825				in0[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].x;
826				in1[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].y;
827			}
828
829			valueNdx += 1;
830		}
831
832		while (valueNdx < numValues)
833		{
834			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
835			{
836				const deInt32	base0	= (deInt32)rnd.getUint32();
837				const deInt32	base1	= (deInt32)rnd.getUint32();
838				const int		adj0	= rnd.getInt(0, 20);
839				const int		adj1	= rnd.getInt(0, 20);
840				in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
841				in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
842			}
843
844			valueNdx += 1;
845		}
846	}
847
848	bool compare (const void* const* inputs, const void* const* outputs)
849	{
850		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
851		const int				scalarSize		= glu::getDataTypeScalarSize(type);
852
853		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
854		{
855			const deInt32	in0		= ((const deInt32*)inputs[0])[compNdx];
856			const deInt32	in1		= ((const deInt32*)inputs[1])[compNdx];
857			const deInt32	out0	= ((const deInt32*)outputs[0])[compNdx];
858			const deInt32	out1	= ((const deInt32*)outputs[1])[compNdx];
859			const deInt64	mul64	= deInt64(in0)*deInt64(in1);
860			const deInt32	ref0	= deInt32(mul64 >> 32);
861			const deInt32	ref1	= deInt32(mul64 & 0xffffffffu);
862
863			if (out0 != ref0 || out1 != ref1)
864			{
865				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
866				return false;
867			}
868		}
869
870		return true;
871	}
872};
873
874class ImulExtendedCase : public IntegerFunctionCase
875{
876public:
877	ImulExtendedCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
878		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "imulExtended", shaderType)
879	{
880		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
881		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
882		m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
883		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
884		m_spec.source = "imulExtended(x, y, msb, lsb);";
885		init();
886	}
887
888	TestInstance* createInstance (Context& ctx) const
889	{
890		return new ImulExtendedCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
891	}
892};
893
894class BitfieldExtractCaseInstance : public IntegerFunctionTestInstance
895{
896public:
897	BitfieldExtractCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
898		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
899	{
900	}
901
902	void getInputValues (int numValues, void* const* values) const
903	{
904		de::Random				rnd			(deStringHash(m_name) ^ 0xa113fca2u);
905		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
906		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
907		const bool				ignoreSign	= precision != glu::PRECISION_HIGHP && glu::isDataTypeIntOrIVec(type);
908		const int				numBits		= getShaderUintBitCount(m_shaderType, precision) - (ignoreSign ? 1 : 0);
909		deUint32*				inValue		= (deUint32*)values[0];
910		int*					inOffset	= (int*)values[1];
911		int*					inBits		= (int*)values[2];
912
913		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
914		{
915			const int		bits	= rnd.getInt(0, numBits);
916			const int		offset	= rnd.getInt(0, numBits-bits);
917
918			inOffset[valueNdx]	= offset;
919			inBits[valueNdx]	= bits;
920		}
921
922		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
923	}
924
925	bool compare (const void* const* inputs, const void* const* outputs)
926	{
927		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
928		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
929		const int				scalarSize		= glu::getDataTypeScalarSize(type);
930		const int				offset			= *((const int*)inputs[1]);
931		const int				bits			= *((const int*)inputs[2]);
932
933		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
934		{
935			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
936			const deUint32	out		= ((const deUint32*)outputs[0])[compNdx];
937			const deUint32	valMask	= (bits == 32 ? ~0u : ((1u<<bits)-1u));
938			const deUint32	baseVal	= (offset == 32) ? (0) : ((value >> offset) & valMask);
939			const deUint32	ref		= baseVal | ((isSigned && (baseVal & (1<<(bits-1)))) ? ~valMask : 0u);
940
941			if (out != ref)
942			{
943				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
944				return false;
945			}
946		}
947
948		return true;
949	}
950};
951
952class BitfieldExtractCase : public IntegerFunctionCase
953{
954public:
955	BitfieldExtractCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
956		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldExtract", shaderType)
957	{
958		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
959		m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
960		m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
961		m_spec.outputs.push_back(Symbol("extracted", glu::VarType(baseType, precision)));
962		m_spec.source = "extracted = bitfieldExtract(value, offset, bits);";
963		init();
964	}
965
966	TestInstance* createInstance (Context& ctx) const
967	{
968		return new BitfieldExtractCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
969	}
970};
971
972class BitfieldInsertCaseInstance : public IntegerFunctionTestInstance
973{
974public:
975	BitfieldInsertCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
976		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
977	{
978	}
979
980	void getInputValues (int numValues, void* const* values) const
981	{
982		de::Random				rnd			(deStringHash(m_name) ^ 0x12c2acff);
983		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
984		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
985		const int				numBits		= getShaderUintBitCount(m_shaderType, precision);
986		deUint32*				inBase		= (deUint32*)values[0];
987		deUint32*				inInsert	= (deUint32*)values[1];
988		int*					inOffset	= (int*)values[2];
989		int*					inBits		= (int*)values[3];
990
991		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
992		{
993			const int bits		= rnd.getInt(0, numBits);
994			const int offset	= rnd.getInt(0, numBits-bits);
995
996			inOffset[valueNdx]	= offset;
997			inBits[valueNdx]	= bits;
998		}
999
1000		generateRandomInputData(rnd, m_shaderType, type, precision, inBase, numValues);
1001		generateRandomInputData(rnd, m_shaderType, type, precision, inInsert, numValues);
1002	}
1003
1004	bool compare (const void* const* inputs, const void* const* outputs)
1005	{
1006		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
1007		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
1008		const int				scalarSize		= glu::getDataTypeScalarSize(type);
1009		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
1010		const deUint32			cmpMask			= getLowBitMask(integerLength);
1011		const int				offset			= *((const int*)inputs[2]);
1012		const int				bits			= *((const int*)inputs[3]);
1013
1014		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1015		{
1016			const deUint32	base	= ((const deUint32*)inputs[0])[compNdx];
1017			const deUint32	insert	= ((const deUint32*)inputs[1])[compNdx];
1018			const deInt32	out		= ((const deUint32*)outputs[0])[compNdx];
1019
1020			const deUint32	mask	= bits == 32 ? ~0u : (1u<<bits)-1;
1021			const deUint32	ref		= (base & ~(mask<<offset)) | ((insert & mask)<<offset);
1022
1023			if ((out&cmpMask) != (ref&cmpMask))
1024			{
1025				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
1026				return false;
1027			}
1028		}
1029
1030		return true;
1031	}
1032};
1033
1034class BitfieldInsertCase : public IntegerFunctionCase
1035{
1036public:
1037	BitfieldInsertCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1038		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldInsert", shaderType)
1039	{
1040		m_spec.inputs.push_back(Symbol("base", glu::VarType(baseType, precision)));
1041		m_spec.inputs.push_back(Symbol("insert", glu::VarType(baseType, precision)));
1042		m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
1043		m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
1044		m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, precision)));
1045		m_spec.source = "result = bitfieldInsert(base, insert, offset, bits);";
1046		init();
1047	}
1048
1049	TestInstance* createInstance (Context& ctx) const
1050	{
1051		return new BitfieldInsertCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
1052	}
1053};
1054
1055class BitfieldReverseCaseInstance : public IntegerFunctionTestInstance
1056{
1057public:
1058	BitfieldReverseCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
1059		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
1060	{
1061	}
1062
1063	void getInputValues (int numValues, void* const* values) const
1064	{
1065		de::Random				rnd			(deStringHash(m_name) ^ 0xff23a4);
1066		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
1067		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
1068		deUint32*				inValue		= (deUint32*)values[0];
1069
1070		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1071	}
1072
1073	bool compare (const void* const* inputs, const void* const* outputs)
1074	{
1075		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
1076		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
1077		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
1078		const int				scalarSize		= glu::getDataTypeScalarSize(type);
1079		const deUint32			cmpMask			= reverseBits(getLowBitMask(integerLength));
1080
1081		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1082		{
1083			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
1084			const deInt32	out		= ((const deUint32*)outputs[0])[compNdx];
1085			const deUint32	ref		= reverseBits(value);
1086
1087			if ((out&cmpMask) != (ref&cmpMask))
1088			{
1089				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
1090				return false;
1091			}
1092		}
1093
1094		return true;
1095	}
1096};
1097
1098class BitfieldReverseCase : public IntegerFunctionCase
1099{
1100public:
1101	BitfieldReverseCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1102		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldReverse", shaderType)
1103	{
1104		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1105		m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, glu::PRECISION_HIGHP)));
1106		m_spec.source = "result = bitfieldReverse(value);";
1107		init();
1108	}
1109
1110	TestInstance* createInstance (Context& ctx) const
1111	{
1112		return new BitfieldReverseCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
1113	}
1114};
1115
1116class BitCountCaseInstance : public IntegerFunctionTestInstance
1117{
1118public:
1119	BitCountCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
1120		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
1121	{
1122	}
1123
1124	void getInputValues (int numValues, void* const* values) const
1125	{
1126		de::Random				rnd			(deStringHash(m_name) ^ 0xab2cca4);
1127		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
1128		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
1129		deUint32*				inValue		= (deUint32*)values[0];
1130
1131		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1132	}
1133
1134	bool compare (const void* const* inputs, const void* const* outputs)
1135	{
1136		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
1137		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
1138		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
1139		const int				scalarSize		= glu::getDataTypeScalarSize(type);
1140		const deUint32			countMask		= getLowBitMask(integerLength);
1141
1142		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1143		{
1144			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
1145			const int		out		= ((const int*)outputs[0])[compNdx];
1146			const int		minRef	= dePop32(value&countMask);
1147			const int		maxRef	= dePop32(value);
1148
1149			if (!de::inRange(out, minRef, maxRef))
1150			{
1151				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1152				return false;
1153			}
1154		}
1155
1156		return true;
1157	}
1158};
1159
1160class BitCountCase : public IntegerFunctionCase
1161{
1162public:
1163	BitCountCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1164		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitCount", shaderType)
1165	{
1166		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
1167		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
1168
1169		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1170		m_spec.outputs.push_back(Symbol("count", glu::VarType(intType, glu::PRECISION_MEDIUMP)));
1171		m_spec.source = "count = bitCount(value);";
1172		init();
1173	}
1174
1175	TestInstance* createInstance (Context& ctx) const
1176	{
1177		return new BitCountCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
1178	}
1179};
1180
1181class FindLSBCaseInstance : public IntegerFunctionTestInstance
1182{
1183public:
1184	FindLSBCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
1185		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
1186	{
1187	}
1188
1189	void getInputValues (int numValues, void* const* values) const
1190	{
1191		de::Random				rnd			(deStringHash(m_name) ^ 0x9923c2af);
1192		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
1193		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
1194		deUint32*				inValue		= (deUint32*)values[0];
1195
1196		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1197	}
1198
1199	bool compare (const void* const* inputs, const void* const* outputs)
1200	{
1201		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
1202		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
1203		const int				scalarSize		= glu::getDataTypeScalarSize(type);
1204		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
1205		const deUint32			mask			= getLowBitMask(integerLength);
1206
1207		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1208		{
1209			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
1210			const int		out		= ((const int*)outputs[0])[compNdx];
1211			const int		minRef	= findLSB(value&mask);
1212			const int		maxRef	= findLSB(value);
1213
1214			if (!de::inRange(out, minRef, maxRef))
1215			{
1216				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1217				return false;
1218			}
1219		}
1220
1221		return true;
1222	}
1223};
1224
1225class FindLSBCase : public IntegerFunctionCase
1226{
1227public:
1228	FindLSBCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1229		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findLSB", shaderType)
1230	{
1231		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
1232		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
1233
1234		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1235		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(intType, glu::PRECISION_LOWP)));
1236		m_spec.source = "lsb = findLSB(value);";
1237		init();
1238	}
1239
1240	TestInstance* createInstance (Context& ctx) const
1241	{
1242		return new FindLSBCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
1243	}
1244};
1245
1246class findMSBCaseInstance : public IntegerFunctionTestInstance
1247{
1248public:
1249	findMSBCaseInstance (Context& context, glu::ShaderType shaderType, ShaderSpec spec, ShaderExecutor& executor, int numValues, const char* name)
1250		: IntegerFunctionTestInstance	(context, shaderType, spec, executor, numValues, name)
1251	{
1252	}
1253
1254	void getInputValues (int numValues, void* const* values) const
1255	{
1256		de::Random				rnd			(deStringHash(m_name) ^ 0x742ac4e);
1257		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
1258		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
1259		deUint32*				inValue		= (deUint32*)values[0];
1260
1261		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1262	}
1263
1264	bool compare (const void* const* inputs, const void* const* outputs)
1265	{
1266		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
1267		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
1268		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
1269		const int				scalarSize		= glu::getDataTypeScalarSize(type);
1270		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
1271
1272		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1273		{
1274			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
1275			const int		out		= ((const deInt32*)outputs[0])[compNdx];
1276			const int		minRef	= isSigned ? findMSB(toPrecision(deInt32(value), integerLength))	: findMSB(toPrecision(value, integerLength));
1277			const int		maxRef	= isSigned ? findMSB(deInt32(value))								: findMSB(value);
1278
1279			if (!de::inRange(out, minRef, maxRef))
1280			{
1281				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1282				return false;
1283			}
1284		}
1285
1286		return true;
1287	}
1288};
1289
1290class findMSBCase : public IntegerFunctionCase
1291{
1292public:
1293	findMSBCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1294		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findMSB", shaderType)
1295	{
1296		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
1297		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
1298
1299		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1300		m_spec.outputs.push_back(Symbol("msb", glu::VarType(intType, glu::PRECISION_LOWP)));
1301		m_spec.source = "msb = findMSB(value);";
1302		init();
1303	}
1304
1305	TestInstance* createInstance (Context& ctx) const
1306	{
1307		return new findMSBCaseInstance(ctx, m_shaderType, m_spec, *m_executor, m_numValues, getName());
1308	}
1309};
1310
1311ShaderIntegerFunctionTests::ShaderIntegerFunctionTests (tcu::TestContext& testCtx)
1312	: tcu::TestCaseGroup	(testCtx, "integer", "Integer function tests")
1313{
1314}
1315
1316ShaderIntegerFunctionTests::~ShaderIntegerFunctionTests (void)
1317{
1318}
1319
1320void ShaderIntegerFunctionTests::init (void)
1321{
1322	enum
1323	{
1324		VS = (1<<glu::SHADERTYPE_VERTEX),
1325		FS = (1<<glu::SHADERTYPE_FRAGMENT),
1326		CS = (1<<glu::SHADERTYPE_COMPUTE),
1327		GS = (1<<glu::SHADERTYPE_GEOMETRY),
1328		TC = (1<<glu::SHADERTYPE_TESSELLATION_CONTROL),
1329		TE = (1<<glu::SHADERTYPE_TESSELLATION_EVALUATION),
1330
1331		ALL_SHADERS = VS|TC|TE|GS|FS|CS
1332	};
1333
1334	//																		Int?	Uint?	AllPrec?	Shaders
1335	addFunctionCases<UaddCarryCase>				(this,	"uaddcarry",		false,	true,	true,		ALL_SHADERS);
1336	addFunctionCases<UsubBorrowCase>			(this,	"usubborrow",		false,	true,	true,		ALL_SHADERS);
1337	addFunctionCases<UmulExtendedCase>			(this,	"umulextended",		false,	true,	false,		ALL_SHADERS);
1338	addFunctionCases<ImulExtendedCase>			(this,	"imulextended",		true,	false,	false,		ALL_SHADERS);
1339	addFunctionCases<BitfieldExtractCase>		(this,	"bitfieldextract",	true,	true,	true,		ALL_SHADERS);
1340	addFunctionCases<BitfieldInsertCase>		(this,	"bitfieldinsert",	true,	true,	true,		ALL_SHADERS);
1341	addFunctionCases<BitfieldReverseCase>		(this,	"bitfieldreverse",	true,	true,	true,		ALL_SHADERS);
1342	addFunctionCases<BitCountCase>				(this,	"bitcount",			true,	true,	true,		ALL_SHADERS);
1343	addFunctionCases<FindLSBCase>				(this,	"findlsb",			true,	true,	true,		ALL_SHADERS);
1344	addFunctionCases<findMSBCase>				(this,	"findMSB",			true,	true,	true,		ALL_SHADERS);
1345}
1346
1347} // shaderexecutor
1348} // vkt
1349