13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Tests for separate shader objects
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fSeparateShaderTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSTLUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuCommandLine.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRGBA.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuStringTemplate.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluCallLogWrapper.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarType.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderLibrary.hpp"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwDefs.hpp"
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cstdarg>
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set>
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::set;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::ostringstream;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::MovePtr;
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::Random;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::UniquePtr;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::MessageBuilder;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::RenderTarget;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::StringTemplate;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Surface;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::ResultCollector;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::CallLogWrapper;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::DataType;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::VariableDeclaration;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::Precision;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::Program;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ProgramPipeline;
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ProgramSources;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::RenderContext;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ShaderProgram;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ShaderType;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::Storage;
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::VarType;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::VertexSource;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::FragmentSource;
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ProgramSeparable;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glw;
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define LOG_CALL(CALL) do	\
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{							\
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enableLogging(true);	\
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CALL;					\
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enableLogging(false);	\
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} while (deGetFalse())
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VIEWPORT_SIZE = 128
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1091bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyryenum VaryingInterpolation
1101bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry{
1111bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VARYINGINTERPOLATION_SMOOTH		= 0,
1121bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VARYINGINTERPOLATION_FLAT,
1131bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VARYINGINTERPOLATION_CENTROID,
1141bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VARYINGINTERPOLATION_DEFAULT,
1151bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VARYINGINTERPOLATION_RANDOM,
1161bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
1171bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VARYINGINTERPOLATION_LAST
1181bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry};
1191bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDataType randomType (Random& rnd)
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (rnd.getInt(0, 7) == 0)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numCols = rnd.getInt(2, 4), numRows = rnd.getInt(2, 4);
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getDataTypeMatrix(numCols, numRows);
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const DataType	s_types[]	= { TYPE_FLOAT,	TYPE_INT,	TYPE_UINT	};
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const float		s_weights[] = { 3.0,		1.0,		1.0			};
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				size		= rnd.getInt(1, 4);
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const DataType			scalarType	= rnd.chooseWeighted<DataType>(
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ARRAY_BEGIN(s_types), DE_ARRAY_END(s_types), DE_ARRAY_BEGIN(s_weights));
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getDataTypeVector(scalarType, size);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!"Impossible");
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return TYPE_INVALID;
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1441bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko PöyryVaryingInterpolation randomInterpolation (Random& rnd)
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1461bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	static const VaryingInterpolation s_validInterpolations[] =
1471bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	{
1481bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		VARYINGINTERPOLATION_SMOOTH,
1491bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		VARYINGINTERPOLATION_FLAT,
1501bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		VARYINGINTERPOLATION_CENTROID,
1511bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		VARYINGINTERPOLATION_DEFAULT,
1521bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	};
1531bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	return s_validInterpolations[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_validInterpolations)-1)];
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1561bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyryglu::Interpolation getGluInterpolation (VaryingInterpolation interpolation)
1571bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry{
1581bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	switch (interpolation)
1591bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	{
1601bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case VARYINGINTERPOLATION_SMOOTH:	return glu::INTERPOLATION_SMOOTH;
1611bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case VARYINGINTERPOLATION_FLAT:		return glu::INTERPOLATION_FLAT;
1621bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case VARYINGINTERPOLATION_CENTROID:	return glu::INTERPOLATION_CENTROID;
1631bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case VARYINGINTERPOLATION_DEFAULT:	return glu::INTERPOLATION_LAST;		//!< Last means no qualifier, i.e. default
1641bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		default:
1651bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			DE_ASSERT(!"Invalid interpolation");
1661bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			return glu::INTERPOLATION_LAST;
1671bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	}
1681bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry}
1691bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
1701bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry// used only for debug sanity checks
1711bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry#if defined(DE_DEBUG)
1721bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko PöyryVaryingInterpolation getVaryingInterpolation (glu::Interpolation interpolation)
1731bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry{
1741bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	switch (interpolation)
1751bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	{
1761bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case glu::INTERPOLATION_SMOOTH:		return VARYINGINTERPOLATION_SMOOTH;
1771bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case glu::INTERPOLATION_FLAT:		return VARYINGINTERPOLATION_FLAT;
1781bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case glu::INTERPOLATION_CENTROID:	return VARYINGINTERPOLATION_CENTROID;
1791bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		case glu::INTERPOLATION_LAST:		return VARYINGINTERPOLATION_DEFAULT;		//!< Last means no qualifier, i.e. default
1801bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		default:
1811bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			DE_ASSERT(!"Invalid interpolation");
1821bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			return VARYINGINTERPOLATION_LAST;
1831bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	}
1841bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry}
1851bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry#endif
1861bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum BindingKind
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BINDING_NAME,
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BINDING_LOCATION,
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BINDING_LAST
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1943c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBindingKind randomBinding (Random& rnd)
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return rnd.getBool() ? BINDING_LOCATION : BINDING_NAME;
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printInputColor (ostringstream& oss, const VariableDeclaration& input)
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DataType	basicType	= input.varType.getBasicType();
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			exp			= input.name;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (getDataTypeScalarType(basicType))
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TYPE_FLOAT:
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TYPE_INT:
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TYPE_UINT:
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DataType floatType = getDataTypeFloatScalars(basicType);
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			exp = string() + "(" + getDataTypeName(floatType) + "(" + exp + ") / 255.0" + ")";
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!"Impossible");
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isDataTypeScalarOrVector(basicType))
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (getDataTypeScalarSize(basicType))
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 1:
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << "hsv(vec3(" << exp << ", 1.0, 1.0))";
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 2:
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << "hsv(vec3(" << exp << ", 1.0))";
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 3:
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << "vec4(" << exp << ", 1.0)";
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 4:
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << exp;
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isDataTypeMatrix(basicType))
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	rows	= getDataTypeMatrixNumRows(basicType);
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	columns	= getDataTypeMatrixNumColumns(basicType);
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (rows == columns)
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << "hsv(vec3(determinant(" << exp << ")))";
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (rows != 3 && columns >= 3)
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				exp = "transpose(" + exp + ")";
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::swap(rows, columns);
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			exp = exp + "[0]";
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (rows > 3)
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				exp = exp + ".xyz";
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << "hsv(" << exp << ")";
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!"Impossible");
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Representation for the varyings between vertex and fragment shaders
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VaryingParams
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2711bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VaryingParams			(void)
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: count				(0)
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, type				(glu::TYPE_LAST)
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, binding			(BINDING_LAST)
2751bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		, vtxInterp			(VARYINGINTERPOLATION_LAST)
2761bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		, frgInterp			(VARYINGINTERPOLATION_LAST) {}
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						count;
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DataType				type;
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BindingKind				binding;
2811bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VaryingInterpolation	vtxInterp;
2821bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	VaryingInterpolation	frgInterp;
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VaryingInterface
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<VariableDeclaration>	vtxOutputs;
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<VariableDeclaration>	frgInputs;
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Generate corresponding input and output variable declarations that may vary
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// in compatible ways.
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2941bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko PöyryVaryingInterpolation chooseInterpolation (VaryingInterpolation param, DataType type, Random& rnd)
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (glu::getDataTypeScalarType(type) != glu::TYPE_FLOAT)
2971bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		return VARYINGINTERPOLATION_FLAT;
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2991bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	if (param == VARYINGINTERPOLATION_RANDOM)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return randomInterpolation(rnd);
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return param;
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3051bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyrybool isSSOCompatibleInterpolation (VaryingInterpolation vertexInterpolation, VaryingInterpolation fragmentInterpolation)
3061bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry{
3071bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	// interpolations must be fully specified
3081bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	DE_ASSERT(vertexInterpolation != VARYINGINTERPOLATION_RANDOM);
3091bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	DE_ASSERT(vertexInterpolation < VARYINGINTERPOLATION_LAST);
3101bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	DE_ASSERT(fragmentInterpolation != VARYINGINTERPOLATION_RANDOM);
3111bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	DE_ASSERT(fragmentInterpolation < VARYINGINTERPOLATION_LAST);
3121bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
3131bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	// interpolation can only be either smooth or flat. Auxiliary storage does not matter.
3141bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	const bool isSmoothVtx =    (vertexInterpolation == VARYINGINTERPOLATION_SMOOTH)      || //!< trivial
3151bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	                            (vertexInterpolation == VARYINGINTERPOLATION_DEFAULT)     || //!< default to smooth
3161bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	                            (vertexInterpolation == VARYINGINTERPOLATION_CENTROID);      //!< default to smooth, ignore storage
3171bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	const bool isSmoothFrag =   (fragmentInterpolation == VARYINGINTERPOLATION_SMOOTH)    || //!< trivial
3181bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	                            (fragmentInterpolation == VARYINGINTERPOLATION_DEFAULT)   || //!< default to smooth
3191bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	                            (fragmentInterpolation == VARYINGINTERPOLATION_CENTROID);    //!< default to smooth, ignore storage
3201bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	// Khronos bug #12630: flat / smooth qualifiers must match in SSO
3211bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	return isSmoothVtx == isSmoothFrag;
3221bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry}
3231bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVaryingInterface genVaryingInterface (const VaryingParams&		params,
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  Random&					rnd)
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace	glu;
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VaryingInterface	ret;
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					offset = 0;
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < params.count; ++varNdx)
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3341bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const BindingKind			binding			= ((params.binding == BINDING_LAST)
3351bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry													   ? randomBinding(rnd) : params.binding);
3361bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const DataType				type			= ((params.type == TYPE_LAST)
3371bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry													   ? randomType(rnd) : params.type);
3381bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const VaryingInterpolation	vtxInterp		= chooseInterpolation(params.vtxInterp, type, rnd);
3391bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const VaryingInterpolation	frgInterp		= chooseInterpolation(params.frgInterp, type, rnd);
3401bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const VaryingInterpolation	vtxCompatInterp	= (isSSOCompatibleInterpolation(vtxInterp, frgInterp))
3411bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry													   ? (vtxInterp) : (frgInterp);
3421bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const int					loc				= ((binding == BINDING_LOCATION) ? offset : -1);
3431bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const string				ndxStr			= de::toString(varNdx);
3441bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const string				vtxName			= ((binding == BINDING_NAME)
3451bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry													   ? "var" + ndxStr : "vtxVar" + ndxStr);
3461bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const string				frgName			= ((binding == BINDING_NAME)
3471bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry													   ? "var" + ndxStr : "frgVar" + ndxStr);
3481bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const VarType				varType			(type, PRECISION_HIGHP);
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		offset += getDataTypeNumLocations(type);
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Over 16 locations aren't necessarily supported, so halt here.
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (offset > 16)
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.vtxOutputs.push_back(
3571bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			VariableDeclaration(varType, vtxName, STORAGE_OUT, getGluInterpolation(vtxCompatInterp), loc));
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.frgInputs.push_back(
3591bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			VariableDeclaration(varType, frgName, STORAGE_IN, getGluInterpolation(frgInterp), loc));
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Create vertex output variable declarations that are maximally compatible
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// with the fragment input variables.
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<VariableDeclaration> varyingCompatVtxOutputs (const VaryingInterface& varyings)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<VariableDeclaration> outputs = varyings.vtxOutputs;
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t i = 0; i < outputs.size(); ++i)
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outputs[i].interpolation = varyings.frgInputs[i].interpolation;
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outputs[i].name = varyings.frgInputs[i].name;
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return outputs;
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Shader source generation
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printFloat (ostringstream& oss, double d)
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.setf(oss.fixed | oss.internal);
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.precision(4);
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.width(7);
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << d;
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printFloatDeclaration (ostringstream&	oss,
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const string&	varName,
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							bool			uniform,
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							GLfloat			value		= 0.0)
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType	varType	(TYPE_FLOAT, PRECISION_HIGHP);
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (uniform)
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << VariableDeclaration(varType, varName, STORAGE_UNIFORM) << ";\n";
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << VariableDeclaration(varType, varName, STORAGE_CONST)
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< " = " << de::floatToString(value, 6) << ";\n";
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printRandomInitializer (ostringstream& oss, DataType type, Random& rnd)
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		size	= getDataTypeScalarSize(type);
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (size > 0)
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << getDataTypeName(type) << "(";
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < size; ++i)
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << (i == 0 ? "" : ", ");
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (getDataTypeScalarType(type))
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT:
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				printFloat(oss, rnd.getInt(0, 16) / 16.0);
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_INT:
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_UINT:
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << rnd.getInt(0, 255);
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_BOOL:
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << (rnd.getBool() ? "true" : "false");
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (size > 0)
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << ")";
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring genVtxShaderSrc (deUint32							seed,
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const vector<VariableDeclaration>&	outputs,
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const string&						varName,
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						bool								uniform,
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						float								value = 0.0)
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		oss;
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random				rnd								(seed);
4501bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	enum {				NUM_COMPONENTS					= 2 };
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int	s_quadrants[][NUM_COMPONENTS]	= { {1, 1}, {-1, 1}, {1, -1} };
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "#version 310 es\n";
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4551bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	printFloatDeclaration(oss, varName, uniform, value);
4561bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
4571bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	for (vector<VariableDeclaration>::const_iterator it = outputs.begin();
4581bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		 it != outputs.end(); ++it)
4591bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		oss << *it << ";\n";
4601bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "const vec2 triangle[3] = vec2[3](\n";
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int vertexNdx = 0; vertexNdx < DE_LENGTH_OF_ARRAY(s_quadrants); ++vertexNdx)
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\tvec2(";
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int componentNdx = 0; componentNdx < NUM_COMPONENTS; ++componentNdx)
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printFloat(oss, s_quadrants[vertexNdx][componentNdx] * rnd.getInt(4,16) / 16.0);
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << (componentNdx < 1 ? ", " : "");
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << ")" << (vertexNdx < 2 ? "," : "") << "\n";
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << ");\n";
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<VariableDeclaration>::const_iterator it = outputs.begin();
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 it != outputs.end(); ++it)
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const DataType	type		= it->varType.getBasicType();
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	typeName	= glu::getDataTypeName(type);
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "const " << typeName << " " << it->name << "Inits[3] = "
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< typeName << "[3](\n";
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 3; ++i)
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << (i == 0 ? "\t" : ",\n\t");
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printRandomInitializer(oss, type, rnd);
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4911bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		oss << ");\n";
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "void main (void)\n"
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tgl_Position = vec4(" << varName << " * triangle[gl_VertexID], 0.0, 1.0);\n";
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<VariableDeclaration>::const_iterator it = outputs.begin();
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 it != outputs.end(); ++it)
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t" << it->name << " = " << it->name << "Inits[gl_VertexID];\n";
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "}\n";
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring genFrgShaderSrc (deUint32							seed,
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const vector<VariableDeclaration>&	inputs,
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const string&						varName,
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						bool								uniform,
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						float								value = 0.0)
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random				rnd		(seed);
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		oss;
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.precision(4);
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.width(7);
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "#version 310 es\n";
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5201bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	oss << "precision highp float;\n";
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5221bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	oss << "out vec4 fragColor;\n";
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	printFloatDeclaration(oss, varName, uniform, value);
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<VariableDeclaration>::const_iterator it = inputs.begin();
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 it != inputs.end(); ++it)
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << *it << ";\n";
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// glsl % isn't defined for negative numbers
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "int imod (int n, int d)" << "\n"
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{" << "\n"
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\t" << "return (n < 0 ? d - 1 - (-1 - n) % d : n % d);" << "\n"
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}" << "\n";
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "vec4 hsv (vec3 hsv)"
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{" << "\n"
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat h = hsv.x * 3.0;\n"
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat r = max(0.0, 1.0 - h) + max(0.0, h - 2.0);\n"
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat g = max(0.0, 1.0 - abs(h - 1.0));\n"
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat b = max(0.0, 1.0 - abs(h - 2.0));\n"
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tvec3 hs = mix(vec3(1.0), vec3(r, g, b), hsv.y);\n"
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\treturn vec4(hsv.z * hs, 1.0);\n"
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "void main (void)\n"
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n";
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "\t" << "fragColor = vec4(vec3(" << varName << "), 1.0);" << "\n";
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (inputs.size() > 0)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t" << "switch (imod(int(0.5 * (gl_FragCoord.x - gl_FragCoord.y)), "
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< inputs.size() << "))" << "\n"
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t" << "{" << "\n";
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t i = 0; i < inputs.size(); ++i)
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << "\t\t" << "case " << i << ":" << "\n"
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "\t\t\t" << "fragColor *= ";
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printInputColor(oss, inputs[i]);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << ";" << "\n"
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "\t\t\t" << "break;" << "\n";
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t" << "case " << inputs.size() << ":\n"
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t\t\t" << "fragColor = vec4(1.0, 0.0, 1.0, 1.0);" << "\n";
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t\t" << "break;" << "\n";
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t" << "case -1:\n"
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t\t\t" << "fragColor = vec4(1.0, 1.0, 0.0, 1.0);" << "\n";
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t\t" << "break;" << "\n";
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t" << "default:" << "\n"
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t\t\t" << "fragColor = vec4(1.0, 1.0, 0.0, 1.0);" << "\n";
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t" << "}\n";
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "}\n";
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ProgramWrapper
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ProgramWrapper
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5931bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	virtual			~ProgramWrapper			(void) {}
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual GLuint	getProgramName			(void) = 0;
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	writeToLog				(TestLog& log) = 0;
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderProgramWrapper : public ProgramWrapper
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ShaderProgramWrapper	(const RenderContext&	renderCtx,
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const ProgramSources&	sources)
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: m_shaderProgram	(renderCtx, sources) {}
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~ShaderProgramWrapper	(void) {}
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint			getProgramName			(void) { return m_shaderProgram.getProgram(); }
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderProgram&	getShaderProgram		(void) { return m_shaderProgram; }
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			writeToLog				(TestLog& log) { log << m_shaderProgram; }
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderProgram	m_shaderProgram;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RawProgramWrapper : public ProgramWrapper
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					RawProgramWrapper		(const RenderContext&	renderCtx,
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 GLuint					programName,
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 ShaderType				shaderType,
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const string&			source)
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: m_program			(renderCtx, programName)
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_shaderType		(shaderType)
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_source			(source) {}
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~RawProgramWrapper		(void) {}
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint			getProgramName			(void) { return m_program.getProgram(); }
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Program&		getProgram				(void) { return m_program; }
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			writeToLog				(TestLog& log);
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Program			m_program;
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderType		m_shaderType;
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	m_source;
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid RawProgramWrapper::writeToLog (TestLog& log)
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	info	= m_program.getInfoLog();
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpShaderType	qpType	= glu::getLogShaderType(m_shaderType);
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ShaderProgram(true, info)
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Shader(qpType, m_source,
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   true, "[Shader created by glCreateShaderProgramv()]")
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::EndShaderProgram;
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ProgramParams
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ProgramParams
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams (deUint32 vtxSeed_, GLfloat vtxScale_, deUint32 frgSeed_, GLfloat frgScale_)
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: vtxSeed	(vtxSeed_)
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, vtxScale	(vtxScale_)
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, frgSeed	(frgSeed_)
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, frgScale	(frgScale_) {}
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32	vtxSeed;
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLfloat		vtxScale;
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32	frgSeed;
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLfloat		frgScale;
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramParams genProgramParams (Random& rnd)
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	vtxSeed		= rnd.getUint32();
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLfloat	vtxScale	= rnd.getInt(8, 16) / 16.0f;
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	frgSeed		= rnd.getUint32();
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLfloat	frgScale	= rnd.getInt(0, 16) / 16.0f;
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ProgramParams(vtxSeed, vtxScale, frgSeed, frgScale);
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TestParams
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct TestParams
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					initSingle;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					switchVtx;
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					switchFrg;
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useUniform;
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useSameName;
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useCreateHelper;
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useProgramUniform;
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VaryingParams			varyings;
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeUint32 paramsSeed (const TestParams& params)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6891bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	deUint32 paramCode	= (params.initSingle			<< 0 |
6901bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry						   params.switchVtx				<< 1 |
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.switchFrg				<< 2 |
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useUniform			<< 3 |
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useSameName			<< 4 |
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useCreateHelper		<< 5 |
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useProgramUniform		<< 6);
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.count;
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.type;
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.binding;
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.vtxInterp;
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.frgInterp;
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deUint32Hash(paramCode);
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring paramsCode (const TestParams& params)
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream oss;
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << (params.initSingle ? "1" : "2")
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.switchVtx ? "v" : "")
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.switchFrg ? "f" : "")
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useProgramUniform ? "p" : "")
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useUniform ? "u" : "")
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useSameName ? "s" : "")
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useCreateHelper ? "c" : "")
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << de::toString(params.varyings.count)
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << (params.varyings.binding == BINDING_NAME ? "n" :
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.binding == BINDING_LOCATION ? "l" :
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.binding == BINDING_LAST ? "r" :
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"")
7241bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		 << (params.varyings.vtxInterp == VARYINGINTERPOLATION_SMOOTH ? "m" :
7251bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			 params.varyings.vtxInterp == VARYINGINTERPOLATION_CENTROID ? "e" :
7261bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			 params.varyings.vtxInterp == VARYINGINTERPOLATION_FLAT ? "a" :
7271bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			 params.varyings.vtxInterp == VARYINGINTERPOLATION_RANDOM ? "r" :
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"o")
7291bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		 << (params.varyings.frgInterp == VARYINGINTERPOLATION_SMOOTH ? "m" :
7301bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			 params.varyings.frgInterp == VARYINGINTERPOLATION_CENTROID ? "e" :
7311bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			 params.varyings.frgInterp == VARYINGINTERPOLATION_FLAT ? "a" :
7321bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			 params.varyings.frgInterp == VARYINGINTERPOLATION_RANDOM ? "r" :
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"o");
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool paramsValid (const TestParams& params)
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Final pipeline has a single program?
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.initSingle)
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Cannot have conflicting names for uniforms or constants
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.useSameName)
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// CreateShaderProgram would never get called
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!params.switchVtx && !params.switchFrg && params.useCreateHelper)
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
7518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
7528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// Must switch either all or nothing
7538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (params.switchVtx != params.switchFrg)
7548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			return false;
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// ProgramUniform would never get called
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.useProgramUniform && !params.useUniform)
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Interpolation is meaningless if we don't use an in/out variable.
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.varyings.count == 0 &&
7631bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		!(params.varyings.vtxInterp == VARYINGINTERPOLATION_LAST &&
7641bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		  params.varyings.frgInterp == VARYINGINTERPOLATION_LAST))
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
767f6981ac458964bbfe296b497bff57c8fee8eb589Pyry Haulos	// Mismatch by flat / smooth is not allowed. See Khronos bug #12630
7681bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	// \note: iterpolations might be RANDOM, causing generated varyings potentially match / mismatch anyway.
7691bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	//        This is checked later on. Here, we just make sure that we don't force the generator to generate
7701bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	//        only invalid varying configurations, i.e. there exists a valid varying configuration for this
7711bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	//        test param config.
7721bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	if ((params.varyings.vtxInterp != VARYINGINTERPOLATION_RANDOM) &&
7731bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		(params.varyings.frgInterp != VARYINGINTERPOLATION_RANDOM) &&
7741bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		(params.varyings.vtxInterp == VARYINGINTERPOLATION_FLAT) != (params.varyings.frgInterp == VARYINGINTERPOLATION_FLAT))
775f6981ac458964bbfe296b497bff57c8fee8eb589Pyry Haulos		return false;
776f6981ac458964bbfe296b497bff57c8fee8eb589Pyry Haulos
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7801bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry// used only for debug sanity checks
7811bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry#if defined(DE_DEBUG)
7821bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyrybool varyingsValid (const VaryingInterface& varyings)
7831bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry{
7841bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	for (int ndx = 0; ndx < (int)varyings.vtxOutputs.size(); ++ndx)
7851bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	{
7861bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const VaryingInterpolation vertexInterpolation		= getVaryingInterpolation(varyings.vtxOutputs[ndx].interpolation);
7871bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const VaryingInterpolation fragmentInterpolation	= getVaryingInterpolation(varyings.frgInputs[ndx].interpolation);
7881bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
7891bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		if (!isSSOCompatibleInterpolation(vertexInterpolation, fragmentInterpolation))
7901bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			return false;
7911bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	}
7921bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
7931bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	return true;
7941bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry}
7951bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry#endif
7961bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid logParams (TestLog& log, const TestParams& params)
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// We don't log operational details here since those are shown
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// in the log messages during execution.
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MessageBuilder msg = log.message();
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << "Pipeline configuration:\n";
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << "Vertex and fragment shaders have "
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useUniform ? "uniform" : "constant") << "s with "
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useSameName ? "the same name" : "different names") << ".\n";
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.varyings.count == 0)
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "There are no varyings.\n";
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.count == 1)
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "There is one varying.\n";
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "There are " << params.varyings.count << " varyings.\n";
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.type == glu::TYPE_LAST)
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "Varyings are of random types.\n";
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "Varyings are of type '"
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::getDataTypeName(params.varyings.type) << "'.\n";
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "Varying outputs and inputs correspond ";
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.varyings.binding)
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_NAME:
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << "by name.\n";
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_LOCATION:
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << "by location.\n";
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_LAST:
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << "randomly either by name or by location.\n";
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "In the vertex shader the varyings are qualified ";
8411bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		if (params.varyings.vtxInterp == VARYINGINTERPOLATION_DEFAULT)
8421bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			msg << "with no interpolation qualifiers.\n";
8431bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		else if (params.varyings.vtxInterp == VARYINGINTERPOLATION_RANDOM)
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "with a random interpolation qualifier.\n";
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8461bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			msg << "'" << glu::getInterpolationName(getGluInterpolation(params.varyings.vtxInterp)) << "'.\n";
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "In the fragment shader the varyings are qualified ";
8491bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		if (params.varyings.frgInterp == VARYINGINTERPOLATION_DEFAULT)
8501bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			msg << "with no interpolation qualifiers.\n";
8511bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		else if (params.varyings.frgInterp == VARYINGINTERPOLATION_RANDOM)
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "with a random interpolation qualifier.\n";
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8541bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			msg << "'" << glu::getInterpolationName(getGluInterpolation(params.varyings.frgInterp)) << "'.\n";
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << TestLog::EndMessage;
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log.writeMessage("");
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestParams genParams (deUint32 seed)
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random		rnd		(seed);
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestParams	params;
8668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	int			tryNdx	= 0;
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	do
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.initSingle			= rnd.getBool();
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.switchVtx			= rnd.getBool();
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.switchFrg			= rnd.getBool();
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useUniform			= rnd.getBool();
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useProgramUniform	= params.useUniform && rnd.getBool();
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useCreateHelper		= rnd.getBool();
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useSameName			= rnd.getBool();
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int i = rnd.getInt(-1, 3);
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.count = (i == -1 ? 0 : 1 << i);
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.count > 0)
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.type		= glu::TYPE_LAST;
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.binding		= BINDING_LAST;
8851bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			params.varyings.vtxInterp	= VARYINGINTERPOLATION_RANDOM;
8861bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			params.varyings.frgInterp	= VARYINGINTERPOLATION_RANDOM;
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.type		= glu::TYPE_INVALID;
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.binding		= BINDING_LAST;
8921bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			params.varyings.vtxInterp	= VARYINGINTERPOLATION_LAST;
8931bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry			params.varyings.frgInterp	= VARYINGINTERPOLATION_LAST;
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
8968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tryNdx += 1;
8978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	} while (!paramsValid(params) && tryNdx < 16);
8988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
8998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(paramsValid(params));
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return params;
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Program pipeline wrapper that retains references to component programs.
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Pipeline
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								Pipeline			(MovePtr<ProgramPipeline>	pipeline_,
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 MovePtr<ProgramWrapper>	fullProg_,
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 MovePtr<ProgramWrapper>	vtxProg_,
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 MovePtr<ProgramWrapper>	frgProg_)
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									: pipeline	(pipeline_)
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									, fullProg	(fullProg_)
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									, vtxProg	(vtxProg_)
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									, frgProg	(frgProg_) {}
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&				getVertexProgram	(void) const
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return vtxProg ? *vtxProg : *fullProg;
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&				getFragmentProgram	(void) const
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return frgProg ? *frgProg : *fullProg;
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramPipeline>	pipeline;
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	fullProg;
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	vtxProg;
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	frgProg;
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid logPipeline(TestLog& log, const Pipeline& pipeline)
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&	vtxProg	= pipeline.getVertexProgram();
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&	frgProg	= pipeline.getFragmentProgram();
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log.writeMessage("// Failed program pipeline:");
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (&vtxProg == &frgProg)
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log.writeMessage("// Common program for both vertex and fragment stages:");
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg.writeToLog(log);
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log.writeMessage("// Vertex stage program:");
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg.writeToLog(log);
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log.writeMessage("// Fragment stage program:");
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frgProg.writeToLog(log);
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Rectangle
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Rectangle
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Rectangle	(int x_, int y_, int width_, int height_)
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				: x			(x_)
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				, y			(y_)
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				, width		(width_)
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				, height	(height_) {}
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	x;
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	y;
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	width;
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	height;
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid setViewport (const RenderContext& renderCtx, const Rectangle& rect)
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	renderCtx.getFunctions().viewport(rect.x, rect.y, rect.width, rect.height);
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid readRectangle (const RenderContext& renderCtx, const Rectangle& rect, Surface& dst)
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.setSize(rect.width, rect.height);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(renderCtx, rect.x, rect.y, dst.getAccess());
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9793c827367444ee418f129b2c238299f49d3264554Jarkko PoyryRectangle randomViewport (const RenderContext& ctx, Random& rnd,
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  GLint maxWidth, GLint maxHeight)
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderTarget&	target	= ctx.getRenderTarget();
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				width	= de::min(target.getWidth(), maxWidth);
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				xOff	= rnd.getInt(0, target.getWidth() - width);
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				height	= de::min(target.getHeight(), maxHeight);
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				yOff	= rnd.getInt(0, target.getHeight() - height);
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Rectangle(xOff, yOff, width, height);
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// SeparateShaderTest
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SeparateShaderTest : public TestCase, private CallLogWrapper
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	void			(SeparateShaderTest::*TestFunc)
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														(MovePtr<Pipeline>&		pipeOut);
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							SeparateShaderTest			(Context&				ctx,
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			name,
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			description,
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 int					iterations,
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const TestParams&		params,
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 TestFunc				testFunc);
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate						(void);
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testPipelineRendering		(MovePtr<Pipeline>&		pipeOut);
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testCurrentProgPriority		(MovePtr<Pipeline>&		pipeOut);
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testActiveProgramUniform	(MovePtr<Pipeline>&		pipeOut);
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testPipelineQueryActive		(MovePtr<Pipeline>&		pipeOut);
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testPipelineQueryPrograms	(MovePtr<Pipeline>&		pipeOut);
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log							(void);
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	getRenderContext			(void);
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					setUniform					(ProgramWrapper&		program,
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			uniformName,
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 GLfloat				value,
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 bool					useProgramUni);
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					drawSurface					(Surface&				dst,
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 deUint32				seed = 0);
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	createShaderProgram			(const string*			vtxSource,
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string*			frgSource,
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 bool					separable);
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	createSingleShaderProgram	(ShaderType			shaderType,
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			src);
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<Pipeline>		createPipeline				(const ProgramParams&	pp);
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	createReferenceProgram		(const ProgramParams&	pp);
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_iterations;
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_currentIteration;
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestParams				m_params;
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestFunc				m_testFunc;
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random					m_rnd;
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ResultCollector			m_status;
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VaryingInterface		m_varyings;
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Per-iteration state required for logging on exception
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	m_fullProg;
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	m_vtxProg;
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	m_frgProg;
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst RenderContext& SeparateShaderTest::getRenderContext (void)
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_context.getRenderContext();
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10573c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestLog& SeparateShaderTest::log (void)
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_testCtx.getLog();
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10623c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySeparateShaderTest::SeparateShaderTest (Context&			ctx,
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										const string&		name,
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										const string&		description,
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										int					iterations,
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										const TestParams&	params,
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										TestFunc			testFunc)
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(ctx, name.c_str(), description.c_str())
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, CallLogWrapper	(ctx.getRenderContext().getFunctions(), log())
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterations		(iterations)
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_currentIteration(0)
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_params			(params)
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_testFunc		(testFunc)
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rnd				(paramsSeed(params))
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_status			(log(), "// ")
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_varyings		(genVaryingInterface(params.varyings, m_rnd))
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(paramsValid(params));
10791bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	DE_ASSERT(varyingsValid(m_varyings));
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10823c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<ProgramWrapper> SeparateShaderTest::createShaderProgram (const string*	vtxSource,
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 const string*	frgSource,
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 bool			separable)
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramSources sources;
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (vtxSource != DE_NULL)
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << VertexSource(*vtxSource);
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (frgSource != DE_NULL)
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << FragmentSource(*frgSource);
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sources << ProgramSeparable(separable);
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ShaderProgramWrapper> wrapper (new ShaderProgramWrapper(getRenderContext(),
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	sources));
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!wrapper->getShaderProgram().isOk())
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log().writeMessage("Couldn't create shader program");
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wrapper->writeToLog(log());
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Couldn't create shader program");
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<ProgramWrapper>(wrapper.release());
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<ProgramWrapper> SeparateShaderTest::createSingleShaderProgram (ShaderType shaderType,
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	   const string& src)
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx	= getRenderContext();
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.useCreateHelper)
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	const	srcStr		= src.c_str();
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const GLenum		glType		= glu::getGLShaderType(shaderType);
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const GLuint		programName	= glCreateShaderProgramv(glType, 1, &srcStr);
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glGetError() != GL_NO_ERROR || programName == 0)
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpShaderType qpType = glu::getLogShaderType(shaderType);
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log() << TestLog::Message << "glCreateShaderProgramv() failed"
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::EndMessage
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::ShaderProgram(false, "[glCreateShaderProgramv() failed]")
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::Shader(qpType, src,
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 false, "[glCreateShaderProgramv() failed]")
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::EndShaderProgram;
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("glCreateShaderProgramv() failed");
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		RawProgramWrapper* const	wrapper	= new RawProgramWrapper(renderCtx, programName,
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	shaderType, src);
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MovePtr<ProgramWrapper>		wrapperPtr(wrapper);
11331bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		Program&					program = wrapper->getProgram();
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!program.getLinkStatus())
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log().writeMessage("glCreateShaderProgramv() failed at linking");
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wrapper->writeToLog(log());
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("glCreateShaderProgram() failed at linking");
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return wrapperPtr;
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (shaderType)
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::SHADERTYPE_VERTEX:
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return createShaderProgram(&src, DE_NULL, true);
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::SHADERTYPE_FRAGMENT:
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return createShaderProgram(DE_NULL, &src, true);
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible case");
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<ProgramWrapper>(); // Shut up compiler warnings.
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::setUniform (ProgramWrapper&	program,
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const string&		uniformName,
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 GLfloat			value,
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 bool				useProgramUniform)
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLuint		progName	= program.getProgramName();
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLint			location	= glGetUniformLocation(progName, uniformName.c_str());
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MessageBuilder		msg			= log().message();
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << "// Set program " << progName << "'s uniform '" << uniformName << "' to " << value;
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useProgramUniform)
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << " using glProgramUniform1f";
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glProgramUniform1f(progName, location, value);
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << " using glUseProgram and glUniform1f";
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(progName);
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUniform1f(location, value);
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(0);
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << TestLog::EndMessage;
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11831bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko PöyryMovePtr<Pipeline> SeparateShaderTest::createPipeline (const ProgramParams& pp)
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		useUniform	= m_params.useUniform;
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	vtxName		= m_params.useSameName ? "scale" : "vtxScale";
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	initVtxSeed	= m_params.switchVtx ? m_rnd.getUint32() : pp.vtxSeed;
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	frgName		= m_params.useSameName ? "scale" : "frgScale";
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	initFrgSeed	= m_params.switchFrg ? m_rnd.getUint32() : pp.frgSeed;
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	frgSource	= genFrgShaderSrc(initFrgSeed, m_varyings.frgInputs,
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  frgName, useUniform, pp.frgScale);
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&		renderCtx	= getRenderContext();
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramPipeline>	pipeline	(new ProgramPipeline(renderCtx));
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>		fullProg;
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>		vtxProg;
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>		frgProg;
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// We cannot allow a situation where we have a single program with a
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// single uniform, because then the vertex and fragment shader uniforms
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// would not be distinct in the final pipeline, and we are going to test
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// that altering one uniform will not affect the other.
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!(m_params.initSingle	&& m_params.useSameName &&
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				!m_params.switchVtx && !m_params.switchFrg));
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.initSingle)
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string vtxSource = genVtxShaderSrc(initVtxSeed,
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   varyingCompatVtxOutputs(m_varyings),
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   vtxName, useUniform, pp.vtxScale);
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fullProg = createShaderProgram(&vtxSource, &frgSource, true);
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT,
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   fullProg->getProgramName());
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Created pipeline " << pipeline->getPipeline()
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << " with two-shader program " << fullProg->getProgramName()
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string vtxSource = genVtxShaderSrc(initVtxSeed, m_varyings.vtxOutputs,
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   vtxName, useUniform, pp.vtxScale);
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg = createSingleShaderProgram(glu::SHADERTYPE_VERTEX, vtxSource);
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_VERTEX_SHADER_BIT, vtxProg->getProgramName());
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frgProg = createSingleShaderProgram(glu::SHADERTYPE_FRAGMENT, frgSource);
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_FRAGMENT_SHADER_BIT, frgProg->getProgramName());
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Created pipeline " << pipeline->getPipeline()
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << " with vertex program " << vtxProg->getProgramName()
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << " and fragment program " << frgProg->getProgramName()
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(pipeline->isValid(),
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Pipeline is invalid after initialization");
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.switchVtx)
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string newSource = genVtxShaderSrc(pp.vtxSeed, m_varyings.vtxOutputs,
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   vtxName, useUniform, pp.vtxScale);
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg = createSingleShaderProgram(glu::SHADERTYPE_VERTEX, newSource);
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_VERTEX_SHADER_BIT, vtxProg->getProgramName());
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Switched pipeline " << pipeline->getPipeline()
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "'s vertex stage to single-shader program " << vtxProg->getProgramName()
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.switchFrg)
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string newSource = genFrgShaderSrc(pp.frgSeed, m_varyings.frgInputs,
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   frgName, useUniform, pp.frgScale);
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frgProg = createSingleShaderProgram(glu::SHADERTYPE_FRAGMENT, newSource);
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_FRAGMENT_SHADER_BIT, frgProg->getProgramName());
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Switched pipeline " << pipeline->getPipeline()
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "'s fragment stage to single-shader program " << frgProg->getProgramName()
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.switchVtx || m_params.switchFrg)
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_status.check(pipeline->isValid(),
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   "Pipeline became invalid after changing a stage's program");
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.useUniform)
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramWrapper& vtxStage = *(vtxProg ? vtxProg : fullProg);
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramWrapper& frgStage = *(frgProg ? frgProg : fullProg);
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(vtxStage, vtxName, pp.vtxScale, m_params.useProgramUniform);
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(frgStage, frgName, pp.frgScale, m_params.useProgramUniform);
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log().writeMessage("// Programs use constants instead of uniforms");
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<Pipeline>(new Pipeline(pipeline, fullProg, vtxProg, frgProg));
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12811bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko PöyryMovePtr<ProgramWrapper> SeparateShaderTest::createReferenceProgram (const ProgramParams& pp)
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useUniform	= m_params.useUniform;
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string			vtxSrc		= genVtxShaderSrc(pp.vtxSeed,
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  varyingCompatVtxOutputs(m_varyings),
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  "vtxScale", useUniform, pp.vtxScale);
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string			frgSrc		= genFrgShaderSrc(pp.frgSeed, m_varyings.frgInputs,
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  "frgScale", useUniform, pp.frgScale);
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	program		= createShaderProgram(&vtxSrc, &frgSrc, false);
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint					progName	= program->getProgramName();
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << "// Created monolithic shader program " << progName
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << TestLog::EndMessage;
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useUniform)
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(*program, "vtxScale", pp.vtxScale, false);
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(*program, "frgScale", pp.frgScale, false);
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return program;
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::drawSurface (Surface& dst, deUint32 seed)
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx	= getRenderContext();
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random					rnd			(seed > 0 ? seed : m_rnd.getUint32());
13091bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	Rectangle				viewport	= randomViewport(renderCtx, rnd,
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 VIEWPORT_SIZE, VIEWPORT_SIZE);
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClearColor(0.125f, 0.25f, 0.5f, 1.f);
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(renderCtx, viewport);
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClear(GL_COLOR_BUFFER_BIT);
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 3));
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	readRectangle(renderCtx, viewport, dst);
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log().writeMessage("// Drew a triangle");
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testPipelineRendering (MovePtr<Pipeline>& pipeOut)
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pp			= genProgramParams(m_rnd);
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pp));
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	refProgram	(createReferenceProgram(pp));
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						refProgName	= refProgram->getProgramName();
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						refSurface;
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						pipelineSurface;
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						drawSeed	= m_rnd.getUint32();
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(refProgName);
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message << "// Use program " << refProgName << TestLog::EndMessage;
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(refSurface, drawSeed);
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(0);
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glBindProgramPipeline(pipeName);
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message << "// Bind pipeline " << pipeName << TestLog::EndMessage;
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(pipelineSurface, drawSeed);
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glBindProgramPipeline(0);
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool result = tcu::fuzzyCompare(
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog(), "Program pipeline result",
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Result of comparing a program pipeline with a monolithic program",
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			refSurface, pipelineSurface, 0.05f, tcu::COMPARE_LOG_RESULT);
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_status.check(result, "Pipeline rendering differs from equivalent monolithic program");
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testCurrentProgPriority (MovePtr<Pipeline>& pipeOut)
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pipePp		= genProgramParams(m_rnd);
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				programPp	= genProgramParams(m_rnd);
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pipePp));
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	program		(createReferenceProgram(programPp));
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						pipelineSurface;
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						refSurface;
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						resultSurface;
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					drawSeed	= m_rnd.getUint32();
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(pipeName));
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(pipelineSurface, drawSeed);
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(0));
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(program->getProgramName()));
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(refSurface, drawSeed);
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(0));
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(program->getProgramName()));
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(pipeName));
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(resultSurface, drawSeed);
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(0));
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(0));
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool result = tcu::pixelThresholdCompare(
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog(), "Active program rendering result",
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"Active program rendering result",
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		refSurface, resultSurface, tcu::RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(result, "glBindProgramPipeline() affects glUseProgram()");
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!result)
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Image("Pipeline image", "Image produced by pipeline",
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								pipelineSurface);
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testActiveProgramUniform (MovePtr<Pipeline>& pipeOut)
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				refPp			= genProgramParams(m_rnd);
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						refSurface;
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						resultSurface;
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					drawSeed		= m_rnd.getUint32();
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(pipeOut);
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UniquePtr<ProgramWrapper>	refProg		(createReferenceProgram(refPp));
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLuint						refProgName	= refProg->getProgramName();
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(refProgName);
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message << "// Use reference program " << refProgName
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawSurface(refSurface, drawSeed);
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(0);
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramParams				changePp	= genProgramParams(m_rnd);
14081bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		changePp.vtxSeed						= refPp.vtxSeed;
14091bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		changePp.frgSeed						= refPp.frgSeed;
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UniquePtr<ProgramWrapper>	changeProg	(createReferenceProgram(changePp));
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLuint						changeName	= changeProg->getProgramName();
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramPipeline				pipeline	(getRenderContext());
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLint						vtxLoc		= glGetUniformLocation(changeName, "vtxScale");
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLint						frgLoc		= glGetUniformLocation(changeName, "frgScale");
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glBindProgramPipeline(pipeline.getPipeline()));
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline.activeShaderProgram(changeName);
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message << "// Set active shader program to " << changeName
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUniform1f(vtxLoc, refPp.vtxScale);
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Set uniform 'vtxScale' to " << refPp.vtxScale << " using glUniform1f"
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUniform1f(frgLoc, refPp.frgScale);
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Set uniform 'frgScale' to " << refPp.frgScale << " using glUniform1f"
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline.activeShaderProgram(0);
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glBindProgramPipeline(0));
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glUseProgram(changeName));
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawSurface(resultSurface, drawSeed);
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glUseProgram(0));
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool result = tcu::fuzzyCompare(
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog(), "Active program uniform result",
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"Active program uniform result",
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		refSurface, resultSurface, 0.05f, tcu::COMPARE_LOG_RESULT);
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(result,
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "glUniform() did not correctly modify "
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "the active program of the bound pipeline");
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testPipelineQueryPrograms (MovePtr<Pipeline>& pipeOut)
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pipePp		= genProgramParams(m_rnd);
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pipePp));
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint						queryVtx	= 0;
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint						queryFrg	= 0;
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_VERTEX_SHADER, &queryVtx)));
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(GLuint(queryVtx) == pipeline.getVertexProgram().getProgramName(),
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported wrong vertex shader program");
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_FRAGMENT_SHADER, &queryFrg)));
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(GLuint(queryFrg) == pipeline.getFragmentProgram().getProgramName(),
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported wrong fragment shader program");
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testPipelineQueryActive (MovePtr<Pipeline>& pipeOut)
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pipePp		= genProgramParams(m_rnd);
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pipePp));
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						newActive	= pipeline.getVertexProgram().getProgramName();
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint						queryActive	= 0;
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_ACTIVE_PROGRAM, &queryActive)));
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(queryActive == 0,
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported non-zero initial active program");
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pipeline.pipeline->activeShaderProgram(newActive);
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << "Set pipeline " << pipeName << "'s active shader program to " << newActive
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << TestLog::EndMessage;
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_ACTIVE_PROGRAM, &queryActive)));
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(GLuint(queryActive) == newActive,
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported incorrect active program");
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pipeline.pipeline->activeShaderProgram(0);
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14903c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCase::IterateResult SeparateShaderTest::iterate (void)
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<Pipeline> pipeline;
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_iterations > 0);
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_currentIteration == 0)
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		logParams(log(), m_params);
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	++m_currentIteration;
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		(this->*m_testFunc)(pipeline);
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log().writeMessage("");
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const tcu::Exception&)
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pipeline)
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			logPipeline(log(), *pipeline);
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_status.getResult() != QP_TEST_RESULT_PASS)
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pipeline)
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			logPipeline(log(), *pipeline);
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_currentIteration < m_iterations)
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return CONTINUE;
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.setTestContextResult(m_testCtx);
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Group construction utilities
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum ParamFlags
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_SWITCH_FRAGMENT	= 1 << 0,
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_SWITCH_VERTEX	= 1 << 1,
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_INIT_SINGLE		= 1 << 2,
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_LAST				= 1 << 3,
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_MASK				= PARAMFLAGS_LAST - 1
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrybool areCaseParamFlagsValid (ParamFlags flags)
15378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
15388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const ParamFlags switchAll = ParamFlags(PARAMFLAGS_SWITCH_VERTEX|PARAMFLAGS_SWITCH_FRAGMENT);
15398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
15408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if ((flags & PARAMFLAGS_INIT_SINGLE) != 0)
15418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		return (flags & switchAll) == 0 ||
15428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			   (flags & switchAll) == switchAll;
15438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	else
15448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		return true;
15458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool addRenderTest (TestCaseGroup& group, const string& namePrefix, const string& descPrefix,
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int numIterations, ParamFlags flags, TestParams params)
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	name;
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	desc;
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(areCaseParamFlagsValid(flags));
15548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	name << namePrefix;
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	desc << descPrefix;
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.initSingle	= (flags & PARAMFLAGS_INIT_SINGLE) != 0;
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.switchVtx	= (flags & PARAMFLAGS_SWITCH_VERTEX) != 0;
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.switchFrg	= (flags & PARAMFLAGS_SWITCH_FRAGMENT) != 0;
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	name << (flags & PARAMFLAGS_INIT_SINGLE ? "single_program" : "separate_programs");
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	desc << (flags & PARAMFLAGS_INIT_SINGLE
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 ? "Single program with two shaders"
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 : "Separate programs for each shader");
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (flags & (PARAMFLAGS_SWITCH_FRAGMENT | PARAMFLAGS_SWITCH_VERTEX))
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 0:
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PARAMFLAGS_SWITCH_FRAGMENT:
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "_add_fragment";
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << ", then add a fragment program";
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PARAMFLAGS_SWITCH_VERTEX:
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "_add_vertex";
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << ", then add a vertex program";
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PARAMFLAGS_SWITCH_FRAGMENT | PARAMFLAGS_SWITCH_VERTEX:
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "_add_both";
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << ", then add both vertex and shader programs";
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!paramsValid(params))
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group.addChild(new SeparateShaderTest(group.getContext(), name.str(), desc.str(),
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  numIterations, params,
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  &SeparateShaderTest::testPipelineRendering));
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15951bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyryvoid describeInterpolation (const string& stage, VaryingInterpolation qual,
15961bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry							ostringstream& name, ostringstream& desc)
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15981bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	DE_ASSERT(qual < VARYINGINTERPOLATION_RANDOM);
15991bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry
16001bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	if (qual == VARYINGINTERPOLATION_DEFAULT)
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		desc << ", unqualified in " << stage << " shader";
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16071bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		const string qualName = glu::getInterpolationName(getGluInterpolation(qual));
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		name << "_" << stage << "_" << qualName;
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		desc << ", qualified '" << qualName << "' in " << stage << " shader";
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16151bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry} // anonymous
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16173c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCaseGroup* createSeparateShaderTests (Context& ctx)
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestParams		defaultParams;
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numIterations	= 4;
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup*	group			=
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "separate_shader", "Separate shader tests");
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useUniform			= false;
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.initSingle			= false;
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.switchVtx				= false;
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.switchFrg				= false;
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useCreateHelper		= false;
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useProgramUniform		= false;
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useSameName			= false;
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.count		= 0;
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.type			= glu::TYPE_INVALID;
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.binding		= BINDING_NAME;
16341bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	defaultParams.varyings.vtxInterp	= VARYINGINTERPOLATION_LAST;
16351bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry	defaultParams.varyings.frgInterp	= VARYINGINTERPOLATION_LAST;
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* stagesGroup =
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "pipeline", "Pipeline configuration tests");
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(stagesGroup);
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < PARAMFLAGS_LAST << 2; ++flags)
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params			= defaultParams;
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream	name;
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream	desc;
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (!areCaseParamFlagsValid(ParamFlags(flags & PARAMFLAGS_MASK)))
16488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			continue;
16498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (flags & (PARAMFLAGS_LAST << 1))
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.useSameName = true;
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "same_";
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "Identically named ";
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "different_";
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "Differently named ";
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (flags & PARAMFLAGS_LAST)
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.useUniform = true;
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "uniform_";
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "uniforms, ";
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "constant_";
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "constants, ";
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addRenderTest(*stagesGroup, name.str(), desc.str(), numIterations,
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  ParamFlags(flags & PARAMFLAGS_MASK), params);
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* programUniformGroup =
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "program_uniform", "ProgramUniform tests");
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(programUniformGroup);
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < PARAMFLAGS_LAST; ++flags)
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params			= defaultParams;
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (!areCaseParamFlagsValid(ParamFlags(flags)))
16878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			continue;
16888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useUniform = true;
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useProgramUniform = true;
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addRenderTest(*programUniformGroup, "", "", numIterations, ParamFlags(flags), params);
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* createShaderProgramGroup =
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "create_shader_program", "CreateShaderProgram tests");
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(createShaderProgramGroup);
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < PARAMFLAGS_LAST; ++flags)
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params			= defaultParams;
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (!areCaseParamFlagsValid(ParamFlags(flags)))
17048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			continue;
17058852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useCreateHelper = true;
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addRenderTest(*createShaderProgramGroup, "", "", numIterations,
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  ParamFlags(flags), params);
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* interfaceGroup =
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "interface", "Shader interface compatibility tests");
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(interfaceGroup);
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17181bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		NUM_INTERPOLATIONS	= VARYINGINTERPOLATION_RANDOM, // VARYINGINTERPOLATION_RANDOM is one after last fully specified interpolation
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		INTERFACEFLAGS_LAST = BINDING_LAST * NUM_INTERPOLATIONS * NUM_INTERPOLATIONS
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < INTERFACEFLAGS_LAST; ++flags)
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17241bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		deUint32				tmpFlags	= flags;
17251bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		VaryingInterpolation	frgInterp	= VaryingInterpolation(tmpFlags % NUM_INTERPOLATIONS);
17261bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		VaryingInterpolation	vtxInterp	= VaryingInterpolation((tmpFlags /= NUM_INTERPOLATIONS)
17271bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry																   % NUM_INTERPOLATIONS);
17281bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		BindingKind				binding		= BindingKind((tmpFlags /= NUM_INTERPOLATIONS)
17291bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry														  % BINDING_LAST);
17301bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		TestParams				params		= defaultParams;
17311bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		ostringstream			name;
17321bfa102df7c2678fa4ac421fa29780848c2c12f3Jarkko Pöyry		ostringstream			desc;
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.count		= 1;
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.type		= glu::TYPE_FLOAT;
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.binding		= binding;
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.vtxInterp	= vtxInterp;
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.frgInterp	= frgInterp;
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (binding)
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_LOCATION:
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << "same_location";
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				desc << "Varyings have same location, ";
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_NAME:
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << "same_name";
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				desc << "Varyings have same name, ";
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		describeInterpolation("vertex", vtxInterp, name, desc);
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		describeInterpolation("fragment", frgInterp, name, desc);
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!paramsValid(params))
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		interfaceGroup->addChild(
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			new SeparateShaderTest(ctx, name.str(), desc.str(), numIterations, params,
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   &SeparateShaderTest::testPipelineRendering));
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32		baseSeed	= ctx.getTestContext().getCommandLine().getBaseSeed();
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random			rnd			(deStringHash("separate_shader.random") + baseSeed);
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	set<string>		seen;
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup*	randomGroup	= new TestCaseGroup(
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ctx, "random", "Random pipeline configuration tests");
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(randomGroup);
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 i = 0; i < 128; ++i)
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params;
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string			code;
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		genIterations	= 4096;
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		do
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params	= genParams(rnd.getUint32());
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code	= paramsCode(params);
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} while (de::contains(seen, code) && --genIterations > 0);
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		seen.insert(code);
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string name = de::toString(i); // Would be code but baseSeed can change
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		randomGroup->addChild(new SeparateShaderTest(
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx, name, name, numIterations, params,
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  &SeparateShaderTest::testPipelineRendering));
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* apiGroup =
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "api", "Program pipeline API tests");
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(apiGroup);
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// More or less random parameters. These shouldn't have much effect, so just
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// do a single sample.
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams params = defaultParams;
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useUniform = true;
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx,
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "current_program_priority",
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "Test priority between current program and pipeline binding",
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  1, params, &SeparateShaderTest::testCurrentProgPriority));
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx,
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "active_program_uniform",
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "Test that glUniform() affects a pipeline's active program",
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  1, params, &SeparateShaderTest::testActiveProgramUniform));
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 ctx,
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "pipeline_programs",
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "Test queries for programs in program pipeline stages",
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 1, params, &SeparateShaderTest::testPipelineQueryPrograms));
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 ctx,
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "pipeline_active",
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "Test query for active programs in a program pipeline",
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 1, params, &SeparateShaderTest::testPipelineQueryActive));
18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* interfaceMismatchGroup =
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "validation", "Negative program pipeline interface matching");
18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(interfaceMismatchGroup);
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gls::ShaderLibrary					shaderLibrary	(ctx.getTestContext(), ctx.getRenderContext(), ctx.getContextInfo());
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::vector<tcu::TestNode*>	children		= shaderLibrary.loadShaderFile("shaders/separate_shader_validation.test");
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < (int)children.size(); i++)
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			interfaceMismatchGroup->addChild(children[i]);
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return group;
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1844