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