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