es31fSeparateShaderTests.cpp revision 3c827367444ee418f129b2c238299f49d3264554
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Tests for separate shader objects
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fSeparateShaderTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSTLUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuCommandLine.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRGBA.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuStringTemplate.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluCallLogWrapper.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarType.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderLibrary.hpp"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwDefs.hpp"
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cstdarg>
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set>
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::set;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::ostringstream;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::MovePtr;
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::Random;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::UniquePtr;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::MessageBuilder;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::RenderTarget;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::StringTemplate;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Surface;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::ResultCollector;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::CallLogWrapper;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::DataType;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::VariableDeclaration;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::Interpolation;
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
1103c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDataType randomType (Random& rnd)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (rnd.getInt(0, 7) == 0)
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numCols = rnd.getInt(2, 4), numRows = rnd.getInt(2, 4);
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getDataTypeMatrix(numCols, numRows);
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const DataType	s_types[]	= { TYPE_FLOAT,	TYPE_INT,	TYPE_UINT	};
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const float		s_weights[] = { 3.0,		1.0,		1.0			};
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				size		= rnd.getInt(1, 4);
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const DataType			scalarType	= rnd.chooseWeighted<DataType>(
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ARRAY_BEGIN(s_types), DE_ARRAY_END(s_types), DE_ARRAY_BEGIN(s_weights));
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getDataTypeVector(scalarType, size);
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!"Impossible");
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return TYPE_INVALID;
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterpolation randomInterpolation (Random& rnd)
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Interpolation(rnd.getInt(0, glu::INTERPOLATION_LAST - 1));
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum BindingKind
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BINDING_NAME,
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BINDING_LOCATION,
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BINDING_LAST
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBindingKind randomBinding (Random& rnd)
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return rnd.getBool() ? BINDING_LOCATION : BINDING_NAME;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printInputColor (ostringstream& oss, const VariableDeclaration& input)
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DataType	basicType	= input.varType.getBasicType();
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			exp			= input.name;
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (getDataTypeScalarType(basicType))
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TYPE_FLOAT:
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TYPE_INT:
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TYPE_UINT:
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DataType floatType = getDataTypeFloatScalars(basicType);
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			exp = string() + "(" + getDataTypeName(floatType) + "(" + exp + ") / 255.0" + ")";
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!"Impossible");
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isDataTypeScalarOrVector(basicType))
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (getDataTypeScalarSize(basicType))
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 1:
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << "hsv(vec3(" << exp << ", 1.0, 1.0))";
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 2:
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << "hsv(vec3(" << exp << ", 1.0))";
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 3:
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << "vec4(" << exp << ", 1.0)";
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 4:
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << exp;
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isDataTypeMatrix(basicType))
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	rows	= getDataTypeMatrixNumRows(basicType);
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	columns	= getDataTypeMatrixNumColumns(basicType);
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (rows == columns)
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << "hsv(vec3(determinant(" << exp << ")))";
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (rows != 3 && columns >= 3)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				exp = "transpose(" + exp + ")";
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::swap(rows, columns);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			exp = exp + "[0]";
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (rows > 3)
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				exp = exp + ".xyz";
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << "hsv(" << exp << ")";
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!"Impossible");
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Representation for the varyings between vertex and fragment shaders
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VaryingParams
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VaryingParams 			(void)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: count				(0)
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, type				(glu::TYPE_LAST)
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, binding			(BINDING_LAST)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, vtxInterp			(glu::INTERPOLATION_LAST)
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, frgInterp			(glu::INTERPOLATION_LAST) {}
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						count;
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DataType				type;
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BindingKind				binding;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interpolation			vtxInterp;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interpolation			frgInterp;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VaryingInterface
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<VariableDeclaration>	vtxOutputs;
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<VariableDeclaration>	frgInputs;
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Generate corresponding input and output variable declarations that may vary
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// in compatible ways.
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterpolation chooseInterpolation (Interpolation param, DataType type, Random& rnd)
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (glu::getDataTypeScalarType(type) != glu::TYPE_FLOAT)
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return glu::INTERPOLATION_FLAT;
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (param == glu::INTERPOLATION_LAST)
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return randomInterpolation(rnd);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return param;
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2573c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVaryingInterface genVaryingInterface (const VaryingParams&		params,
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  Random&					rnd)
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace	glu;
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VaryingInterface	ret;
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					offset = 0;
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < params.count; ++varNdx)
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BindingKind	binding			= ((params.binding == BINDING_LAST)
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   ? randomBinding(rnd) : params.binding);
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const DataType		type			= ((params.type == TYPE_LAST)
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   ? randomType(rnd) : params.type);
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Interpolation	vtxInterp		= chooseInterpolation(params.vtxInterp, type, rnd);
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Interpolation	frgInterp		= chooseInterpolation(params.frgInterp, type, rnd);
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			loc				= ((binding == BINDING_LOCATION) ? offset : -1);
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string		ndxStr			= de::toString(varNdx);
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string		vtxName			= ((binding == BINDING_NAME)
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   ? "var" + ndxStr : "vtxVar" + ndxStr);
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string		frgName			= ((binding == BINDING_NAME)
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   ? "var" + ndxStr : "frgVar" + ndxStr);
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const VarType		varType			(type, PRECISION_HIGHP);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		offset += getDataTypeNumLocations(type);
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Over 16 locations aren't necessarily supported, so halt here.
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (offset > 16)
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.vtxOutputs.push_back(
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			VariableDeclaration(varType, vtxName, STORAGE_OUT, vtxInterp, loc));
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.frgInputs.push_back(
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			VariableDeclaration(varType, frgName, STORAGE_IN, frgInterp, loc));
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Create vertex output variable declarations that are maximally compatible
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// with the fragment input variables.
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<VariableDeclaration> varyingCompatVtxOutputs (const VaryingInterface& varyings)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<VariableDeclaration> outputs = varyings.vtxOutputs;
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t i = 0; i < outputs.size(); ++i)
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outputs[i].interpolation = varyings.frgInputs[i].interpolation;
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outputs[i].name = varyings.frgInputs[i].name;
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return outputs;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Shader source generation
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printFloat (ostringstream& oss, double d)
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.setf(oss.fixed | oss.internal);
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.precision(4);
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.width(7);
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << d;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printFloatDeclaration (ostringstream&	oss,
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const string&	varName,
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							bool			uniform,
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							GLfloat			value		= 0.0)
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType	varType	(TYPE_FLOAT, PRECISION_HIGHP);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (uniform)
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << VariableDeclaration(varType, varName, STORAGE_UNIFORM) << ";\n";
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << VariableDeclaration(varType, varName, STORAGE_CONST)
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< " = " << de::floatToString(value, 6) << ";\n";
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printRandomInitializer (ostringstream& oss, DataType type, Random& rnd)
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		size	= getDataTypeScalarSize(type);
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (size > 0)
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << getDataTypeName(type) << "(";
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < size; ++i)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << (i == 0 ? "" : ", ");
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (getDataTypeScalarType(type))
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT:
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				printFloat(oss, rnd.getInt(0, 16) / 16.0);
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_INT:
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_UINT:
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << rnd.getInt(0, 255);
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_BOOL:
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				oss << (rnd.getBool() ? "true" : "false");
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (size > 0)
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << ")";
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring genVtxShaderSrc (deUint32							seed,
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const vector<VariableDeclaration>&	outputs,
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const string&						varName,
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						bool								uniform,
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						float								value = 0.0)
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		oss;
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random				rnd								(seed);
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum { 				NUM_COMPONENTS 					= 2 };
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int	s_quadrants[][NUM_COMPONENTS]	= { {1, 1}, {-1, 1}, {1, -1} };
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "#version 310 es\n";
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "const vec2 triangle[3] = vec2[3](\n";
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int vertexNdx = 0; vertexNdx < DE_LENGTH_OF_ARRAY(s_quadrants); ++vertexNdx)
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\tvec2(";
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int componentNdx = 0; componentNdx < NUM_COMPONENTS; ++componentNdx)
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printFloat(oss, s_quadrants[vertexNdx][componentNdx] * rnd.getInt(4,16) / 16.0);
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << (componentNdx < 1 ? ", " : "");
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << ")" << (vertexNdx < 2 ? "," : "") << "\n";
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << ");\n";
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<VariableDeclaration>::const_iterator it = outputs.begin();
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 it != outputs.end(); ++it)
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const DataType	type		= it->varType.getBasicType();
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	typeName	= glu::getDataTypeName(type);
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "const " << typeName << " " << it->name << "Inits[3] = "
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< typeName << "[3](\n";
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 3; ++i)
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << (i == 0 ? "\t" : ",\n\t");
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printRandomInitializer(oss, type, rnd);
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << ");\n"
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< *it << ";\n";
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	printFloatDeclaration(oss, varName, uniform, value);
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "void main (void)\n"
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tgl_Position = vec4(" << varName << " * triangle[gl_VertexID], 0.0, 1.0);\n";
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<VariableDeclaration>::const_iterator it = outputs.begin();
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 it != outputs.end(); ++it)
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t" << it->name << " = " << it->name << "Inits[gl_VertexID];\n";
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "}\n";
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring genFrgShaderSrc (deUint32							seed,
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const vector<VariableDeclaration>&	inputs,
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const string&						varName,
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						bool								uniform,
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						float								value = 0.0)
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random				rnd		(seed);
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		oss;
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.precision(4);
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss.width(7);
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "#version 310 es\n";
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "precision highp float;\n";;
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "out vec4 fragColor;\n";;
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	printFloatDeclaration(oss, varName, uniform, value);
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<VariableDeclaration>::const_iterator it = inputs.begin();
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 it != inputs.end(); ++it)
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << *it << ";\n";
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// glsl % isn't defined for negative numbers
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "int imod (int n, int d)" << "\n"
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{" << "\n"
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\t" << "return (n < 0 ? d - 1 - (-1 - n) % d : n % d);" << "\n"
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}" << "\n";
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "vec4 hsv (vec3 hsv)"
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{" << "\n"
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat h = hsv.x * 3.0;\n"
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat r = max(0.0, 1.0 - h) + max(0.0, h - 2.0);\n"
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat g = max(0.0, 1.0 - abs(h - 1.0));\n"
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tfloat b = max(0.0, 1.0 - abs(h - 2.0));\n"
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tvec3 hs = mix(vec3(1.0), vec3(r, g, b), hsv.y);\n"
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\treturn vec4(hsv.z * hs, 1.0);\n"
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "void main (void)\n"
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n";
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "\t" << "fragColor = vec4(vec3(" << varName << "), 1.0);" << "\n";
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (inputs.size() > 0)
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t" << "switch (imod(int(0.5 * (gl_FragCoord.x - gl_FragCoord.y)), "
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< inputs.size() << "))" << "\n"
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t" << "{" << "\n";
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t i = 0; i < inputs.size(); ++i)
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << "\t\t" << "case " << i << ":" << "\n"
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "\t\t\t" << "fragColor *= ";
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printInputColor(oss, inputs[i]);
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oss << ";" << "\n"
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "\t\t\t" << "break;" << "\n";
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t" << "case " << inputs.size() << ":\n"
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t\t\t" << "fragColor = vec4(1.0, 0.0, 1.0, 1.0);" << "\n";
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t\t" << "break;" << "\n";
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t" << "case -1:\n"
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t\t\t" << "fragColor = vec4(1.0, 1.0, 0.0, 1.0);" << "\n";
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t\t" << "break;" << "\n";
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t\t" << "default:" << "\n"
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\t\t\t" << "fragColor = vec4(1.0, 1.0, 0.0, 1.0);" << "\n";
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		oss << "\t" << "}\n";
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << "}\n";
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ProgramWrapper
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ProgramWrapper
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual 		~ProgramWrapper			(void) {}
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual GLuint	getProgramName			(void) = 0;
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	writeToLog				(TestLog& log) = 0;
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderProgramWrapper : public ProgramWrapper
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ShaderProgramWrapper	(const RenderContext&	renderCtx,
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const ProgramSources&	sources)
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: m_shaderProgram	(renderCtx, sources) {}
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~ShaderProgramWrapper	(void) {}
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint			getProgramName			(void) { return m_shaderProgram.getProgram(); }
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderProgram&	getShaderProgram		(void) { return m_shaderProgram; }
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			writeToLog				(TestLog& log) { log << m_shaderProgram; }
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderProgram	m_shaderProgram;
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RawProgramWrapper : public ProgramWrapper
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					RawProgramWrapper		(const RenderContext&	renderCtx,
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 GLuint					programName,
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 ShaderType				shaderType,
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const string&			source)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: m_program			(renderCtx, programName)
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_shaderType		(shaderType)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_source			(source) {}
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~RawProgramWrapper		(void) {}
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint			getProgramName			(void) { return m_program.getProgram(); }
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Program&		getProgram				(void) { return m_program; }
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			writeToLog				(TestLog& log);
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Program			m_program;
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderType		m_shaderType;
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	m_source;
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid RawProgramWrapper::writeToLog (TestLog& log)
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	info	= m_program.getInfoLog();
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpShaderType	qpType	= glu::getLogShaderType(m_shaderType);
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ShaderProgram(true, info)
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Shader(qpType, m_source,
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   true, "[Shader created by glCreateShaderProgramv()]")
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::EndShaderProgram;
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ProgramParams
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ProgramParams
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams (deUint32 vtxSeed_, GLfloat vtxScale_, deUint32 frgSeed_, GLfloat frgScale_)
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: vtxSeed	(vtxSeed_)
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, vtxScale	(vtxScale_)
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, frgSeed	(frgSeed_)
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, frgScale	(frgScale_) {}
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32	vtxSeed;
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLfloat		vtxScale;
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32	frgSeed;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLfloat		frgScale;
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5913c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramParams genProgramParams (Random& rnd)
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	vtxSeed		= rnd.getUint32();
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLfloat	vtxScale	= rnd.getInt(8, 16) / 16.0f;
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	frgSeed		= rnd.getUint32();
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLfloat	frgScale	= rnd.getInt(0, 16) / 16.0f;
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ProgramParams(vtxSeed, vtxScale, frgSeed, frgScale);
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TestParams
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct TestParams
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					initSingle;
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					switchVtx;
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					switchFrg;
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useUniform;
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useSameName;
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useCreateHelper;
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useProgramUniform;
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VaryingParams			varyings;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6153c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeUint32 paramsSeed (const TestParams& params)
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 paramCode 	= (params.initSingle	 		<< 0 |
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.switchVtx 			<< 1 |
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.switchFrg				<< 2 |
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useUniform			<< 3 |
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useSameName			<< 4 |
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useCreateHelper		<< 5 |
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   params.useProgramUniform		<< 6);
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.count;
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.type;
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.binding;
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.vtxInterp;
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	paramCode = deUint32Hash(paramCode) + params.varyings.frgInterp;
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deUint32Hash(paramCode);
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring paramsCode (const TestParams& params)
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream oss;
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	oss << (params.initSingle ? "1" : "2")
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.switchVtx ? "v" : "")
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.switchFrg ? "f" : "")
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useProgramUniform ? "p" : "")
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useUniform ? "u" : "")
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useSameName ? "s" : "")
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useCreateHelper ? "c" : "")
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << de::toString(params.varyings.count)
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << (params.varyings.binding == BINDING_NAME ? "n" :
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.binding == BINDING_LOCATION ? "l" :
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.binding == BINDING_LAST ? "r" :
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"")
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << (params.varyings.vtxInterp == INTERPOLATION_SMOOTH ? "m" :
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.vtxInterp == INTERPOLATION_CENTROID ? "e" :
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.vtxInterp == INTERPOLATION_FLAT ? "a" :
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.vtxInterp == INTERPOLATION_LAST ? "r" :
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"o")
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << (params.varyings.frgInterp == INTERPOLATION_SMOOTH ? "m" :
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.frgInterp == INTERPOLATION_CENTROID ? "e" :
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.frgInterp == INTERPOLATION_FLAT ? "a" :
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 params.varyings.frgInterp == INTERPOLATION_LAST ? "r" :
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"o");
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool paramsValid (const TestParams& params)
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace glu;
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Final pipeline has a single program?
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.initSingle)
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Cannot have conflicting names for uniforms or constants
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.useSameName)
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// CreateShaderProgram would never get called
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!params.switchVtx && !params.switchFrg && params.useCreateHelper)
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// ProgramUniform would never get called
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.useProgramUniform && !params.useUniform)
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Interpolation is meaningless if we don't use an in/out variable.
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.varyings.count == 0 &&
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!(params.varyings.vtxInterp == INTERPOLATION_LAST &&
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  params.varyings.frgInterp == INTERPOLATION_LAST))
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid logParams (TestLog& log, const TestParams& params)
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// We don't log operational details here since those are shown
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// in the log messages during execution.
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MessageBuilder msg = log.message();
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << "Pipeline configuration:\n";
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << "Vertex and fragment shaders have "
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useUniform ? "uniform" : "constant") << "s with "
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< (params.useSameName ? "the same name" : "different names") << ".\n";
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.varyings.count == 0)
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "There are no varyings.\n";
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.count == 1)
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "There is one varying.\n";
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "There are " << params.varyings.count << " varyings.\n";
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.type == glu::TYPE_LAST)
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "Varyings are of random types.\n";
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "Varyings are of type '"
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::getDataTypeName(params.varyings.type) << "'.\n";
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "Varying outputs and inputs correspond ";
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.varyings.binding)
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_NAME:
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << "by name.\n";
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_LOCATION:
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << "by location.\n";
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_LAST:
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << "randomly either by name or by location.\n";
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "In the vertex shader the varyings are qualified ";
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.vtxInterp == glu::INTERPOLATION_LAST)
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "with a random interpolation qualifier.\n";
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "'" << glu::getInterpolationName(params.varyings.vtxInterp) << "'.\n";
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << "In the fragment shader the varyings are qualified ";
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.frgInterp == glu::INTERPOLATION_LAST)
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "with a random interpolation qualifier.\n";
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			msg << "'" << glu::getInterpolationName(params.varyings.frgInterp) << "'.\n";
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << TestLog::EndMessage;
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log.writeMessage("");
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestParams genParams (deUint32 seed)
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random		rnd		(seed);
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestParams	params;
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	do
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.initSingle			= rnd.getBool();
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.switchVtx			= rnd.getBool();
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.switchFrg			= rnd.getBool();
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useUniform			= rnd.getBool();
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useProgramUniform	= params.useUniform && rnd.getBool();
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useCreateHelper		= rnd.getBool();
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useSameName			= rnd.getBool();
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int i = rnd.getInt(-1, 3);
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.count = (i == -1 ? 0 : 1 << i);
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (params.varyings.count > 0)
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.type		= glu::TYPE_LAST;
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.binding		= BINDING_LAST;
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.vtxInterp	= glu::INTERPOLATION_LAST;
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.frgInterp	= glu::INTERPOLATION_LAST;
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.type		= glu::TYPE_INVALID;
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.binding		= BINDING_LAST;
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.vtxInterp	= glu::INTERPOLATION_LAST;
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.varyings.frgInterp	= glu::INTERPOLATION_LAST;
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} while (!paramsValid(params));
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return params;
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Program pipeline wrapper that retains references to component programs.
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Pipeline
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								Pipeline			(MovePtr<ProgramPipeline>	pipeline_,
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 MovePtr<ProgramWrapper>	fullProg_,
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 MovePtr<ProgramWrapper>	vtxProg_,
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 MovePtr<ProgramWrapper>	frgProg_)
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									: pipeline	(pipeline_)
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									, fullProg	(fullProg_)
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									, vtxProg	(vtxProg_)
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									, frgProg	(frgProg_) {}
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&				getVertexProgram	(void) const
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return vtxProg ? *vtxProg : *fullProg;
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&				getFragmentProgram	(void) const
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return frgProg ? *frgProg : *fullProg;
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramPipeline>	pipeline;
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	fullProg;
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	vtxProg;
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	frgProg;
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid logPipeline(TestLog& log, const Pipeline& pipeline)
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&	vtxProg	= pipeline.getVertexProgram();
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramWrapper&	frgProg	= pipeline.getFragmentProgram();
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log.writeMessage("// Failed program pipeline:");
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (&vtxProg == &frgProg)
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log.writeMessage("// Common program for both vertex and fragment stages:");
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg.writeToLog(log);
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log.writeMessage("// Vertex stage program:");
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg.writeToLog(log);
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log.writeMessage("// Fragment stage program:");
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frgProg.writeToLog(log);
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Rectangle
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Rectangle
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Rectangle	(int x_, int y_, int width_, int height_)
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				: x			(x_)
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				, y			(y_)
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				, width		(width_)
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				, height	(height_) {}
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	x;
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	y;
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	width;
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	height;
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid setViewport (const RenderContext& renderCtx, const Rectangle& rect)
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	renderCtx.getFunctions().viewport(rect.x, rect.y, rect.width, rect.height);
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid readRectangle (const RenderContext& renderCtx, const Rectangle& rect, Surface& dst)
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.setSize(rect.width, rect.height);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(renderCtx, rect.x, rect.y, dst.getAccess());
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryRectangle randomViewport (const RenderContext& ctx, Random& rnd,
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  GLint maxWidth, GLint maxHeight)
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderTarget&	target	= ctx.getRenderTarget();
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				width	= de::min(target.getWidth(), maxWidth);
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				xOff	= rnd.getInt(0, target.getWidth() - width);
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				height	= de::min(target.getHeight(), maxHeight);
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint				yOff	= rnd.getInt(0, target.getHeight() - height);
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Rectangle(xOff, yOff, width, height);
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// SeparateShaderTest
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SeparateShaderTest : public TestCase, private CallLogWrapper
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	void			(SeparateShaderTest::*TestFunc)
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														(MovePtr<Pipeline>&		pipeOut);
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							SeparateShaderTest			(Context&				ctx,
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			name,
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			description,
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 int					iterations,
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const TestParams&		params,
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 TestFunc				testFunc);
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate						(void);
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testPipelineRendering		(MovePtr<Pipeline>&		pipeOut);
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testCurrentProgPriority		(MovePtr<Pipeline>&		pipeOut);
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testActiveProgramUniform	(MovePtr<Pipeline>&		pipeOut);
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testPipelineQueryActive		(MovePtr<Pipeline>&		pipeOut);
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					testPipelineQueryPrograms	(MovePtr<Pipeline>&		pipeOut);
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log							(void);
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	getRenderContext			(void);
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					setUniform					(ProgramWrapper&		program,
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			uniformName,
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 GLfloat				value,
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 bool					useProgramUni);
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					drawSurface					(Surface&				dst,
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 deUint32				seed = 0);
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	createShaderProgram			(const string*			vtxSource,
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string*			frgSource,
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 bool					separable);
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	createSingleShaderProgram	(ShaderType			shaderType,
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 const string&			src);
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<Pipeline>		createPipeline				(const ProgramParams&	pp);
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	createReferenceProgram		(const ProgramParams&	pp);
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_iterations;
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_currentIteration;
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestParams				m_params;
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestFunc				m_testFunc;
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random					m_rnd;
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ResultCollector			m_status;
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VaryingInterface		m_varyings;
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Per-iteration state required for logging on exception
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	m_fullProg;
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	m_vtxProg;
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	m_frgProg;
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst RenderContext& SeparateShaderTest::getRenderContext (void)
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_context.getRenderContext();
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestLog& SeparateShaderTest::log (void)
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_testCtx.getLog();
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9503c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySeparateShaderTest::SeparateShaderTest (Context&			ctx,
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										const string&		name,
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										const string&		description,
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										int					iterations,
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										const TestParams&	params,
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										TestFunc			testFunc)
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(ctx, name.c_str(), description.c_str())
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, CallLogWrapper	(ctx.getRenderContext().getFunctions(), log())
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterations		(iterations)
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_currentIteration(0)
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_params			(params)
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_testFunc		(testFunc)
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_rnd				(paramsSeed(params))
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_status			(log(), "// ")
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_varyings		(genVaryingInterface(params.varyings, m_rnd))
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9683c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<ProgramWrapper> SeparateShaderTest::createShaderProgram (const string*	vtxSource,
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 const string*	frgSource,
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 bool			separable)
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramSources sources;
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (vtxSource != DE_NULL)
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << VertexSource(*vtxSource);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (frgSource != DE_NULL)
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << FragmentSource(*frgSource);
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sources << ProgramSeparable(separable);
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ShaderProgramWrapper> wrapper (new ShaderProgramWrapper(getRenderContext(),
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	sources));
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!wrapper->getShaderProgram().isOk())
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log().writeMessage("Couldn't create shader program");
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wrapper->writeToLog(log());
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Couldn't create shader program");
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<ProgramWrapper>(wrapper.release());
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<ProgramWrapper> SeparateShaderTest::createSingleShaderProgram (ShaderType shaderType,
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	   const string& src)
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx	= getRenderContext();
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.useCreateHelper)
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	const	srcStr		= src.c_str();
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const GLenum		glType		= glu::getGLShaderType(shaderType);
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const GLuint		programName	= glCreateShaderProgramv(glType, 1, &srcStr);
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glGetError() != GL_NO_ERROR || programName == 0)
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpShaderType qpType = glu::getLogShaderType(shaderType);
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log() << TestLog::Message << "glCreateShaderProgramv() failed"
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::EndMessage
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::ShaderProgram(false, "[glCreateShaderProgramv() failed]")
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::Shader(qpType, src,
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 false, "[glCreateShaderProgramv() failed]")
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::EndShaderProgram;
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("glCreateShaderProgramv() failed");
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		RawProgramWrapper* const	wrapper	= new RawProgramWrapper(renderCtx, programName,
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	shaderType, src);
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MovePtr<ProgramWrapper>		wrapperPtr(wrapper);
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Program& 					program = wrapper->getProgram();
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!program.getLinkStatus())
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log().writeMessage("glCreateShaderProgramv() failed at linking");
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wrapper->writeToLog(log());
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("glCreateShaderProgram() failed at linking");
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return wrapperPtr;
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (shaderType)
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::SHADERTYPE_VERTEX:
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return createShaderProgram(&src, DE_NULL, true);
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::SHADERTYPE_FRAGMENT:
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return createShaderProgram(DE_NULL, &src, true);
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible case");
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<ProgramWrapper>(); // Shut up compiler warnings.
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::setUniform (ProgramWrapper&	program,
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const string&		uniformName,
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 GLfloat			value,
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 bool				useProgramUniform)
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLuint		progName	= program.getProgramName();
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GLint			location	= glGetUniformLocation(progName, uniformName.c_str());
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MessageBuilder		msg			= log().message();
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << "// Set program " << progName << "'s uniform '" << uniformName << "' to " << value;
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useProgramUniform)
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << " using glProgramUniform1f";
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glProgramUniform1f(progName, location, value);
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		msg << " using glUseProgram and glUniform1f";
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(progName);
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUniform1f(location, value);
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(0);
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	msg << TestLog::EndMessage;
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10693c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<Pipeline> SeparateShaderTest::createPipeline(const ProgramParams& pp)
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		useUniform	= m_params.useUniform;
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	vtxName		= m_params.useSameName ? "scale" : "vtxScale";
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	initVtxSeed	= m_params.switchVtx ? m_rnd.getUint32() : pp.vtxSeed;
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	frgName		= m_params.useSameName ? "scale" : "frgScale";
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	initFrgSeed	= m_params.switchFrg ? m_rnd.getUint32() : pp.frgSeed;
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	frgSource	= genFrgShaderSrc(initFrgSeed, m_varyings.frgInputs,
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  frgName, useUniform, pp.frgScale);
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&		renderCtx	= getRenderContext();
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramPipeline>	pipeline	(new ProgramPipeline(renderCtx));
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>		fullProg;
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>		vtxProg;
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>		frgProg;
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// We cannot allow a situation where we have a single program with a
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// single uniform, because then the vertex and fragment shader uniforms
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// would not be distinct in the final pipeline, and we are going to test
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// that altering one uniform will not affect the other.
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!(m_params.initSingle	&& m_params.useSameName &&
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				!m_params.switchVtx && !m_params.switchFrg));
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.initSingle)
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string vtxSource = genVtxShaderSrc(initVtxSeed,
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   varyingCompatVtxOutputs(m_varyings),
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   vtxName, useUniform, pp.vtxScale);
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fullProg = createShaderProgram(&vtxSource, &frgSource, true);
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT,
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   fullProg->getProgramName());
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Created pipeline " << pipeline->getPipeline()
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << " with two-shader program " << fullProg->getProgramName()
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string vtxSource = genVtxShaderSrc(initVtxSeed, m_varyings.vtxOutputs,
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   vtxName, useUniform, pp.vtxScale);
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg = createSingleShaderProgram(glu::SHADERTYPE_VERTEX, vtxSource);
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_VERTEX_SHADER_BIT, vtxProg->getProgramName());
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frgProg = createSingleShaderProgram(glu::SHADERTYPE_FRAGMENT, frgSource);
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_FRAGMENT_SHADER_BIT, frgProg->getProgramName());
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Created pipeline " << pipeline->getPipeline()
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << " with vertex program " << vtxProg->getProgramName()
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << " and fragment program " << frgProg->getProgramName()
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(pipeline->isValid(),
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Pipeline is invalid after initialization");
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.switchVtx)
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string newSource = genVtxShaderSrc(pp.vtxSeed, m_varyings.vtxOutputs,
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   vtxName, useUniform, pp.vtxScale);
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtxProg = createSingleShaderProgram(glu::SHADERTYPE_VERTEX, newSource);
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_VERTEX_SHADER_BIT, vtxProg->getProgramName());
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Switched pipeline " << pipeline->getPipeline()
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "'s vertex stage to single-shader program " << vtxProg->getProgramName()
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.switchFrg)
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string newSource = genFrgShaderSrc(pp.frgSeed, m_varyings.frgInputs,
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   frgName, useUniform, pp.frgScale);
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frgProg = createSingleShaderProgram(glu::SHADERTYPE_FRAGMENT, newSource);
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline->useProgramStages(GL_FRAGMENT_SHADER_BIT, frgProg->getProgramName());
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Switched pipeline " << pipeline->getPipeline()
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "'s fragment stage to single-shader program " << frgProg->getProgramName()
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.switchVtx || m_params.switchFrg)
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_status.check(pipeline->isValid(),
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   "Pipeline became invalid after changing a stage's program");
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_params.useUniform)
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramWrapper& vtxStage = *(vtxProg ? vtxProg : fullProg);
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramWrapper& frgStage = *(frgProg ? frgProg : fullProg);
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(vtxStage, vtxName, pp.vtxScale, m_params.useProgramUniform);
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(frgStage, frgName, pp.frgScale, m_params.useProgramUniform);
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log().writeMessage("// Programs use constants instead of uniforms");
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<Pipeline>(new Pipeline(pipeline, fullProg, vtxProg, frgProg));
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<ProgramWrapper> SeparateShaderTest::createReferenceProgram(const ProgramParams& pp)
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useUniform	= m_params.useUniform;
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string			vtxSrc		= genVtxShaderSrc(pp.vtxSeed,
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  varyingCompatVtxOutputs(m_varyings),
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  "vtxScale", useUniform, pp.vtxScale);
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string			frgSrc		= genFrgShaderSrc(pp.frgSeed, m_varyings.frgInputs,
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  "frgScale", useUniform, pp.frgScale);
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ProgramWrapper>	program		= createShaderProgram(&vtxSrc, &frgSrc, false);
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint					progName	= program->getProgramName();
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << "// Created monolithic shader program " << progName
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << TestLog::EndMessage;
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useUniform)
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(*program, "vtxScale", pp.vtxScale, false);
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setUniform(*program, "frgScale", pp.frgScale, false);
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return program;
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::drawSurface (Surface& dst, deUint32 seed)
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx	= getRenderContext();
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random					rnd			(seed > 0 ? seed : m_rnd.getUint32());
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Rectangle				viewport 	= randomViewport(renderCtx, rnd,
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 VIEWPORT_SIZE, VIEWPORT_SIZE);
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClearColor(0.125f, 0.25f, 0.5f, 1.f);
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(renderCtx, viewport);
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClear(GL_COLOR_BUFFER_BIT);
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 3));
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	readRectangle(renderCtx, viewport, dst);
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log().writeMessage("// Drew a triangle");
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testPipelineRendering (MovePtr<Pipeline>& pipeOut)
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pp			= genProgramParams(m_rnd);
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pp));
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	refProgram	(createReferenceProgram(pp));
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						refProgName	= refProgram->getProgramName();
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						refSurface;
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						pipelineSurface;
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						drawSeed	= m_rnd.getUint32();
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(refProgName);
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message << "// Use program " << refProgName << TestLog::EndMessage;
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(refSurface, drawSeed);
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(0);
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glBindProgramPipeline(pipeName);
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message << "// Bind pipeline " << pipeName << TestLog::EndMessage;
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(pipelineSurface, drawSeed);
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glBindProgramPipeline(0);
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool result = tcu::fuzzyCompare(
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog(), "Program pipeline result",
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Result of comparing a program pipeline with a monolithic program",
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			refSurface, pipelineSurface, 0.05f, tcu::COMPARE_LOG_RESULT);
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_status.check(result, "Pipeline rendering differs from equivalent monolithic program");
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testCurrentProgPriority (MovePtr<Pipeline>& pipeOut)
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pipePp		= genProgramParams(m_rnd);
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				programPp	= genProgramParams(m_rnd);
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pipePp));
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UniquePtr<ProgramWrapper>	program		(createReferenceProgram(programPp));
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						pipelineSurface;
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						refSurface;
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						resultSurface;
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					drawSeed	= m_rnd.getUint32();
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(pipeName));
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(pipelineSurface, drawSeed);
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(0));
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(program->getProgramName()));
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(refSurface, drawSeed);
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(0));
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(program->getProgramName()));
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(pipeName));
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawSurface(resultSurface, drawSeed);
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glBindProgramPipeline(0));
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(glUseProgram(0));
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool result = tcu::pixelThresholdCompare(
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog(), "Active program rendering result",
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"Active program rendering result",
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		refSurface, resultSurface, tcu::RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(result, "glBindProgramPipeline() affects glUseProgram()");
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!result)
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Image("Pipeline image", "Image produced by pipeline",
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								pipelineSurface);
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testActiveProgramUniform (MovePtr<Pipeline>& pipeOut)
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				refPp			= genProgramParams(m_rnd);
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						refSurface;
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Surface						resultSurface;
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					drawSeed		= m_rnd.getUint32();
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(pipeOut);
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UniquePtr<ProgramWrapper>	refProg		(createReferenceProgram(refPp));
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLuint						refProgName	= refProg->getProgramName();
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(refProgName);
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message << "// Use reference program " << refProgName
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawSurface(refSurface, drawSeed);
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUseProgram(0);
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramParams				changePp	= genProgramParams(m_rnd);
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		changePp.vtxSeed 						= refPp.vtxSeed;
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		changePp.frgSeed 						= refPp.frgSeed;
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UniquePtr<ProgramWrapper>	changeProg	(createReferenceProgram(changePp));
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLuint						changeName	= changeProg->getProgramName();
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramPipeline				pipeline	(getRenderContext());
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLint						vtxLoc		= glGetUniformLocation(changeName, "vtxScale");
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLint						frgLoc		= glGetUniformLocation(changeName, "frgScale");
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glBindProgramPipeline(pipeline.getPipeline()));
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline.activeShaderProgram(changeName);
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message << "// Set active shader program to " << changeName
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUniform1f(vtxLoc, refPp.vtxScale);
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Set uniform 'vtxScale' to " << refPp.vtxScale << " using glUniform1f"
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glUniform1f(frgLoc, refPp.frgScale);
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << "// Set uniform 'frgScale' to " << refPp.frgScale << " using glUniform1f"
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipeline.activeShaderProgram(0);
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glBindProgramPipeline(0));
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glUseProgram(changeName));
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawSurface(resultSurface, drawSeed);
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOG_CALL(glUseProgram(0));
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool result = tcu::fuzzyCompare(
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog(), "Active program uniform result",
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"Active program uniform result",
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		refSurface, resultSurface, 0.05f, tcu::COMPARE_LOG_RESULT);
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(result,
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "glUniform() did not correctly modify "
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "the active program of the bound pipeline");
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testPipelineQueryPrograms (MovePtr<Pipeline>& pipeOut)
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pipePp		= genProgramParams(m_rnd);
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pipePp));
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint						queryVtx	= 0;
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint						queryFrg	= 0;
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_VERTEX_SHADER, &queryVtx)));
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(GLuint(queryVtx) == pipeline.getVertexProgram().getProgramName(),
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported wrong vertex shader program");
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_FRAGMENT_SHADER, &queryFrg)));
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(GLuint(queryFrg) == pipeline.getFragmentProgram().getProgramName(),
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported wrong fragment shader program");
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SeparateShaderTest::testPipelineQueryActive (MovePtr<Pipeline>& pipeOut)
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramParams				pipePp		= genProgramParams(m_rnd);
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pipeline&					pipeline	= *(pipeOut = createPipeline(pipePp));
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						pipeName	= pipeline.pipeline->getPipeline();
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLuint						newActive	= pipeline.getVertexProgram().getProgramName();
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLint						queryActive	= 0;
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_ACTIVE_PROGRAM, &queryActive)));
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(queryActive == 0,
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported non-zero initial active program");
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pipeline.pipeline->activeShaderProgram(newActive);
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << "Set pipeline " << pipeName << "'s active shader program to " << newActive
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  << TestLog::EndMessage;
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_ACTIVE_PROGRAM, &queryActive)));
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.check(GLuint(queryActive) == newActive,
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Program pipeline query reported incorrect active program");
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pipeline.pipeline->activeShaderProgram(0);
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13763c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCase::IterateResult SeparateShaderTest::iterate (void)
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<Pipeline> pipeline;
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_iterations > 0);
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_currentIteration == 0)
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		logParams(log(), m_params);
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	++m_currentIteration;
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		(this->*m_testFunc)(pipeline);
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log().writeMessage("");
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const tcu::Exception&)
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pipeline)
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			logPipeline(log(), *pipeline);
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_status.getResult() != QP_TEST_RESULT_PASS)
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pipeline)
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			logPipeline(log(), *pipeline);
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_currentIteration < m_iterations)
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return CONTINUE;
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.setTestContextResult(m_testCtx);
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Group construction utilities
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum ParamFlags
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_SWITCH_FRAGMENT	= 1 << 0,
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_SWITCH_VERTEX	= 1 << 1,
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_INIT_SINGLE		= 1 << 2,
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_LAST				= 1 << 3,
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PARAMFLAGS_MASK				= PARAMFLAGS_LAST - 1
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool addRenderTest (TestCaseGroup& group, const string& namePrefix, const string& descPrefix,
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int numIterations, ParamFlags flags, TestParams params)
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	name;
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	desc;
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	name << namePrefix;
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	desc << descPrefix;
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.initSingle	= (flags & PARAMFLAGS_INIT_SINGLE) != 0;
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.switchVtx	= (flags & PARAMFLAGS_SWITCH_VERTEX) != 0;
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.switchFrg	= (flags & PARAMFLAGS_SWITCH_FRAGMENT) != 0;
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	name << (flags & PARAMFLAGS_INIT_SINGLE ? "single_program" : "separate_programs");
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	desc << (flags & PARAMFLAGS_INIT_SINGLE
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 ? "Single program with two shaders"
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 : "Separate programs for each shader");
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (flags & (PARAMFLAGS_SWITCH_FRAGMENT | PARAMFLAGS_SWITCH_VERTEX))
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 0:
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PARAMFLAGS_SWITCH_FRAGMENT:
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "_add_fragment";
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << ", then add a fragment program";
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PARAMFLAGS_SWITCH_VERTEX:
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "_add_vertex";
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << ", then add a vertex program";
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PARAMFLAGS_SWITCH_FRAGMENT | PARAMFLAGS_SWITCH_VERTEX:
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "_add_both";
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << ", then add both vertex and shader programs";
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!paramsValid(params))
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group.addChild(new SeparateShaderTest(group.getContext(), name.str(), desc.str(),
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  numIterations, params,
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  &SeparateShaderTest::testPipelineRendering));
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid describeInterpolation(const string& stage, Interpolation qual,
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   ostringstream& name, ostringstream& desc)
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (qual == glu::INTERPOLATION_LAST)
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		desc << ", unqualified in " << stage << " shader";
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string qualName = glu::getInterpolationName(qual);
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		name << "_" << stage << "_" << qualName;
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		desc << ", qualified '" << qualName << "' in " << stage << " shader";
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous namespace
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14893c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCaseGroup* createSeparateShaderTests (Context& ctx)
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestParams		defaultParams;
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numIterations	= 4;
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup*	group			=
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "separate_shader", "Separate shader tests");
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useUniform			= false;
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.initSingle			= false;
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.switchVtx				= false;
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.switchFrg				= false;
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useCreateHelper		= false;
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useProgramUniform		= false;
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.useSameName			= false;
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.count		= 0;
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.type			= glu::TYPE_INVALID;
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.binding		= BINDING_NAME;
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.vtxInterp	= glu::INTERPOLATION_LAST;
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	defaultParams.varyings.frgInterp	= glu::INTERPOLATION_LAST;
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* stagesGroup =
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "pipeline", "Pipeline configuration tests");
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(stagesGroup);
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < PARAMFLAGS_LAST << 2; ++flags)
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params			= defaultParams;
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream	name;
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream	desc;
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (flags & (PARAMFLAGS_LAST << 1))
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.useSameName = true;
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "same_";
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "Identically named ";
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "different_";
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "Differently named ";
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (flags & PARAMFLAGS_LAST)
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.useUniform = true;
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "uniform_";
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "uniforms, ";
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "constant_";
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			desc << "constants, ";
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addRenderTest(*stagesGroup, name.str(), desc.str(), numIterations,
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  ParamFlags(flags & PARAMFLAGS_MASK), params);
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* programUniformGroup =
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "program_uniform", "ProgramUniform tests");
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(programUniformGroup);
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < PARAMFLAGS_LAST; ++flags)
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params			= defaultParams;
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useUniform = true;
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useProgramUniform = true;
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addRenderTest(*programUniformGroup, "", "", numIterations, ParamFlags(flags), params);
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* createShaderProgramGroup =
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "create_shader_program", "CreateShaderProgram tests");
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(createShaderProgramGroup);
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < PARAMFLAGS_LAST; ++flags)
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params			= defaultParams;
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useCreateHelper = true;
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addRenderTest(*createShaderProgramGroup, "", "", numIterations,
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  ParamFlags(flags), params);
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* interfaceGroup =
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "interface", "Shader interface compatibility tests");
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(interfaceGroup);
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		NUM_INTERPOLATIONS	= glu::INTERPOLATION_LAST + 1, // INTERPOLATION_LAST is valid
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		INTERFACEFLAGS_LAST = BINDING_LAST * NUM_INTERPOLATIONS * NUM_INTERPOLATIONS
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 flags = 0; flags < INTERFACEFLAGS_LAST; ++flags)
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		tmpFlags	= flags;
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interpolation	frgInterp	= Interpolation(tmpFlags % NUM_INTERPOLATIONS);
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interpolation	vtxInterp	= Interpolation((tmpFlags /= NUM_INTERPOLATIONS)
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													% NUM_INTERPOLATIONS);
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BindingKind		binding		= BindingKind((tmpFlags /= NUM_INTERPOLATIONS)
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  % BINDING_LAST);
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params		= defaultParams;
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream	name;
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream	desc;
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.count		= 1;
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.type		= glu::TYPE_FLOAT;
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.binding		= binding;
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.vtxInterp	= vtxInterp;
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.varyings.frgInterp	= frgInterp;
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (binding)
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_LOCATION:
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << "same_location";
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				desc << "Varyings have same location, ";
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case BINDING_NAME:
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << "same_name";
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				desc << "Varyings have same name, ";
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"Impossible");
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		describeInterpolation("vertex", vtxInterp, name, desc);
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		describeInterpolation("fragment", frgInterp, name, desc);
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!paramsValid(params))
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		interfaceGroup->addChild(
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			new SeparateShaderTest(ctx, name.str(), desc.str(), numIterations, params,
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   &SeparateShaderTest::testPipelineRendering));
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32		baseSeed	= ctx.getTestContext().getCommandLine().getBaseSeed();
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random			rnd			(deStringHash("separate_shader.random") + baseSeed);
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	set<string>		seen;
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup*	randomGroup	= new TestCaseGroup(
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ctx, "random", "Random pipeline configuration tests");
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(randomGroup);
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (deUint32 i = 0; i < 128; ++i)
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams		params;
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string			code;
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		genIterations	= 4096;
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		do
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params	= genParams(rnd.getUint32());
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code	= paramsCode(params);
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} while (de::contains(seen, code) && --genIterations > 0);
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		seen.insert(code);
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string name = de::toString(i); // Would be code but baseSeed can change
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		randomGroup->addChild(new SeparateShaderTest(
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx, name, name, numIterations, params,
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  &SeparateShaderTest::testPipelineRendering));
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* apiGroup =
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "api", "Program pipeline API tests");
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(apiGroup);
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// More or less random parameters. These shouldn't have much effect, so just
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// do a single sample.
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestParams params = defaultParams;
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.useUniform = true;
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx,
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "current_program_priority",
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "Test priority between current program and pipeline binding",
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  1, params, &SeparateShaderTest::testCurrentProgPriority));
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx,
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "active_program_uniform",
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  "Test that glUniform() affects a pipeline's active program",
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  1, params, &SeparateShaderTest::testActiveProgramUniform));
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 ctx,
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "pipeline_programs",
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "Test queries for programs in program pipeline stages",
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 1, params, &SeparateShaderTest::testPipelineQueryPrograms));
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		apiGroup->addChild(new SeparateShaderTest(
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 ctx,
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "pipeline_active",
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 "Test query for active programs in a program pipeline",
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 1, params, &SeparateShaderTest::testPipelineQueryActive));
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* interfaceMismatchGroup =
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new TestCaseGroup(ctx, "validation", "Negative program pipeline interface matching");
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group->addChild(interfaceMismatchGroup);
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gls::ShaderLibrary					shaderLibrary	(ctx.getTestContext(), ctx.getRenderContext(), ctx.getContextInfo());
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::vector<tcu::TestNode*>	children		= shaderLibrary.loadShaderFile("shaders/separate_shader_validation.test");
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < (int)children.size(); i++)
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			interfaceMismatchGroup->addChild(children[i]);
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return group;
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1707