13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 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 Shader precision tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \note Floating-point case uses R32UI render target and uses
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *		 floatBitsToUint() in shader to write out floating-point value bits.
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *		 This is done since ES3 core doesn't support FP render targets.
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fShaderPrecisionTests.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderUtil.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::ostringstream;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FRAMEBUFFER_WIDTH	= 32,
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FRAMEBUFFER_HEIGHT	= 32
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::ShaderProgram* createFloatPrecisionEvalProgram (const glu::RenderContext& context, glu::Precision precision, const char* evalOp, bool isVertexCase)
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::DataType	type		= glu::TYPE_FLOAT;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::DataType	outType		= glu::TYPE_UINT;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		typeName	= glu::getDataTypeName(type);
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		outTypeName	= glu::getDataTypeName(outType);
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		precName	= glu::getPrecisionName(precision);
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	vtx;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	frag;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream&	op			= isVertexCase ? vtx : frag;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "#version 300 es\n"
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in highp vec4 a_position;\n"
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in " << precName << " " << typeName << " a_in0;\n"
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in " << precName << " " << typeName << " a_in1;\n";
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "#version 300 es\n"
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << "layout(location = 0) out highp " << outTypeName << " o_out;\n";
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "flat out " << precName << " " << typeName << " v_out;\n";
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "flat in " << precName << " " << typeName << " v_out;\n";
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "flat out " << precName << " " << typeName << " v_in0;\n"
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "flat out " << precName << " " << typeName << " v_in1;\n";
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "flat in " << precName << " " << typeName << " v_in0;\n"
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 << "flat in " << precName << " " << typeName << " v_in1;\n";
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "\nvoid main (void)\n{\n"
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_Position = a_position;\n";
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\nvoid main (void)\n{\n";
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\t" << precName << " " << typeName << " in0 = " << (isVertexCase ? "a_" : "v_") << "in0;\n"
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	   << "\t" << precName << " " << typeName << " in1 = " << (isVertexCase ? "a_" : "v_") << "in1;\n";
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isVertexCase)
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "\t" << precName << " " << typeName << " res;\n";
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\t" << (isVertexCase ? "v_out" : "res") << " = " << evalOp << ";\n";
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	o_out = floatBitsToUint(v_out);\n";
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_in0 = a_in0;\n"
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	v_in1 = a_in1;\n";
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	o_out = floatBitsToUint(res);\n";
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "}\n";
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "}\n";
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(context, glu::makeVtxFragSources(vtx.str(), frag.str()));
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::ShaderProgram* createIntUintPrecisionEvalProgram (const glu::RenderContext& context, glu::DataType type, glu::Precision precision, const char* evalOp, bool isVertexCase)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		typeName	= glu::getDataTypeName(type);
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		precName	= glu::getPrecisionName(precision);
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	vtx;
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	frag;
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream&	op			= isVertexCase ? vtx : frag;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "#version 300 es\n"
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in highp vec4 a_position;\n"
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in " << precName << " " << typeName << " a_in0;\n"
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in " << precName << " " << typeName << " a_in1;\n";
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "#version 300 es\n"
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << "layout(location = 0) out " << precName << " " << typeName << " o_out;\n";
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "flat out " << precName << " " << typeName << " v_out;\n";
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "flat in " << precName << " " << typeName << " v_out;\n";
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "flat out " << precName << " " << typeName << " v_in0;\n"
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "flat out " << precName << " " << typeName << " v_in1;\n";
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "flat in " << precName << " " << typeName << " v_in0;\n"
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 << "flat in " << precName << " " << typeName << " v_in1;\n";
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "\nvoid main (void)\n{\n"
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_Position = a_position;\n";
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\nvoid main (void)\n{\n";
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\t" << precName << " " << typeName << " in0 = " << (isVertexCase ? "a_" : "v_") << "in0;\n"
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	   << "\t" << precName << " " << typeName << " in1 = " << (isVertexCase ? "a_" : "v_") << "in1;\n";
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\t" << (isVertexCase ? "v_" : "o_") << "out = " << evalOp << ";\n";
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	o_out = v_out;\n";
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_in0 = a_in0;\n"
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	v_in1 = a_in1;\n";
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "}\n";
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "}\n";
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(context, glu::makeVtxFragSources(vtx.str(), frag.str()));
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderFloatPrecisionCase : public TestCase
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef double (*EvalFunc) (double in0, double in1);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								ShaderFloatPrecisionCase	(Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, const tcu::Vec2& rangeA, const tcu::Vec2& rangeB, bool isVertexCase);
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~ShaderFloatPrecisionCase	(void);
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init						(void);
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit						(void);
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate						(void);
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
19000b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos	bool						compare						(float in0, float in1, double reference, float result)
19100b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos#if (DE_COMPILER == DE_COMPILER_GCC) && (DE_CPU == DE_CPU_ARM_64)
19200b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos#	if (__GNUC__ == 4) && (__GNUC_MINOR__ == 9) && (__GNUC_PATCHLEVEL__ == 0)
19300b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// Some prerelease GCC 4.9 versions have a bug in shift right when
19400b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// targeting ARMv8.
19500b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		//
19600b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// If compiler wants to perform logical shift by variable/register
19700b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// in fp/vector registers it uses USHL that selects shift direction
19800b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// based on shift operand value. Thus for right shifts the shift
19900b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// operand needs to be negated.
20000b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		//
20100b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// The bug is in right shift pattern; it doesn't mark shift operand
20200b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// as clobbered and thus later code using that same register may
20300b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// see the negated value.
20400b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		//
20500b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// Workaround is to disable optimization for this function.
20600b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		//
20700b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61633
20800b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos		__attribute__((optimize(0)))
20900b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos#	endif
21000b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos#endif
21100b60d29a1da01c554a3af8f96112199231145d2Pyry Haulos	;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								ShaderFloatPrecisionCase	(const ShaderFloatPrecisionCase& other);
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderFloatPrecisionCase&	operator=					(const ShaderFloatPrecisionCase& other);
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Case parameters.
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string					m_op;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	EvalFunc					m_evalFunc;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision				m_precision;
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec2					m_rangeA;
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec2					m_rangeB;
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool						m_isVertexCase;
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_numTestsPerIter;
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_numIters;
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random					m_rnd;
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Iteration state.
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*			m_program;
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_framebuffer;
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_renderbuffer;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_iterNdx;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderFloatPrecisionCase::ShaderFloatPrecisionCase (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, const tcu::Vec2& rangeA, const tcu::Vec2& rangeB, bool isVertexCase)
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, name, desc)
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_op				(op)
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_evalFunc		(evalFunc)
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_precision		(precision)
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rangeA			(rangeA)
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rangeB			(rangeB)
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_isVertexCase	(isVertexCase)
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numTestsPerIter	(32)
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numIters		(4)
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rnd				(deStringHash(name))
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program			(DE_NULL)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_framebuffer		(0)
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderbuffer	(0)
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterNdx			(0)
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderFloatPrecisionCase::~ShaderFloatPrecisionCase (void)
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderFloatPrecisionCase::deinit();
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderFloatPrecisionCase::init (void)
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log	= m_testCtx.getLog();
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_program && !m_framebuffer && !m_renderbuffer);
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create program.
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = createFloatPrecisionEvalProgram(m_context.getRenderContext(), m_precision, m_op.c_str(), m_isVertexCase);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << *m_program;
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(m_program->isOk());
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create framebuffer.
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genFramebuffers(1, &m_framebuffer);
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genRenderbuffers(1, &m_renderbuffer);
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Post framebuffer setup");
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize test result to pass.
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx = 0;
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderFloatPrecisionCase::deinit (void)
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_framebuffer)
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_framebuffer);
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_renderbuffer)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_renderbuffer);
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program		= DE_NULL;
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_framebuffer	= 0;
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_renderbuffer	= 0;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ShaderFloatPrecisionCase::compare (float in0, float in1, double reference, float result)
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Comparison is done using 64-bit reference value to accurately evaluate rounding mode error.
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// If 32-bit reference value is used, 2 bits of rounding error must be allowed.
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// For mediump and lowp types the comparison currently allows 3 bits of rounding error:
3138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// two bits from conversions and one from actual operation.
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2013-09-30 pyry] Make this more strict: determine if rounding can actually happen.
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		mantissaBits		= m_precision == glu::PRECISION_HIGHP ? 23 : 10;
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numPrecBits			= 52 - mantissaBits;
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		in0Exp				= tcu::Float32(in0).exponent();
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		in1Exp				= tcu::Float32(in1).exponent();
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		resExp				= tcu::Float32(result).exponent();
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numLostBits			= de::max(de::max(in0Exp-resExp, in1Exp-resExp), 0); // Lost due to mantissa shift.
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int		roundingUlpError	= m_precision == glu::PRECISION_HIGHP ? 1 : 3;
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		maskBits			= numLostBits + numPrecBits;
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << TestLog::Message << "Assuming " << mantissaBits << " mantissa bits, " << numLostBits << " bits lost in operation, and " << roundingUlpError << " ULP rounding error."
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   << TestLog::EndMessage;
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint64	refBits				= tcu::Float64(reference).bits();
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint64	resBits				= tcu::Float64(result).bits();
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint64	accurateRefBits		= refBits >> maskBits;
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint64	accurateResBits		= resBits >> maskBits;
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint64	ulpDiff				= (deUint64)de::abs((deInt64)accurateRefBits - (deInt64)accurateResBits);
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ulpDiff > (deUint64)roundingUlpError)
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed! ULP diff (ignoring lost/undefined bits) = " << ulpDiff << TestLog::EndMessage;
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderFloatPrecisionCase::IterateResult ShaderFloatPrecisionCase::iterate (void)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Constant data.
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float position[] =
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, 0.0f, 1.0f,
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, 0.0f, 1.0f,
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, 0.0f, 1.0f,
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f,  1.0f, 0.0f, 1.0f
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint16					indices[]	= { 0, 1, 2, 2, 1, 3 };
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numVertices	= 4;
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float							in0Arr[4]	= { 0.0f };
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float							in1Arr[4]	= { 0.0f };
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&						log			= m_testCtx.getLog();
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl			= m_context.getRenderContext().getFunctions();
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<glu::VertexArrayBinding>	vertexArrays;
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Image read from GL.
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<float>	pixels		(FRAMEBUFFER_WIDTH*FRAMEBUFFER_HEIGHT*4);
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2012-05-03 pyry] Could be cached.
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32			prog		= m_program->getProgram();
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(prog);
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Float("a_position", 4, numVertices, 0, &position[0]));
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Float("a_in0", 1, numVertices, 0, &in0Arr[0]));
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Float("a_in1", 1, numVertices, 0, &in1Arr[0]));
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup");
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute values and reference.
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int testNdx = 0; testNdx < m_numTestsPerIter; testNdx++)
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		in0		= m_rnd.getFloat(m_rangeA.x(), m_rangeA.y());
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		in1		= m_rnd.getFloat(m_rangeB.x(), m_rangeB.y());
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double	refD	= m_evalFunc((double)in0, (double)in1);
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		refF	= tcu::Float64(refD).asFloat(); // Uses RTE rounding mode.
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "iter " << m_iterNdx << ", test " << testNdx << ": "
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< "in0 = " << in0 << " / " << tcu::toHex(tcu::Float32(in0).bits())
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< ", in1 = " << in1 << " / " << tcu::toHex(tcu::Float32(in1).bits())
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::EndMessage
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Message << "  reference = " << refF << " / " << tcu::toHex(tcu::Float32(refF).bits()) << TestLog::EndMessage;
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::fill(&in0Arr[0], &in0Arr[0] + DE_LENGTH_OF_ARRAY(in0Arr), in0);
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::fill(&in1Arr[0], &in1Arr[0] + DE_LENGTH_OF_ARRAY(in1Arr), in1);
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_context.getRenderContext(), prog, (int)vertexArrays.size(), &vertexArrays[0],
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.readPixels(0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "After render");
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "  result = " << pixels[0] << " / " << tcu::toHex(tcu::Float32(pixels[0]).bits()) << TestLog::EndMessage;
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Verify results
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool firstPixelOk = compare(in0, in1, refD, pixels[0]);
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (firstPixelOk)
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Check that rest of pixels match to first one.
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	firstPixelBits	= tcu::Float32(pixels[0]).bits();
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			allPixelsOk		= true;
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int y = 0; y < FRAMEBUFFER_HEIGHT; y++)
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int x = 0; x < FRAMEBUFFER_WIDTH; x++)
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const deUint32 pixelBits = tcu::Float32(pixels[(y*FRAMEBUFFER_WIDTH + x)*4]).bits();
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (pixelBits != firstPixelBits)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "ERROR: Inconsistent results, got " << tcu::toHex(pixelBits) << " at (" << x << ", " << y << ")" << TestLog::EndMessage;
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							allPixelsOk = false;
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!allPixelsOk)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!allPixelsOk)
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Inconsistent values in framebuffer");
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After iteration");
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx += 1;
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (m_iterNdx < m_numIters && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) ? CONTINUE : STOP;
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderIntPrecisionCase : public TestCase
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef int					(*EvalFunc)					(int a, int b);
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								ShaderIntPrecisionCase		(Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::IVec2& rangeA, const tcu::IVec2& rangeB, bool isVertexCase);
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~ShaderIntPrecisionCase		(void);
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init						(void);
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit						(void);
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate						(void);
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								ShaderIntPrecisionCase		(const ShaderIntPrecisionCase& other);
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderIntPrecisionCase&		operator=					(const ShaderIntPrecisionCase& other);
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Case parameters.
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string					m_op;
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	EvalFunc					m_evalFunc;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision				m_precision;
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_bits;
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2					m_rangeA;
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2					m_rangeB;
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool						m_isVertexCase;
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_numTestsPerIter;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_numIters;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random					m_rnd;
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Iteration state.
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*			m_program;
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_framebuffer;
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_renderbuffer;
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_iterNdx;
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4883c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderIntPrecisionCase::ShaderIntPrecisionCase (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::IVec2& rangeA, const tcu::IVec2& rangeB, bool isVertexCase)
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, name, desc)
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_op				(op)
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_evalFunc		(evalFunc)
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_precision		(precision)
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bits			(bits)
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rangeA			(rangeA)
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rangeB			(rangeB)
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_isVertexCase	(isVertexCase)
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numTestsPerIter	(32)
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numIters		(4)
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rnd				(deStringHash(name))
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program			(DE_NULL)
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_framebuffer		(0)
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderbuffer	(0)
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterNdx			(0)
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5073c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderIntPrecisionCase::~ShaderIntPrecisionCase (void)
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderIntPrecisionCase::deinit();
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderIntPrecisionCase::init (void)
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log	= m_testCtx.getLog();
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_program && !m_framebuffer && !m_renderbuffer);
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create program.
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = createIntUintPrecisionEvalProgram(m_context.getRenderContext(), glu::TYPE_INT, m_precision, m_op.c_str(), m_isVertexCase);
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << *m_program;
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(m_program->isOk());
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create framebuffer.
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genFramebuffers(1, &m_framebuffer);
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genRenderbuffers(1, &m_renderbuffer);
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32I, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Post framebuffer setup");
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize test result to pass.
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx = 0;
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Number of accurate bits assumed = " << m_bits << TestLog::EndMessage;
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderIntPrecisionCase::deinit (void)
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_framebuffer)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_framebuffer);
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_renderbuffer)
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_renderbuffer);
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program		= DE_NULL;
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_framebuffer	= 0;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_renderbuffer	= 0;
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int extendTo32Bit (int value, int bits)
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (value & ((1<<(bits-1))-1)) | (((value & (1<<(bits-1))) << (32-bits)) >> (32-bits));
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderIntPrecisionCase::IterateResult ShaderIntPrecisionCase::iterate (void)
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Constant data.
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float position[] =
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, 0.0f, 1.0f,
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, 0.0f, 1.0f,
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, 0.0f, 1.0f,
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f,  1.0f, 0.0f, 1.0f
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint16					indices[]	= { 0, 1, 2, 2, 1, 3 };
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numVertices	= 4;
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								in0Arr[4]	= { 0 };
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								in1Arr[4]	= { 0 };
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&						log			= m_testCtx.getLog();
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl			= m_context.getRenderContext().getFunctions();
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						mask		= m_bits == 32 ? 0xffffffffu : ((1u<<m_bits)-1);
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>						pixels		(FRAMEBUFFER_WIDTH*FRAMEBUFFER_HEIGHT*4);
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<glu::VertexArrayBinding>	vertexArrays;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						prog		= m_program->getProgram();
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2012-05-03 pyry] A bit hacky. getInt() should work fine with ranges like this.
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							isMaxRangeA	= m_rangeA.x() == (int)0x80000000 && m_rangeA.y() == (int)0x7fffffff;
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							isMaxRangeB	= m_rangeB.x() == (int)0x80000000 && m_rangeB.y() == (int)0x7fffffff;
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(prog);
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Float("a_position", 4, numVertices, 0, &position[0]));
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Int32("a_in0", 1, numVertices, 0, &in0Arr[0]));
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Int32("a_in1", 1, numVertices, 0, &in1Arr[0]));
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup");
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute values and reference.
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int testNdx = 0; testNdx < m_numTestsPerIter; testNdx++)
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		in0			= extendTo32Bit(((isMaxRangeA ? (int)m_rnd.getUint32() : m_rnd.getInt(m_rangeA.x(), m_rangeA.y())) & mask), m_bits);
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		in1			= extendTo32Bit(((isMaxRangeB ? (int)m_rnd.getUint32() : m_rnd.getInt(m_rangeB.x(), m_rangeB.y())) & mask), m_bits);
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		refMasked	= m_evalFunc(in0, in1) & mask;
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		refOut		= extendTo32Bit(refMasked, m_bits);
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "iter " << m_iterNdx << ", test " << testNdx << ": "
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< "in0 = " << in0 << ", in1 = " << in1 << ", ref out = " << refOut << " / " << tcu::toHex(refMasked)
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::EndMessage;
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::fill(&in0Arr[0], &in0Arr[0] + DE_LENGTH_OF_ARRAY(in0Arr), in0);
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::fill(&in1Arr[0], &in1Arr[0] + DE_LENGTH_OF_ARRAY(in1Arr), in1);
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_context.getRenderContext(), prog, (int)vertexArrays.size(), &vertexArrays[0],
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.readPixels(0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, GL_RGBA_INTEGER, GL_INT, &pixels[0]);
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "After render");
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compare pixels.
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int y = 0; y < FRAMEBUFFER_HEIGHT; y++)
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int x = 0; x < FRAMEBUFFER_WIDTH; x++)
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			cmpOut		= pixels[(y*FRAMEBUFFER_WIDTH + x)*4];
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			cmpMasked	= cmpOut & mask;
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (cmpMasked != refMasked)
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Comparison failed (at " << x << ", " << y << "): "
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< "got " << cmpOut << " / " << tcu::toHex(cmpOut)
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< TestLog::EndMessage;
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return STOP;
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After iteration");
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx += 1;
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderUintPrecisionCase : public TestCase
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef deUint32			(*EvalFunc)					(deUint32 a, deUint32 b);
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								ShaderUintPrecisionCase		(Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::UVec2& rangeA, const tcu::UVec2& rangeB, bool isVertexCase);
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~ShaderUintPrecisionCase	(void);
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init						(void);
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit						(void);
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate						(void);
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								ShaderUintPrecisionCase		(const ShaderUintPrecisionCase& other);
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderUintPrecisionCase&	operator=					(const ShaderUintPrecisionCase& other);
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Case parameters.
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string					m_op;
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	EvalFunc					m_evalFunc;
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision				m_precision;
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_bits;
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::UVec2					m_rangeA;
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::UVec2					m_rangeB;
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool						m_isVertexCase;
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_numTestsPerIter;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_numIters;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random					m_rnd;
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Iteration state.
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*			m_program;
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_framebuffer;
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_renderbuffer;
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_iterNdx;
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderUintPrecisionCase::ShaderUintPrecisionCase (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::UVec2& rangeA, const tcu::UVec2& rangeB, bool isVertexCase)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, name, desc)
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_op				(op)
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_evalFunc		(evalFunc)
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_precision		(precision)
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bits			(bits)
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rangeA			(rangeA)
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rangeB			(rangeB)
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_isVertexCase	(isVertexCase)
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numTestsPerIter	(32)
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numIters		(4)
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rnd				(deStringHash(name))
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program			(DE_NULL)
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_framebuffer		(0)
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderbuffer	(0)
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterNdx			(0)
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderUintPrecisionCase::~ShaderUintPrecisionCase (void)
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderUintPrecisionCase::deinit();
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderUintPrecisionCase::init (void)
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log	= m_testCtx.getLog();
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_program && !m_framebuffer && !m_renderbuffer);
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create program.
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = createIntUintPrecisionEvalProgram(m_context.getRenderContext(), glu::TYPE_UINT, m_precision, m_op.c_str(), m_isVertexCase);
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << *m_program;
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(m_program->isOk());
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create framebuffer.
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genFramebuffers(1, &m_framebuffer);
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genRenderbuffers(1, &m_renderbuffer);
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Post framebuffer setup");
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize test result to pass.
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx = 0;
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Number of accurate bits assumed = " << m_bits << TestLog::EndMessage;
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderUintPrecisionCase::deinit (void)
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_framebuffer)
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_framebuffer);
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_renderbuffer)
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_renderbuffer);
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program		= DE_NULL;
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_framebuffer	= 0;
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_renderbuffer	= 0;
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderUintPrecisionCase::IterateResult ShaderUintPrecisionCase::iterate (void)
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Constant data.
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float position[] =
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, 0.0f, 1.0f,
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, 0.0f, 1.0f,
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, 0.0f, 1.0f,
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f,  1.0f, 0.0f, 1.0f
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint16					indices[]	= { 0, 1, 2, 2, 1, 3 };
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numVertices	= 4;
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						in0Arr[4]	= { 0 };
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						in1Arr[4]	= { 0 };
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&						log			= m_testCtx.getLog();
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl			= m_context.getRenderContext().getFunctions();
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						mask		= m_bits == 32 ? 0xffffffffu : ((1u<<m_bits)-1);
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>				pixels		(FRAMEBUFFER_WIDTH*FRAMEBUFFER_HEIGHT*4);
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<glu::VertexArrayBinding>	vertexArrays;
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						prog		= m_program->getProgram();
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2012-05-03 pyry] A bit hacky.
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							isMaxRangeA	= m_rangeA.x() == 0 && m_rangeA.y() == 0xffffffff;
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							isMaxRangeB	= m_rangeB.x() == 0 && m_rangeB.y() == 0xffffffff;
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(prog);
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Float("a_position", 4, numVertices, 0, &position[0]));
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Uint32("a_in0", 1, numVertices, 0, &in0Arr[0]));
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Uint32("a_in1", 1, numVertices, 0, &in1Arr[0]));
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup");
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute values and reference.
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int testNdx = 0; testNdx < m_numTestsPerIter; testNdx++)
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32	in0		= (isMaxRangeA ? m_rnd.getUint32() : (m_rangeA.x() + m_rnd.getUint32()%(m_rangeA.y()-m_rangeA.x()+1))) & mask;
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32	in1		= (isMaxRangeB ? m_rnd.getUint32() : (m_rangeB.x() + m_rnd.getUint32()%(m_rangeB.y()-m_rangeB.x()+1))) & mask;
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32	refOut	= m_evalFunc(in0, in1) & mask;
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "iter " << m_iterNdx << ", test " << testNdx << ": "
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< "in0 = " << tcu::toHex(in0) << ", in1 = " << tcu::toHex(in1) << ", ref out = " << tcu::toHex(refOut)
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::EndMessage;
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::fill(&in0Arr[0], &in0Arr[0] + DE_LENGTH_OF_ARRAY(in0Arr), in0);
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::fill(&in1Arr[0], &in1Arr[0] + DE_LENGTH_OF_ARRAY(in1Arr), in1);
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_context.getRenderContext(), prog, (int)vertexArrays.size(), &vertexArrays[0],
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.readPixels(0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "After render");
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compare pixels.
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int y = 0; y < FRAMEBUFFER_HEIGHT; y++)
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int x = 0; x < FRAMEBUFFER_WIDTH; x++)
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32	cmpOut		= pixels[(y*FRAMEBUFFER_WIDTH + x)*4];
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32	cmpMasked	= cmpOut & mask;
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (cmpMasked != refOut)
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Comparison failed (at " << x << ", " << y << "): "
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< "got " << tcu::toHex(cmpOut)
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< TestLog::EndMessage;
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return STOP;
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After iteration");
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx += 1;
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8443c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderPrecisionTests::ShaderPrecisionTests (Context& context)
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "precision", "Shader precision requirements validation tests")
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8493c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderPrecisionTests::~ShaderPrecisionTests (void)
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderPrecisionTests::init (void)
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::add;
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::sub;
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::mul;
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::div;
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::Vec2;
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::IVec2;
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::UVec2;
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Exp = Emax-2, Mantissa = 0
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		minF32			= tcu::Float32((1u<<31) | (0xfdu<<23) | 0x0u).asFloat();
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		maxF32			= tcu::Float32((0u<<31) | (0xfdu<<23) | 0x0u).asFloat();
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		minF16			= tcu::Float16((deUint16)((1u<<15) | (0x1du<<10) | 0x0u)).asFloat();
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		maxF16			= tcu::Float16((deUint16)((0u<<15) | (0x1du<<10) | 0x0u)).asFloat();
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec2	fullRange32F	(minF32, maxF32);
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec2	fullRange16F	(minF16, maxF16);
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	fullRange32I	(0x80000000, 0x7fffffff);
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	fullRange16I	(-(1<<15), (1<<15)-1);
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	fullRange8I		(-(1<<7), (1<<7)-1);
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::UVec2	fullRange32U	(0u, 0xffffffffu);
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::UVec2	fullRange16U	(0u, 0xffffu);
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::UVec2	fullRange8U		(0u, 0xffu);
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Right now it is not programmatically verified that the results shouldn't end up being inf/nan but
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//       actual values used are ok.
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*							name;
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*							op;
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderFloatPrecisionCase::EvalFunc	evalFunc;
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::Precision						precision;
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2							rangeA;
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2							rangeB;
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} floatCases[] =
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Name				Op				Eval			Precision				RangeA				RangeB
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_add",		"in0 + in1",	add<double>,	glu::PRECISION_HIGHP,	fullRange32F,		fullRange32F		},
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_sub",		"in0 - in1",	sub<double>,	glu::PRECISION_HIGHP,	fullRange32F,		fullRange32F		},
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_mul",		"in0 * in1",	mul<double>,	glu::PRECISION_HIGHP,	Vec2(-1e5f, 1e5f),	Vec2(-1e5f, 1e5f)	},
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_div",		"in0 / in1",	div<double>,	glu::PRECISION_HIGHP,	Vec2(-1e5f, 1e5f),	Vec2(-1e5f, 1e5f)	},
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_add",	"in0 + in1",	add<double>,	glu::PRECISION_MEDIUMP,	fullRange16F,		fullRange16F		},
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_sub",	"in0 - in1",	sub<double>,	glu::PRECISION_MEDIUMP,	fullRange16F,		fullRange16F		},
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_mul",	"in0 * in1",	mul<double>,	glu::PRECISION_MEDIUMP,	Vec2(-1e2f, 1e2f),	Vec2(-1e2f, 1e2f)	},
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_div",	"in0 / in1",	div<double>,	glu::PRECISION_MEDIUMP,	Vec2(-1e2f, 1e2f),	Vec2(-1e2f, 1e2f)	}
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*							name;
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*							op;
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderIntPrecisionCase::EvalFunc	evalFunc;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::Precision						precision;
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int									bits;
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::IVec2							rangeA;
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::IVec2							rangeB;
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} intCases[] =
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Name				Op				Eval				Precision				Bits	RangeA			RangeB
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_add",		"in0 + in1",	add<int>,			glu::PRECISION_HIGHP,	32,		fullRange32I,	fullRange32I },
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_sub",		"in0 - in1",	sub<int>,			glu::PRECISION_HIGHP,	32,		fullRange32I,	fullRange32I },
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_mul",		"in0 * in1",	mul<int>,			glu::PRECISION_HIGHP,	32,		fullRange32I,	fullRange32I },
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_div",		"in0 / in1",	div<int>,			glu::PRECISION_HIGHP,	32,		fullRange32I,	IVec2(-10000, -1) },
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_add",	"in0 + in1",	add<int>,			glu::PRECISION_MEDIUMP,	16,		fullRange16I,	fullRange16I },
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_sub",	"in0 - in1",	sub<int>,			glu::PRECISION_MEDIUMP,	16,		fullRange16I,	fullRange16I },
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_mul",	"in0 * in1",	mul<int>,			glu::PRECISION_MEDIUMP,	16,		fullRange16I,	fullRange16I },
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_div",	"in0 / in1",	div<int>,			glu::PRECISION_MEDIUMP,	16,		fullRange16I,	IVec2(1, 1000) },
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_add",		"in0 + in1",	add<int>,			glu::PRECISION_LOWP,	8,		fullRange8I,	fullRange8I },
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_sub",		"in0 - in1",	sub<int>,			glu::PRECISION_LOWP,	8,		fullRange8I,	fullRange8I },
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_mul",		"in0 * in1",	mul<int>,			glu::PRECISION_LOWP,	8,		fullRange8I,	fullRange8I },
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_div",		"in0 / in1",	div<int>,			glu::PRECISION_LOWP,	8,		fullRange8I,	IVec2(-50, -1) }
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*							name;
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*							op;
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderUintPrecisionCase::EvalFunc	evalFunc;
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::Precision						precision;
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int									bits;
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::UVec2							rangeA;
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::UVec2							rangeB;
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} uintCases[] =
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Name				Op				Eval				Precision				Bits	RangeA			RangeB
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_add",		"in0 + in1",	add<deUint32>,		glu::PRECISION_HIGHP,	32,		fullRange32U,	fullRange32U },
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_sub",		"in0 - in1",	sub<deUint32>,		glu::PRECISION_HIGHP,	32,		fullRange32U,	fullRange32U },
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_mul",		"in0 * in1",	mul<deUint32>,		glu::PRECISION_HIGHP,	32,		fullRange32U,	fullRange32U },
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "highp_div",		"in0 / in1",	div<deUint32>,		glu::PRECISION_HIGHP,	32,		fullRange32U,	UVec2(1u, 10000u) },
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_add",	"in0 + in1",	add<deUint32>,		glu::PRECISION_MEDIUMP,	16,		fullRange16U,	fullRange16U },
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_sub",	"in0 - in1",	sub<deUint32>,		glu::PRECISION_MEDIUMP,	16,		fullRange16U,	fullRange16U },
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_mul",	"in0 * in1",	mul<deUint32>,		glu::PRECISION_MEDIUMP,	16,		fullRange16U,	fullRange16U },
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mediump_div",	"in0 / in1",	div<deUint32>,		glu::PRECISION_MEDIUMP,	16,		fullRange16U,	UVec2(1, 1000u) },
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_add",		"in0 + in1",	add<deUint32>,		glu::PRECISION_LOWP,	8,		fullRange8U,	fullRange8U },
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_sub",		"in0 - in1",	sub<deUint32>,		glu::PRECISION_LOWP,	8,		fullRange8U,	fullRange8U },
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_mul",		"in0 * in1",	mul<deUint32>,		glu::PRECISION_LOWP,	8,		fullRange8U,	fullRange8U },
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lowp_div",		"in0 / in1",	div<deUint32>,		glu::PRECISION_LOWP,	8,		fullRange8U,	UVec2(1, 50u) }
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "Floating-point precision tests");
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(floatGroup);
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(floatCases); ndx++)
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		floatGroup->addChild(new ShaderFloatPrecisionCase(m_context,
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  (string(floatCases[ndx].name) + "_vertex").c_str(), "",
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].op,
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].evalFunc,
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].precision,
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].rangeA,
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].rangeB,
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  true));
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		floatGroup->addChild(new ShaderFloatPrecisionCase(m_context,
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  (string(floatCases[ndx].name) + "_fragment").c_str(), "",
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].op,
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].evalFunc,
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].precision,
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].rangeA,
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  floatCases[ndx].rangeB,
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  false));
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "int", "Integer precision tests");
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(intGroup);
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(intCases); ndx++)
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		intGroup->addChild(new ShaderIntPrecisionCase(m_context,
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  (string(intCases[ndx].name) + "_vertex").c_str(), "",
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].op,
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].evalFunc,
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].precision,
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].bits,
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].rangeA,
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].rangeB,
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  true));
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		intGroup->addChild(new ShaderIntPrecisionCase(m_context,
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  (string(intCases[ndx].name) + "_fragment").c_str(), "",
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].op,
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].evalFunc,
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].precision,
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].bits,
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].rangeA,
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  intCases[ndx].rangeB,
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  false));
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uint", "Unsigned integer precision tests");
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(uintGroup);
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uintCases); ndx++)
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		uintGroup->addChild(new ShaderUintPrecisionCase(m_context,
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														(string(uintCases[ndx].name) + "_vertex").c_str(), "",
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].op,
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].evalFunc,
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].precision,
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].bits,
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].rangeA,
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].rangeB,
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														true));
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		uintGroup->addChild(new ShaderUintPrecisionCase(m_context,
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														(string(uintCases[ndx].name) + "_fragment").c_str(), "",
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].op,
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].evalFunc,
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].precision,
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].bits,
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].rangeA,
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														uintCases[ndx].rangeB,
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														false));
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1027