13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Transform feedback tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fTransformFeedbackTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarType.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarTypeUtil.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set>
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::set;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::set;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace TransformFeedback
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VIEWPORT_WIDTH			= 128,
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VIEWPORT_HEIGHT			= 128,
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BUFFER_GUARD_MULTIPLIER = 2		//!< stride*BUFFER_GUARD_MULTIPLIER bytes are added to the end of tf buffer and used to check for overruns.
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum Interpolation
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INTERPOLATION_SMOOTH = 0,
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INTERPOLATION_FLAT,
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INTERPOLATION_CENTROID,
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INTERPOLATION_LAST
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getInterpolationName (Interpolation interp)
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (interp)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INTERPOLATION_SMOOTH:		return "smooth";
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INTERPOLATION_FLAT:		return "flat";
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INTERPOLATION_CENTROID:	return "centroid";
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Varying
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						Varying				(const char* name_, const glu::VarType& type_, Interpolation interp_)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							: name			(name_)
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							, type			(type_)
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							, interpolation	(interp_)
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			name;				//!< Variable name.
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::VarType		type;				//!< Variable type.
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interpolation		interpolation;		//!< Interpolation mode (smooth, flat, centroid).
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VaryingNameEquals
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					VaryingNameEquals	(const std::string& name_) : name(name_) {}
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			operator()			(const Varying& var) const { return var.name == name; }
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		name;
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Attribute
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Attribute (const std::string& name_, const glu::VarType& type_, int offset_)
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: name		(name_)
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, type		(type_)
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, offset	(offset_)
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			name;
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::VarType		type;
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					offset;
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct AttributeNameEquals
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					AttributeNameEquals	(const std::string& name_) : name(name_) {}
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			operator()			(const Attribute& attr) const { return attr.name == name; }
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		name;
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Output
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Output (void)
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: bufferNdx	(0)
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, offset	(0)
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string					name;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::VarType				type;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							bufferNdx;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							offset;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<const Attribute*>	inputs;
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct DrawCall
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DrawCall (int numElements_, bool tfEnabled_)
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					: numElements				(numElements_)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					, transformFeedbackEnabled	(tfEnabled_)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DrawCall (void)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					: numElements				(0)
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					, transformFeedbackEnabled	(false)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numElements;
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		transformFeedbackEnabled;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const DrawCall& call)
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << "(" << call.numElements << ", " << (call.transformFeedbackEnabled ? "resumed" : "paused") << ")";
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ProgramSpec
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									ProgramSpec						(void);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									~ProgramSpec					(void);
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::StructType*				createStruct					(const char* name);
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							addVarying						(const char* name, const glu::VarType& type, Interpolation interp);
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							addTransformFeedbackVarying		(const char* name);
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<glu::StructType*>&	getStructs						(void) const { return m_structs;	}
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<Varying>&			getVaryings						(void) const { return m_varyings;	}
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<string>&			getTransformFeedbackVaryings	(void) const { return m_transformFeedbackVaryings; }
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							isPointSizeUsed					(void) const;
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									ProgramSpec						(const ProgramSpec& other);
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramSpec&					operator=						(const ProgramSpec& other);
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<glu::StructType*>		m_structs;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Varying>					m_varyings;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<string>					m_transformFeedbackVaryings;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ProgramSpec
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramSpec::ProgramSpec (void)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2083c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramSpec::~ProgramSpec (void)
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<glu::StructType*>::iterator i = m_structs.begin(); i != m_structs.end(); i++)
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::StructType* ProgramSpec::createStruct (const char* name)
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_structs.reserve(m_structs.size()+1);
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_structs.push_back(new glu::StructType(name));
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_structs.back();
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ProgramSpec::addVarying (const char* name, const glu::VarType& type, Interpolation interp)
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_varyings.push_back(Varying(name, type, interp));
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ProgramSpec::addTransformFeedbackVarying (const char* name)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_transformFeedbackVaryings.push_back(name);
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ProgramSpec::isPointSizeUsed (void) const
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return std::find(m_transformFeedbackVaryings.begin(), m_transformFeedbackVaryings.end(), "gl_PointSize") != m_transformFeedbackVaryings.end();
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isProgramSupported (const glw::Functions& gl, const ProgramSpec& spec, deUint32 tfMode)
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		maxVertexAttribs			= 0;
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		maxTfInterleavedComponents	= 0;
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		maxTfSeparateAttribs		= 0;
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		maxTfSeparateComponents		= 0;
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS,								&maxVertexAttribs);
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,	&maxTfInterleavedComponents);
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,			&maxTfSeparateAttribs);
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,		&maxTfSeparateComponents);
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check vertex attribs.
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int totalVertexAttribs	= 1 /* a_position */ + (spec.isPointSizeUsed() ? 1 : 0);
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&var->type); vecIter != glu::VectorTypeIterator::end(&var->type); vecIter++)
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			totalVertexAttribs += 1;
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (totalVertexAttribs > maxVertexAttribs)
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false; // Vertex attribute count exceeded.
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check varyings.
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int totalTfComponents	= 0;
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int totalTfAttribs		= 0;
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<string>::const_iterator iter = spec.getTransformFeedbackVaryings().begin(); iter != spec.getTransformFeedbackVaryings().end(); iter++)
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string&	name			= *iter;
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				numComponents	= 0;
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (name == "gl_Position")
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numComponents = 4;
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (name == "gl_PointSize")
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numComponents = 1;
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string						varName		= glu::parseVariableName(name.c_str());
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Varying&				varying		= *std::find_if(spec.getVaryings().begin(), spec.getVaryings().end(), VaryingNameEquals(varName));
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TypeComponentVector	varPath;
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::parseTypePath(name.c_str(), varying.type, varPath);
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numComponents = glu::getVarType(varying.type, varPath).getScalarSize();
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (tfMode == GL_SEPARATE_ATTRIBS && numComponents > maxTfSeparateComponents)
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false; // Per-attribute component count exceeded.
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalTfComponents	+= numComponents;
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalTfAttribs		+= 1;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tfMode == GL_SEPARATE_ATTRIBS && totalTfAttribs > maxTfSeparateAttribs)
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tfMode == GL_INTERLEAVED_ATTRIBS && totalTfComponents > maxTfInterleavedComponents)
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Program
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string getAttributeName (const char* varyingName, const glu::TypeComponentVector& path)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream str;
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	str << "a_" << (deStringBeginsWith(varyingName, "v_") ? varyingName+2 : varyingName);
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (glu::TypeComponentVector::const_iterator iter = path.begin(); iter != path.end(); iter++)
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char* prefix = DE_NULL;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (iter->type)
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::VarTypeComponent::STRUCT_MEMBER:		prefix = "_m";	break;
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::VarTypeComponent::ARRAY_ELEMENT:		prefix = "_e";	break;
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::VarTypeComponent::MATRIX_COLUMN:		prefix = "_c";	break;
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::VarTypeComponent::VECTOR_COMPONENT:	prefix = "_s";	break;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << prefix << iter->index;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str.str();
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void genShaderSources (const ProgramSpec& spec, std::string& vertSource, std::string& fragSource, bool pointSizeRequired)
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	vtx;
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	frag;
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				addPointSize	= spec.isPointSizeUsed();
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "#version 300 es\n"
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in highp vec4 a_position;\n";
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "#version 300 es\n"
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << "layout(location = 0) out mediump vec4 o_color;\n"
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << "uniform highp vec4 u_scale;\n"
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << "uniform highp vec4 u_bias;\n";
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (addPointSize)
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "in highp float a_pointSize;\n";
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Declare attributes.
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*			name	= var->name.c_str();
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VarType&	type	= var->type;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&type); vecIter != glu::VectorTypeIterator::end(&type); vecIter++)
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::VarType	attribType	= glu::getVarType(type, vecIter.getPath());
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string			attribName	= getAttributeName(name, vecIter.getPath());
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vtx << "in " << glu::declare(attribType, attribName.c_str()) << ";\n";
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Declare vayrings.
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < 2; ndx++)
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*			inout	= ndx ? "in" : "out";
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::ostringstream&	str		= ndx ? frag : vtx;
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Declare structs that have type name.
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<glu::StructType*>::const_iterator structIter = spec.getStructs().begin(); structIter != spec.getStructs().end(); structIter++)
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::StructType* structPtr = *structIter;
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (structPtr->hasTypeName())
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				str << glu::declare(structPtr) << ";\n";
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			str << getInterpolationName(var->interpolation) << " " << inout << " " << glu::declare(var->type, var->name.c_str()) << ";\n";
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "\nvoid main (void)\n{\n"
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\tgl_Position = a_position;\n";
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\nvoid main (void)\n{\n"
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 << "\thighp vec4 res = vec4(0.0);\n";
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (addPointSize)
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "\tgl_PointSize = a_pointSize;\n";
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (pointSizeRequired)
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "\tgl_PointSize = 1.0;\n";
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Generate assignments / usage.
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*			name	= var->name.c_str();
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VarType&	type	= var->type;
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&type); vecIter != glu::VectorTypeIterator::end(&type); vecIter++)
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::VarType	subType		= glu::getVarType(type, vecIter.getPath());
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string			attribName	= getAttributeName(name, vecIter.getPath());
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(subType.isBasicType() && glu::isDataTypeScalarOrVector(subType.getBasicType()));
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Vertex: assign from attribute.
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vtx << "\t" << name << vecIter << " = " << attribName << ";\n";
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Fragment: add to res variable.
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int scalarSize = glu::getDataTypeScalarSize(subType.getBasicType());
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			frag << "\tres += ";
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (scalarSize == 1)		frag << "vec4(" << name << vecIter << ")";
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (scalarSize == 2)	frag << "vec2(" << name << vecIter << ").xxyy";
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (scalarSize == 3)	frag << "vec3(" << name << vecIter << ").xyzx";
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (scalarSize == 4)	frag << "vec4(" << name << vecIter << ")";
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			frag << ";\n";
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\to_color = res * u_scale + u_bias;\n";
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "}\n";
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "}\n";
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertSource = vtx.str();
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragSource = frag.str();
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::ShaderProgram* createVertexCaptureProgram (const glu::RenderContext& context, const ProgramSpec& spec, deUint32 bufferMode, deUint32 primitiveType)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string vertSource, fragSource;
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genShaderSources(spec, vertSource, fragSource, primitiveType == GL_POINTS /* Is point size required? */);
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(context, glu::ProgramSources()
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << glu::VertexSource(vertSource)
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << glu::FragmentSource(fragSource)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << glu::TransformFeedbackVaryings<vector<string>::const_iterator>(spec.getTransformFeedbackVaryings().begin(), spec.getTransformFeedbackVaryings().end())
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << glu::TransformFeedbackMode(bufferMode));
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Helpers.
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void computeInputLayout (vector<Attribute>& attributes, int& inputStride, const vector<Varying>& varyings, bool usePointSize)
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	inputStride = 0;
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Add position.
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	attributes.push_back(Attribute("a_position", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), inputStride));
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	inputStride += 4*sizeof(deUint32);
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (usePointSize)
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attributes.push_back(Attribute("a_pointSize", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), inputStride));
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		inputStride += 1*sizeof(deUint32);
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute attribute vector.
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Varying>::const_iterator var = varyings.begin(); var != varyings.end(); var++)
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&var->type); vecIter != glu::VectorTypeIterator::end(&var->type); vecIter++)
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::VarType	type	= vecIter.getType();
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string			name	= getAttributeName(var->name.c_str(), vecIter.getPath());
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			attributes.push_back(Attribute(name, type, inputStride));
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			inputStride += glu::getDataTypeScalarSize(type.getBasicType())*sizeof(deUint32);
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void computeTransformFeedbackOutputs (vector<Output>& transformFeedbackOutputs, const vector<Attribute>& attributes, const vector<Varying>& varyings, const vector<string>& transformFeedbackVaryings, deUint32 bufferMode)
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int accumulatedSize = 0;
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	transformFeedbackOutputs.resize(transformFeedbackVaryings.size());
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)transformFeedbackVaryings.size(); varNdx++)
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string&	name		= transformFeedbackVaryings[varNdx];
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				bufNdx		= (bufferMode == GL_SEPARATE_ATTRIBS ? varNdx : 0);
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				offset		= (bufferMode == GL_SEPARATE_ATTRIBS ? 0 : accumulatedSize);
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Output&			output		= transformFeedbackOutputs[varNdx];
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		output.name			= name;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		output.bufferNdx	= bufNdx;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		output.offset		= offset;
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (name == "gl_Position")
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Attribute* posIn = &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_position")));
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			output.type = posIn->type;
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			output.inputs.push_back(posIn);
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (name == "gl_PointSize")
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Attribute* sizeIn = &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_pointSize")));
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			output.type = sizeIn->type;
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			output.inputs.push_back(sizeIn);
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string						varName		= glu::parseVariableName(name.c_str());
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Varying&				varying		= *std::find_if(varyings.begin(), varyings.end(), VaryingNameEquals(varName));
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TypeComponentVector	varPath;
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::parseTypePath(name.c_str(), varying.type, varPath);
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			output.type = glu::getVarType(varying.type, varPath);
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Add all vectorized attributes as inputs.
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (glu::VectorTypeIterator iter = glu::VectorTypeIterator::begin(&output.type); iter != glu::VectorTypeIterator::end(&output.type); iter++)
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Full path.
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::TypeComponentVector fullPath(varPath.size() + iter.getPath().size());
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::copy(varPath.begin(), varPath.end(), fullPath.begin());
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::copy(iter.getPath().begin(), iter.getPath().end(), fullPath.begin()+varPath.size());
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string				attribName	= getAttributeName(varName.c_str(), fullPath);
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Attribute*	attrib		= &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals(attribName)));
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				output.inputs.push_back(attrib);
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		accumulatedSize += output.type.getScalarSize()*sizeof(deUint32);
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyrystatic deUint32 signExtend (deUint32 value, deUint32 numBits)
524da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry{
525da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	DE_ASSERT(numBits >= 1u && numBits <= 32u);
526da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	if (numBits == 32u)
527da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry		return value;
528da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	else if ((value & (1u << (numBits-1u))) == 0u)
529da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry		return value;
530da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	else
531da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry		return value | ~((1u << numBits) - 1u);
532da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry}
533da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void genAttributeData (const Attribute& attrib, deUint8* basePtr, int stride, int numElements, de::Random& rnd)
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
536da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	const int				elementSize	= (int)sizeof(deUint32);
537da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	const bool				isFloat		= glu::isDataTypeFloatOrVec(attrib.type.getBasicType());
538da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	const bool				isInt		= glu::isDataTypeIntOrIVec(attrib.type.getBasicType());
539da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	const bool				isUint		= glu::isDataTypeUintOrUVec(attrib.type.getBasicType());
540da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	const glu::Precision	precision	= attrib.type.getPrecision();
541da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry	const int				numComps	= glu::getDataTypeScalarSize(attrib.type.getBasicType());
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int elemNdx = 0; elemNdx < numElements; elemNdx++)
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < numComps; compNdx++)
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int offset = attrib.offset+elemNdx*stride+compNdx*elementSize;
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isFloat)
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				float* comp = (float*)(basePtr+offset);
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				switch (precision)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case glu::PRECISION_LOWP:		*comp = 0.0f + 0.25f*(float)rnd.getInt(0, 4);	break;
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case glu::PRECISION_MEDIUMP:	*comp = rnd.getFloat(-1e3f, 1e3f);				break;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case glu::PRECISION_HIGHP:		*comp = rnd.getFloat(-1e5f, 1e5f);				break;
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					default:
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(false);
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (isInt)
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int* comp = (int*)(basePtr+offset);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				switch (precision)
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
565da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry					case glu::PRECISION_LOWP:		*comp = (int)signExtend(rnd.getUint32()&0xff, 8);		break;
566da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry					case glu::PRECISION_MEDIUMP:	*comp = (int)signExtend(rnd.getUint32()&0xffff, 16);	break;
567da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry					case glu::PRECISION_HIGHP:		*comp = (int)rnd.getUint32();							break;
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					default:
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(false);
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (isUint)
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32* comp = (deUint32*)(basePtr+offset);
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				switch (precision)
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case glu::PRECISION_LOWP:		*comp = rnd.getUint32()&0xff;	break;
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case glu::PRECISION_MEDIUMP:	*comp = rnd.getUint32()&0xffff;	break;
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case glu::PRECISION_HIGHP:		*comp = rnd.getUint32();		break;
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					default:
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(false);
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
584da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry			else
585da9829f1bdad57a396728922a406486c2a0d700cJarkko Pöyry				DE_ASSERT(false);
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void genInputData (const vector<Attribute>& attributes, int numInputs, int inputStride, deUint8* inputBasePtr, de::Random& rnd)
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Random positions.
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Attribute& position = *std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_position"));
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numInputs; ndx++)
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8* ptr = inputBasePtr + position.offset + inputStride*ndx;
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*((float*)(ptr+ 0)) = rnd.getFloat(-1.2f, 1.2f);
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*((float*)(ptr+ 4)) = rnd.getFloat(-1.2f, 1.2f);
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*((float*)(ptr+ 8)) = rnd.getFloat(-1.2f, 1.2f);
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*((float*)(ptr+12)) = rnd.getFloat(0.1f, 2.0f);
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Point size.
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Attribute>::const_iterator pointSizePos = std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_pointSize"));
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pointSizePos != attributes.end())
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < numInputs; ndx++)
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8* ptr = inputBasePtr + pointSizePos->offset + inputStride*ndx;
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			*((float*)ptr) = rnd.getFloat(1.0f, 8.0f);
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Random data for rest of components.
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Attribute>::const_iterator attrib = attributes.begin(); attrib != attributes.end(); attrib++)
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (attrib->name == "a_position" || attrib->name == "a_pointSize")
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		genAttributeData(*attrib, inputBasePtr, inputStride, numInputs, rnd);
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getTransformFeedbackOutputCount (deUint32 primitiveType, int numElements)
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveType)
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLES:			return numElements - numElements%3;
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_STRIP:		return de::max(0, numElements-2)*3;
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_FAN:		return de::max(0, numElements-2)*3;
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINES:				return numElements - numElements%2;
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_STRIP:			return de::max(0, numElements-1)*2;
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_LOOP:			return numElements > 1 ? numElements*2 : 0;
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_POINTS:				return numElements;
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getTransformFeedbackPrimitiveCount (deUint32 primitiveType, int numElements)
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveType)
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLES:			return numElements/3;
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_STRIP:		return de::max(0, numElements-2);
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_FAN:		return de::max(0, numElements-2);
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINES:				return numElements/2;
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_STRIP:			return de::max(0, numElements-1);
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_LOOP:			return numElements > 1 ? numElements : 0;
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_POINTS:				return numElements;
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getTransformFeedbackPrimitiveMode (deUint32 primitiveType)
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveType)
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLES:
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_STRIP:
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_FAN:
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return GL_TRIANGLES;
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINES:
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_LOOP:
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_STRIP:
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return GL_LINES;
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_POINTS:
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return GL_POINTS;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getAttributeIndex (deUint32 primitiveType, int numInputs, int outNdx)
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveType)
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLES:			return outNdx;
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINES:				return outNdx;
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_POINTS:				return outNdx;
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_STRIP:
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int triNdx = outNdx/3;
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int vtxNdx = outNdx%3;
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (triNdx%2 != 0 && vtxNdx < 2) ? (triNdx+1-vtxNdx) : (triNdx+vtxNdx);
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLE_FAN:
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (outNdx%3 != 0) ? (outNdx/3 + outNdx%3) : 0;
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_STRIP:
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return outNdx/2 + outNdx%2;
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINE_LOOP:
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inNdx = outNdx/2 + outNdx%2;
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return inNdx < numInputs ? inNdx : 0;
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool compareTransformFeedbackOutput (tcu::TestLog& log, deUint32 primitiveType, const Output& output, int numInputs, const deUint8* inBasePtr, int inStride, const deUint8* outBasePtr, int outStride)
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		isOk		= true;
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			outOffset	= output.offset;
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int attrNdx = 0; attrNdx < (int)output.inputs.size(); attrNdx++)
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Attribute&	attribute		= *output.inputs[attrNdx];
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::DataType		type			= attribute.type.getBasicType();
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					numComponents	= glu::getDataTypeScalarSize(type);
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::Precision		precision		= attribute.type.getPrecision();
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::DataType		scalarType		= glu::getDataTypeScalarType(type);
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					numOutputs		= getTransformFeedbackOutputCount(primitiveType, numInputs);
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int outNdx = 0; outNdx < numOutputs; outNdx++)
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inNdx = getAttributeIndex(primitiveType, numInputs, outNdx);
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < numComponents; compNdx++)
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint8*	inPtr	= inBasePtr + inStride*inNdx + attribute.offset + compNdx*sizeof(deUint32);
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint8*	outPtr	= outBasePtr + outStride*outNdx + outOffset + compNdx*sizeof(deUint32);
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32		inVal	= *(const deUint32*)inPtr;
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32		outVal	= *(const deUint32*)outPtr;
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			isEqual	= false;
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (scalarType == glu::TYPE_FLOAT)
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// ULP comparison is used for highp and mediump. Lowp uses threshold-comparison.
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					switch (precision)
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						case glu::PRECISION_HIGHP:		isEqual = de::abs((int)inVal - (int)outVal) < 2;				break;
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						case glu::PRECISION_MEDIUMP:	isEqual = de::abs((int)inVal - (int)outVal) < 2+(1<<13);		break;
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						case glu::PRECISION_LOWP:
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							float inF	= *(const float*)inPtr;
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							float outF	= *(const float*)outPtr;
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							isEqual = de::abs(inF - outF) < 0.1f;
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							break;
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						default:
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							DE_ASSERT(false);
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					isEqual = (inVal == outVal); // Bit-exact match required for integer types.
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isEqual)
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Mismatch in " << output.name << " (" << attribute.name << "), output = " << outNdx << ", input = " << inNdx << ", component = " << compNdx << TestLog::EndMessage;
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					isOk = false;
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!isOk)
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outOffset += numComponents*sizeof(deUint32);
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isOk;
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int computeTransformFeedbackPrimitiveCount (deUint32 primitiveType, const DrawCall* first, const DrawCall* end)
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int primCount = 0;
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (const DrawCall* call = first; call != end; ++call)
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (call->transformFeedbackEnabled)
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			primCount += getTransformFeedbackPrimitiveCount(primitiveType, call->numElements);
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return primCount;
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeBufferGuard (const glw::Functions& gl, deUint32 target, int bufferSize, int guardSize)
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8* ptr = (deUint8*)gl.mapBufferRange(target, bufferSize, guardSize, GL_MAP_WRITE_BIT);
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ptr)
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemset(ptr, 0xcd, guardSize);
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.unmapBuffer(target);
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "guardband write");
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool verifyGuard (const deUint8* ptr, int guardSize)
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < guardSize; ndx++)
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ptr[ndx] != 0xcd)
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void logTransformFeedbackVaryings (TestLog& log, const glw::Functions& gl, deUint32 program)
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numTfVaryings	= 0;
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	maxNameLen		= 0;
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &numTfVaryings);
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxNameLen);
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Query TF varyings");
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_VARYINGS = " << numTfVaryings << TestLog::EndMessage;
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<char> nameBuf(maxNameLen+1);
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numTfVaryings; ndx++)
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLsizei	size	= 0;
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLenum		type	= 0;
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.getTransformFeedbackVarying(program, ndx, (glw::GLsizei)nameBuf.size(), DE_NULL, &size, &type, &nameBuf[0]);
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying()");
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	dataType	= glu::getDataTypeFromGLType(type);
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string	typeName	= dataType != glu::TYPE_LAST ? std::string(glu::getDataTypeName(dataType))
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 : (std::string("unknown(") + tcu::toHex(type).toString() + ")");
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << (const char*)&nameBuf[0] << ": " << typeName << "[" << size << "]" << TestLog::EndMessage;
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TransformFeedbackCase : public TestCase
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								TransformFeedbackCase		(Context& context, const char* name, const char* desc, deUint32 bufferMode, deUint32 primitiveType);
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~TransformFeedbackCase		(void);
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init						(void);
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit						(void);
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate						(void);
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramSpec					m_progSpec;
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_bufferMode;
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_primitiveType;
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								TransformFeedbackCase		(const TransformFeedbackCase& other);
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TransformFeedbackCase&		operator=					(const TransformFeedbackCase& other);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool						runTest						(const DrawCall* first, const DrawCall* end, deUint32 seed);
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Derived from ProgramSpec in init()
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_inputStride;
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Attribute>			m_attributes;
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Output>				m_transformFeedbackOutputs;
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>					m_bufferStrides;
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// GL state.
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*			m_program;
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::TransformFeedback*		m_transformFeedback;
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>			m_outputBuffers;
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							m_iterNdx;
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8813c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTransformFeedbackCase::TransformFeedbackCase (Context& context, const char* name, const char* desc, deUint32 bufferMode, deUint32 primitiveType)
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase				(context, name, desc)
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bufferMode			(bufferMode)
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_primitiveType		(primitiveType)
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_inputStride			(0)
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program				(DE_NULL)
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_transformFeedback	(DE_NULL)
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterNdx				(0)
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTransformFeedbackCase::~TransformFeedbackCase (void)
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TransformFeedbackCase::deinit();
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool hasArraysInTFVaryings (const ProgramSpec& spec)
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<string>::const_iterator tfVar = spec.getTransformFeedbackVaryings().begin(); tfVar != spec.getTransformFeedbackVaryings().end(); ++tfVar)
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string							varName	= glu::parseVariableName(tfVar->c_str());
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<Varying>::const_iterator	varIter	= std::find_if(spec.getVaryings().begin(), spec.getVaryings().end(), VaryingNameEquals(varName));
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (varName == "gl_Position" || varName == "gl_PointSize")
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(varIter != spec.getVaryings().end());
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (varIter->type.isArrayType())
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return false;
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TransformFeedbackCase::init (void)
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log	= m_testCtx.getLog();
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_program);
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = createVertexCaptureProgram(m_context.getRenderContext(), m_progSpec, m_bufferMode, m_primitiveType);
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << *m_program;
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool linkFail = m_program->getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk &&
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk &&
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  !m_program->getProgramInfo().linkOk;
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (linkFail)
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!isProgramSupported(gl, m_progSpec, m_bufferMode))
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::NotSupportedError("Implementation limits execeeded", "", __FILE__, __LINE__);
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (hasArraysInTFVaryings(m_progSpec))
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::NotSupportedError("Capturing arrays is not supported (undefined in specification)", "", __FILE__, __LINE__);
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("Link failed", "", __FILE__, __LINE__);
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("Compile failed", "", __FILE__, __LINE__);
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Transform feedback varyings: " << tcu::formatArray(m_progSpec.getTransformFeedbackVaryings().begin(), m_progSpec.getTransformFeedbackVaryings().end()) << TestLog::EndMessage;
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Print out transform feedback points reported by GL.
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Transform feedback varyings reported by compiler:" << TestLog::EndMessage;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	logTransformFeedbackVaryings(log, gl, m_program->getProgram());
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute input specification.
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	computeInputLayout(m_attributes, m_inputStride, m_progSpec.getVaryings(), m_progSpec.isPointSizeUsed());
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Build list of varyings used in transform feedback.
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	computeTransformFeedbackOutputs(m_transformFeedbackOutputs, m_attributes, m_progSpec.getVaryings(), m_progSpec.getTransformFeedbackVaryings(), m_bufferMode);
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_transformFeedbackOutputs.empty());
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Buffer strides.
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_bufferStrides.empty());
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_bufferMode == GL_SEPARATE_ATTRIBS)
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<Output>::const_iterator outIter = m_transformFeedbackOutputs.begin(); outIter != m_transformFeedbackOutputs.end(); outIter++)
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_bufferStrides.push_back(outIter->type.getScalarSize()*sizeof(deUint32));
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int totalSize = 0;
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<Output>::const_iterator outIter = m_transformFeedbackOutputs.begin(); outIter != m_transformFeedbackOutputs.end(); outIter++)
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			totalSize += outIter->type.getScalarSize()*sizeof(deUint32);
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_bufferStrides.push_back(totalSize);
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Actual storage is allocated in iterate().
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_outputBuffers.resize(m_bufferStrides.size());
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genBuffers((glw::GLsizei)m_outputBuffers.size(), &m_outputBuffers[0]);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_transformFeedback);
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_transformFeedback = new glu::TransformFeedback(m_context.getRenderContext());
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "init");
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx = 0;
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TransformFeedbackCase::deinit (void)
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_outputBuffers.empty())
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.deleteBuffers((glw::GLsizei)m_outputBuffers.size(), &m_outputBuffers[0]);
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_outputBuffers.clear();
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_transformFeedback;
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_transformFeedback = DE_NULL;
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Clean up state.
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_attributes.clear();
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_transformFeedbackOutputs.clear();
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_bufferStrides.clear();
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_inputStride = 0;
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10093c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTransformFeedbackCase::IterateResult TransformFeedbackCase::iterate (void)
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Test cases.
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_elemCount1[]	= { DrawCall(1, true) };
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_elemCount2[]	= { DrawCall(2, true) };
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_elemCount3[]	= { DrawCall(3, true) };
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_elemCount4[]	= { DrawCall(4, true) };
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_elemCount123[]	= { DrawCall(123, true) };
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_basicPause1[]	= { DrawCall(64, true), DrawCall(64, false), DrawCall(64, true) };
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_basicPause2[]	= { DrawCall(13, true), DrawCall(5, true), DrawCall(17, false), DrawCall(3, true), DrawCall(7, false) };
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_startPaused[]	= { DrawCall(123, false), DrawCall(123, true) };
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_random1[]		= { DrawCall(65, true), DrawCall(135, false), DrawCall(74, true), DrawCall(16, false), DrawCall(226, false), DrawCall(9, true), DrawCall(174, false) };
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const DrawCall s_random2[]		= { DrawCall(217, true), DrawCall(171, true), DrawCall(147, true), DrawCall(152, false), DrawCall(55, true) };
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const DrawCall*		calls;
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					numCalls;
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_iterations[] =
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define ITER(ARR) { ARR, DE_LENGTH_OF_ARRAY(ARR) }
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_elemCount1),
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_elemCount2),
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_elemCount3),
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_elemCount4),
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_elemCount123),
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_basicPause1),
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_basicPause2),
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_startPaused),
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_random1),
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ITER(s_random2)
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#undef ITER
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log				= m_testCtx.getLog();
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					isOk			= true;
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				seed			= deStringHash(getName()) ^ deInt32Hash(m_iterNdx);
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						numIterations	= DE_LENGTH_OF_ARRAY(s_iterations);
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DrawCall*			first			= s_iterations[m_iterNdx].calls;
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DrawCall*			end				= s_iterations[m_iterNdx].calls + s_iterations[m_iterNdx].numCalls;
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				sectionName		= std::string("Iteration") + de::toString(m_iterNdx+1);
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				sectionDesc		= std::string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(numIterations);
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::ScopedLogSection	section			(log, sectionName, sectionDesc);
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Testing " << s_iterations[m_iterNdx].numCalls << " draw calls, (element count, TF state): " << tcu::formatArray(first, end) << TestLog::EndMessage;
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	isOk = runTest(first, end, seed);
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isOk)
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx += 1;
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (isOk && m_iterNdx < numIterations) ? CONTINUE : STOP;
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool TransformFeedbackCase::runTest (const DrawCall* first, const DrawCall* end, deUint32 seed)
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log				= m_testCtx.getLog();
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random				rnd				(seed);
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						numInputs		= 0;		//!< Sum of element counts in calls.
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						numOutputs		= 0;		//!< Sum of output counts for calls that have transform feedback enabled.
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						width			= m_context.getRenderContext().getRenderTarget().getWidth();
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						height			= m_context.getRenderContext().getRenderTarget().getHeight();
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						viewportW		= de::min((int)VIEWPORT_WIDTH, width);
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						viewportH		= de::min((int)VIEWPORT_HEIGHT, height);
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						viewportX		= rnd.getInt(0, width-viewportW);
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						viewportY		= rnd.getInt(0, height-viewportH);
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface			frameWithTf		(viewportW, viewportH);
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface			frameWithoutTf	(viewportW, viewportH);
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Query				primitiveQuery	(m_context.getRenderContext());
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					outputsOk		= true;
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					imagesOk		= true;
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					queryOk			= true;
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute totals.
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (const DrawCall* call = first; call != end; call++)
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numInputs	+= call->numElements;
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numOutputs	+= call->transformFeedbackEnabled ? getTransformFeedbackOutputCount(m_primitiveType, call->numElements) : 0;
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Input data.
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint8> inputData(m_inputStride*numInputs);
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genInputData(m_attributes, numInputs, m_inputStride, &inputData[0], rnd);
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transformFeedback->get());
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback()");
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Allocate storage for transform feedback output buffers and bind to targets.
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int bufNdx = 0; bufNdx < (int)m_outputBuffers.size(); bufNdx++)
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		buffer		= m_outputBuffers[bufNdx];
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				stride		= m_bufferStrides[bufNdx];
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				target		= bufNdx;
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				size		= stride*numOutputs;
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				guardSize	= stride*BUFFER_GUARD_MULTIPLIER;
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32	usage		= GL_DYNAMIC_READ;
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size+guardSize, DE_NULL, usage);
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeBufferGuard(gl, GL_TRANSFORM_FEEDBACK_BUFFER, size, guardSize);
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2012-07-30 pyry] glBindBufferRange()?
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, target, buffer);
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "transform feedback buffer setup");
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Setup attributes.
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Attribute>::const_iterator attrib = m_attributes.begin(); attrib != m_attributes.end(); attrib++)
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				loc				= gl.getAttribLocation(m_program->getProgram(), attrib->name.c_str());
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::DataType	scalarType		= glu::getDataTypeScalarType(attrib->type.getBasicType());
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				numComponents	= glu::getDataTypeScalarSize(attrib->type.getBasicType());
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const void*		ptr				= &inputData[0] + attrib->offset;
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (loc >= 0)
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.enableVertexAttribArray(loc);
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (scalarType == glu::TYPE_FLOAT)		gl.vertexAttribPointer	(loc, numComponents, GL_FLOAT, GL_FALSE, m_inputStride, ptr);
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (scalarType == glu::TYPE_INT)	gl.vertexAttribIPointer	(loc, numComponents, GL_INT, m_inputStride, ptr);
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (scalarType == glu::TYPE_UINT)	gl.vertexAttribIPointer	(loc, numComponents, GL_UNSIGNED_INT, m_inputStride, ptr);
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Setup viewport.
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(viewportX, viewportY, viewportW, viewportH);
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Setup program.
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_program->getProgram());
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform4fv(gl.getUniformLocation(m_program->getProgram(), "u_scale"),	1, tcu::Vec4(0.01f).getPtr());
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform4fv(gl.getUniformLocation(m_program->getProgram(), "u_bias"),		1, tcu::Vec4(0.5f).getPtr());
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Enable query.
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, *primitiveQuery);
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)");
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Draw.
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		offset		= 0;
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool	tfEnabled	= true;
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.beginTransformFeedback(getTransformFeedbackPrimitiveMode(m_primitiveType));
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (const DrawCall* call = first; call != end; call++)
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Pause or resume transform feedback if necessary.
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (call->transformFeedbackEnabled != tfEnabled)
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (call->transformFeedbackEnabled)
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.resumeTransformFeedback();
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.pauseTransformFeedback();
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tfEnabled = call->transformFeedbackEnabled;
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.drawArrays(m_primitiveType, offset, call->numElements);
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			offset += call->numElements;
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Resume feedback before finishing it.
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!tfEnabled)
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.resumeTransformFeedback();
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.endTransformFeedback();
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "render");
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)");
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check and log query status right after submit
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32 available = GL_FALSE;
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT_AVAILABLE, &available);
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv()");
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN status after submit: " << (available != GL_FALSE ? "GL_TRUE" : "GL_FALSE") << TestLog::EndMessage;
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare result buffers.
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int bufferNdx = 0; bufferNdx < (int)m_outputBuffers.size(); bufferNdx++)
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		buffer		= m_outputBuffers[bufferNdx];
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				stride		= m_bufferStrides[bufferNdx];
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				size		= stride*numOutputs;
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				guardSize	= stride*BUFFER_GUARD_MULTIPLIER;
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const void*		bufPtr		= DE_NULL;
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Bind buffer for reading.
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bufPtr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size+guardSize, GL_MAP_READ_BIT);
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "mapping buffer");
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Verify all output variables that are written to this buffer.
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<Output>::const_iterator out = m_transformFeedbackOutputs.begin(); out != m_transformFeedbackOutputs.end(); out++)
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (out->bufferNdx != bufferNdx)
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inputOffset		= 0;
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int	outputOffset	= 0;
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Process all draw calls and check ones with transform feedback enabled.
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (const DrawCall* call = first; call != end; call++)
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (call->transformFeedbackEnabled)
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint8*	inputPtr	= &inputData[0] + inputOffset*m_inputStride;
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint8*	outputPtr	= (const deUint8*)bufPtr + outputOffset*stride;
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!compareTransformFeedbackOutput(log, m_primitiveType, *out, call->numElements, inputPtr, m_inputStride, outputPtr, stride))
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						outputsOk = false;
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				inputOffset		+= call->numElements;
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				outputOffset	+= call->transformFeedbackEnabled ? getTransformFeedbackOutputCount(m_primitiveType, call->numElements) : 0;
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Verify guardband.
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!verifyGuard((const deUint8*)bufPtr + size, guardSize))
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Error: Transform feedback buffer overrun detected" << TestLog::EndMessage;
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			outputsOk = false;
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check status after mapping buffers.
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool	mustBeReady		= !m_outputBuffers.empty(); // Mapping buffer forces synchronization.
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	expectedCount	= computeTransformFeedbackPrimitiveCount(m_primitiveType, first, end);
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32	available		= GL_FALSE;
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32	numPrimitives	= 0;
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT_AVAILABLE, &available);
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT, &numPrimitives);
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv()");
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!mustBeReady && available == GL_FALSE)
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "ERROR: GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN result not available after mapping buffers!" << TestLog::EndMessage;
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			queryOk = false;
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = " << numPrimitives << TestLog::EndMessage;
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((int)numPrimitives != expectedCount)
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "ERROR: Expected " << expectedCount << " primitives!" << TestLog::EndMessage;
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			queryOk = false;
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Clear transform feedback state.
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int bufNdx = 0; bufNdx < (int)m_outputBuffers.size(); bufNdx++)
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer		(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase	(GL_TRANSFORM_FEEDBACK_BUFFER, bufNdx, 0);
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read back rendered image.
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, frameWithTf.getAccess());
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render without transform feedback.
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int offset = 0;
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (const DrawCall* call = first; call != end; call++)
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.drawArrays(m_primitiveType, offset, call->numElements);
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			offset += call->numElements;
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "render");
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, frameWithoutTf.getAccess());
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare images with and without transform feedback.
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	imagesOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", frameWithoutTf, frameWithTf, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_ON_ERROR);
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (imagesOk)
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message << "Rendering result comparison between TF enabled and TF disabled passed." << TestLog::EndMessage;
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message << "ERROR: Rendering result comparison between TF enabled and TF disabled failed!" << TestLog::EndMessage;
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return outputsOk && imagesOk && queryOk;
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Test cases.
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PositionCase : public TransformFeedbackCase
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PositionCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType)
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("gl_Position");
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PointSizeCase : public TransformFeedbackCase
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PointSizeCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType)
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("gl_PointSize");
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BasicTypeCase : public TransformFeedbackCase
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BasicTypeCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, glu::DataType type, glu::Precision precision, Interpolation interpolation)
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addVarying("v_varA", glu::VarType(type, precision), interpolation);
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addVarying("v_varB", glu::VarType(type, precision), interpolation);
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("v_varA");
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("v_varB");
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BasicArrayCase : public TransformFeedbackCase
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BasicArrayCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, glu::DataType type, glu::Precision precision, Interpolation interpolation)
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeMatrix(type) || m_bufferMode == GL_SEPARATE_ATTRIBS)
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note For matrix types we need to use reduced array sizes or otherwise we will exceed maximum attribute (16)
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			//		 or transform feedback component count (64).
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			//		 On separate attribs mode maximum component count per varying is 4.
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 1), interpolation);
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 2), interpolation);
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 3), interpolation);
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 4), interpolation);
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("v_varA");
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("v_varB");
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ArrayElementCase : public TransformFeedbackCase
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ArrayElementCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, glu::DataType type, glu::Precision precision, Interpolation interpolation)
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 3), interpolation);
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 4), interpolation);
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("v_varA[1]");
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("v_varB[0]");
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_progSpec.addTransformFeedbackVarying("v_varB[3]");
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RandomCase : public TransformFeedbackCase
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RandomCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, deUint32 seed)
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TransformFeedbackCase	(context, name, desc, bufferType, primitiveType)
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_seed				(seed)
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void init (void)
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Hard-coded indices and hackery are used when indexing this, beware.
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const glu::DataType typeCandidates[] =
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT,
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_VEC2,
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_VEC3,
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_VEC4,
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_INT,
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_INT_VEC2,
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_INT_VEC3,
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_INT_VEC4,
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_UINT,
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_UINT_VEC2,
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_UINT_VEC3,
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_UINT_VEC4,
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT2,
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT2X3,
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT2X4,
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT3X2,
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT3,
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT3X4,
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT4X2,
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT4X3,
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::TYPE_FLOAT_MAT4
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const glu::Precision precisions[] =
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::PRECISION_LOWP,
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::PRECISION_MEDIUMP,
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::PRECISION_HIGHP
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const Interpolation interpModes[] =
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			INTERPOLATION_FLAT,
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			INTERPOLATION_SMOOTH,
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			INTERPOLATION_CENTROID
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	maxAttributeVectors					= 16;
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//		const int	maxTransformFeedbackComponents		= 64; // \note It is enough to limit attribute set size.
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool		isSeparateMode						= m_bufferMode == GL_SEPARATE_ATTRIBS;
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			maxTransformFeedbackVars			= isSeparateMode ? 4 : maxAttributeVectors;
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float	arrayWeight							= 0.3f;
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float	positionWeight						= 0.7f;
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float	pointSizeWeight						= 0.1f;
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float	captureFullArrayWeight				= 0.5f;
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random	rnd									(m_seed);
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool		usePosition							= rnd.getFloat() < positionWeight;
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool		usePointSize						= rnd.getFloat() < pointSizeWeight;
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			numAttribVectorsToUse				= rnd.getInt(1, maxAttributeVectors - 1/*position*/ - (usePointSize ? 1 : 0));
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			numAttributeVectors					= 0;
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			varNdx								= 0;
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Generate varyings.
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (numAttributeVectors < numAttribVectorsToUse)
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						maxVecs		= isSeparateMode ? de::min(2 /*at most 2*mat2*/, numAttribVectorsToUse-numAttributeVectors) : numAttribVectorsToUse-numAttributeVectors;
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType*	begin		= &typeCandidates[0];
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType*	end			= begin + (maxVecs >= 4 ? 21 :
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   maxVecs >= 3 ? 18 :
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   maxVecs >= 2 ? (isSeparateMode ? 13 : 15) : 12);
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::DataType			type		= rnd.choose<glu::DataType>(begin, end);
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::Precision			precision	= rnd.choose<glu::Precision>(&precisions[0], &precisions[0]+DE_LENGTH_OF_ARRAY(precisions));
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Interpolation			interp		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												? rnd.choose<Interpolation>(&interpModes[0], &interpModes[0]+DE_LENGTH_OF_ARRAY(interpModes))
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												: INTERPOLATION_FLAT;
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						numVecs		= glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumColumns(type) : 1;
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						numComps	= glu::getDataTypeScalarSize(type);
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						maxArrayLen	= de::max(1, isSeparateMode ? 4/numComps : maxVecs/numVecs);
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					useArray	= rnd.getFloat() < arrayWeight;
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						arrayLen	= useArray ? rnd.getInt(1, maxArrayLen) : 1;
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::string				name		= "v_var" + de::toString(varNdx);
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (useArray)
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_progSpec.addVarying(name.c_str(), glu::VarType(glu::VarType(type, precision), arrayLen), interp);
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_progSpec.addVarying(name.c_str(), glu::VarType(type, precision), interp);
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numAttributeVectors	+= arrayLen*numVecs;
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			varNdx				+= 1;
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Generate transform feedback candidate set.
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<string> tfCandidates;
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (usePosition)	tfCandidates.push_back("gl_Position");
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (usePointSize)	tfCandidates.push_back("gl_PointSize");
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < varNdx /* num varyings */; ndx++)
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Varying& var = m_progSpec.getVaryings()[ndx];
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (var.type.isArrayType())
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool captureFull = rnd.getFloat() < captureFullArrayWeight;
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (captureFull)
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					tfCandidates.push_back(var.name);
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int numElem = var.type.getArraySize();
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int elemNdx = 0; elemNdx < numElem; elemNdx++)
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						tfCandidates.push_back(var.name + "[" + de::toString(elemNdx) + "]");
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tfCandidates.push_back(var.name);
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Pick random selection.
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<string> tfVaryings(de::min((int)tfCandidates.size(), maxTransformFeedbackVars));
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rnd.choose(tfCandidates.begin(), tfCandidates.end(), tfVaryings.begin(), (int)tfVaryings.size());
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rnd.shuffle(tfVaryings.begin(), tfVaryings.end());
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<string>::const_iterator var = tfVaryings.begin(); var != tfVaryings.end(); var++)
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_progSpec.addTransformFeedbackVarying(var->c_str());
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TransformFeedbackCase::init();
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 m_seed;
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // TransformFeedback
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace TransformFeedback;
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTransformFeedbackTests::TransformFeedbackTests (Context& context)
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "transform_feedback", "Transform feedback tests")
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15403c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTransformFeedbackTests::~TransformFeedbackTests (void)
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TransformFeedbackTests::init (void)
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		mode;
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} bufferModes[] =
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "separate",		GL_SEPARATE_ATTRIBS		},
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "interleaved",	GL_INTERLEAVED_ATTRIBS	}
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		type;
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} primitiveTypes[] =
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "points",			GL_POINTS			},
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lines",			GL_LINES			},
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "triangles",		GL_TRIANGLES		}
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Not supported by GLES3.
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//		{ "line_strip",		GL_LINE_STRIP		},
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//		{ "line_loop",		GL_LINE_LOOP		},
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//		{ "triangle_fan",	GL_TRIANGLE_FAN		},
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//		{ "triangle_strip",	GL_TRIANGLE_STRIP	}
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const glu::DataType basicTypes[] =
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT,
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_VEC2,
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_VEC3,
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_VEC4,
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT2,
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT2X3,
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT2X4,
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT3X2,
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT3,
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT3X4,
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT4X2,
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT4X3,
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_MAT4,
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT,
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT_VEC2,
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT_VEC3,
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT_VEC4,
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT,
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT_VEC2,
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT_VEC3,
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT_VEC4
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const glu::Precision precisions[] =
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_LOWP,
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_MEDIUMP,
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_HIGHP
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interpolation	interp;
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} interpModes[] =
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "smooth",		INTERPOLATION_SMOOTH	},
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "flat",		INTERPOLATION_FLAT		},
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "centroid",	INTERPOLATION_CENTROID	}
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .position
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* positionGroup = new tcu::TestCaseGroup(m_testCtx, "position", "gl_Position capture using transform feedback");
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(positionGroup);
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string name = string(primitiveTypes[primitiveType].name) + "_" + bufferModes[bufferMode].name;
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positionGroup->addChild(new PositionCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode, primitiveTypes[primitiveType].type));
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .point_size
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* pointSizeGroup = new tcu::TestCaseGroup(m_testCtx, "point_size", "gl_PointSize capture using transform feedback");
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(pointSizeGroup);
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string name = string(primitiveTypes[primitiveType].name) + "_" + bufferModes[bufferMode].name;
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				pointSizeGroup->addChild(new PointSizeCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode, primitiveTypes[primitiveType].type));
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .basic_type
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* basicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "basic_types", "Basic types in transform feedback");
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(basicTypeGroup);
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			basicTypeGroup->addChild(modeGroup);
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				modeGroup->addChild(primitiveGroup);
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::DataType		type		= basicTypes[typeNdx];
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					bool				isFloat		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						glu::Precision precision = precisions[precNdx];
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						primitiveGroup->addChild(new BasicTypeCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision, isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .array
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* arrayGroup = new tcu::TestCaseGroup(m_testCtx, "array", "Capturing whole array in TF");
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(arrayGroup);
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			arrayGroup->addChild(modeGroup);
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				modeGroup->addChild(primitiveGroup);
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::DataType		type		= basicTypes[typeNdx];
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					bool				isFloat		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						glu::Precision precision = precisions[precNdx];
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						primitiveGroup->addChild(new BasicArrayCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision, isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .array_element
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* arrayElemGroup = new tcu::TestCaseGroup(m_testCtx, "array_element", "Capturing single array element in TF");
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(arrayElemGroup);
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			arrayElemGroup->addChild(modeGroup);
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				modeGroup->addChild(primitiveGroup);
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::DataType		type		= basicTypes[typeNdx];
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					bool				isFloat		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						glu::Precision precision = precisions[precNdx];
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						primitiveGroup->addChild(new ArrayElementCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision, isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .interpolation
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* interpolationGroup = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Different interpolation modes in transform feedback varyings");
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(interpolationGroup);
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(interpModes); modeNdx++)
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Interpolation		interp		= interpModes[modeNdx].interp;
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup*	modeGroup	= new tcu::TestCaseGroup(m_testCtx, interpModes[modeNdx].name, "");
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			interpolationGroup->addChild(modeGroup);
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision precision = precisions[precNdx];
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						string name = string(glu::getPrecisionName(precision)) + "_vec4_" + primitiveTypes[primitiveType].name + "_" + bufferModes[bufferMode].name;
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						modeGroup->addChild(new BasicTypeCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode, primitiveTypes[primitiveType].type, glu::TYPE_FLOAT_VEC4, precision, interp));
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .random
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Randomized transform feedback cases");
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(randomGroup);
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			randomGroup->addChild(modeGroup);
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				modeGroup->addChild(primitiveGroup);
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int ndx = 0; ndx < 10; ndx++)
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					deUint32 seed = deInt32Hash(bufferMode) ^ deInt32Hash(primitiveType) ^ deInt32Hash(ndx);
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					primitiveGroup->addChild(new RandomCase(m_context, de::toString(ndx+1).c_str(), "", bufferMode, primitiveType, seed));
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1806