13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Integer built-in function tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fShaderIntegerFunctionTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::ShaderExecUtil;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec2;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec3;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec4;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexFloat
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float value;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HexFloat (const float value_) : value(value_) {}
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexFloat& v)
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VarValue
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VarType&	type;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const void*			value;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {}
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const VarValue& varValue)
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(varValue.type.isBasicType());
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		basicType		= varValue.type.getBasicType();
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		scalarType		= glu::getDataTypeScalarType(basicType);
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numComponents	= glu::getDataTypeScalarSize(basicType);
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numComponents > 1)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << glu::getDataTypeName(basicType) << "(";
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int compNdx = 0; compNdx < numComponents; compNdx++)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (compNdx != 0)
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			str << ", ";
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (scalarType)
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_FLOAT:	str << HexFloat(((const float*)varValue.value)[compNdx]);						break;
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_INT:		str << ((const deInt32*)varValue.value)[compNdx];								break;
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_UINT:	str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]);					break;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_BOOL:	str << (((const deUint32*)varValue.value)[compNdx] != 0 ? "true" : "false");	break;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numComponents > 1)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << ")";
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str;
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int getShaderUintBitCount (glu::ShaderType shaderType, glu::Precision precision)
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2013-10-31 pyry] Query from GL for vertex and fragment shaders.
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(shaderType);
115ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	const int bitCounts[] = { 9, 16, 32 };
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bitCounts) == glu::PRECISION_LAST);
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return bitCounts[precision];
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
120ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyrystatic inline deUint32 extendSignTo32 (deUint32 integer, deUint32 integerLength)
121ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry{
122ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	DE_ASSERT(integerLength > 0 && integerLength <= 32);
123ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
124ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	return deUint32(0 - deInt32((integer & (1 << (integerLength - 1))) << 1)) | integer;
125ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry}
126ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
127ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyrystatic inline deUint32 getLowBitMask (int integerLength)
128ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry{
129ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	DE_ASSERT(integerLength >= 0 && integerLength <= 32);
130ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
131ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	// \note: shifting more or equal to 32 => undefined behavior. Avoid it by shifting in two parts (1 << (num-1) << 1)
132ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	if (integerLength == 0u)
133ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		return 0u;
134ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	return ((1u << ((deUint32)integerLength - 1u)) << 1u) - 1u;
135ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry}
136ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
137ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyrystatic void generateRandomInputData (de::Random& rnd, glu::ShaderType shaderType, glu::DataType dataType, glu::Precision precision, deUint32* dst, int numValues)
138ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry{
139ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	const int				scalarSize		= glu::getDataTypeScalarSize(dataType);
140ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	const deUint32			integerLength	= (deUint32)getShaderUintBitCount(shaderType, precision);
141ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	const deUint32			integerMask		= getLowBitMask(integerLength);
142ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	const bool				isUnsigned		= glu::isDataTypeUintOrUVec(dataType);
143ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
144ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	if (isUnsigned)
145ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	{
146ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
147ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
148ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				dst[valueNdx*scalarSize + compNdx] = rnd.getUint32() & integerMask;
149ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	}
150ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	else
151ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	{
152ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
153ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
154ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				dst[valueNdx*scalarSize + compNdx] = extendSignTo32(rnd.getUint32() & integerMask, integerLength);
155ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	}
156ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry}
157ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// IntegerFunctionCase
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IntegerFunctionCase : public TestCase
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							IntegerFunctionCase		(Context& context, const char* name, const char* description, glu::ShaderType shaderType);
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~IntegerFunctionCase	(void);
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init					(void);
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit					(void);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate					(void);
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							IntegerFunctionCase		(const IntegerFunctionCase& other);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IntegerFunctionCase&	operator=				(const IntegerFunctionCase& other);
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void			getInputValues			(int numValues, void* const* values) const = 0;
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool			compare					(const void* const* inputs, const void* const* outputs) = 0;
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderType			m_shaderType;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderSpec				m_spec;
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_numValues;
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream		m_failMsg;				//!< Comparison failure help message.
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderExecutor*			m_executor;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIntegerFunctionCase::IntegerFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(context, name, description)
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shaderType	(shaderType)
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numValues	(100)
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_executor	(DE_NULL)
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_spec.version = glu::GLSL_VERSION_310_ES;
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1983c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIntegerFunctionCase::~IntegerFunctionCase (void)
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IntegerFunctionCase::deinit();
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid IntegerFunctionCase::init (void)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_executor);
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << m_executor;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_executor->isOk())
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("Compile failed");
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid IntegerFunctionCase::deinit (void)
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_executor;
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor = DE_NULL;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<int> getScalarSizes (const vector<Symbol>& symbols)
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int> sizes(symbols.size());
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sizes[ndx] = symbols[ndx].varType.getScalarSize();
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sizes;
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int computeTotalScalarSize (const vector<Symbol>& symbols)
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int totalSize = 0;
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalSize += sym->varType.getScalarSize();
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return totalSize;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues)
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<void*>	pointers		(symbols.size());
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				curScalarOffset	= 0;
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Symbol&	var				= symbols[varNdx];
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		scalarSize		= var.varType.getScalarSize();
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Uses planar layout as input/output specs do not support strides.
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pointers[varNdx] = &data[curScalarOffset];
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		curScalarOffset += scalarSize*numValues;
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(curScalarOffset == (int)data.size());
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pointers;
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIntegerFunctionCase::IterateResult IntegerFunctionCase::iterate (void)
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numInputScalars			= computeTotalScalarSize(m_spec.inputs);
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numOutputScalars		= computeTotalScalarSize(m_spec.outputs);
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>		inputData				(numInputScalars * m_numValues);
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>		outputData				(numOutputScalars * m_numValues);
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<void*>		inputPointers			= getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<void*>		outputPointers			= getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize input data.
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	getInputValues(m_numValues, &inputPointers[0]);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Execute shader.
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor->useProgram();
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare results.
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<int>		inScalarSizes		= getScalarSizes(m_spec.inputs);
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<int>		outScalarSizes		= getScalarSizes(m_spec.outputs);
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			curInputPtr			(inputPointers.size());
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			curOutputPtr		(outputPointers.size());
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numFailed			= 0;
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valNdx = 0; valNdx < m_numValues; valNdx++)
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Set up pointers for comparison.
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx;
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx;
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!compare(&curInputPtr[0], &curOutputPtr[0]))
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \todo [2013-08-08 pyry] We probably want to log reference value as well?
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  " << m_failMsg.str() << TestLog::EndMessage;
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg.str("");
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg.clear();
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage;
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								numFailed == 0 ? "Pass"					: "Result comparison failed");
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getPrecisionPostfix (glu::Precision precision)
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_postfix[] =
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_lowp",
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_mediump",
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_highp"
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST);
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_postfix[precision];
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getShaderTypePostfix (glu::ShaderType shaderType)
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_postfix[] =
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_vertex",
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_fragment",
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_geometry",
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_tess_control",
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_tess_eval",
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_compute"
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_postfix[shaderType];
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string getIntegerFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass UaddCarryCase : public IntegerFunctionCase
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UaddCarryCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "uaddCarry", shaderType)
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("sum", glu::VarType(baseType, precision)));
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "sum = uaddCarry(x, y, carry);";
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
370ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		de::Random				rnd				(deStringHash(getName()) ^ 0x235facu);
371ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
372ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
373ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
374ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
375ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			integerMask		= getLowBitMask(integerLength);
376ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
377ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		deUint32*				in0				= (deUint32*)values[0];
378ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		deUint32*				in1				= (deUint32*)values[1];
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const struct
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	x;
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	y;
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} easyCases[] =
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000000u,	0x00000000u },
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xfffffffeu,	0x00000001u },
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000001u,	0xfffffffeu },
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0x00000001u },
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000001u,	0xffffffffu },
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xfffffffeu,	0x00000002u },
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000002u,	0xfffffffeu },
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0xffffffffu }
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
396ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		// generate integers with proper bit count
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
401ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
402ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
406ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		// convert to signed
407ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		if (isSigned)
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
409ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
411ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
412ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				{
413ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry					in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
414ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry					in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
415ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				}
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
418ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
419ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
420ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
428ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
429ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			mask0			= getLowBitMask(integerLength);
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref0	= in0+in1;
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref1	= (deUint64(in0)+deUint64(in1)) > 0xffffffffu ? 1u : 0u;
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
440ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass UsubBorrowCase : public IntegerFunctionCase
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UsubBorrowCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "usubBorrow", shaderType)
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("diff", glu::VarType(baseType, precision)));
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "diff = usubBorrow(x, y, carry);";
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
466ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		de::Random				rnd				(deStringHash(getName()) ^ 0x235facu);
467ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
468ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
469ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
470ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
471ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			integerMask		= getLowBitMask(integerLength);
472ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
473ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		deUint32*				in0				= (deUint32*)values[0];
474ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		deUint32*				in1				= (deUint32*)values[1];
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const struct
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	x;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	y;
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} easyCases[] =
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000000u,	0x00000000u },
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000001u,	0x00000001u },
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000001u,	0x00000002u },
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000001u,	0xffffffffu },
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xfffffffeu,	0xffffffffu },
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0xffffffffu },
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
490ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		// generate integers with proper bit count
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
495ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
496ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
500ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		// convert to signed
501ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		if (isSigned)
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
503ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
505ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
506ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				{
507ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry					in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
508ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry					in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
509ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				}
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
512ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
513ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
514ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
522ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
523ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			mask0			= getLowBitMask(integerLength);
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref0	= in0-in1;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref1	= in0 >= in1 ? 0u : 1u;
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
534ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass UmulExtendedCase : public IntegerFunctionCase
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UmulExtendedCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "umulExtended", shaderType)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "umulExtended(x, y, msb, lsb);";
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x235facu);
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				in0			= (deUint32*)values[0];
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				in1			= (deUint32*)values[1];
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						valueNdx	= 0;
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const struct
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	x;
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	y;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} easyCases[] =
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000000u,	0x00000000u },
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0x00000001u },
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0x00000002u },
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000001u,	0xffffffffu },
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000002u,	0xffffffffu },
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0xffffffffu },
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in0[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x;
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in1[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			valueNdx += 1;
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (valueNdx < numValues)
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	base0	= rnd.getUint32();
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	base1	= rnd.getUint32();
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		adj0	= rnd.getInt(0, 20);
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		adj1	= rnd.getInt(0, 20);
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			valueNdx += 1;
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint64	mul64	= deUint64(in0)*deUint64(in1);
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref0	= deUint32(mul64 >> 32);
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref1	= deUint32(mul64 & 0xffffffffu);
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (out0 != ref0 || out1 != ref1)
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ImulExtendedCase : public IntegerFunctionCase
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ImulExtendedCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "imulExtended", shaderType)
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "imulExtended(x, y, msb, lsb);";
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x224fa1u);
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				in0			= (deUint32*)values[0];
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				in1			= (deUint32*)values[1];
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						valueNdx	= 0;
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const struct
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	x;
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	y;
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} easyCases[] =
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x00000000u,	0x00000000u },
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0x00000002u },
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x7fffffffu,	0x00000001u },
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x7fffffffu,	0x00000002u },
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x7fffffffu,	0x7fffffffu },
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0xffffffffu,	0xffffffffu },
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0x7fffffffu,	0xfffffffeu },
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in0[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].x;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in1[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].y;
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			valueNdx += 1;
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (valueNdx < numValues)
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deInt32	base0	= (deInt32)rnd.getUint32();
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deInt32	base1	= (deInt32)rnd.getUint32();
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		adj0	= rnd.getInt(0, 20);
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		adj1	= rnd.getInt(0, 20);
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			valueNdx += 1;
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	in0		= ((const deInt32*)inputs[0])[compNdx];
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	in1		= ((const deInt32*)inputs[1])[compNdx];
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	out0	= ((const deInt32*)outputs[0])[compNdx];
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	out1	= ((const deInt32*)outputs[1])[compNdx];
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt64	mul64	= deInt64(in0)*deInt64(in1);
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	ref0	= deInt32(mul64 >> 32);
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	ref1	= deInt32(mul64 & 0xffffffffu);
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (out0 != ref0 || out1 != ref1)
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitfieldExtractCase : public IntegerFunctionCase
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BitfieldExtractCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldExtract", shaderType)
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("extracted", glu::VarType(baseType, precision)));
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "extracted = bitfieldExtract(value, offset, bits);";
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xa113fca2u);
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				ignoreSign	= precision != glu::PRECISION_HIGHP && glu::isDataTypeIntOrIVec(type);
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numBits		= getShaderUintBitCount(m_shaderType, precision) - (ignoreSign ? 1 : 0);
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				inValue		= (deUint32*)values[0];
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int*					inOffset	= (int*)values[1];
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int*					inBits		= (int*)values[2];
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
750ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		bits	= rnd.getInt(0, numBits);
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		offset	= rnd.getInt(0, numBits-bits);
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			inOffset[valueNdx]	= offset;
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			inBits[valueNdx]	= bits;
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
758ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
759ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				offset			= *((const int*)inputs[1]);
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bits			= *((const int*)inputs[2]);
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out		= ((const deUint32*)outputs[0])[compNdx];
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	valMask	= (bits == 32 ? ~0u : ((1u<<bits)-1u));
775ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			const deUint32	baseVal	= (offset == 32) ? (0) : ((value >> offset) & valMask);
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref		= baseVal | ((isSigned && (baseVal & (1<<(bits-1)))) ? ~valMask : 0u);
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (out != ref)
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitfieldInsertCase : public IntegerFunctionCase
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BitfieldInsertCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldInsert", shaderType)
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("base", glu::VarType(baseType, precision)));
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("insert", glu::VarType(baseType, precision)));
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, precision)));
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "result = bitfieldInsert(base, insert, offset, bits);";
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x12c2acff);
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numBits		= getShaderUintBitCount(m_shaderType, precision);
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				inBase		= (deUint32*)values[0];
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				inInsert	= (deUint32*)values[1];
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int*					inOffset	= (int*)values[2];
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int*					inBits		= (int*)values[3];
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
814ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
816ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			const int bits		= rnd.getInt(0, numBits);
817ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			const int offset	= rnd.getInt(0, numBits-bits);
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			inOffset[valueNdx]	= offset;
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			inBits[valueNdx]	= bits;
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
822ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry
823ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, inBase, numValues);
824ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, inInsert, numValues);
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
832ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
833ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			cmpMask			= getLowBitMask(integerLength);
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				offset			= *((const int*)inputs[2]);
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bits			= *((const int*)inputs[3]);
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	base	= ((const deUint32*)inputs[0])[compNdx];
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	insert	= ((const deUint32*)inputs[1])[compNdx];
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	out		= ((const deUint32*)outputs[0])[compNdx];
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	mask	= bits == 32 ? ~0u : (1u<<bits)-1;
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref		= (base & ~(mask<<offset)) | ((insert & mask)<<offset);
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if ((out&cmpMask) != (ref&cmpMask))
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint32 reverseBits (deUint32 v)
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	v = (((v & 0xaaaaaaaa) >> 1) | ((v & 0x55555555) << 1));
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	v = (((v & 0xcccccccc) >> 2) | ((v & 0x33333333) << 2));
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	v = (((v & 0xf0f0f0f0) >> 4) | ((v & 0x0f0f0f0f) << 4));
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	v = (((v & 0xff00ff00) >> 8) | ((v & 0x00ff00ff) << 8));
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return((v >> 16) | (v << 16));
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitfieldReverseCase : public IntegerFunctionCase
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BitfieldReverseCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldReverse", shaderType)
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, glu::PRECISION_HIGHP)));
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "result = bitfieldReverse(value);";
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xff23a4);
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
881ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				inValue		= (deUint32*)values[0];
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
884ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
891ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
893ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			cmpMask			= reverseBits(getLowBitMask(integerLength));
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32	out		= ((const deUint32*)outputs[0])[compNdx];
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ref		= reverseBits(value);
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if ((out&cmpMask) != (ref&cmpMask))
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitCountCase : public IntegerFunctionCase
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BitCountCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitCount", shaderType)
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("count", glu::VarType(intType, glu::PRECISION_LOWP)));
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "count = bitCount(value);";
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xab2cca4);
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
930ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				inValue		= (deUint32*)values[0];
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
940ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
942ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			countMask		= getLowBitMask(integerLength);
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		out		= ((const int*)outputs[0])[compNdx];
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		minRef	= dePop32(value&countMask);
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		maxRef	= dePop32(value);
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!de::inRange(out, minRef, maxRef))
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int findLSB (deUint32 value)
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < 32; i++)
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (value & (1u<<i))
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return i;
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return -1;
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FindLSBCase : public IntegerFunctionCase
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FindLSBCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findLSB", shaderType)
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(intType, glu::PRECISION_LOWP)));
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "lsb = findLSB(value);";
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x9923c2af);
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
990ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				inValue		= (deUint32*)values[0];
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
1001ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
1002ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const deUint32			mask			= getLowBitMask(integerLength);
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		out		= ((const int*)outputs[0])[compNdx];
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		minRef	= findLSB(value&mask);
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		maxRef	= findLSB(value);
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!de::inRange(out, minRef, maxRef))
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1022ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyrystatic int findMSB (deInt32 value)
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (value > 0)
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 31 - deClz32((deUint32)value);
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (value < 0)
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 31 - deClz32(~(deUint32)value);
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int findMSB (deUint32 value)
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (value > 0)
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 31 - deClz32(value);
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1040ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyrystatic deUint32 toPrecision (deUint32 value, int numIntegerBits)
10418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
1042ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	return value & getLowBitMask(numIntegerBits);
10438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
10448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
1045ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyrystatic deInt32 toPrecision (deInt32 value, int numIntegerBits)
10468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
1047ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry	return (deInt32)extendSignTo32((deUint32)value & getLowBitMask(numIntegerBits), numIntegerBits);
10488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
10498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FindMSBCase : public IntegerFunctionCase
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FindMSBCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findMSB", shaderType)
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("msb", glu::VarType(intType, glu::PRECISION_LOWP)));
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "msb = findMSB(value);";
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x742ac4e);
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
1068ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32*				inValue		= (deUint32*)values[0];
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1071ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
1080ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
1085ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			const int		out		= ((const deInt32*)outputs[0])[compNdx];
1086ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			const int		minRef	= isSigned ? findMSB(toPrecision(deInt32(value), integerLength))	: findMSB(toPrecision(value, integerLength));
1087ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry			const int		maxRef	= isSigned ? findMSB(deInt32(value))								: findMSB(value);
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!de::inRange(out, minRef, maxRef))
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11003c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderIntegerFunctionTests::ShaderIntegerFunctionTests (Context& context)
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "integer", "Integer function tests")
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11053c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderIntegerFunctionTests::~ShaderIntegerFunctionTests (void)
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<class TestClass>
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void addFunctionCases (TestCaseGroup* parent, const char* functionName, bool intTypes, bool uintTypes, bool allPrec, deUint32 shaderBits)
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	parent->addChild(group);
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType scalarTypes[] =
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT,
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((!intTypes && scalarType == glu::TYPE_INT) || (!uintTypes && scalarType == glu::TYPE_UINT))
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int vecSize = 1; vecSize <= 4; vecSize++)
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (prec != glu::PRECISION_HIGHP && !allPrec)
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					continue;
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (shaderBits & (1<<shaderTypeNdx))
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderIntegerFunctionTests::init (void)
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VS = (1<<glu::SHADERTYPE_VERTEX),
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FS = (1<<glu::SHADERTYPE_FRAGMENT),
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CS = (1<<glu::SHADERTYPE_COMPUTE),
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GS = (1<<glu::SHADERTYPE_GEOMETRY),
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TC = (1<<glu::SHADERTYPE_TESSELLATION_CONTROL),
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TE = (1<<glu::SHADERTYPE_TESSELLATION_EVALUATION),
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ALL_SHADERS = VS|TC|TE|GS|FS|CS
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//																		Int?	Uint?	AllPrec?	Shaders
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<UaddCarryCase>				(this,	"uaddcarry",		false,	true,	true,		ALL_SHADERS);
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<UsubBorrowCase>			(this,	"usubborrow",		false,	true,	true,		ALL_SHADERS);
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<UmulExtendedCase>			(this,	"umulextended",		false,	true,	false,		ALL_SHADERS);
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<ImulExtendedCase>			(this,	"imulextended",		true,	false,	false,		ALL_SHADERS);
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<BitfieldExtractCase>		(this,	"bitfieldextract",	true,	true,	true,		ALL_SHADERS);
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<BitfieldInsertCase>		(this,	"bitfieldinsert",	true,	true,	true,		ALL_SHADERS);
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<BitfieldReverseCase>		(this,	"bitfieldreverse",	true,	true,	true,		ALL_SHADERS);
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<BitCountCase>				(this,	"bitcount",			true,	true,	true,		ALL_SHADERS);
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FindLSBCase>				(this,	"findlsb",			true,	true,	true,		ALL_SHADERS);
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FindMSBCase>				(this,	"findmsb",			true,	true,	true,		ALL_SHADERS);
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1175