13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Tessellation Tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fTessellationTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsTextureTestUtil.hpp"
2618c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry#include "glsShaderLibrary.hpp"
27c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry#include "glsStateQueryUtil.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluStrUtil.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarType.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarTypeUtil.hpp"
37c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry#include "gluCallLogWrapper.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageIO.hpp"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuResource.hpp"
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSharedPtr.hpp"
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwDefs.hpp"
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <functional>
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set>
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <limits>
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ShaderProgram;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::RenderContext;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::RenderTarget;
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::Random;
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::SharedPtr;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glw; // For GL types.
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing gls::TextureTestUtil::RandomViewport;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
88c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryusing namespace gls::StateQueryUtil;
89c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MINIMUM_MAX_TESS_GEN_LEVEL = 64 //!< GL-defined minimum for GL_MAX_TESS_GEN_LEVEL.
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool vec3XLessThan (const Vec3& a, const Vec3& b) { return a.x() < b.x(); }
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename IterT>
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string elemsStr (const IterT& begin, const IterT& end, int wrapLengthParam = 0, int numIndentationSpaces = 0)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	baseIndentation	= string(numIndentationSpaces, ' ');
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	deepIndentation	= baseIndentation + string(4, ' ');
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		wrapLength		= wrapLengthParam > 0 ? wrapLengthParam : std::numeric_limits<int>::max();
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		length			= (int)std::distance(begin, end);
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			result;
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (length > wrapLength)
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += "(amount: " + de::toString(length) + ") ";
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result += string() + "{" + (length > wrapLength ? "\n"+deepIndentation : " ");
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int index = 0;
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (IterT it = begin; it != end; ++it)
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (it != begin)
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result += string() + ", " + (index % wrapLength == 0 ? "\n"+deepIndentation : "");
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result += de::toString(*it);
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			index++;
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += length > wrapLength ? "\n"+baseIndentation : " ";
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result += "}";
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerT>
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string containerStr (const ContainerT& c, int wrapLengthParam = 0, int numIndentationSpaces = 0)
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return elemsStr(c.begin(), c.end(), wrapLengthParam, numIndentationSpaces);
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int N>
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string arrayStr (const T (&arr)[N], int wrapLengthParam = 0, int numIndentationSpaces = 0)
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return elemsStr(DE_ARRAY_BEGIN(arr), DE_ARRAY_END(arr), wrapLengthParam, numIndentationSpaces);
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int N>
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic T arrayMax (const T (&arr)[N])
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *std::max_element(DE_ARRAY_BEGIN(arr), DE_ARRAY_END(arr));
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, typename MembT>
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<MembT> members (const vector<T>& objs, MembT T::* membP)
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<MembT> result(objs.size());
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < (int)objs.size(); i++)
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result[i] = objs[i].*membP;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int N>
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<T> arrayToVector (const T (&arr)[N])
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return vector<T>(DE_ARRAY_BEGIN(arr), DE_ARRAY_END(arr));
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ContainerT, typename T>
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool contains (const ContainerT& c, const T& key)
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return c.find(key) != c.end();
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vector<bool, Size> singleTrueMask (int index)
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds(index, 0, Size));
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<bool, Size> result;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result[index] = true;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int intPow (int base, int exp)
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(exp >= 0);
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (exp == 0)
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int sub = intPow(base, exp/2);
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (exp % 2 == 0)
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return sub*sub;
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return sub*sub*base;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::Surface getPixels (const glu::RenderContext& rCtx, int x, int y, int width, int height)
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface result(width, height);
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(rCtx, x, y, result.getAccess());
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::Surface getPixels (const glu::RenderContext& rCtx, const RandomViewport& vp)
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getPixels(rCtx, vp.x, vp.y, vp.width, vp.height);
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void checkRenderTargetSize (const RenderTarget& renderTarget, int minSize)
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (renderTarget.getWidth() < minSize || renderTarget.getHeight() < minSize)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Render target width and height must be at least " + de::toString(minSize));
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::TextureLevel getPNG (const tcu::Archive& archive, const string& filename)
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TextureLevel result;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::ImageIO::loadPNG(result, archive, filename.c_str());
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int numBasicSubobjects (const glu::VarType& type)
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return type.getArraySize()*numBasicSubobjects(type.getElementType());
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isStructType())
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::StructType&	structType	= *type.getStructPtr();
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						result		= 0;
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < structType.getNumMembers(); i++)
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result += numBasicSubobjects(structType.getMember(i).getType());
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline int numVerticesPerPrimitive (deUint32 primitiveTypeGL)
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveTypeGL)
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_POINTS:		return 1;
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_TRIANGLES:	return 3;
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GL_LINES:		return 2;
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return -1;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void setViewport (const glw::Functions& gl, const RandomViewport& vp)
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(vp.x, vp.y, vp.width, vp.height);
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint32 getQueryResult (const glw::Functions& gl, deUint32 queryObject)
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 result = (deUint32)-1;
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getQueryObjectuiv(queryObject, GL_QUERY_RESULT, &result);
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(result != (deUint32)-1);
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void readDataMapped (const glw::Functions& gl, deUint32 bufferTarget, int numElems, T* dst)
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int							numBytes	= numElems*(int)sizeof(T);
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const T* const						mappedData	= (const T*)gl.mapBufferRange(bufferTarget, 0, numBytes, GL_MAP_READ_BIT);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), (string() + "glMapBufferRange(" + glu::getBufferTargetName((int)bufferTarget) + ", 0, " + de::toString(numBytes) + ", GL_MAP_READ_BIT)").c_str());
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(mappedData != DE_NULL);
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < numElems; i++)
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst[i] = mappedData[i];
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.unmapBuffer(bufferTarget);
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<T> readDataMapped (const glw::Functions& gl, deUint32 bufferTarget, int numElems)
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<T> result(numElems);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	readDataMapped(gl, bufferTarget, numElems, &result[0]);
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ArgT, bool res>
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ConstantUnaryPredicate
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const ArgT&) const { return res; }
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Helper for handling simple, one-varying transform feedbacks.
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename VaryingT>
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TransformFeedbackHandler
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct Result
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					numPrimitives;
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<VaryingT>	varying;
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Result (void)								: numPrimitives(-1) {}
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Result (int n, const vector<VaryingT>& v)	: numPrimitives(n), varying(v) {}
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									TransformFeedbackHandler	(const glu::RenderContext& renderCtx, int maxNumVertices);
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Result							renderAndGetPrimitives		(deUint32 programGL, deUint32 tfPrimTypeGL, int numBindings, const glu::VertexArrayBinding* bindings, int numVertices) const;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&		m_renderCtx;
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::TransformFeedback	m_tf;
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::Buffer				m_tfBuffer;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::Query				m_tfPrimQuery;
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename AttribType>
3193c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTransformFeedbackHandler<AttribType>::TransformFeedbackHandler (const glu::RenderContext& renderCtx, int maxNumVertices)
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_renderCtx		(renderCtx)
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_tf				(renderCtx)
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_tfBuffer		(renderCtx)
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_tfPrimQuery		(renderCtx)
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl			= m_renderCtx.getFunctions();
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Room for 1 extra triangle, to detect if GL returns too many primitives.
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				bufferSize	= (maxNumVertices + 3) * (int)sizeof(AttribType);
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, *m_tfBuffer);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize, DE_NULL, GL_DYNAMIC_READ);
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename AttribType>
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypename TransformFeedbackHandler<AttribType>::Result TransformFeedbackHandler<AttribType>::renderAndGetPrimitives (deUint32 programGL, deUint32 tfPrimTypeGL, int numBindings, const glu::VertexArrayBinding* bindings, int numVertices) const
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(tfPrimTypeGL == GL_POINTS || tfPrimTypeGL == GL_LINES || tfPrimTypeGL == GL_TRIANGLES);
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, *m_tf);
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, *m_tfBuffer);
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, *m_tfBuffer);
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, *m_tfPrimQuery);
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.beginTransformFeedback(tfPrimTypeGL);
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::draw(m_renderCtx, programGL, numBindings, bindings, glu::pr::Patches(numVertices));
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.endTransformFeedback();
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numPrimsWritten = (int)getQueryResult(gl, *m_tfPrimQuery);
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Result(numPrimsWritten, readDataMapped<AttribType>(gl, GL_TRANSFORM_FEEDBACK_BUFFER, numPrimsWritten * numVerticesPerPrimitive(tfPrimTypeGL)));
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SizeLessThan
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const T& a, const T& b) const { return a.size() < b.size(); }
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Predicate functor for comparing structs by their members.
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Pred, typename T, typename MembT>
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MemberPred
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				MemberPred	(MembT T::* membP) : m_membP(membP), m_pred(Pred()) {}
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		operator()	(const T& a, const T& b) const { return m_pred(a.*m_membP, b.*m_membP); }
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MembT T::*	m_membP;
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pred		m_pred;
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Convenience wrapper for MemberPred, because class template arguments aren't deduced based on constructor arguments.
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <template <typename> class Pred, typename T, typename MembT>
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic MemberPred<Pred<MembT>, T, MembT> memberPred (MembT T::* membP) { return MemberPred<Pred<MembT>, T, MembT>(membP); }
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename SeqT, int Size, typename Pred>
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LexCompare
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LexCompare (void) : m_pred(Pred()) {}
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const SeqT& a, const SeqT& b) const
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < Size; i++)
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_pred(a[i], b[i]))
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_pred(b[i], a[i]))
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Pred m_pred;
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VecLexLessThan : public LexCompare<tcu::Vector<float, Size>, Size, std::less<float> >
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum TessPrimitiveType
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TESSPRIMITIVETYPE_TRIANGLES = 0,
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TESSPRIMITIVETYPE_QUADS,
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TESSPRIMITIVETYPE_ISOLINES,
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TESSPRIMITIVETYPE_LAST
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum SpacingMode
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SPACINGMODE_EQUAL,
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SPACINGMODE_FRACTIONAL_ODD,
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SPACINGMODE_FRACTIONAL_EVEN,
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SPACINGMODE_LAST
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum Winding
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	WINDING_CCW = 0,
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	WINDING_CW,
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	WINDING_LAST
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline const char* getTessPrimitiveTypeShaderName (TessPrimitiveType type)
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_TRIANGLES:	return "triangles";
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_QUADS:		return "quads";
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_ISOLINES:	return "isolines";
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline const char* getSpacingModeShaderName (SpacingMode mode)
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_EQUAL:				return "equal_spacing";
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_FRACTIONAL_ODD:	return "fractional_odd_spacing";
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_FRACTIONAL_EVEN:	return "fractional_even_spacing";
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline const char* getWindingShaderName (Winding winding)
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (winding)
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case WINDING_CCW:	return "ccw";
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case WINDING_CW:	return "cw";
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getTessellationEvaluationInLayoutString (TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode=false)
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return string() + "layout (" + getTessPrimitiveTypeShaderName(primType)
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ", " + getSpacingModeShaderName(spacing)
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ", " + getWindingShaderName(winding)
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + (usePointMode ? ", point_mode" : "")
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ") in;\n";
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getTessellationEvaluationInLayoutString (TessPrimitiveType primType, SpacingMode spacing, bool usePointMode=false)
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return string() + "layout (" + getTessPrimitiveTypeShaderName(primType)
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ", " + getSpacingModeShaderName(spacing)
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + (usePointMode ? ", point_mode" : "")
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ") in;\n";
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getTessellationEvaluationInLayoutString (TessPrimitiveType primType, Winding winding, bool usePointMode=false)
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return string() + "layout (" + getTessPrimitiveTypeShaderName(primType)
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ", " + getWindingShaderName(winding)
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + (usePointMode ? ", point_mode" : "")
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ") in;\n";
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getTessellationEvaluationInLayoutString (TessPrimitiveType primType, bool usePointMode=false)
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return string() + "layout (" + getTessPrimitiveTypeShaderName(primType)
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + (usePointMode ? ", point_mode" : "")
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 + ") in;\n";
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint32 outputPrimitiveTypeGL (TessPrimitiveType tessPrimType, bool usePointMode)
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (usePointMode)
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return GL_POINTS;
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (tessPrimType)
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TESSPRIMITIVETYPE_TRIANGLES:	return GL_TRIANGLES;
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TESSPRIMITIVETYPE_QUADS:		return GL_TRIANGLES;
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TESSPRIMITIVETYPE_ISOLINES:	return GL_LINES;
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return (deUint32)-1;
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline int numInnerTessellationLevels (TessPrimitiveType primType)
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primType)
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_TRIANGLES:	return 1;
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_QUADS:		return 2;
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_ISOLINES:	return 0;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: DE_ASSERT(false); return -1;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline int numOuterTessellationLevels (TessPrimitiveType primType)
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primType)
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_TRIANGLES:	return 3;
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_QUADS:		return 4;
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_ISOLINES:	return 2;
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: DE_ASSERT(false); return -1;
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string tessellationLevelsString (const float* inner, int numInner, const float* outer, int numOuter)
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numInner >= 0 && numOuter >= 0);
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return "inner: " + elemsStr(inner, inner+numInner) + ", outer: " + elemsStr(outer, outer+numOuter);
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string tessellationLevelsString (const float* inner, const float* outer, TessPrimitiveType primType)
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tessellationLevelsString(inner, numInnerTessellationLevels(primType), outer, numOuterTessellationLevels(primType));
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string tessellationLevelsString (const float* inner, const float* outer)
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tessellationLevelsString(inner, 2, outer, 4);
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float getClampedTessLevel (SpacingMode mode, float tessLevel)
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_EQUAL:				return de::max(1.0f, tessLevel);
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_FRACTIONAL_ODD:	return de::max(1.0f, tessLevel);
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_FRACTIONAL_EVEN:	return de::max(2.0f, tessLevel);
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return -1.0f;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline int getRoundedTessLevel (SpacingMode mode, float clampedTessLevel)
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int result = (int)deFloatCeil(clampedTessLevel);
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_EQUAL:											break;
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_FRACTIONAL_ODD:	result += 1 - result % 2;	break;
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SPACINGMODE_FRACTIONAL_EVEN:	result += result % 2;		break;
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inRange<int>(result, 1, MINIMUM_MAX_TESS_GEN_LEVEL));
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getClampedRoundedTessLevel (SpacingMode mode, float tessLevel)
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getRoundedTessLevel(mode, getClampedTessLevel(mode, tessLevel));
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! A description of an outer edge of a triangle, quad or isolines.
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! An outer edge can be described by the index of a u/v/w coordinate
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! and the coordinate's value along that edge.
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct OuterEdgeDescription
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		constantCoordinateIndex;
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	constantCoordinateValueChoices[2];
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		numConstantCoordinateValueChoices;
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OuterEdgeDescription (int i, float c0)			: constantCoordinateIndex(i), numConstantCoordinateValueChoices(1) { constantCoordinateValueChoices[0] = c0; }
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OuterEdgeDescription (int i, float c0, float c1)	: constantCoordinateIndex(i), numConstantCoordinateValueChoices(2) { constantCoordinateValueChoices[0] = c0; constantCoordinateValueChoices[1] = c1; }
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string description (void) const
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const char* const	coordinateNames[] = { "u", "v", "w" };
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string						result;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < numConstantCoordinateValueChoices; i++)
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result += string() + (i > 0 ? " or " : "") + coordinateNames[constantCoordinateIndex] + "=" + de::toString(constantCoordinateValueChoices[i]);
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool contains (const Vec3& v) const
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < numConstantCoordinateValueChoices; i++)
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (v[constantCoordinateIndex] == constantCoordinateValueChoices[i])
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<OuterEdgeDescription> outerEdgeDescriptions (TessPrimitiveType primType)
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const OuterEdgeDescription triangleOuterEdgeDescriptions[3] =
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(0, 0.0f),
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(1, 0.0f),
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(2, 0.0f)
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const OuterEdgeDescription quadOuterEdgeDescriptions[4] =
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(0, 0.0f),
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(1, 0.0f),
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(0, 1.0f),
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(1, 1.0f)
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const OuterEdgeDescription isolinesOuterEdgeDescriptions[1] =
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OuterEdgeDescription(0, 0.0f, 1.0f),
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primType)
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_TRIANGLES:	return arrayToVector(triangleOuterEdgeDescriptions);
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_QUADS:		return arrayToVector(quadOuterEdgeDescriptions);
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_ISOLINES:	return arrayToVector(isolinesOuterEdgeDescriptions);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: DE_ASSERT(false); return vector<OuterEdgeDescription>();
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \note The tessellation coordinates generated by this function could break some of the rules given in the spec (e.g. it may not exactly hold that u+v+w == 1.0f, or [uvw] + (1.0f-[uvw]) == 1.0f).
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<Vec3> generateReferenceTriangleTessCoords (SpacingMode spacingMode, int inner, int outer0, int outer1, int outer2)
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec3> tessCoords;
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (inner == 1)
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (outer0 == 1 && outer1 == 1 && outer2 == 1)
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3(1.0f, 0.0f, 0.0f));
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3(0.0f, 1.0f, 0.0f));
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3(0.0f, 0.0f, 1.0f));
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return tessCoords;
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return generateReferenceTriangleTessCoords(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	outer0, outer1, outer2);
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(Vec3(	   0.0f,		   v,	1.0f - v)); }
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(Vec3(1.0f - v,		0.0f,		   v)); }
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(Vec3(		  v,	1.0f - v,		0.0f)); }
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numInnerTriangles = inner/2;
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curInnerTriangleLevel == 0)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tessCoords.push_back(Vec3(1.0f/3.0f));
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		minUVW		= (float)(2 * (innerTriangleNdx + 1)) / (float)(3 * inner);
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		maxUVW		= 1.0f - 2.0f*minUVW;
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Vec3		corners[3]	=
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Vec3(maxUVW, minUVW, minUVW),
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Vec3(minUVW, maxUVW, minUVW),
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Vec3(minUVW, minUVW, maxUVW)
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				};
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int i = 0; i < curInnerTriangleLevel; i++)
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float f = (float)i / (float)curInnerTriangleLevel;
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int j = 0; j < 3; j++)
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						tessCoords.push_back((1.0f - f)*corners[j] + f*corners[(j+1)%3]);
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tessCoords;
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int referenceTriangleNonPointModePrimitiveCount (SpacingMode spacingMode, int inner, int outer0, int outer1, int outer2)
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (inner == 1)
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (outer0 == 1 && outer1 == 1 && outer2 == 1)
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 1;
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return referenceTriangleNonPointModePrimitiveCount(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			outer0, outer1, outer2);
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int result = outer0 + outer1 + outer2;
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numInnerTriangles = inner/2;
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curInnerTriangleLevel == 1)
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result += 4;
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result += 2*3*curInnerTriangleLevel;
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \note The tessellation coordinates generated by this function could break some of the rules given in the spec (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<Vec3> generateReferenceQuadTessCoords (SpacingMode spacingMode, int inner0, int inner1, int outer0, int outer1, int outer2, int outer3)
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec3> tessCoords;
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (inner0 == 1 || inner1 == 1)
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3(0.0f, 0.0f, 0.0f));
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3(1.0f, 0.0f, 0.0f));
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3(0.0f, 1.0f, 0.0f));
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3(1.0f, 1.0f, 0.0f));
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return tessCoords;
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return generateReferenceQuadTessCoords(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																outer0, outer1, outer2, outer3);
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(Vec3(0.0f,	v,			0.0f)); }
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(Vec3(1.0f-v,	0.0f,		0.0f)); }
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(Vec3(1.0f,	1.0f-v,		0.0f)); }
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < outer3; i++) { const float v = (float)i / (float)outer3; tessCoords.push_back(Vec3(v,		1.0f,		0.0f)); }
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int innerVtxY = 0; innerVtxY < inner1-1; innerVtxY++)
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int innerVtxX = 0; innerVtxX < inner0-1; innerVtxX++)
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tessCoords.push_back(Vec3((float)(innerVtxX + 1) / (float)inner0,
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  (float)(innerVtxY + 1) / (float)inner1,
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  0.0f));
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tessCoords;
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int referenceQuadNonPointModePrimitiveCount (SpacingMode spacingMode, int inner0, int inner1, int outer0, int outer1, int outer2, int outer3)
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec3> tessCoords;
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (inner0 == 1 || inner1 == 1)
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 2;
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return referenceQuadNonPointModePrimitiveCount(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		outer0, outer1, outer2, outer3);
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 2*(inner0-2)*(inner1-2) + 2*(inner0-2) + 2*(inner1-2) + outer0+outer1+outer2+outer3;
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \note The tessellation coordinates generated by this function could break some of the rules given in the spec (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<Vec3> generateReferenceIsolineTessCoords (int outer0, int outer1)
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec3> tessCoords;
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < outer0;		y++)
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < outer1+1;	x++)
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tessCoords.push_back(Vec3((float)x / (float)outer1,
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  (float)y / (float)outer0,
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  0.0f));
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tessCoords;
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int referenceIsolineNonPointModePrimitiveCount (int outer0, int outer1)
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return outer0*outer1;
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void getClampedRoundedTriangleTessLevels (SpacingMode spacingMode, const float* innerSrc, const float* outerSrc, int* innerDst, int *outerDst)
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	innerDst[0] = getClampedRoundedTessLevel(spacingMode, innerSrc[0]);
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < 3; i++)
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void getClampedRoundedQuadTessLevels (SpacingMode spacingMode, const float* innerSrc, const float* outerSrc, int* innerDst, int *outerDst)
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < 2; i++)
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		innerDst[i] = getClampedRoundedTessLevel(spacingMode, innerSrc[i]);
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < 4; i++)
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void getClampedRoundedIsolineTessLevels (SpacingMode spacingMode, const float* outerSrc, int* outerDst)
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	outerDst[0] = getClampedRoundedTessLevel(SPACINGMODE_EQUAL,	outerSrc[0]);
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	outerDst[1] = getClampedRoundedTessLevel(spacingMode,		outerSrc[1]);
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isPatchDiscarded (TessPrimitiveType primitiveType, const float* outerLevels)
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int numOuterLevels = numOuterTessellationLevels(primitiveType);
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < numOuterLevels; i++)
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (outerLevels[i] <= 0.0f)
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return false;
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<Vec3> generateReferenceTessCoords (TessPrimitiveType primitiveType, SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isPatchDiscarded(primitiveType, outerLevels))
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return vector<Vec3>();
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveType)
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_TRIANGLES:
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inner;
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[3];
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (spacingMode != SPACINGMODE_EQUAL)
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \note For fractional spacing modes, exact results are implementation-defined except in special cases.
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(de::abs(innerLevels[0] - (float)inner) < 0.001f);
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int i = 0; i < 3; i++)
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(de::abs(outerLevels[i] - (float)outer[i]) < 0.001f);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(inner > 1 || (outer[0] == 1 && outer[1] == 1 && outer[2] == 1));
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]);
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_QUADS:
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inner[2];
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[4];
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (spacingMode != SPACINGMODE_EQUAL)
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \note For fractional spacing modes, exact results are implementation-defined except in special cases.
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int i = 0; i < 2; i++)
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(de::abs(innerLevels[i] - (float)inner[i]) < 0.001f);
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int i = 0; i < 4; i++)
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(de::abs(outerLevels[i] - (float)outer[i]) < 0.001f);
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT((inner[0] > 1 && inner[1] > 1) || (inner[0] == 1 && inner[1] == 1 && outer[0] == 1 && outer[1] == 1 && outer[2] == 1 && outer[3] == 1));
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]);
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_ISOLINES:
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[2];
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (spacingMode != SPACINGMODE_EQUAL)
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \note For fractional spacing modes, exact results are implementation-defined except in special cases.
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(de::abs(outerLevels[1] - (float)outer[1]) < 0.001f);
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return generateReferenceIsolineTessCoords(outer[0], outer[1]);
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return vector<Vec3>();
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int referencePointModePrimitiveCount (TessPrimitiveType primitiveType, SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isPatchDiscarded(primitiveType, outerLevels))
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveType)
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_TRIANGLES:
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inner;
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[3];
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (int)generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]).size();
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_QUADS:
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inner[2];
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[4];
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (int)generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]).size();
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_ISOLINES:
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[2];
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (int)generateReferenceIsolineTessCoords(outer[0], outer[1]).size();
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return -1;
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int referenceNonPointModePrimitiveCount (TessPrimitiveType primitiveType, SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isPatchDiscarded(primitiveType, outerLevels))
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primitiveType)
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_TRIANGLES:
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inner;
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[3];
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return referenceTriangleNonPointModePrimitiveCount(spacingMode, inner, outer[0], outer[1], outer[2]);
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_QUADS:
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int inner[2];
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[4];
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return referenceQuadNonPointModePrimitiveCount(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]);
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSPRIMITIVETYPE_ISOLINES:
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int outer[2];
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return referenceIsolineNonPointModePrimitiveCount(outer[0], outer[1]);
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return -1;
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int referencePrimitiveCount (TessPrimitiveType primitiveType, SpacingMode spacingMode, bool usePointMode, const float* innerLevels, const float* outerLevels)
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return usePointMode ? referencePointModePrimitiveCount		(primitiveType, spacingMode, innerLevels, outerLevels)
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: referenceNonPointModePrimitiveCount	(primitiveType, spacingMode, innerLevels, outerLevels);
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int referenceVertexCount (TessPrimitiveType primitiveType, SpacingMode spacingMode, bool usePointMode, const float* innerLevels, const float* outerLevels)
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return referencePrimitiveCount(primitiveType, spacingMode, usePointMode, innerLevels, outerLevels)
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   * numVerticesPerPrimitive(outputPrimitiveTypeGL(primitiveType, usePointMode));
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Helper for calling referenceVertexCount multiple times with different tessellation levels.
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! \note Levels contains inner and outer levels, per patch, in order IIOOOO. The full 6 levels must always be present, irrespective of primitiveType.
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int multiplePatchReferenceVertexCount (TessPrimitiveType primitiveType, SpacingMode spacingMode, bool usePointMode, const float* levels, int numPatches)
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int result = 0;
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int patchNdx = 0; patchNdx < numPatches; patchNdx++)
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += referenceVertexCount(primitiveType, spacingMode, usePointMode, &levels[6*patchNdx + 0], &levels[6*patchNdx + 2]);
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<float> generateRandomPatchTessLevels (int numPatches, int constantOuterLevelIndex, float constantOuterLevel, de::Random& rnd)
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float> tessLevels(numPatches*6);
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int patchNdx = 0; patchNdx < numPatches; patchNdx++)
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float* const inner = &tessLevels[patchNdx*6 + 0];
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float* const outer = &tessLevels[patchNdx*6 + 2];
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int j = 0; j < 2; j++)
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			inner[j] = rnd.getFloat(1.0f, 62.0f);
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int j = 0; j < 4; j++)
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			outer[j] = j == constantOuterLevelIndex ? constantOuterLevel : rnd.getFloat(1.0f, 62.0f);
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tessLevels;
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void drawPoint (tcu::Surface& dst, int centerX, int centerY, const tcu::RGBA& color, int size)
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int width		= dst.getWidth();
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int height	= dst.getHeight();
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds(centerX, 0, width) && de::inBounds(centerY, 0, height));
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(size > 0);
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int yOff = -((size-1)/2); yOff <= size/2; yOff++)
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int xOff = -((size-1)/2); xOff <= size/2; xOff++)
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int pixX = centerX + xOff;
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int pixY = centerY + yOff;
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (de::inBounds(pixX, 0, width) && de::inBounds(pixY, 0, height))
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(pixX, pixY, color);
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void drawTessCoordPoint (tcu::Surface& dst, TessPrimitiveType primitiveType, const Vec3& pt, const tcu::RGBA& color, int size)
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note These coordinates should match the description in the log message in TessCoordCase::iterate.
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const Vec2 triangleCorners[3] =
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2(0.95f, 0.95f),
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2(0.5f,  0.95f - 0.9f*deFloatSqrt(3.0f/4.0f)),
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2(0.05f, 0.95f)
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float quadIsolineLDRU[4] =
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0.1f, 0.9f, 0.9f, 0.1f
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 dstPos = primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? pt.x()*triangleCorners[0]
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 + pt.y()*triangleCorners[1]
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 + pt.z()*triangleCorners[2]
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  : primitiveType == TESSPRIMITIVETYPE_QUADS ||
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						primitiveType == TESSPRIMITIVETYPE_ISOLINES ? Vec2((1.0f - pt.x())*quadIsolineLDRU[0] + pt.x()*quadIsolineLDRU[2],
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		   (1.0f - pt.y())*quadIsolineLDRU[1] + pt.y()*quadIsolineLDRU[3])
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  : Vec2(-1.0f);
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawPoint(dst, (int)(dstPos.x()*dst.getWidth()), (int)(dstPos.y()*dst.getHeight()), color, size);
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void drawTessCoordVisualization (tcu::Surface& dst, TessPrimitiveType primitiveType, const vector<Vec3>& coords)
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		imageWidth		= 256;
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		imageHeight		= 256;
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.setSize(imageWidth, imageHeight);
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(dst.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < (int)coords.size(); i++)
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawTessCoordPoint(dst, primitiveType, coords[i], tcu::RGBA::white, 2);
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int binarySearchFirstVec3WithXAtLeast (const vector<Vec3>& sorted, float x)
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec3 ref(x, 0.0f, 0.0f);
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<Vec3>::const_iterator first = std::lower_bound(sorted.begin(), sorted.end(), ref, vec3XLessThan);
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (first == sorted.end())
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (int)std::distance(sorted.begin(), first);
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, typename P>
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<T> sorted (const vector<T>& unsorted, P pred)
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<T> result = unsorted;
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::sort(result.begin(), result.end(), pred);
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<T> sorted (const vector<T>& unsorted)
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<T> result = unsorted;
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::sort(result.begin(), result.end());
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Check that all points in subset are (approximately) present also in superset.
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool oneWayComparePointSets (TestLog&				log,
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									tcu::Surface&			errorDst,
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									TessPrimitiveType		primitiveType,
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const vector<Vec3>&		subset,
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const vector<Vec3>&		superset,
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const char*				subsetName,
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const char*				supersetName,
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const tcu::RGBA&		errorColor)
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<Vec3>	supersetSorted			= sorted(superset, vec3XLessThan);
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			epsilon					= 0.01f;
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			maxNumFailurePrints		= 5;
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailuresDetected		= 0;
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int subNdx = 0; subNdx < (int)subset.size(); subNdx++)
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec3& subPt = subset[subNdx];
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool matchFound = false;
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Binary search the index of the first point in supersetSorted with x in the [subPt.x() - epsilon, subPt.x() + epsilon] range.
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec3	matchMin			= subPt - epsilon;
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec3	matchMax			= subPt + epsilon;
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			firstCandidateNdx	= binarySearchFirstVec3WithXAtLeast(supersetSorted, matchMin.x());
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (firstCandidateNdx >= 0)
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compare subPt to all points in supersetSorted with x in the [subPt.x() - epsilon, subPt.x() + epsilon] range.
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int superNdx = firstCandidateNdx; superNdx < (int)supersetSorted.size() && supersetSorted[superNdx].x() <= matchMax.x(); superNdx++)
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const Vec3& superPt = supersetSorted[superNdx];
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (tcu::boolAll(tcu::greaterThanEqual	(superPt, matchMin)) &&
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						tcu::boolAll(tcu::lessThanEqual		(superPt, matchMax)))
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						matchFound = true;
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!matchFound)
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numFailuresDetected++;
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numFailuresDetected < maxNumFailurePrints)
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: no matching " << supersetName << " point found for " << subsetName << " point " << subPt << TestLog::EndMessage;
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (numFailuresDetected == maxNumFailurePrints)
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Note: More errors follow" << TestLog::EndMessage;
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			drawTessCoordPoint(errorDst, primitiveType, subPt, errorColor, 4);
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailuresDetected == 0;
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool compareTessCoords (TestLog& log, TessPrimitiveType primitiveType, const vector<Vec3>& refCoords, const vector<Vec3>& resCoords)
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	refVisual;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	resVisual;
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			success = true;
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawTessCoordVisualization(refVisual, primitiveType, refCoords);
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawTessCoordVisualization(resVisual, primitiveType, resCoords);
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check that all points in reference also exist in result.
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	success = oneWayComparePointSets(log, refVisual, primitiveType, refCoords, resCoords, "reference", "result", tcu::RGBA::blue) && success;
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check that all points in result also exist in reference.
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	success = oneWayComparePointSets(log, resVisual, primitiveType, resCoords, refCoords, "result", "reference", tcu::RGBA::red) && success;
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!success)
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Note: in the following reference visualization, points that are missing in result point set are blue (if any)" << TestLog::EndMessage
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("RefTessCoordVisualization", "Reference tessCoord visualization", refVisual)
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Message << "Note: in the following result visualization, points that are missing in reference point set are red (if any)" << TestLog::EndMessage;
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Image("ResTessCoordVisualization", "Result tessCoord visualization", resVisual);
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return success;
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace VerifyFractionalSpacingSingleInternal
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Segment
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		index; //!< Index of left coordinate in sortedXCoords.
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	length;
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Segment (void)						: index(-1),		length(-1.0f)	{}
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Segment (int index_, float length_)	: index(index_),	length(length_)	{}
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static vector<float> lengths (const vector<Segment>& segments) { return members(segments, &Segment::length); }
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Verify fractional spacing conditions for a single line
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Verify that the splitting of an edge (resulting from e.g. an isoline
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * with outer levels { 1.0, tessLevel }) with a given fractional spacing
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * mode fulfills certain conditions given in the spec.
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Note that some conditions can't be checked from just one line
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * (specifically, that the additional segment decreases monotonically
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * length and the requirement that the additional segments be placed
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * identically for identical values of clamped level).
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Therefore, the function stores some values to additionalSegmentLengthDst
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * and additionalSegmentLocationDst that can later be given to
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * verifyFractionalSpacingMultiple(). A negative value in length means that
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * no additional segments are present, i.e. there's just one segment.
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * A negative value in location means that the value wasn't determinable,
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * i.e. all segments had same length.
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The values are not stored if false is returned.
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool verifyFractionalSpacingSingle (TestLog& log, SpacingMode spacingMode, float tessLevel, const vector<float>& coords, float& additionalSegmentLengthDst, int& additionalSegmentLocationDst)
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace VerifyFractionalSpacingSingleInternal;
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(spacingMode == SPACINGMODE_FRACTIONAL_ODD || spacingMode == SPACINGMODE_FRACTIONAL_EVEN);
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float				clampedLevel	= getClampedTessLevel(spacingMode, tessLevel);
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				finalLevel		= getRoundedTessLevel(spacingMode, clampedLevel);
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<float>		sortedCoords	= sorted(coords);
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string					failNote		= "Note: tessellation level is " + de::toString(tessLevel) + "\nNote: sorted coordinates are:\n    " + containerStr(sortedCoords);
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((int)coords.size() != finalLevel + 1)
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Failure: number of vertices is " << coords.size() << "; expected " << finalLevel + 1
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< " (clamped tessellation level is " << clampedLevel << ")"
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "; final level (clamped level rounded up to " << (spacingMode == SPACINGMODE_FRACTIONAL_EVEN ? "even" : "odd") << ") is " << finalLevel
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< " and should equal the number of segments, i.e. number of vertices minus 1" << TestLog::EndMessage
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Message << failNote << TestLog::EndMessage;
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sortedCoords[0] != 0.0f || sortedCoords.back() != 1.0f)
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Failure: smallest coordinate should be 0.0 and biggest should be 1.0" << TestLog::EndMessage
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Message << failNote << TestLog::EndMessage;
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<Segment> segments(finalLevel);
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < finalLevel; i++)
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			segments[i] = Segment(i, sortedCoords[i+1] - sortedCoords[i]);
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		failNote += "\nNote: segment lengths are, from left to right:\n    " + containerStr(Segment::lengths(segments));
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Divide segments to two different groups based on length.
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<Segment> segmentsA;
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<Segment> segmentsB;
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			segmentsA.push_back(segments[0]);
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int segNdx = 1; segNdx < (int)segments.size(); segNdx++)
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		epsilon		= 0.001f;
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Segment&	seg			= segments[segNdx];
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (de::abs(seg.length - segmentsA[0].length) < epsilon)
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					segmentsA.push_back(seg);
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (segmentsB.empty() || de::abs(seg.length - segmentsB[0].length) < epsilon)
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					segmentsB.push_back(seg);
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: couldn't divide segments to 2 groups by length; "
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< "e.g. segment of length " << seg.length << " isn't approximately equal to either "
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< segmentsA[0].length << " or " << segmentsB[0].length << TestLog::EndMessage
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< TestLog::Message << failNote << TestLog::EndMessage;
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (clampedLevel == (float)finalLevel)
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// All segments should be of equal length.
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!segmentsA.empty() && !segmentsB.empty())
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: clamped and final tessellation level are equal, but not all segments are of equal length." << TestLog::EndMessage
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< TestLog::Message << failNote << TestLog::EndMessage;
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (segmentsA.empty() || segmentsB.empty()) // All segments have same length. This is ok.
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				additionalSegmentLengthDst		= segments.size() == 1 ? -1.0f : segments[0].length;
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				additionalSegmentLocationDst	= -1;
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (segmentsA.size() != 2 && segmentsB.size() != 2)
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: when dividing the segments to 2 groups by length, neither of the two groups has exactly 2 or 0 segments in it" << TestLog::EndMessage
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::Message << failNote << TestLog::EndMessage;
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// For convenience, arrange so that the 2-segment group is segmentsB.
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (segmentsB.size() != 2)
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::swap(segmentsA, segmentsB);
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note For 4-segment lines both segmentsA and segmentsB have 2 segments each.
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			//		 Thus, we can't be sure which ones were meant as the additional segments.
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			//		 We give the benefit of the doubt by assuming that they're the shorter
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			//		 ones (as they should).
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (segmentsA.size() != 2)
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (segmentsB[0].length > segmentsA[0].length + 0.001f)
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: the two additional segments are longer than the other segments" << TestLog::EndMessage
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< TestLog::Message << failNote << TestLog::EndMessage;
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1329b802d8a74b19daa161a07eca2a90bc4620b94021Jarkko Pöyry			else
1330b802d8a74b19daa161a07eca2a90bc4620b94021Jarkko Pöyry			{
1331b802d8a74b19daa161a07eca2a90bc4620b94021Jarkko Pöyry				// We have 2 segmentsA and 2 segmentsB, ensure segmentsB has the shorter lengths
1332b802d8a74b19daa161a07eca2a90bc4620b94021Jarkko Pöyry				if (segmentsB[0].length > segmentsA[0].length)
1333b802d8a74b19daa161a07eca2a90bc4620b94021Jarkko Pöyry					std::swap(segmentsA, segmentsB);
1334b802d8a74b19daa161a07eca2a90bc4620b94021Jarkko Pöyry			}
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Check that the additional segments are placed symmetrically.
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (segmentsB[0].index + segmentsB[1].index + 1 != (int)segments.size())
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: the two additional segments aren't placed symmetrically; "
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< "one is at index " << segmentsB[0].index << " and other is at index " << segmentsB[1].index
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< " (note: the two indexes should sum to " << (int)segments.size()-1 << ", i.e. numberOfSegments-1)" << TestLog::EndMessage
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::Message << failNote << TestLog::EndMessage;
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			additionalSegmentLengthDst = segmentsB[0].length;
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (segmentsA.size() != 2)
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				additionalSegmentLocationDst = de::min(segmentsB[0].index, segmentsB[1].index);
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				additionalSegmentLocationDst = segmentsB[0].length < segmentsA[0].length - 0.001f ? de::min(segmentsB[0].index, segmentsB[1].index)
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 : -1; // \note -1 when can't reliably decide which ones are the additional segments, a or b.
1352b802d8a74b19daa161a07eca2a90bc4620b94021Jarkko Pöyry
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace VerifyFractionalSpacingMultipleInternal
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct LineData
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	tessLevel;
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	additionalSegmentLength;
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		additionalSegmentLocation;
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LineData (float lev, float len, int loc) : tessLevel(lev), additionalSegmentLength(len), additionalSegmentLocation(loc) {}
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Verify fractional spacing conditions between multiple lines
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Verify the fractional spacing conditions that are not checked in
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * verifyFractionalSpacingSingle(). Uses values given by said function
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * as parameters, in addition to the spacing mode and tessellation level.
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool verifyFractionalSpacingMultiple (TestLog& log, SpacingMode spacingMode, const vector<float>& tessLevels, const vector<float>& additionalSegmentLengths, const vector<int>& additionalSegmentLocations)
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace VerifyFractionalSpacingMultipleInternal;
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(spacingMode == SPACINGMODE_FRACTIONAL_ODD || spacingMode == SPACINGMODE_FRACTIONAL_EVEN);
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(tessLevels.size() == additionalSegmentLengths.size() &&
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  tessLevels.size() == additionalSegmentLocations.size());
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<LineData> lineDatas;
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < (int)tessLevels.size(); i++)
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		lineDatas.push_back(LineData(tessLevels[i], additionalSegmentLengths[i], additionalSegmentLocations[i]));
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<LineData> lineDatasSortedByLevel = sorted(lineDatas, memberPred<std::less>(&LineData::tessLevel));
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Check that lines with identical clamped tessellation levels have identical additionalSegmentLocation.
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int lineNdx = 1; lineNdx < (int)lineDatasSortedByLevel.size(); lineNdx++)
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const LineData& curData		= lineDatasSortedByLevel[lineNdx];
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const LineData& prevData	= lineDatasSortedByLevel[lineNdx-1];
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curData.additionalSegmentLocation < 0 || prevData.additionalSegmentLocation < 0)
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue; // Unknown locations, skip.
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getClampedTessLevel(spacingMode, curData.tessLevel) == getClampedTessLevel(spacingMode, prevData.tessLevel) &&
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curData.additionalSegmentLocation != prevData.additionalSegmentLocation)
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: additional segments not located identically for two edges with identical clamped tessellation levels" << TestLog::EndMessage
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::Message << "Note: tessellation levels are " << curData.tessLevel << " and " << prevData.tessLevel
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< " (clamped level " << getClampedTessLevel(spacingMode, curData.tessLevel) << ")"
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< "; but first additional segments located at indices "
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< curData.additionalSegmentLocation << " and " << prevData.additionalSegmentLocation << ", respectively" << TestLog::EndMessage;
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Check that, among lines with same clamped rounded tessellation level, additionalSegmentLength is monotonically decreasing with "clampedRoundedTessLevel - clampedTessLevel" (the "fraction").
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int lineNdx = 1; lineNdx < (int)lineDatasSortedByLevel.size(); lineNdx++)
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const LineData&		curData				= lineDatasSortedByLevel[lineNdx];
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const LineData&		prevData			= lineDatasSortedByLevel[lineNdx-1];
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curData.additionalSegmentLength < 0.0f || prevData.additionalSegmentLength < 0.0f)
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue; // Unknown segment lengths, skip.
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float			curClampedLevel		= getClampedTessLevel(spacingMode, curData.tessLevel);
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float			prevClampedLevel	= getClampedTessLevel(spacingMode, prevData.tessLevel);
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int			curFinalLevel		= getRoundedTessLevel(spacingMode, curClampedLevel);
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int			prevFinalLevel		= getRoundedTessLevel(spacingMode, prevClampedLevel);
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curFinalLevel != prevFinalLevel)
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float			curFraction		= curFinalLevel - curClampedLevel;
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float			prevFraction	= prevFinalLevel - prevClampedLevel;
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curData.additionalSegmentLength < prevData.additionalSegmentLength ||
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(curClampedLevel == prevClampedLevel && curData.additionalSegmentLength != prevData.additionalSegmentLength))
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: additional segment length isn't monotonically decreasing with the fraction <n> - <f>, among edges with same final tessellation level" << TestLog::EndMessage
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::Message << "Note: <f> stands for the clamped tessellation level and <n> for the final (rounded and clamped) tessellation level" << TestLog::EndMessage
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::Message << "Note: two edges have tessellation levels " << prevData.tessLevel << " and " << curData.tessLevel << " respectively"
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< ", clamped " << prevClampedLevel << " and " << curClampedLevel << ", final " << prevFinalLevel << " and " << curFinalLevel
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< "; fractions are " << prevFraction << " and " << curFraction
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< ", but resulted in segment lengths " << prevData.additionalSegmentLength << " and " << curData.additionalSegmentLength << TestLog::EndMessage;
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Compare triangle sets, ignoring triangle order and vertex order within triangle, and possibly exclude some triangles too.
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename IsTriangleRelevantT>
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool compareTriangleSets (const vector<Vec3>&			coordsA,
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const vector<Vec3>&			coordsB,
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 TestLog&						log,
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const IsTriangleRelevantT&		isTriangleRelevant,
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const char*					ignoredTriangleDescription = DE_NULL)
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef tcu::Vector<Vec3, 3>							Triangle;
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef LexCompare<Triangle, 3, VecLexLessThan<3> >		TriangleLexLessThan;
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef std::set<Triangle, TriangleLexLessThan>			TriangleSet;
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(coordsA.size() % 3 == 0 && coordsB.size() % 3 == 0);
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numTrianglesA = (int)coordsA.size()/3;
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numTrianglesB = (int)coordsB.size()/3;
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TriangleSet		trianglesA;
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TriangleSet		trianglesB;
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int aOrB = 0; aOrB < 2; aOrB++)
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<Vec3>&		coords			= aOrB == 0 ? coordsA			: coordsB;
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numTriangles	= aOrB == 0 ? numTrianglesA		: numTrianglesB;
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TriangleSet&			triangles		= aOrB == 0 ? trianglesA		: trianglesB;
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int triNdx = 0; triNdx < numTriangles; triNdx++)
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Triangle triangle(coords[3*triNdx + 0],
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  coords[3*triNdx + 1],
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  coords[3*triNdx + 2]);
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isTriangleRelevant(triangle.getPtr()))
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::sort(triangle.getPtr(), triangle.getPtr()+3, VecLexLessThan<3>());
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				triangles.insert(triangle);
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TriangleSet::const_iterator aIt = trianglesA.begin();
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TriangleSet::const_iterator bIt = trianglesB.begin();
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (aIt != trianglesA.end() || bIt != trianglesB.end())
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool aEnd = aIt == trianglesA.end();
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool bEnd = bIt == trianglesB.end();
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (aEnd || bEnd || *aIt != *bIt)
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: triangle sets in two cases are not equal (when ignoring triangle and vertex order"
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< (ignoredTriangleDescription == DE_NULL ? "" : string() + ", and " + ignoredTriangleDescription) << ")" << TestLog::EndMessage;
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!aEnd && (bEnd || TriangleLexLessThan()(*aIt, *bIt)))
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Note: e.g. triangle " << *aIt << " exists for first case but not for second" << TestLog::EndMessage;
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Note: e.g. triangle " << *bIt << " exists for second case but not for first" << TestLog::EndMessage;
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			++aIt;
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			++bIt;
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool compareTriangleSets (const vector<Vec3>& coordsA, const vector<Vec3>& coordsB, TestLog& log)
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return compareTriangleSets(coordsA, coordsB, log, ConstantUnaryPredicate<const Vec3*, true>());
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void checkExtensionSupport (Context& context, const char* extName)
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!context.getContextInfo().isExtensionSupported(extName))
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError(string(extName) + " not supported");
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void checkTessellationSupport (Context& context)
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkExtensionSupport(context, "GL_EXT_tessellation_shader");
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Draw primitives with shared edges and check that no cracks are visible at the shared edges.
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CommonEdgeCase : public TestCase
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum CaseType
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_BASIC = 0,		//!< Order patch vertices such that when two patches share a vertex, it's at the same index for both.
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_PRECISE,		//!< Vertex indices don't match like for CASETYPE_BASIC, but other measures are taken, using the 'precise' qualifier.
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_LAST
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CommonEdgeCase (Context& context, const char* name, const char* description, TessPrimitiveType primitiveType, SpacingMode spacing, CaseType caseType)
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase			(context, name, description)
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType	(primitiveType)
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_spacing			(spacing)
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_caseType		(caseType)
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES || m_primitiveType == TESSPRIMITIVETYPE_QUADS);
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							init		(void);
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							deinit		(void);
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult					iterate		(void);
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				RENDER_SIZE = 256;
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType			m_primitiveType;
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode				m_spacing;
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseType					m_caseType;
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>	m_program;
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonEdgeCase::init (void)
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_caseType == CASETYPE_PRECISE)
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		checkExtensionSupport(m_context, "GL_EXT_gpu_shader5");
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_v_position;\n"
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_v_tessParam;\n"
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp vec2 in_tc_position;\n"
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_tc_tessParam;\n"
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_tc_position = in_v_position;\n"
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_tc_tessParam = in_v_tessParam;\n"
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationControlSource		("#version 310 es\n"
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + string(m_caseType == CASETYPE_PRECISE ? "#extension GL_EXT_gpu_shader5 : require\n" : "") +
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (vertices = " + string(m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? "3" : m_primitiveType == TESSPRIMITIVETYPE_QUADS ? "4" : DE_NULL) + ") out;\n"
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_tc_position[];\n"
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_tc_tessParam[];\n"
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp vec2 in_te_position[];\n"
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_caseType == CASETYPE_PRECISE ? "precise gl_TessLevelOuter;\n\n" : "") +
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_te_position[gl_InvocationID] = in_tc_position[gl_InvocationID];\n"
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[0] = 5.0;\n"
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[1] = 5.0;\n"
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_TessLevelOuter[0] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[1] + in_tc_tessParam[2]);\n"
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_TessLevelOuter[1] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[2] + in_tc_tessParam[0]);\n"
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_TessLevelOuter[2] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[0] + in_tc_tessParam[1]);\n"
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_primitiveType == TESSPRIMITIVETYPE_QUADS ?
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_TessLevelOuter[0] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[0] + in_tc_tessParam[2]);\n"
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_TessLevelOuter[1] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[1] + in_tc_tessParam[0]);\n"
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_TessLevelOuter[2] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[3] + in_tc_tessParam[1]);\n"
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_TessLevelOuter[3] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[2] + in_tc_tessParam[3]);\n"
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : DE_NULL) +
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + string(m_caseType == CASETYPE_PRECISE ? "#extension GL_EXT_gpu_shader5 : require\n" : "") +
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing) +
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_te_position[];\n"
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out mediump vec4 in_f_color;\n"
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_caseType == CASETYPE_PRECISE ? "precise gl_Position;\n\n" : "") +
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 pos = gl_TessCoord.x*in_te_position[0] + gl_TessCoord.y*in_te_position[1] + gl_TessCoord.z*in_te_position[2];\n"
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"\n"
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp float f = sqrt(3.0 * min(gl_TessCoord.x, min(gl_TessCoord.y, gl_TessCoord.z))) * 0.5 + 0.5;\n"
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	in_f_color = vec4(gl_TessCoord*f, 1.0);\n"
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_primitiveType == TESSPRIMITIVETYPE_QUADS ?
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													    string()
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														+ (m_caseType == CASETYPE_BASIC ?
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	highp vec2 pos = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*in_te_position[0]\n"
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	               + (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*in_te_position[1]\n"
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	               + (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*in_te_position[2]\n"
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	               + (    gl_TessCoord.x)*(    gl_TessCoord.y)*in_te_position[3];\n"
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 : m_caseType == CASETYPE_PRECISE ?
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	highp vec2 a = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*in_te_position[0];\n"
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	highp vec2 b = (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*in_te_position[1];\n"
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	highp vec2 c = (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*in_te_position[2];\n"
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	highp vec2 d = (    gl_TessCoord.x)*(    gl_TessCoord.y)*in_te_position[3];\n"
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															"	highp vec2 pos = a+b+c+d;\n"
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 : DE_NULL) +
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"\n"
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp float f = sqrt(1.0 - 2.0 * max(abs(gl_TessCoord.x - 0.5), abs(gl_TessCoord.y - 0.5)))*0.5 + 0.5;\n"
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	in_f_color = vec4(0.1, gl_TessCoord.xy*f, 1.0);\n"
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : DE_NULL) +
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	// Offset the position slightly, based on the parity of the bits in the float representation.\n"
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	// This is done to detect possible small differences in edge vertex positions between patches.\n"
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	uvec2 bits = floatBitsToUint(pos);\n"
16698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 "	uint numBits = 0u;\n"
16708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 "	for (uint i = 0u; i < 32u; i++)\n"
16718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 "		numBits += ((bits[0] >> i) & 1u) + ((bits[1] >> i) & 1u);\n"
16728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 "	pos += float(numBits&1u)*0.04;\n"
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(pos, 0.0, 1.0);\n"
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in mediump vec4 in_f_color;\n"
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = in_f_color;\n"
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")));
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonEdgeCase::deinit (void)
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16983c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonEdgeCase::IterateResult CommonEdgeCase::iterate (void)
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&					log						= m_testCtx.getLog();
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&		renderCtx				= m_context.getRenderContext();
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport		viewport				(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				programGL				= m_program->getProgram();
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl						= renderCtx.getFunctions();
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					gridWidth				= 4;
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					gridHeight				= 4;
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numVertices				= (gridWidth+1)*(gridHeight+1);
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numIndices				= gridWidth*gridHeight * (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3*2 : m_primitiveType == TESSPRIMITIVETYPE_QUADS ? 4 : -1);
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numPosCompsPerVertex	= 2;
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					totalNumPosComps		= numPosCompsPerVertex*numVertices;
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>				gridPosComps;
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>				gridTessParams;
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint16>			gridIndices;
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gridPosComps.reserve(totalNumPosComps);
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gridTessParams.reserve(numVertices);
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gridIndices.reserve(numIndices);
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < gridHeight+1; i++)
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int j = 0; j < gridWidth+1; j++)
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gridPosComps.push_back(-1.0f + 2.0f * ((float)j + 0.5f) / (float)(gridWidth+1));
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gridPosComps.push_back(-1.0f + 2.0f * ((float)i + 0.5f) / (float)(gridHeight+1));
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gridTessParams.push_back((float)(i*(gridWidth+1) + j) / (float)(numVertices-1));
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Generate patch vertex indices.
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note If CASETYPE_BASIC, the vertices are ordered such that when multiple
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 triangles/quads share a vertex, it's at the same index for everyone.
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < gridHeight; i++)
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int j = 0; j < gridWidth; j++)
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int corners[4] =
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(i+0)*(gridWidth+1) + j+0,
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(i+0)*(gridWidth+1) + j+1,
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(i+1)*(gridWidth+1) + j+0,
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(i+1)*(gridWidth+1) + j+1
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int secondTriangleVertexIndexOffset = m_caseType == CASETYPE_BASIC	? 0
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_PRECISE	? 1
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : -1;
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(secondTriangleVertexIndexOffset != -1);
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int k = 0; k < 3; k++)
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gridIndices.push_back(corners[(k+0 + i + (2-j%3)) % 3]);
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int k = 0; k < 3; k++)
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gridIndices.push_back(corners[(k+2 + i + (2-j%3) + secondTriangleVertexIndexOffset) % 3 + 1]);
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS)
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < gridHeight; i++)
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int j = 0; j < gridWidth; j++)
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note The vertices are ordered such that when multiple quads
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			//		 share a vertices, it's at the same index for everyone.
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int m = 0; m < 2; m++)
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int n = 0; n < 2; n++)
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gridIndices.push_back((i+(i+m)%2)*(gridWidth+1) + j+(j+n)%2);
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if(m_caseType == CASETYPE_PRECISE && (i+j) % 2 == 0)
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::reverse(gridIndices.begin() + (gridIndices.size() - 4),
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 gridIndices.begin() + gridIndices.size());
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)gridPosComps.size() == totalNumPosComps);
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)gridTessParams.size() == numVertices);
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)gridIndices.size() == numIndices);
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.patchParameteri(GL_PATCH_VERTICES, m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3 : m_primitiveType == TESSPRIMITIVETYPE_QUADS ? 4 : -1);
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding attrBindings[] =
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("in_v_position", numPosCompsPerVertex, numVertices, 0, &gridPosComps[0]),
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("in_v_tessParam", 1, numVertices, 0, &gridTessParams[0])
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(renderCtx, programGL, DE_LENGTH_OF_ARRAY(attrBindings), &attrBindings[0],
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::pr::Patches((int)gridIndices.size(), &gridIndices[0]));
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Surface rendered = getPixels(renderCtx, viewport);
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("RenderedImage", "Rendered Image", rendered)
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Message << "Note: coloring is done to clarify the positioning and orientation of the "
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? "triangles" : m_primitiveType == TESSPRIMITIVETYPE_QUADS ? "quads" : DE_NULL)
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< "; the color of a vertex corresponds to the index of that vertex in the patch"
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< TestLog::EndMessage;
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_caseType == CASETYPE_BASIC)
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Note: each shared vertex has the same index among the primitives it belongs to" << TestLog::EndMessage;
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_caseType == CASETYPE_PRECISE)
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Note: the 'precise' qualifier is used to avoid cracks between primitives" << TestLog::EndMessage;
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ad-hoc result verification - check that a certain rectangle in the image contains no black pixels.
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int startX	= (int)(0.15f * (float)rendered.getWidth());
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int endX		= (int)(0.85f * (float)rendered.getWidth());
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int startY	= (int)(0.15f * (float)rendered.getHeight());
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int endY		= (int)(0.85f * (float)rendered.getHeight());
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int y = startY; y < endY; y++)
18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = startX; x < endX; x++)
18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::RGBA pixel = rendered.getPixel(x, y);
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (pixel.getRed() == 0 && pixel.getGreen() == 0 && pixel.getBlue() == 0)
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: there seem to be cracks in the rendered result" << TestLog::EndMessage
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::Message << "Note: pixel with zero r, g and b channels found at " << tcu::IVec2(x, y) << TestLog::EndMessage;
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Success: there seem to be no cracks in the rendered result" << TestLog::EndMessage;
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Check tessellation coordinates (read with transform feedback).
18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TessCoordCase : public TestCase
18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					TessCoordCase (Context& context, const char* name, const char* description, TessPrimitiveType primitiveType, SpacingMode spacing)
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: TestCase			(context, name, description)
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_primitiveType	(primitiveType)
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_spacing			(spacing)
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			init		(void);
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			deinit		(void);
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult	iterate		(void);
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct TessLevels
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float inner[2];
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float outer[4];
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				RENDER_SIZE = 16;
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<TessLevels>				genTessLevelCases (void) const;
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType			m_primitiveType;
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode				m_spacing;
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>	m_program;
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessCoordCase::init (void)
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationControlSource		("#version 310 es\n"
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (vertices = 1) out;\n"
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelInner0;\n"
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelInner1;\n"
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelOuter0;\n"
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelOuter1;\n"
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelOuter2;\n"
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelOuter3;\n"
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[0] = u_tessLevelInner0;\n"
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[1] = u_tessLevelInner1;\n"
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[0] = u_tessLevelOuter0;\n"
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[1] = u_tessLevelOuter1;\n"
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[2] = u_tessLevelOuter2;\n"
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[3] = u_tessLevelOuter3;\n"
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing, true) +
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp vec3 out_te_tessCoord;\n"
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	out_te_tessCoord = gl_TessCoord;\n"
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(gl_TessCoord.xy*1.6 - 0.8, 0.0, 1.0);\n"
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = vec4(1.0);\n"
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TransformFeedbackVarying		("out_te_tessCoord")
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)));
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessCoordCase::deinit (void)
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<TessCoordCase::TessLevels> TessCoordCase::genTessLevelCases (void) const
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const TessLevels rawTessLevelCases[] =
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 1.0f,	1.0f	},	{ 1.0f,		1.0f,	1.0f,	1.0f	} },
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 63.0f,	24.0f	},	{ 15.0f,	42.0f,	10.0f,	12.0f	} },
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 3.0f,	2.0f	},	{ 6.0f,		8.0f,	7.0f,	9.0f	} },
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 4.0f,	6.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 2.0f,	2.0f	},	{ 6.0f,		8.0f,	7.0f,	9.0f	} },
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 5.0f,	6.0f	},	{ 1.0f,		1.0f,	1.0f,	1.0f	} },
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 1.0f,	6.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 5.0f,	1.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 5.2f,	1.6f	},	{ 2.9f,		3.4f,	1.5f,	4.1f	} }
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_spacing == SPACINGMODE_EQUAL)
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return vector<TessLevels>(DE_ARRAY_BEGIN(rawTessLevelCases), DE_ARRAY_END(rawTessLevelCases));
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<TessLevels> result;
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result.reserve(DE_LENGTH_OF_ARRAY(rawTessLevelCases));
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < DE_LENGTH_OF_ARRAY(rawTessLevelCases); tessLevelCaseNdx++)
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TessLevels curTessLevelCase = rawTessLevelCases[tessLevelCaseNdx];
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float* const inner = &curTessLevelCase.inner[0];
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float* const outer = &curTessLevelCase.outer[0];
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int j = 0; j < 2; j++) inner[j] = (float)getClampedRoundedTessLevel(m_spacing, inner[j]);
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int j = 0; j < 4; j++) outer[j] = (float)getClampedRoundedTessLevel(m_spacing, outer[j]);
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (outer[0] > 1.0f || outer[1] > 1.0f || outer[2] > 1.0f)
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (inner[0] == 1.0f)
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						inner[0] = (float)getClampedRoundedTessLevel(m_spacing, inner[0] + 0.1f);
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS)
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (outer[0] > 1.0f || outer[1] > 1.0f || outer[2] > 1.0f || outer[3] > 1.0f)
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (inner[0] == 1.0f) inner[0] = (float)getClampedRoundedTessLevel(m_spacing, inner[0] + 0.1f);
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (inner[1] == 1.0f) inner[1] = (float)getClampedRoundedTessLevel(m_spacing, inner[1] + 0.1f);
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result.push_back(curTessLevelCase);
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT((int)result.size() == DE_LENGTH_OF_ARRAY(rawTessLevelCases));
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20053c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessCoordCase::IterateResult TessCoordCase::iterate (void)
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<Vec3> TFHandler;
20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&						log							= m_testCtx.getLog();
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&			renderCtx					= m_context.getRenderContext();
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport			viewport					(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32					programGL					= m_program->getProgram();
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl							= renderCtx.getFunctions();
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						tessLevelInner0Loc			= gl.getUniformLocation(programGL, "u_tessLevelInner0");
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						tessLevelInner1Loc			= gl.getUniformLocation(programGL, "u_tessLevelInner1");
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						tessLevelOuter0Loc			= gl.getUniformLocation(programGL, "u_tessLevelOuter0");
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						tessLevelOuter1Loc			= gl.getUniformLocation(programGL, "u_tessLevelOuter1");
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						tessLevelOuter2Loc			= gl.getUniformLocation(programGL, "u_tessLevelOuter2");
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						tessLevelOuter3Loc			= gl.getUniformLocation(programGL, "u_tessLevelOuter3");
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<TessLevels>		tessLevelCases				= genTessLevelCases();
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<vector<Vec3> >			caseReferences				(tessLevelCases.size());
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < (int)tessLevelCases.size(); i++)
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		caseReferences[i] = generateReferenceTessCoords(m_primitiveType, m_spacing, &tessLevelCases[i].inner[0], &tessLevelCases[i].outer[0]);
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						maxNumVertices				= (int)std::max_element(caseReferences.begin(), caseReferences.end(), SizeLessThan<vector<Vec3> >())->size();
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TFHandler					tfHandler					(m_context.getRenderContext(), maxNumVertices);
20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							success						= true;
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 1);
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < (int)tessLevelCases.size(); tessLevelCaseNdx++)
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float* const innerLevels = &tessLevelCases[tessLevelCaseNdx].inner[0];
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float* const outerLevels = &tessLevelCases[tessLevelCaseNdx].outer[0];
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Tessellation levels: " << tessellationLevelsString(innerLevels, outerLevels, m_primitiveType) << TestLog::EndMessage;
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(tessLevelInner0Loc, innerLevels[0]);
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(tessLevelInner1Loc, innerLevels[1]);
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(tessLevelOuter0Loc, outerLevels[0]);
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(tessLevelOuter1Loc, outerLevels[1]);
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(tessLevelOuter2Loc, outerLevels[2]);
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(tessLevelOuter3Loc, outerLevels[3]);
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Setup failed");
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const vector<Vec3>&			tessCoordsRef	= caseReferences[tessLevelCaseNdx];
20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler::Result		tfResult		= tfHandler.renderAndGetPrimitives(programGL, GL_POINTS, 0, DE_NULL, 1);
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (tfResult.numPrimitives != (int)tessCoordsRef.size())
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: GL reported GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN to be "
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< tfResult.numPrimitives << ", reference value is " << tessCoordsRef.size()
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< " (logging further info anyway)" << TestLog::EndMessage;
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				success = false;
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Note: GL reported GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN to be " << tfResult.numPrimitives << TestLog::EndMessage;
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Note: in the following visualization(s), the u=1, v=1, w=1 corners are at the right, top, and left corners, respectively" << TestLog::EndMessage;
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS || m_primitiveType == TESSPRIMITIVETYPE_ISOLINES)
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Note: in the following visualization(s), u and v coordinate go left-to-right and bottom-to-top, respectively" << TestLog::EndMessage;
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			success = compareTessCoords(log, m_primitiveType, tessCoordsRef, tfResult.varying) && success;
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!success)
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "All OK" << TestLog::EndMessage;
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, success ? "Pass" : "Invalid tessellation coordinates");
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Check validity of fractional spacing modes. Draws a single isoline, reads tesscoords with transform feedback.
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FractionalSpacingModeCase : public TestCase
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					FractionalSpacingModeCase (Context& context, const char* name, const char* description, SpacingMode spacing)
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: TestCase	(context, name, description)
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_spacing	(spacing)
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(m_spacing == SPACINGMODE_FRACTIONAL_EVEN || m_spacing == SPACINGMODE_FRACTIONAL_ODD);
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			init		(void);
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			deinit		(void);
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult	iterate		(void);
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				RENDER_SIZE = 16;
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static vector<float>			genTessLevelCases (void);
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode				m_spacing;
21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>	m_program;
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FractionalSpacingModeCase::init (void)
21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationControlSource		("#version 310 es\n"
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (vertices = 1) out;\n"
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelOuter1;\n"
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[0] = 1.0;\n"
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[1] = u_tessLevelOuter1;\n"
21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(TESSPRIMITIVETYPE_ISOLINES, m_spacing, true) +
21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float out_te_tessCoord;\n"
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	out_te_tessCoord = gl_TessCoord.x;\n"
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(gl_TessCoord.xy*1.6 - 0.8, 0.0, 1.0);\n"
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = vec4(1.0);\n"
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TransformFeedbackVarying		("out_te_tessCoord")
21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)));
21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FractionalSpacingModeCase::deinit (void)
21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<float> FractionalSpacingModeCase::genTessLevelCases (void)
21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float> result;
21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Ranges [7.0 .. 8.0), [8.0 .. 9.0) and [9.0 .. 10.0)
21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const float	rangeStarts[]		= { 7.0f, 8.0f, 9.0f };
21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numSamplesPerRange	= 10;
21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int rangeNdx = 0; rangeNdx < DE_LENGTH_OF_ARRAY(rangeStarts); rangeNdx++)
21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int i = 0; i < numSamplesPerRange; i++)
21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.push_back(rangeStarts[rangeNdx] + (float)i/(float)numSamplesPerRange);
21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// 0.3, 1.3, 2.3,  ... , 62.3
21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i <= 62; i++)
21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result.push_back((float)i + 0.3f);
21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21933c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFractionalSpacingModeCase::IterateResult FractionalSpacingModeCase::iterate (void)
21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<float> TFHandler;
21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&						log							= m_testCtx.getLog();
21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&			renderCtx					= m_context.getRenderContext();
21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport			viewport					(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32					programGL					= m_program->getProgram();
22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl							= renderCtx.getFunctions();
22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						tessLevelOuter1Loc			= gl.getUniformLocation(programGL, "u_tessLevelOuter1");
22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Second outer tessellation levels.
22063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<float>				tessLevelCases				= genTessLevelCases();
22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						maxNumVertices				= 1 + getClampedRoundedTessLevel(m_spacing, *std::max_element(tessLevelCases.begin(), tessLevelCases.end()));
22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>					additionalSegmentLengths;
22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>						additionalSegmentLocations;
22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TFHandler					tfHandler					(m_context.getRenderContext(), maxNumVertices);
22123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							success						= true;
22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 1);
22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < (int)tessLevelCases.size(); tessLevelCaseNdx++)
22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float outerLevel1 = tessLevelCases[tessLevelCaseNdx];
22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(tessLevelOuter1Loc, outerLevel1);
22253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Setup failed");
22263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler::Result		tfResult = tfHandler.renderAndGetPrimitives(programGL, GL_POINTS, 0, DE_NULL, 1);
22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float						additionalSegmentLength;
22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int							additionalSegmentLocation;
22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			success = verifyFractionalSpacingSingle(log, m_spacing, outerLevel1, tfResult.varying,
22333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													additionalSegmentLength, additionalSegmentLocation);
22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!success)
22363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			additionalSegmentLengths.push_back(additionalSegmentLength);
22393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			additionalSegmentLocations.push_back(additionalSegmentLocation);
22403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (success)
22443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		success = verifyFractionalSpacingMultiple(log, m_spacing, tessLevelCases, additionalSegmentLengths, additionalSegmentLocations);
22453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, success ? "Pass" : "Invalid tessellation coordinates");
22473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
22483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
22493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Base class for a case with one input attribute (in_v_position) and optionally a TCS; tests with a couple of different sets of tessellation levels.
22513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BasicVariousTessLevelsPosAttrCase : public TestCase
22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
22533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					BasicVariousTessLevelsPosAttrCase (Context&				context,
22553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   const char*			name,
22563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   const char*			description,
22573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   TessPrimitiveType	primitiveType,
22583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   SpacingMode			spacing,
22593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   const char*			referenceImagePathPrefix)
22603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: TestCase						(context, name, description)
22613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_primitiveType				(primitiveType)
22623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_spacing						(spacing)
22633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_referenceImagePathPrefix	(referenceImagePathPrefix)
22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
22663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			init			(void);
22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			deinit			(void);
22693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult	iterate			(void);
22703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual const glu::ProgramSources	makeSources (TessPrimitiveType, SpacingMode, const char* vtxOutPosAttrName) const = DE_NULL;
22733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int					RENDER_SIZE = 256;
22763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType				m_primitiveType;
22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode					m_spacing;
22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string						m_referenceImagePathPrefix;
22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>		m_program;
22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BasicVariousTessLevelsPosAttrCase::init (void)
22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::ProgramSources sources = makeSources(m_primitiveType, m_spacing, "in_tc_position");
22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].empty());
22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << glu::TessellationControlSource(	"#version 310 es\n"
22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"\n"
22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"layout (vertices = " + string(m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? "3" : "4") + ") out;\n"
22973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"\n"
22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"in highp vec2 in_tc_position[];\n"
22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"\n"
23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"out highp vec2 in_te_position[];\n"
23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"\n"
23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"uniform mediump float u_tessLevelInner0;\n"
23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"uniform mediump float u_tessLevelInner1;\n"
23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"uniform mediump float u_tessLevelOuter0;\n"
23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"uniform mediump float u_tessLevelOuter1;\n"
23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"uniform mediump float u_tessLevelOuter2;\n"
23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"uniform mediump float u_tessLevelOuter3;\n"
23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"\n"
23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"void main (void)\n"
23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"{\n"
23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	in_te_position[gl_InvocationID] = in_tc_position[gl_InvocationID];\n"
23123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"\n"
23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelInner[0] = u_tessLevelInner0;\n"
23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelInner[1] = u_tessLevelInner1;\n"
23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"\n"
23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[0] = u_tessLevelOuter0;\n"
23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[1] = u_tessLevelOuter1;\n"
23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[2] = u_tessLevelOuter2;\n"
23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[3] = u_tessLevelOuter3;\n"
23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"}\n");
23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_program = SharedPtr<const ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), sources));
23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BasicVariousTessLevelsPosAttrCase::deinit (void)
23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBasicVariousTessLevelsPosAttrCase::IterateResult BasicVariousTessLevelsPosAttrCase::iterate (void)
23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float inner[2];
23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float outer[4];
23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} tessLevelCases[] =
23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 9.0f,	9.0f	},	{ 9.0f,		9.0f,	9.0f,	9.0f	} },
23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 8.0f,	11.0f	},	{ 13.0f,	15.0f,	18.0f,	21.0f	} },
23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 17.0f,	14.0f	},	{ 3.0f,		6.0f,	9.0f,	12.0f	} }
23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
23473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log					= m_testCtx.getLog();
23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx			= m_context.getRenderContext();
23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport	viewport			(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			programGL			= m_program->getProgram();
23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= renderCtx.getFunctions();
23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				patchSize			= m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES	? 3
23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												: m_primitiveType == TESSPRIMITIVETYPE_QUADS		? 4
23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												: m_primitiveType == TESSPRIMITIVETYPE_ISOLINES		? 4
23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												: -1;
23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, patchSize);
23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < DE_LENGTH_OF_ARRAY(tessLevelCases); tessLevelCaseNdx++)
23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float innerLevels[2];
23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float outerLevels[4];
23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < DE_LENGTH_OF_ARRAY(innerLevels); i++)
23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			innerLevels[i] = (float)getClampedRoundedTessLevel(m_spacing, tessLevelCases[tessLevelCaseNdx].inner[i]);
23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < DE_LENGTH_OF_ARRAY(outerLevels); i++)
23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			outerLevels[i] = (float)getClampedRoundedTessLevel(m_spacing, tessLevelCases[tessLevelCaseNdx].outer[i]);
23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Tessellation levels: " << tessellationLevelsString(&innerLevels[0], &outerLevels[0], m_primitiveType) << TestLog::EndMessage;
23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(programGL, "u_tessLevelInner0"), innerLevels[0]);
23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(programGL, "u_tessLevelInner1"), innerLevels[1]);
23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(programGL, "u_tessLevelOuter0"), outerLevels[0]);
23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(programGL, "u_tessLevelOuter1"), outerLevels[1]);
23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(programGL, "u_tessLevelOuter2"), outerLevels[2]);
23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(programGL, "u_tessLevelOuter3"), outerLevels[3]);
23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<Vec2> positions;
23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			positions.reserve(4);
23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
23913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positions.push_back(Vec2( 0.8f,    0.6f));
23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positions.push_back(Vec2( 0.0f, -0.786f));
23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positions.push_back(Vec2(-0.8f,    0.6f));
23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS || m_primitiveType == TESSPRIMITIVETYPE_ISOLINES)
23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positions.push_back(Vec2(-0.8f, -0.8f));
23993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positions.push_back(Vec2( 0.8f, -0.8f));
24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positions.push_back(Vec2(-0.8f,  0.8f));
24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				positions.push_back(Vec2( 0.8f,  0.8f));
24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT((int)positions.size() == patchSize);
24073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::VertexArrayBinding attrBindings[] =
24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::va::Float("in_v_position", 2, (int)positions.size(), 0, &positions[0].x())
24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::draw(m_context.getRenderContext(), programGL, DE_LENGTH_OF_ARRAY(attrBindings), &attrBindings[0],
24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::pr::Patches(patchSize));
24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Surface			rendered	= getPixels(renderCtx, viewport);
24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::TextureLevel		reference	= getPNG(m_testCtx.getArchive(), m_referenceImagePathPrefix + "_" + de::toString(tessLevelCaseNdx) + ".png");
24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					success		= tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", reference.getAccess(), rendered.getAccess(), 0.002f, tcu::COMPARE_LOG_RESULT);
24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!success)
24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
24323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
24333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Test that there are no obvious gaps in the triangulation of a tessellated triangle or quad.
24363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BasicTriangleFillCoverCase : public BasicVariousTessLevelsPosAttrCase
24373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BasicTriangleFillCoverCase (Context& context, const char* name, const char* description, TessPrimitiveType primitiveType, SpacingMode spacing, const char* referenceImagePathPrefix)
24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: BasicVariousTessLevelsPosAttrCase (context, name, description, primitiveType, spacing, referenceImagePathPrefix)
24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS);
24433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
24467f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry	void init (void)
24477f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry	{
24487f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry		checkExtensionSupport(m_context, "GL_EXT_gpu_shader5");
24497f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry		BasicVariousTessLevelsPosAttrCase::init();
24507f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry	}
24517f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry
24523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ProgramSources makeSources (TessPrimitiveType primitiveType, SpacingMode spacing, const char* vtxOutPosAttrName) const
24533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return glu::ProgramSources()
24553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
24563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
24573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_v_position;\n"
24583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
24593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp vec2 " + string(vtxOutPosAttrName) + ";\n"
24603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
24613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
24623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
24633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	" + vtxOutPosAttrName + " = in_v_position;\n"
24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
24673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
24687f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry													 "#extension GL_EXT_gpu_shader5 : require\n"
24693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(primitiveType, spacing) +
24713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_te_position[];\n"
24733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
24747f553a46ae44aeab4277e572bf61fb59b29f1208Jarkko Pöyry													 "precise gl_Position;\n"
24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"\n"
24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp float d = 3.0 * min(gl_TessCoord.x, min(gl_TessCoord.y, gl_TessCoord.z));\n"
24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner0 = in_te_position[0];\n"
24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner1 = in_te_position[1];\n"
24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner2 = in_te_position[2];\n"
24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 pos =  corner0*gl_TessCoord.x + corner1*gl_TessCoord.y + corner2*gl_TessCoord.z;\n"
24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 fromCenter = pos - (corner0 + corner1 + corner2) / 3.0;\n"
24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp float f = (1.0 - length(fromCenter)) * (1.5 - d);\n"
24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	pos += 0.75 * f * fromCenter / (length(fromCenter) + 0.3);\n"
24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_Position = vec4(pos, 0.0, 1.0);\n"
24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : primitiveType == TESSPRIMITIVETYPE_QUADS ?
24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner0 = in_te_position[0];\n"
24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner1 = in_te_position[1];\n"
24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner2 = in_te_position[2];\n"
24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner3 = in_te_position[3];\n"
24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 pos = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner0\n"
24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	               + (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner1\n"
24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	               + (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*corner2\n"
24963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	               + (    gl_TessCoord.x)*(    gl_TessCoord.y)*corner3;\n"
24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp float d = 2.0 * min(abs(gl_TessCoord.x-0.5), abs(gl_TessCoord.y-0.5));\n"
24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 fromCenter = pos - (corner0 + corner1 + corner2 + corner3) / 4.0;\n"
24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp float f = (1.0 - length(fromCenter)) * sqrt(1.7 - d);\n"
25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	pos += 0.75 * f * fromCenter / (length(fromCenter) + 0.3);\n"
25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_Position = vec4(pos, 0.0, 1.0);\n"
25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : DE_NULL) +
25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = vec4(1.0);\n"
25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n");
25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Check that there are no obvious overlaps in the triangulation of a tessellated triangle or quad.
25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BasicTriangleFillNonOverlapCase : public BasicVariousTessLevelsPosAttrCase
25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BasicTriangleFillNonOverlapCase (Context& context, const char* name, const char* description, TessPrimitiveType primitiveType, SpacingMode spacing, const char* referenceImagePathPrefix)
25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: BasicVariousTessLevelsPosAttrCase (context, name, description, primitiveType, spacing, referenceImagePathPrefix)
25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS);
25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ProgramSources makeSources (TessPrimitiveType primitiveType, SpacingMode spacing, const char* vtxOutPosAttrName) const
25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return glu::ProgramSources()
25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_v_position;\n"
25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp vec2 " + string(vtxOutPosAttrName) + ";\n"
25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	" + vtxOutPosAttrName + " = in_v_position;\n"
25393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(primitiveType, spacing) +
25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_te_position[];\n"
25473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out mediump vec4 in_f_color;\n"
25493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelInner0;\n"
25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelInner1;\n"
25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"\n"
25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner0 = in_te_position[0];\n"
25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner1 = in_te_position[1];\n"
25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner2 = in_te_position[2];\n"
25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 pos =  corner0*gl_TessCoord.x + corner1*gl_TessCoord.y + corner2*gl_TessCoord.z;\n"
25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_Position = vec4(pos, 0.0, 1.0);\n"
25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp int numConcentricTriangles = int(round(u_tessLevelInner0)) / 2 + 1;\n"
25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp float d = 3.0 * min(gl_TessCoord.x, min(gl_TessCoord.y, gl_TessCoord.z));\n"
25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp int phase = int(d*float(numConcentricTriangles)) % 3;\n"
25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	in_f_color = phase == 0 ? vec4(1.0, 0.0, 0.0, 1.0)\n"
25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	           : phase == 1 ? vec4(0.0, 1.0, 0.0, 1.0)\n"
25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	           :              vec4(0.0, 0.0, 1.0, 1.0);\n"
25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : primitiveType == TESSPRIMITIVETYPE_QUADS ?
25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner0 = in_te_position[0];\n"
25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner1 = in_te_position[1];\n"
25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner2 = in_te_position[2];\n"
25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 corner3 = in_te_position[3];\n"
25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp vec2 pos = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner0\n"
25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	               + (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner1\n"
25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	               + (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*corner2\n"
25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	               + (    gl_TessCoord.x)*(    gl_TessCoord.y)*corner3;\n"
25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_Position = vec4(pos, 0.0, 1.0);\n"
25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp int phaseX = int(round((0.5 - abs(gl_TessCoord.x-0.5)) * u_tessLevelInner0));\n"
25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp int phaseY = int(round((0.5 - abs(gl_TessCoord.y-0.5)) * u_tessLevelInner1));\n"
25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	highp int phase = min(phaseX, phaseY) % 3;\n"
25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	in_f_color = phase == 0 ? vec4(1.0, 0.0, 0.0, 1.0)\n"
25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	           : phase == 1 ? vec4(0.0, 1.0, 0.0, 1.0)\n"
25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	           :              vec4(0.0, 0.0, 1.0, 1.0);\n"
25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : DE_NULL) +
25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in mediump vec4 in_f_color;\n"
25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = in_f_color;\n"
25963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n");
25973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
25993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Basic isolines rendering case.
26013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsolinesRenderCase : public BasicVariousTessLevelsPosAttrCase
26023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
26043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IsolinesRenderCase (Context& context, const char* name, const char* description, SpacingMode spacing, const char* referenceImagePathPrefix)
26053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: BasicVariousTessLevelsPosAttrCase (context, name, description, TESSPRIMITIVETYPE_ISOLINES, spacing, referenceImagePathPrefix)
26063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
26103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ProgramSources makeSources (TessPrimitiveType primitiveType, SpacingMode spacing, const char* vtxOutPosAttrName) const
26113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primitiveType == TESSPRIMITIVETYPE_ISOLINES);
26133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_UNREF(primitiveType);
26143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return glu::ProgramSources()
26163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
26173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_v_position;\n"
26193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp vec2 " + string(vtxOutPosAttrName) + ";\n"
26213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
26233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
26243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	" + vtxOutPosAttrName + " = in_v_position;\n"
26253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
26263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
26283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
26293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(TESSPRIMITIVETYPE_ISOLINES, spacing) +
26313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp vec2 in_te_position[];\n"
26333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out mediump vec4 in_f_color;\n"
26353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelOuter0;\n"
26373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform mediump float u_tessLevelOuter1;\n"
26383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
26403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
26413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp vec2 corner0 = in_te_position[0];\n"
26423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp vec2 corner1 = in_te_position[1];\n"
26433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp vec2 corner2 = in_te_position[2];\n"
26443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp vec2 corner3 = in_te_position[3];\n"
26453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp vec2 pos = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner0\n"
26463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	               + (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner1\n"
26473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	               + (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*corner2\n"
26483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	               + (    gl_TessCoord.x)*(    gl_TessCoord.y)*corner3;\n"
26493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	pos.y += 0.15*sin(gl_TessCoord.x*10.0);\n"
26503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(pos, 0.0, 1.0);\n"
26513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp int phaseX = int(round(gl_TessCoord.x*u_tessLevelOuter1));\n"
26523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp int phaseY = int(round(gl_TessCoord.y*u_tessLevelOuter0));\n"
26533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp int phase = (phaseX + phaseY) % 3;\n"
26543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_f_color = phase == 0 ? vec4(1.0, 0.0, 0.0, 1.0)\n"
26553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	           : phase == 1 ? vec4(0.0, 1.0, 0.0, 1.0)\n"
26563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	           :              vec4(0.0, 0.0, 1.0, 1.0);\n"
26573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
26583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
26603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
26623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in mediump vec4 in_f_color;\n"
26643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
26653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
26663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
26673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = in_f_color;\n"
26683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n");
26693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
26713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Test the "cw" and "ccw" TES input layout qualifiers.
26733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass WindingCase : public TestCase
26743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
26763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					WindingCase (Context& context, const char* name, const char* description, TessPrimitiveType primitiveType, Winding winding)
26773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: TestCase			(context, name, description)
26783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_primitiveType	(primitiveType)
26793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_winding			(winding)
26803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
26813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS);
26823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
26833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			init		(void);
26853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			deinit		(void);
26863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult	iterate		(void);
26873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
26893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				RENDER_SIZE = 64;
26903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType			m_primitiveType;
26923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Winding					m_winding;
26933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>	m_program;
26953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
26963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid WindingCase::init (void)
26983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
27003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
27013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
27033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
27043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
27063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
27073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
27083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationControlSource		("#version 310 es\n"
27103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
27113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (vertices = 1) out;\n"
27133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
27153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
27163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[0] = 5.0;\n"
27173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[1] = 5.0;\n"
27183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[0] = 5.0;\n"
27203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[1] = 5.0;\n"
27213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[2] = 5.0;\n"
27223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[3] = 5.0;\n"
27233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
27243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
27263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
27273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(m_primitiveType, m_winding) +
27293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
27313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
27323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(gl_TessCoord.xy*2.0 - 1.0, 0.0, 1.0);\n"
27333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
27343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
27363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
27383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
27393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
27403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
27413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = vec4(1.0);\n"
27423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")));
27433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
27453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
27463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
27473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
27483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid WindingCase::deinit (void)
27503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
27523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
27533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27543c827367444ee418f129b2c238299f49d3264554Jarkko PoyryWindingCase::IterateResult WindingCase::iterate (void)
27553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&						log							= m_testCtx.getLog();
27573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&			renderCtx					= m_context.getRenderContext();
27583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport			viewport					(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
27593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32					programGL					= m_program->getProgram();
27603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl							= renderCtx.getFunctions();
27613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VertexArray			vao							(renderCtx);
27623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							success						= true;
27643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
27663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
27673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
27683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 1);
27703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.enable(GL_CULL_FACE);
27723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(*vao);
27743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Face culling enabled" << TestLog::EndMessage;
27763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int frontFaceWinding = 0; frontFaceWinding < WINDING_LAST; frontFaceWinding++)
27783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Setting glFrontFace(" << (frontFaceWinding == WINDING_CW ? "GL_CW" : "GL_CCW") << ")" << TestLog::EndMessage;
27803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.frontFace(frontFaceWinding == WINDING_CW ? GL_CW : GL_CCW);
27823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
27843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.drawArrays(GL_PATCHES, 0, 1);
27853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
27863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Surface rendered = getPixels(renderCtx, viewport);
27893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Image("RenderedImage", "Rendered Image", rendered);
27903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
27923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int totalNumPixels		= rendered.getWidth()*rendered.getHeight();
27933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int badPixelTolerance		= m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 5*de::max(rendered.getWidth(), rendered.getHeight()) : 0;
27943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int numWhitePixels	= 0;
27963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int numRedPixels	= 0;
27973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int y = 0; y < rendered.getHeight();	y++)
27983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int x = 0; x < rendered.getWidth();	x++)
27993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
28003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numWhitePixels	+= rendered.getPixel(x, y) == tcu::RGBA::white	? 1 : 0;
28013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numRedPixels	+= rendered.getPixel(x, y) == tcu::RGBA::red	? 1 : 0;
28023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
28033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(numWhitePixels + numRedPixels <= totalNumPixels);
28053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Note: got " << numWhitePixels << " white and " << numRedPixels << " red pixels" << TestLog::EndMessage;
28073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (totalNumPixels - numWhitePixels - numRedPixels > badPixelTolerance)
28093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
28103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: Got " << totalNumPixels - numWhitePixels - numRedPixels << " other than white or red pixels (maximum tolerance " << badPixelTolerance << ")" << TestLog::EndMessage;
28113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					success = false;
28123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
28133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
28143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if ((Winding)frontFaceWinding == m_winding)
28163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
28173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
28183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
28193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (de::abs(numWhitePixels - totalNumPixels/2) > badPixelTolerance)
28203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
28213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "Failure: wrong number of white pixels; expected approximately " << totalNumPixels/2 << TestLog::EndMessage;
28223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							success = false;
28233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							break;
28243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
28253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
28263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS)
28273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
28283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (numWhitePixels != totalNumPixels)
28293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
28303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "Failure: expected only white pixels (full-viewport quad)" << TestLog::EndMessage;
28313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							success = false;
28323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							break;
28333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
28343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
28353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
28363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(false);
28373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
28383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
28393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
28403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (numWhitePixels != 0)
28413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
28423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						log << TestLog::Message << "Failure: expected only red pixels (everything culled)" << TestLog::EndMessage;
28433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						success = false;
28443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
28453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
28463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
28473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
28483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
28493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, success ? "Pass" : "Image verification failed");
28523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
28533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Test potentially differing input and output patch sizes.
28563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PatchVertexCountCase : public TestCase
28573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
28593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PatchVertexCountCase (Context& context, const char* name, const char* description, int inputPatchSize, int outputPatchSize, const char* referenceImagePath)
28603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase				(context, name, description)
28613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_inputPatchSize		(inputPatchSize)
28623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_outputPatchSize		(outputPatchSize)
28633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_referenceImagePath	(referenceImagePath)
28643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							init				(void);
28683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							deinit				(void);
28693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult					iterate				(void);
28703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
28723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				RENDER_SIZE = 256;
28733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						m_inputPatchSize;
28753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						m_outputPatchSize;
28763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string					m_referenceImagePath;
28783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>	m_program;
28803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
28813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PatchVertexCountCase::init (void)
28833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
28853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
28863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string inSizeStr		= de::toString(m_inputPatchSize);
28883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string outSizeStr		= de::toString(m_outputPatchSize);
28893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
28913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
28923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
28933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_v_attr;\n"
28943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
28953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_tc_attr;\n"
28963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
28973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
28983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
28993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_tc_attr = in_v_attr;\n"
29003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
29013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationControlSource		("#version 310 es\n"
29033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
29043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (vertices = " + outSizeStr + ") out;\n"
29063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_tc_attr[];\n"
29083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_te_attr[];\n"
29103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
29123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
29133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID*" + inSizeStr + "/" + outSizeStr + "];\n"
29143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[0] = 5.0;\n"
29163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[1] = 5.0;\n"
29173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[0] = 5.0;\n"
29193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[1] = 5.0;\n"
29203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[2] = 5.0;\n"
29213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[3] = 5.0;\n"
29223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
29233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
29253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
29263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(TESSPRIMITIVETYPE_QUADS) +
29283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_te_attr[];\n"
29303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out mediump vec4 in_f_color;\n"
29323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
29343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
29353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
29363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" + outSizeStr + "-1)))];\n"
29373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(x, y, 0.0, 1.0);\n"
29383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_f_color = vec4(1.0);\n"
29393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
29403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
29423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
29443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in mediump vec4 in_f_color;\n"
29463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
29473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
29483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
29493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = in_f_color;\n"
29503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")));
29513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
29533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
29543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
29553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PatchVertexCountCase::deinit (void)
29583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
29603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPatchVertexCountCase::IterateResult PatchVertexCountCase::iterate (void)
29633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&					log						= m_testCtx.getLog();
29653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&		renderCtx				= m_context.getRenderContext();
29663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport		viewport				(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
29673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				programGL				= m_program->getProgram();
29683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl						= renderCtx.getFunctions();
29693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
29713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
29723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
29733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Note: input patch size is " << m_inputPatchSize << ", output patch size is " << m_outputPatchSize << TestLog::EndMessage;
29753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<float> attributeData;
29783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attributeData.reserve(m_inputPatchSize);
29793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < m_inputPatchSize; i++)
29813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
29823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float f = (float)i / (float)(m_inputPatchSize-1);
29833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			attributeData.push_back(f*f);
29843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
29853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.patchParameteri(GL_PATCH_VERTICES, m_inputPatchSize);
29873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
29883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding attrBindings[] =
29903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
29913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("in_v_attr", 1, (int)attributeData.size(), 0, &attributeData[0])
29923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
29933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_context.getRenderContext(), programGL, DE_LENGTH_OF_ARRAY(attrBindings), &attrBindings[0],
29953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::pr::Patches(m_inputPatchSize));
29963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
29973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Surface			rendered	= getPixels(renderCtx, viewport);
30013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureLevel		reference	= getPNG(m_testCtx.getArchive(), m_referenceImagePath);
30023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool					success		= tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", reference.getAccess(), rendered.getAccess(), 0.02f, tcu::COMPARE_LOG_RESULT);
30033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, success ? "Pass" : "Image comparison failed");
30053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return STOP;
30063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Test per-patch inputs/outputs.
30103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PerPatchDataCase : public TestCase
30113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
30133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum CaseType
30143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_PRIMITIVE_ID_TCS = 0,
30163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_PRIMITIVE_ID_TES,
30173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_PATCH_VERTICES_IN_TCS,
30183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_PATCH_VERTICES_IN_TES,
30193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_TESS_LEVEL_INNER0_TES,
30203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_TESS_LEVEL_INNER1_TES,
30213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_TESS_LEVEL_OUTER0_TES,
30223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_TESS_LEVEL_OUTER1_TES,
30233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_TESS_LEVEL_OUTER2_TES,
30243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_TESS_LEVEL_OUTER3_TES,
30253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_LAST
30273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
30283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PerPatchDataCase (Context& context, const char* name, const char* description, CaseType caseType, const char* referenceImagePath)
30303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase				(context, name, description)
30313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_caseType			(caseType)
30323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_referenceImagePath	(caseTypeUsesRefImageFromFile(caseType) ? referenceImagePath : "")
30333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(caseTypeUsesRefImageFromFile(caseType) == (referenceImagePath != DE_NULL));
30353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							init							(void);
30383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							deinit							(void);
30393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult					iterate							(void);
30403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*				getCaseTypeName					(CaseType);
30423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*				getCaseTypeDescription			(CaseType);
30433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static bool						caseTypeUsesRefImageFromFile	(CaseType);
30443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
30463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				RENDER_SIZE = 256;
30473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				INPUT_PATCH_SIZE;
30483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				OUTPUT_PATCH_SIZE;
30493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseType					m_caseType;
30513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string					m_referenceImagePath;
30523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>	m_program;
30543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
30553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int PerPatchDataCase::INPUT_PATCH_SIZE	= 10;
30573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int PerPatchDataCase::OUTPUT_PATCH_SIZE	= 5;
30583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* PerPatchDataCase::getCaseTypeName (CaseType type)
30603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
30623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PRIMITIVE_ID_TCS:			return "primitive_id_tcs";
30643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PRIMITIVE_ID_TES:			return "primitive_id_tes";
30653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PATCH_VERTICES_IN_TCS:	return "patch_vertices_in_tcs";
30663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PATCH_VERTICES_IN_TES:	return "patch_vertices_in_tes";
30673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_INNER0_TES:	return "tess_level_inner_0_tes";
30683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_INNER1_TES:	return "tess_level_inner_1_tes";
30693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER0_TES:	return "tess_level_outer_0_tes";
30703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER1_TES:	return "tess_level_outer_1_tes";
30713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER2_TES:	return "tess_level_outer_2_tes";
30723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER3_TES:	return "tess_level_outer_3_tes";
30733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
30743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
30753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
30763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* PerPatchDataCase::getCaseTypeDescription (CaseType type)
30803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
30823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PRIMITIVE_ID_TCS:			return "Read gl_PrimitiveID in TCS and pass it as patch output to TES";
30843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PRIMITIVE_ID_TES:			return "Read gl_PrimitiveID in TES";
30853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PATCH_VERTICES_IN_TCS:	return "Read gl_PatchVerticesIn in TCS and pass it as patch output to TES";
30863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PATCH_VERTICES_IN_TES:	return "Read gl_PatchVerticesIn in TES";
30873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_INNER0_TES:	return "Read gl_TessLevelInner[0] in TES";
30883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_INNER1_TES:	return "Read gl_TessLevelInner[1] in TES";
30893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER0_TES:	return "Read gl_TessLevelOuter[0] in TES";
30903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER1_TES:	return "Read gl_TessLevelOuter[1] in TES";
30913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER2_TES:	return "Read gl_TessLevelOuter[2] in TES";
30923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TESS_LEVEL_OUTER3_TES:	return "Read gl_TessLevelOuter[3] in TES";
30933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
30943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
30953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
30963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool PerPatchDataCase::caseTypeUsesRefImageFromFile (CaseType type)
31003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
31023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PRIMITIVE_ID_TCS:
31043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_PRIMITIVE_ID_TES:
31053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
31063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
31083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
31093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PerPatchDataCase::init (void)
31133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
31153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
31163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(OUTPUT_PATCH_SIZE < INPUT_PATCH_SIZE);
31183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string inSizeStr		= de::toString(INPUT_PATCH_SIZE);
31203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string outSizeStr		= de::toString(OUTPUT_PATCH_SIZE);
31213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
31233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
31243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_v_attr;\n"
31263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_tc_attr;\n"
31283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
31303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
31313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_tc_attr = in_v_attr;\n"
31323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
31333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationControlSource		("#version 310 es\n"
31353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
31363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (vertices = " + outSizeStr + ") out;\n"
31383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_tc_attr[];\n"
31403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_te_attr[];\n"
31423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_caseType == CASETYPE_PRIMITIVE_ID_TCS			? "patch out mediump int in_te_primitiveIDFromTCS;\n"
31433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_PATCH_VERTICES_IN_TCS	? "patch out mediump int in_te_patchVerticesInFromTCS;\n"
31443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : "") +
31453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
31473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
31483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
31493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_caseType == CASETYPE_PRIMITIVE_ID_TCS			? "\tin_te_primitiveIDFromTCS = gl_PrimitiveID;\n"
31503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_PATCH_VERTICES_IN_TCS	? "\tin_te_patchVerticesInFromTCS = gl_PatchVerticesIn;\n"
31513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : "") +
31523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[0] = 9.0;\n"
31543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[1] = 8.0;\n"
31553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[0] = 7.0;\n"
31573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[1] = 6.0;\n"
31583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[2] = 5.0;\n"
31593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	gl_TessLevelOuter[3] = 4.0;\n"
31603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
31613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
31633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
31643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(TESSPRIMITIVETYPE_QUADS) +
31663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_te_attr[];\n"
31683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_caseType == CASETYPE_PRIMITIVE_ID_TCS			? "patch in mediump int in_te_primitiveIDFromTCS;\n"
31693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_PATCH_VERTICES_IN_TCS	? "patch in mediump int in_te_patchVerticesInFromTCS;\n"
31703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : string()) +
31713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out mediump vec4 in_f_color;\n"
31733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "uniform highp float u_xScale;\n"
31753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
31773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
31783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp float x = (gl_TessCoord.x*u_xScale + in_te_attr[0]) * 2.0 - 1.0;\n"
31793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
31803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(x, y, 0.0, 1.0);\n"
31813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + (m_caseType == CASETYPE_PRIMITIVE_ID_TCS			? "\tbool ok = in_te_primitiveIDFromTCS == 3;\n"
31823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_PRIMITIVE_ID_TES			? "\tbool ok = gl_PrimitiveID == 3;\n"
31833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_PATCH_VERTICES_IN_TCS	? "\tbool ok = in_te_patchVerticesInFromTCS == " + inSizeStr + ";\n"
31843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_PATCH_VERTICES_IN_TES	? "\tbool ok = gl_PatchVerticesIn == " + outSizeStr + ";\n"
31853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_TESS_LEVEL_INNER0_TES	? "\tbool ok = abs(gl_TessLevelInner[0] - 9.0) < 0.1f;\n"
31863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_TESS_LEVEL_INNER1_TES	? "\tbool ok = abs(gl_TessLevelInner[1] - 8.0) < 0.1f;\n"
31873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_TESS_LEVEL_OUTER0_TES	? "\tbool ok = abs(gl_TessLevelOuter[0] - 7.0) < 0.1f;\n"
31883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_TESS_LEVEL_OUTER1_TES	? "\tbool ok = abs(gl_TessLevelOuter[1] - 6.0) < 0.1f;\n"
31893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_TESS_LEVEL_OUTER2_TES	? "\tbool ok = abs(gl_TessLevelOuter[2] - 5.0) < 0.1f;\n"
31903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : m_caseType == CASETYPE_TESS_LEVEL_OUTER3_TES	? "\tbool ok = abs(gl_TessLevelOuter[3] - 4.0) < 0.1f;\n"
31913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : DE_NULL) +
31923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  "	in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
31933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
31943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
31963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
31983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
31993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in mediump vec4 in_f_color;\n"
32003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
32013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
32023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
32033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = in_f_color;\n"
32043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")));
32053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
32073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
32083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
32093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PerPatchDataCase::deinit (void)
32123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
32143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32163c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPerPatchDataCase::IterateResult PerPatchDataCase::iterate (void)
32173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&					log						= m_testCtx.getLog();
32193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&		renderCtx				= m_context.getRenderContext();
32203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport		viewport				(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
32213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				programGL				= m_program->getProgram();
32223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl						= renderCtx.getFunctions();
32233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
32253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
32263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
32273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Note: input patch size is " << INPUT_PATCH_SIZE << ", output patch size is " << OUTPUT_PATCH_SIZE << TestLog::EndMessage;
32293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numPrimitives = m_caseType == CASETYPE_PRIMITIVE_ID_TCS || m_caseType == CASETYPE_PRIMITIVE_ID_TES ? 8 : 1;
32323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<float> attributeData;
32343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attributeData.reserve(numPrimitives*INPUT_PATCH_SIZE);
32353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < numPrimitives; i++)
32373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			attributeData.push_back((float)i / (float)numPrimitives);
32393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int j = 0; j < INPUT_PATCH_SIZE-1; j++)
32403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				attributeData.push_back(0.0f);
32413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.patchParameteri(GL_PATCH_VERTICES, INPUT_PATCH_SIZE);
32443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
32453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(programGL, "u_xScale"), 1.0f / (float)numPrimitives);
32473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding attrBindings[] =
32493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("in_v_attr", 1, (int)attributeData.size(), 0, &attributeData[0])
32513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
32523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_context.getRenderContext(), programGL, DE_LENGTH_OF_ARRAY(attrBindings), &attrBindings[0],
32543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::pr::Patches(numPrimitives*INPUT_PATCH_SIZE));
32553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
32563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Surface rendered = getPixels(renderCtx, viewport);
32603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_caseType == CASETYPE_PRIMITIVE_ID_TCS || m_caseType == CASETYPE_PRIMITIVE_ID_TES)
32623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(caseTypeUsesRefImageFromFile(m_caseType));
32643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::TextureLevel		reference	= getPNG(m_testCtx.getArchive(), m_referenceImagePath);
32663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					success		= tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", reference.getAccess(), rendered.getAccess(), 0.02f, tcu::COMPARE_LOG_RESULT);
32673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, success ? "Pass" : "Image comparison failed");
32693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return STOP;
32703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
32723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!caseTypeUsesRefImageFromFile(m_caseType));
32743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Image("RenderedImage", "Rendered Image", rendered);
32763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int y = 0; y < rendered.getHeight();	y++)
32783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int x = 0; x < rendered.getWidth();	x++)
32793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
32803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (rendered.getPixel(x, y) != tcu::RGBA::white)
32813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
32823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: expected all white pixels" << TestLog::EndMessage;
32833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
32843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return STOP;
32853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
32863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
32873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
32893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return STOP;
32903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Basic barrier() usage in TCS.
32953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BarrierCase : public TestCase
32963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
32983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BarrierCase (Context& context, const char* name, const char* description, const char* referenceImagePath)
32993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase				(context, name, description)
33003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_referenceImagePath	(referenceImagePath)
33013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							init		(void);
33053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							deinit		(void);
33063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult					iterate		(void);
33073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
33093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				RENDER_SIZE = 256;
33103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int				NUM_VERTICES;
33113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string					m_referenceImagePath;
33133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const ShaderProgram>	m_program;
33153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
33163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int BarrierCase::NUM_VERTICES = 32;
33183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BarrierCase::init (void)
33203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
33213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
33223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
33233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string numVertsStr = de::toString(NUM_VERTICES);
33253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
33273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource					("#version 310 es\n"
33283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_v_attr;\n"
33303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_tc_attr;\n"
33323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
33343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
33353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_tc_attr = in_v_attr;\n"
33363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
33373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationControlSource		("#version 310 es\n"
33393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
33403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (vertices = " + numVertsStr + ") out;\n"
33423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_tc_attr[];\n"
33443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_te_attr[];\n"
33463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "patch out highp float in_te_patchAttr;\n"
33473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
33493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
33503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
33513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_te_patchAttr = 0.0f;\n"
33523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	barrier();\n"
33533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	if (gl_InvocationID == 5)\n"
33543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "		in_te_patchAttr = float(gl_InvocationID)*0.1;\n"
33553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	barrier();\n"
33563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp float temp = in_te_patchAttr + in_te_attr[gl_InvocationID];\n"
33573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	barrier();\n"
33583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	if (gl_InvocationID == " + numVertsStr + "-1)\n"
33593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "		in_te_patchAttr = float(gl_InvocationID);\n"
33603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	barrier();\n"
33613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_te_attr[gl_InvocationID] = temp;\n"
33623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	barrier();\n"
33633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	temp = temp + in_te_attr[(gl_InvocationID+1) % " + numVertsStr + "];\n"
33643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	barrier();\n"
33653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	in_te_attr[gl_InvocationID] = 0.25*temp;\n"
33663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[0] = 32.0;\n"
33683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelInner[1] = 32.0;\n"
33693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[0] = 32.0;\n"
33713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[1] = 32.0;\n"
33723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[2] = 32.0;\n"
33733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_TessLevelOuter[3] = 32.0;\n"
33743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
33753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::TessellationEvaluationSource	("#version 310 es\n"
33773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "#extension GL_EXT_tessellation_shader : require\n"
33783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 + getTessellationEvaluationInLayoutString(TESSPRIMITIVETYPE_QUADS) +
33803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_te_attr[];\n"
33823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "patch in highp float in_te_patchAttr;\n"
33833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "out highp float in_f_blue;\n"
33853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
33873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
33883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
33893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" + numVertsStr + "-1)))];\n"
33903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	gl_Position = vec4(x, y, 0.0, 1.0);\n"
33918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 "	in_f_blue = abs(in_te_patchAttr - float(" + numVertsStr + "-1));\n"
33923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")
33933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource					("#version 310 es\n"
33953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "layout (location = 0) out mediump vec4 o_color;\n"
33973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
33983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "in highp float in_f_blue;\n"
33993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "\n"
34003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "void main (void)\n"
34013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "{\n"
34023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "	o_color = vec4(1.0, 0.0, in_f_blue, 1.0);\n"
34033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 "}\n")));
34043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
34063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
34073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
34083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
34093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BarrierCase::deinit (void)
34113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
34133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
34143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34153c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBarrierCase::IterateResult BarrierCase::iterate (void)
34163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&					log						= m_testCtx.getLog();
34183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&		renderCtx				= m_context.getRenderContext();
34193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport		viewport				(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
34203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				programGL				= m_program->getProgram();
34213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl						= renderCtx.getFunctions();
34223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
34243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
34253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
34263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<float> attributeData(NUM_VERTICES);
34293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < NUM_VERTICES; i++)
34313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			attributeData[i] = (float)i / (float)(NUM_VERTICES-1);
34323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.patchParameteri(GL_PATCH_VERTICES, NUM_VERTICES);
34343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
34353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding attrBindings[] =
34373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
34383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("in_v_attr", 1, (int)attributeData.size(), 0, &attributeData[0])
34393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
34403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_context.getRenderContext(), programGL, DE_LENGTH_OF_ARRAY(attrBindings), &attrBindings[0],
34423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::pr::Patches(NUM_VERTICES));
34433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
34443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Surface			rendered	= getPixels(renderCtx, viewport);
34483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureLevel		reference	= getPNG(m_testCtx.getArchive(), m_referenceImagePath);
34493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool					success		= tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", reference.getAccess(), rendered.getAccess(), 0.02f, tcu::COMPARE_LOG_RESULT);
34503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, success ? "Pass" : "Image comparison failed");
34523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return STOP;
34533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
34553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
34573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Base class for testing invariance of entire primitive set
34583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
34593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Draws two patches with identical tessellation levels and compares the
34603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * results. Repeats the same with other programs that are only different
34613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * in irrelevant ways; compares the results between these two programs.
34623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Also potentially compares to results produced by different tessellation
34633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * levels (see e.g. invariance rule #6).
34643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Furthermore, repeats the above with multiple different tessellation
34653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * value sets.
34663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
34673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The manner of primitive set comparison is defined by subclass. E.g.
34683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * case for invariance rule #1 tests that same vertices come out, in same
34693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * order; rule #5 only requires that the same triangles are output, but
34703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * not necessarily in the same order.
34713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
34723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PrimitiveSetInvarianceCase : public TestCase
34733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
34753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum WindingUsage
34763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WINDINGUSAGE_CCW = 0,
34783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WINDINGUSAGE_CW,
34793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WINDINGUSAGE_VARY,
34803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WINDINGUSAGE_LAST
34823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
34833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PrimitiveSetInvarianceCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, bool usePointMode, WindingUsage windingUsage)
34853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase			(context, name, description)
34863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType	(primType)
34873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_spacing			(spacing)
34883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_usePointMode	(usePointMode)
34893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_windingUsage	(windingUsage)
34903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									init				(void);
34943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									deinit				(void);
34953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult							iterate				(void);
34963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
34983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct TessLevels
34993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float inner[2];
35013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float outer[4];
35023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string description (void) const { return tessellationLevelsString(&inner[0], &outer[0]); }
35033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
35043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct LevelCase
35053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<TessLevels>	levels;
35073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					mem; //!< Subclass-defined arbitrary piece of data, for type of the levelcase, if needed. Passed to compare().
35083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LevelCase (const TessLevels& lev) : levels(vector<TessLevels>(1, lev)), mem(0) {}
35093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LevelCase (void) : mem(0) {}
35103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
35113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual vector<LevelCase>	genTessLevelCases	(void) const;
35133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool				compare				(const vector<Vec3>& coordsA, const vector<Vec3>& coordsB, int levelCaseMem) const = 0;
35143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType		m_primitiveType;
35163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
35183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct Program
35193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Winding							winding;
35213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SharedPtr<const ShaderProgram>	program;
35223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Program			(Winding w, const SharedPtr<const ShaderProgram>& prog) : winding(w), program(prog) {}
35243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string	description		(void) const { return string() + "winding mode " + getWindingShaderName(winding); };
35263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
35273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int			RENDER_SIZE = 16;
35293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode			m_spacing;
35313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool					m_usePointMode;
35323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const WindingUsage			m_windingUsage;
35333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Program>				m_programs;
35353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
35363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<PrimitiveSetInvarianceCase::LevelCase> PrimitiveSetInvarianceCase::genTessLevelCases (void) const
35383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const TessLevels basicTessLevelCases[] =
35403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 1.0f,	1.0f	},	{ 1.0f,		1.0f,	1.0f,	1.0f	} },
35423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 63.0f,	24.0f	},	{ 15.0f,	42.0f,	10.0f,	12.0f	} },
35433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 3.0f,	2.0f	},	{ 6.0f,		8.0f,	7.0f,	9.0f	} },
35443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 4.0f,	6.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
35453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 2.0f,	2.0f	},	{ 6.0f,		8.0f,	7.0f,	9.0f	} },
35463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 5.0f,	6.0f	},	{ 1.0f,		1.0f,	1.0f,	1.0f	} },
35473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 1.0f,	6.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
35483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 5.0f,	1.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
35493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ { 5.2f,	1.6f	},	{ 2.9f,		3.4f,	1.5f,	4.1f	} }
35503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
35513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<LevelCase> result;
35533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < DE_LENGTH_OF_ARRAY(basicTessLevelCases); i++)
35543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result.push_back(LevelCase(basicTessLevelCases[i]));
35553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random rnd(123);
35583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 10; i++)
35593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
35603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TessLevels levels;
35613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int j = 0; j < DE_LENGTH_OF_ARRAY(levels.inner); j++)
35623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levels.inner[j] = rnd.getFloat(1.0f, 16.0f);
35633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int j = 0; j < DE_LENGTH_OF_ARRAY(levels.outer); j++)
35643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levels.outer[j] = rnd.getFloat(1.0f, 16.0f);
35653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result.push_back(LevelCase(levels));
35663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
35673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
35683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
35703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
35713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PrimitiveSetInvarianceCase::init (void)
35733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numDifferentConstantExprCases = 2;
35753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Winding>		windings;
35763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_windingUsage)
35773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case WINDINGUSAGE_CCW:		windings.push_back(WINDING_CCW); break;
35793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case WINDINGUSAGE_CW:		windings.push_back(WINDING_CW); break;
35803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case WINDINGUSAGE_VARY:		windings.push_back(WINDING_CCW);
35813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									windings.push_back(WINDING_CW); break;
35823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: DE_ASSERT(false);
35833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
35843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
35863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
35873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int constantExprCaseNdx = 0; constantExprCaseNdx < numDifferentConstantExprCases; constantExprCaseNdx++)
35893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int windingCaseNdx = 0; windingCaseNdx < (int)windings.size(); windingCaseNdx++)
35913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
35923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string	floatLit01 = de::floatToString(10.0f / (float)(constantExprCaseNdx + 10), 2);
35933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		programNdx = (int)m_programs.size();
35943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_programs.push_back(Program(windings[windingCaseNdx],
35963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
35973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::VertexSource					("#version 310 es\n"
35983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
35993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "in highp float in_v_attr;\n"
36003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "out highp float in_tc_attr;\n"
36013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "void main (void)\n"
36033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "{\n"
36043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	in_tc_attr = in_v_attr;\n"
36053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "}\n")
36063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::TessellationControlSource		("#version 310 es\n"
36083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "#extension GL_EXT_tessellation_shader : require\n"
36093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "layout (vertices = " + de::toString(constantExprCaseNdx+1) + ") out;\n"
36113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "in highp float in_tc_attr[];\n"
36133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "patch out highp float in_te_positionOffset;\n"
36153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "void main (void)\n"
36173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "{\n"
36183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	in_te_positionOffset = in_tc_attr[6];\n"
36193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
36213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
36223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
36243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
36253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
36263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
36273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "}\n")
36283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::TessellationEvaluationSource	("#version 310 es\n"
36303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "#extension GL_EXT_tessellation_shader : require\n"
36313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing, windings[windingCaseNdx], m_usePointMode) +
36333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "patch in highp float in_te_positionOffset;\n"
36353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "out highp vec4 in_f_color;\n"
36373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "invariant out highp vec3 out_te_tessCoord;\n"
36383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "void main (void)\n"
36403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "{\n"
36413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	gl_Position = vec4(gl_TessCoord.xy*" + floatLit01 + " - in_te_positionOffset + float(gl_PrimitiveID)*0.1, 0.0, 1.0);\n"
36423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	in_f_color = vec4(" + floatLit01 + ");\n"
36433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	out_te_tessCoord = gl_TessCoord;\n"
36443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "}\n")
36453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::FragmentSource					("#version 310 es\n"
36473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "layout (location = 0) out mediump vec4 o_color;\n"
36493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "in highp vec4 in_f_color;\n"
36513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "\n"
36523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "void main (void)\n"
36533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "{\n"
36543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "	o_color = in_f_color;\n"
36553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 "}\n")
36563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::TransformFeedbackVarying		("out_te_tessCoord")
36583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)))));
36593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
36613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program" + de::toString(programNdx), "Program " + de::toString(programNdx));
36623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (programNdx == 0 || !m_programs.back().program->isOk())
36643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *m_programs.back().program;
36653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!m_programs.back().program->isOk())
36673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					TCU_FAIL("Program compilation failed");
36683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (programNdx > 0)
36703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "Note: program " << programNdx << " is similar to above, except some constants are different, and: " << m_programs.back().description() << TestLog::EndMessage;
36713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
36723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
36733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
36743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
36753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PrimitiveSetInvarianceCase::deinit (void)
36773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
36783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_programs.clear();
36793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
36803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36813c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPrimitiveSetInvarianceCase::IterateResult PrimitiveSetInvarianceCase::iterate (void)
36823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
36833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<Vec3> TFHandler;
36843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&					log					= m_testCtx.getLog();
36863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&		renderCtx			= m_context.getRenderContext();
36873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport		viewport			(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
36883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl					= renderCtx.getFunctions();
36893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<LevelCase>		tessLevelCases		= genTessLevelCases();
36903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<vector<int> >		primitiveCounts;
36913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							maxNumPrimitives	= -1;
36923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int caseNdx = 0; caseNdx < (int)tessLevelCases.size(); caseNdx++)
36943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
36953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		primitiveCounts.push_back(vector<int>());
36963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < (int)tessLevelCases[caseNdx].levels.size(); i++)
36973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
36983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int primCount = referencePrimitiveCount(m_primitiveType, m_spacing, m_usePointMode,
36993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  &tessLevelCases[caseNdx].levels[i].inner[0], &tessLevelCases[caseNdx].levels[i].outer[0]);
37003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			primitiveCounts.back().push_back(primCount);
37013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxNumPrimitives = de::max(maxNumPrimitives, primCount);
37023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
37033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				primitiveTypeGL		= outputPrimitiveTypeGL(m_primitiveType, m_usePointMode);
37063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TFHandler				transformFeedback	(m_context.getRenderContext(), 2*maxNumPrimitives*numVerticesPerPrimitive(primitiveTypeGL));
37073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
37093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 7);
37103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < (int)tessLevelCases.size(); tessLevelCaseNdx++)
37123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const LevelCase&	levelCase = tessLevelCases[tessLevelCaseNdx];
37143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<Vec3>		firstPrimVertices;
37153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
37173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string tessLevelsStr;
37183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int i = 0; i < (int)levelCase.levels.size(); i++)
37193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tessLevelsStr += (levelCase.levels.size() > 1 ? "\n" : "") + levelCase.levels[i].description();
37203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Tessellation level sets: " << tessLevelsStr << TestLog::EndMessage;
37213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
37223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int subTessLevelCaseNdx = 0; subTessLevelCaseNdx < (int)levelCase.levels.size(); subTessLevelCaseNdx++)
37243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
37253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessLevels&				tessLevels		= levelCase.levels[subTessLevelCaseNdx];
37263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float						(&inner)[2]		= tessLevels.inner;
37273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float						(&outer)[4]		= tessLevels.outer;
37283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float						attribute[2*7]	= { inner[0], inner[1], outer[0], outer[1], outer[2], outer[3], 0.0f,
37293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																inner[0], inner[1], outer[0], outer[1], outer[2], outer[3], 0.5f };
37303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::VertexArrayBinding	bindings[]		= { glu::va::Float("in_v_attr", 1, DE_LENGTH_OF_ARRAY(attribute), 0, &attribute[0]) };
37313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int programNdx = 0; programNdx < (int)m_programs.size(); programNdx++)
37333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
37343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32				programGL	= m_programs[programNdx].program->getProgram();
37353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.useProgram(programGL);
37363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const TFHandler::Result		tfResult	= transformFeedback.renderAndGetPrimitives(programGL, primitiveTypeGL, DE_LENGTH_OF_ARRAY(bindings), &bindings[0], DE_LENGTH_OF_ARRAY(attribute));
37373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (tfResult.numPrimitives != 2*primitiveCounts[tessLevelCaseNdx][subTessLevelCaseNdx])
37393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
37403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: GL reported GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN to be "
37413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< tfResult.numPrimitives << ", reference value is " << 2*primitiveCounts[tessLevelCaseNdx][subTessLevelCaseNdx]
37423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< TestLog::EndMessage;
37433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of primitives");
37453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return STOP;
37463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
37473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
37493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int			half			= (int)tfResult.varying.size()/2;
37503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const vector<Vec3>	prim0Vertices	= vector<Vec3>(tfResult.varying.begin(), tfResult.varying.begin() + half);
37513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const Vec3* const	prim1Vertices	= &tfResult.varying[half];
37523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int vtxNdx = 0; vtxNdx < (int)prim0Vertices.size(); vtxNdx++)
37543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
37553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (prim0Vertices[vtxNdx] != prim1Vertices[vtxNdx])
37563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
37573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "Failure: tessellation coordinate at index " << vtxNdx << " differs between two primitives drawn in one draw call" << TestLog::EndMessage
37583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< TestLog::Message << "Note: the coordinate is " << prim0Vertices[vtxNdx] << " for the first primitive and " << prim1Vertices[vtxNdx] << " for the second" << TestLog::EndMessage
37593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< TestLog::Message << "Note: tessellation levels for both primitives were: " << tessellationLevelsString(&inner[0], &outer[0]) << TestLog::EndMessage;
37603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of primitives");
37613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							return STOP;
37623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
37633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
37643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (programNdx == 0 && subTessLevelCaseNdx == 0)
37663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						firstPrimVertices = prim0Vertices;
37673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
37683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
37693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const bool compareOk = compare(firstPrimVertices, prim0Vertices, levelCase.mem);
37703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (!compareOk)
37713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
37723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "Note: comparison of tessellation coordinates failed; comparison was made between following cases:\n"
37733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< "  - case A: program 0, tessellation levels: " << tessLevelCases[tessLevelCaseNdx].levels[0].description() << "\n"
37743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< "  - case B: program " << programNdx << ", tessellation levels: " << tessLevels.description() << TestLog::EndMessage;
37753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of primitives");
37763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							return STOP;
37773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
37783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
37793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
37803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
37813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
37823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
37853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
37863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
37873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
37893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test invariance rule #1
37903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
37913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that the sequence of primitives input to the TES only depends on
37923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the tessellation levels, tessellation mode, spacing mode, winding, and
37933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * point mode.
37943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
37953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvariantPrimitiveSetCase : public PrimitiveSetInvarianceCase
37963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
37983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InvariantPrimitiveSetCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode)
37993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: PrimitiveSetInvarianceCase(context, name, description, primType, spacing, usePointMode, winding == WINDING_CCW	? WINDINGUSAGE_CCW
38003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																								: winding == WINDING_CW		? WINDINGUSAGE_CW
38013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																								: WINDINGUSAGE_LAST)
38023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
38063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool compare (const vector<Vec3>& coordsA, const vector<Vec3>& coordsB, int) const
38073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int vtxNdx = 0; vtxNdx < (int)coordsA.size(); vtxNdx++)
38093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
38103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (coordsA[vtxNdx] != coordsB[vtxNdx])
38113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
38123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "Failure: tessellation coordinate at index " << vtxNdx << " differs between two programs" << TestLog::EndMessage
38133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   << TestLog::Message << "Note: the coordinate is " << coordsA[vtxNdx] << " for the first program and " << coordsB[vtxNdx] << " for the other" << TestLog::EndMessage;
38143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
38153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
38163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
38173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
38183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
38203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
38223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test invariance rule #2
38233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
38243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that the set of vertices along an outer edge of a quad or triangle
38253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * only depends on that edge's tessellation level, and spacing.
38263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
38273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * For each (outer) edge in the quad or triangle, draw multiple patches
38283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * with identical tessellation levels for that outer edge but with
38293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * different values for the other outer edges; compare, among the
38303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * primitives, the vertices generated for that outer edge. Repeat with
38313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * different programs, using different winding etc. settings. Compare
38323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the edge's vertices between different programs.
38333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
38343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvariantOuterEdgeCase : public TestCase
38353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
38373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InvariantOuterEdgeCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing)
38383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase			(context, name, description)
38393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType	(primType)
38403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_spacing			(spacing)
38413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primType == TESSPRIMITIVETYPE_TRIANGLES || primType == TESSPRIMITIVETYPE_QUADS);
38433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init		(void);
38463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit		(void);
38473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate		(void);
38483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
38503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct Program
38513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Winding							winding;
38533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool							usePointMode;
38543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SharedPtr<const ShaderProgram>	program;
38553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Program			(Winding w, bool point, const SharedPtr<const ShaderProgram>& prog) : winding(w), usePointMode(point), program(prog) {}
38573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string	description		(void) const { return string() + "winding mode " + getWindingShaderName(winding) + ", " + (usePointMode ? "" : "don't ") + "use point mode"; };
38593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
38603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static vector<float>		generatePatchTessLevels (int numPatches, int constantOuterLevelIndex, float constantOuterLevel);
38623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int			RENDER_SIZE = 16;
38643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType		m_primitiveType;
38663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode			m_spacing;
38673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Program>				m_programs;
38693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
38703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<float> InvariantOuterEdgeCase::generatePatchTessLevels (int numPatches, int constantOuterLevelIndex, float constantOuterLevel)
38723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random rnd(123);
38743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return generateRandomPatchTessLevels(numPatches, constantOuterLevelIndex, constantOuterLevel, rnd);
38753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
38763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InvariantOuterEdgeCase::init (void)
38783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
38803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
38813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int windingI = 0; windingI < WINDING_LAST; windingI++)
38833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Winding winding = (Winding)windingI;
38853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int usePointModeI = 0; usePointModeI <= 1; usePointModeI++)
38873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
38883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		usePointMode	= usePointModeI != 0;
38893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		programNdx		= (int)m_programs.size();
38903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string	floatLit01		= de::floatToString(10.0f / (float)(programNdx + 10), 2);
38913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_programs.push_back(Program(winding, usePointMode,
38933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
38943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::VertexSource					("#version 310 es\n"
38953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
38963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "in highp float in_v_attr;\n"
38973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "out highp float in_tc_attr;\n"
38983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
38993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "void main (void)\n"
39003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "{\n"
39013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	in_tc_attr = in_v_attr;\n"
39023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "}\n")
39033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::TessellationControlSource		("#version 310 es\n"
39053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "#extension GL_EXT_tessellation_shader : require\n"
39063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "layout (vertices = " + de::toString(programNdx+1) + ") out;\n"
39083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "in highp float in_tc_attr[];\n"
39103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "void main (void)\n"
39123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "{\n"
39133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
39143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
39153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
39173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
39183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
39193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
39203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "}\n")
39213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::TessellationEvaluationSource	("#version 310 es\n"
39233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "#extension GL_EXT_tessellation_shader : require\n"
39243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing, winding, usePointMode) +
39263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "out highp vec4 in_f_color;\n"
39283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "invariant out highp vec3 out_te_tessCoord;\n"
39293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "void main (void)\n"
39313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "{\n"
39323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	gl_Position = vec4(gl_TessCoord.xy*" + floatLit01 + " - float(gl_PrimitiveID)*0.05, 0.0, 1.0);\n"
39333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	in_f_color = vec4(" + floatLit01 + ");\n"
39343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	out_te_tessCoord = gl_TessCoord;\n"
39353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "}\n")
39363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::FragmentSource					("#version 310 es\n"
39383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "layout (location = 0) out mediump vec4 o_color;\n"
39403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "in highp vec4 in_f_color;\n"
39423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "\n"
39433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "void main (void)\n"
39443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "{\n"
39453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "	o_color = in_f_color;\n"
39463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 "}\n")
39473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::TransformFeedbackVarying		("out_te_tessCoord")
39493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)))));
39503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
39523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program" + de::toString(programNdx), "Program " + de::toString(programNdx));
39533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (programNdx == 0 || !m_programs.back().program->isOk())
39553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *m_programs.back().program;
39563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!m_programs.back().program->isOk())
39583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					TCU_FAIL("Program compilation failed");
39593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (programNdx > 0)
39613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "Note: program " << programNdx << " is similar to above, except some constants are different, and: " << m_programs.back().description() << TestLog::EndMessage;
39623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
39633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
39643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
39653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InvariantOuterEdgeCase::deinit (void)
39683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_programs.clear();
39703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39723c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvariantOuterEdgeCase::IterateResult InvariantOuterEdgeCase::iterate (void)
39733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<Vec3> TFHandler;
39753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&							log							= m_testCtx.getLog();
39773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&				renderCtx					= m_context.getRenderContext();
39783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport				viewport					(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
39793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&				gl							= renderCtx.getFunctions();
39803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float					singleOuterEdgeLevels[]		= { 1.0f, 1.2f, 1.9f, 2.3f, 2.8f, 3.3f, 3.8f, 10.2f, 1.6f, 24.4f, 24.7f, 63.0f };
39823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int							numPatchesPerDrawCall		= 10;
39833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<OuterEdgeDescription>	edgeDescriptions			= outerEdgeDescriptions(m_primitiveType);
39843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
39863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute the number vertices in the largest draw call, so we can allocate the TF buffer just once.
39873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int maxNumVerticesInDrawCall = 0;
39883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
39893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const vector<float> patchTessLevels = generatePatchTessLevels(numPatchesPerDrawCall, 0 /* outer-edge index doesn't affect vertex count */, arrayMax(singleOuterEdgeLevels));
39903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int usePointModeI = 0; usePointModeI <= 1; usePointModeI++)
39923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				maxNumVerticesInDrawCall = de::max(maxNumVerticesInDrawCall,
39933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												   multiplePatchReferenceVertexCount(m_primitiveType, m_spacing, usePointModeI != 0, &patchTessLevels[0], numPatchesPerDrawCall));
39943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
39953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
39973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler tfHandler(m_context.getRenderContext(), maxNumVerticesInDrawCall);
39983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setViewport(gl, viewport);
40003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.patchParameteri(GL_PATCH_VERTICES, 6);
40013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int outerEdgeIndex = 0; outerEdgeIndex < (int)edgeDescriptions.size(); outerEdgeIndex++)
40033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
40043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const OuterEdgeDescription& edgeDesc = edgeDescriptions[outerEdgeIndex];
40053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int outerEdgeLevelCaseNdx = 0; outerEdgeLevelCaseNdx < DE_LENGTH_OF_ARRAY(singleOuterEdgeLevels); outerEdgeLevelCaseNdx++)
40073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
40083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					typedef std::set<Vec3, VecLexLessThan<3> > Vec3Set;
40093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const vector<float>				patchTessLevels		= generatePatchTessLevels(numPatchesPerDrawCall, outerEdgeIndex, singleOuterEdgeLevels[outerEdgeLevelCaseNdx]);
40113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::VertexArrayBinding	bindings[]			= { glu::va::Float("in_v_attr", 1, (int)patchTessLevels.size(), 0, &patchTessLevels[0]) };
40123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Vec3Set							firstOuterEdgeVertices; // Vertices of the outer edge of the first patch of the first program's draw call; used for comparison with other patches.
40133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Testing with outer tessellation level " << singleOuterEdgeLevels[outerEdgeLevelCaseNdx]
40153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< " for the " << edgeDesc.description() << " edge, and with various levels for other edges, and with all programs" << TestLog::EndMessage;
40163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int programNdx = 0; programNdx < (int)m_programs.size(); programNdx++)
40183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
40193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const Program& program		= m_programs[programNdx];
40203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const deUint32 programGL	= program.program->getProgram();
40213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						gl.useProgram(programGL);
40233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
40253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const TFHandler::Result		tfResult			= tfHandler.renderAndGetPrimitives(programGL, outputPrimitiveTypeGL(m_primitiveType, program.usePointMode),
40263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																											   DE_LENGTH_OF_ARRAY(bindings), &bindings[0], (int)patchTessLevels.size());
40273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const int					refNumVertices		= multiplePatchReferenceVertexCount(m_primitiveType, m_spacing, program.usePointMode, &patchTessLevels[0], numPatchesPerDrawCall);
40283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							int							numVerticesRead		= 0;
40293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							if ((int)tfResult.varying.size() != refNumVertices)
40313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
40323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								log << TestLog::Message << "Failure: the number of vertices returned by transform feedback is "
40333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< tfResult.varying.size() << ", expected " << refNumVertices << TestLog::EndMessage
40343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									<< TestLog::Message << "Note: rendered " << numPatchesPerDrawCall
40353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< " patches in one draw call; tessellation levels for each patch are (in order [inner0, inner1, outer0, outer1, outer2, outer3]):\n"
40363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< containerStr(patchTessLevels, 6) << TestLog::EndMessage;
40373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
40393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								return STOP;
40403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
40413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							// Check the vertices of each patch.
40433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							for (int patchNdx = 0; patchNdx < numPatchesPerDrawCall; patchNdx++)
40453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
40463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const float* const	innerLevels			= &patchTessLevels[6*patchNdx + 0];
40473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const float* const	outerLevels			= &patchTessLevels[6*patchNdx + 2];
40483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const int			patchNumVertices	= referenceVertexCount(m_primitiveType, m_spacing, program.usePointMode, innerLevels, outerLevels);
40493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								Vec3Set				outerEdgeVertices;
40503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								// We're interested in just the vertices on the current outer edge.
40523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								for(int vtxNdx = numVerticesRead; vtxNdx < numVerticesRead + patchNumVertices; vtxNdx++)
40533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
40543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const Vec3& vtx = tfResult.varying[vtxNdx];
40553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									if (edgeDesc.contains(vtx))
40563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										outerEdgeVertices.insert(tfResult.varying[vtxNdx]);
40573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
40583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								// Check that the outer edge contains an appropriate number of vertices.
40603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
40613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const int refNumVerticesOnOuterEdge = 1 + getClampedRoundedTessLevel(m_spacing, singleOuterEdgeLevels[outerEdgeLevelCaseNdx]);
40623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									if ((int)outerEdgeVertices.size() != refNumVerticesOnOuterEdge)
40643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
40653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										log << TestLog::Message << "Failure: the number of vertices on outer edge is " << outerEdgeVertices.size()
40663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< ", expected " << refNumVerticesOnOuterEdge << TestLog::EndMessage
40673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< TestLog::Message << "Note: vertices on the outer edge are:\n" << containerStr(outerEdgeVertices, 5, 0) << TestLog::EndMessage
40683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< TestLog::Message << "Note: the following parameters were used: " << program.description()
40693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< ", tessellation levels: " << tessellationLevelsString(innerLevels, outerLevels) << TestLog::EndMessage;
40703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
40713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										return STOP;
40723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
40733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
40743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								// Compare the vertices to those of the first patch (unless this is the first patch).
40763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (programNdx == 0 && patchNdx == 0)
40783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									firstOuterEdgeVertices = outerEdgeVertices;
40793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								else
40803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
40813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									if (firstOuterEdgeVertices != outerEdgeVertices)
40823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
40833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										log << TestLog::Message << "Failure: vertices generated for the edge differ between the following cases:\n"
40843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< "  - case A: " << m_programs[0].description() << ", tessellation levels: "
40853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				  << tessellationLevelsString(&patchTessLevels[0], &patchTessLevels[2]) << "\n"
40863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< "  - case B: " << program.description() << ", tessellation levels: "
40873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				  << tessellationLevelsString(innerLevels, outerLevels) << TestLog::EndMessage;
40883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										log << TestLog::Message << "Note: resulting vertices for the edge for the cases were:\n"
40903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< "  - case A: " << containerStr(firstOuterEdgeVertices, 5, 14) << "\n"
40913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< "  - case B: " << containerStr(outerEdgeVertices, 5, 14) << TestLog::EndMessage;
40923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
40943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										return STOP;
40953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
40963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
40973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								numVerticesRead += patchNumVertices;
40993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
41003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							DE_ASSERT(numVerticesRead == (int)tfResult.varying.size());
41023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
41033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
41043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
41053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
41063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
41073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
41083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
41103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
41113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
41123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
41143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test invariance rule #3
41153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
41163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that the vertices along an outer edge are placed symmetrically.
41173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
41183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Draw multiple patches with different tessellation levels and different
41193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * point_mode, winding etc. Before outputting tesscoords with TF, mirror
41203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the vertices in the TES such that every vertex on an outer edge -
41213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * except the possible middle vertex - should be duplicated in the output.
41223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Check that appropriate duplicates exist.
41233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
41243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SymmetricOuterEdgeCase : public TestCase
41253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
41263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
41273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SymmetricOuterEdgeCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode)
41283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase			(context, name, description)
41293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType	(primType)
41303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_spacing			(spacing)
41313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_winding			(winding)
41323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_usePointMode	(usePointMode)
41333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
41343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
41353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									init		(void);
41373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									deinit		(void);
41383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult							iterate		(void);
41393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
41413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static vector<float>					generatePatchTessLevels (int numPatches, int constantOuterLevelIndex, float constantOuterLevel);
41423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int						RENDER_SIZE = 16;
41443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType					m_primitiveType;
41463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode						m_spacing;
41473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Winding							m_winding;
41483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool								m_usePointMode;
41493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const glu::ShaderProgram>		m_program;
41513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
41523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<float> SymmetricOuterEdgeCase::generatePatchTessLevels (int numPatches, int constantOuterLevelIndex, float constantOuterLevel)
41543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
41553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random rnd(123);
41563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return generateRandomPatchTessLevels(numPatches, constantOuterLevelIndex, constantOuterLevel, rnd);
41573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
41583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SymmetricOuterEdgeCase::init (void)
41603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
41613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
41623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
41633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
41653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::VertexSource					("#version 310 es\n"
41663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_v_attr;\n"
41683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp float in_tc_attr;\n"
41693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
41713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
41723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_tc_attr = in_v_attr;\n"
41733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
41743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationControlSource		("#version 310 es\n"
41763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
41773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (vertices = 1) out;\n"
41793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_tc_attr[];\n"
41813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
41833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
41843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
41853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
41863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
41883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
41893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
41903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
41913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
41923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationEvaluationSource	("#version 310 es\n"
41943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
41953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing, m_winding, m_usePointMode) +
41973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
41983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec4 in_f_color;\n"
41993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec4 out_te_tessCoord_isMirrored;\n"
42003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
42013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
42023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
42033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
42043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	float x = gl_TessCoord.x;\n"
42053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	float y = gl_TessCoord.y;\n"
42063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	float z = gl_TessCoord.z;\n"
42073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	// Mirror one half of each outer edge onto the other half, except the endpoints (because they belong to two edges)\n"
42083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	out_te_tessCoord_isMirrored = z == 0.0 && x > 0.5 && x != 1.0 ? vec4(1.0-x,  1.0-y,    0.0, 1.0)\n"
42093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	                            : y == 0.0 && z > 0.5 && z != 1.0 ? vec4(1.0-x,    0.0,  1.0-z, 1.0)\n"
42103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	                            : x == 0.0 && y > 0.5 && y != 1.0 ? vec4(  0.0,  1.0-y,  1.0-z, 1.0)\n"
42113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	                            : vec4(x, y, z, 0.0);\n"
42123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  : m_primitiveType == TESSPRIMITIVETYPE_QUADS ?
42133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	float x = gl_TessCoord.x;\n"
42143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	float y = gl_TessCoord.y;\n"
42153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	// Mirror one half of each outer edge onto the other half, except the endpoints (because they belong to two edges)\n"
42163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	out_te_tessCoord_isMirrored = (x == 0.0 || x == 1.0) && y > 0.5 && y != 1.0 ? vec4(    x, 1.0-y, 0.0, 1.0)\n"
42173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	                            : (y == 0.0 || y == 1.0) && x > 0.5 && x != 1.0 ? vec4(1.0-x,     y, 0.0, 1.0)\n"
42183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	                            : vec4(x, y, 0.0, 0.0);\n"
42193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  : m_primitiveType == TESSPRIMITIVETYPE_ISOLINES ?
42203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	float x = gl_TessCoord.x;\n"
42213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	float y = gl_TessCoord.y;\n"
42223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	// Mirror one half of each outer edge onto the other half\n"
42233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	out_te_tessCoord_isMirrored = (x == 0.0 || x == 1.0) && y > 0.5 ? vec4(x, 1.0-y, 0.0, 1.0)\n"
42243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	                            : vec4(x, y, 0.0, 0.0f);\n"
42253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  : DE_NULL) +
42263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
42273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
42283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_f_color = vec4(1.0);\n"
42293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
42303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::FragmentSource					("#version 310 es\n"
42323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
42333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (location = 0) out mediump vec4 o_color;\n"
42343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
42353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp vec4 in_f_color;\n"
42363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
42373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
42383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
42393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	o_color = in_f_color;\n"
42403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
42413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackVarying		("out_te_tessCoord_isMirrored")
42433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)));
42443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
42463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
42473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
42483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
42493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SymmetricOuterEdgeCase::deinit (void)
42513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
42523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
42533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
42543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42553c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySymmetricOuterEdgeCase::IterateResult SymmetricOuterEdgeCase::iterate (void)
42563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
42573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<Vec4> TFHandler;
42583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&							log							= m_testCtx.getLog();
42603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&				renderCtx					= m_context.getRenderContext();
42613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport				viewport					(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
42623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&				gl							= renderCtx.getFunctions();
42633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float					singleOuterEdgeLevels[]		= { 1.0f, 1.2f, 1.9f, 2.3f, 2.8f, 3.3f, 3.8f, 10.2f, 1.6f, 24.4f, 24.7f, 63.0f };
42653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<OuterEdgeDescription>	edgeDescriptions			= outerEdgeDescriptions(m_primitiveType);
42663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
42683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute the number vertices in the largest draw call, so we can allocate the TF buffer just once.
42693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int maxNumVerticesInDrawCall;
42703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
42713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const vector<float> patchTessLevels = generatePatchTessLevels(1, 0 /* outer-edge index doesn't affect vertex count */, arrayMax(singleOuterEdgeLevels));
42723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxNumVerticesInDrawCall = referenceVertexCount(m_primitiveType, m_spacing, m_usePointMode, &patchTessLevels[0], &patchTessLevels[2]);
42733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
42743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
42763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler tfHandler(m_context.getRenderContext(), maxNumVerticesInDrawCall);
42773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setViewport(gl, viewport);
42793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.patchParameteri(GL_PATCH_VERTICES, 6);
42803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int outerEdgeIndex = 0; outerEdgeIndex < (int)edgeDescriptions.size(); outerEdgeIndex++)
42823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
42833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const OuterEdgeDescription& edgeDesc = edgeDescriptions[outerEdgeIndex];
42843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int outerEdgeLevelCaseNdx = 0; outerEdgeLevelCaseNdx < DE_LENGTH_OF_ARRAY(singleOuterEdgeLevels); outerEdgeLevelCaseNdx++)
42863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
42873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					typedef std::set<Vec3, VecLexLessThan<3> > Vec3Set;
42883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const vector<float>				patchTessLevels		= generatePatchTessLevels(1, outerEdgeIndex, singleOuterEdgeLevels[outerEdgeLevelCaseNdx]);
42903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::VertexArrayBinding	bindings[]			= { glu::va::Float("in_v_attr", 1, (int)patchTessLevels.size(), 0, &patchTessLevels[0]) };
42913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Testing with outer tessellation level " << singleOuterEdgeLevels[outerEdgeLevelCaseNdx]
42933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< " for the " << edgeDesc.description() << " edge, and with various levels for other edges" << TestLog::EndMessage;
42943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
42963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const deUint32 programGL = m_program->getProgram();
42973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						gl.useProgram(programGL);
42993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
43013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const TFHandler::Result		tfResult		= tfHandler.renderAndGetPrimitives(programGL, outputPrimitiveTypeGL(m_primitiveType, m_usePointMode),
43023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																										   DE_LENGTH_OF_ARRAY(bindings), &bindings[0], (int)patchTessLevels.size());
43033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const int					refNumVertices	= referenceVertexCount(m_primitiveType, m_spacing, m_usePointMode, &patchTessLevels[0], &patchTessLevels[2]);
43043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							if ((int)tfResult.varying.size() != refNumVertices)
43063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
43073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								log << TestLog::Message << "Failure: the number of vertices returned by transform feedback is "
43083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< tfResult.varying.size() << ", expected " << refNumVertices << TestLog::EndMessage
43093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									<< TestLog::Message << "Note: rendered 1 patch, tessellation levels are (in order [inner0, inner1, outer0, outer1, outer2, outer3]):\n"
43103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< containerStr(patchTessLevels, 6) << TestLog::EndMessage;
43113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
43133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								return STOP;
43143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
43153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							// Check the vertices.
43173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
43193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								Vec3Set nonMirroredEdgeVertices;
43203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								Vec3Set mirroredEdgeVertices;
43213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								// We're interested in just the vertices on the current outer edge.
43233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								for(int vtxNdx = 0; vtxNdx < refNumVertices; vtxNdx++)
43243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
43253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const Vec3& vtx = tfResult.varying[vtxNdx].swizzle(0,1,2);
43263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									if (edgeDesc.contains(vtx))
43273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
43283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										// Ignore the middle vertex of the outer edge, as it's exactly at the mirroring point;
43293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										// for isolines, also ignore (0, 0) and (1, 0) because there's no mirrored counterpart for them.
43303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES && vtx == tcu::select(Vec3(0.0f), Vec3(0.5f), singleTrueMask<3>(edgeDesc.constantCoordinateIndex)))
43313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											continue;
43323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										if (m_primitiveType == TESSPRIMITIVETYPE_QUADS && vtx.swizzle(0,1) == tcu::select(Vec2(edgeDesc.constantCoordinateValueChoices[0]),
43333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																															   Vec2(0.5f),
43343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																															   singleTrueMask<2>(edgeDesc.constantCoordinateIndex)))
43353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											continue;
43363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										if (m_primitiveType == TESSPRIMITIVETYPE_ISOLINES && (vtx == Vec3(0.0f, 0.5f, 0.0f) || vtx == Vec3(1.0f, 0.5f, 0.0f) ||
43373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																							  vtx == Vec3(0.0f, 0.0f, 0.0f) || vtx == Vec3(1.0f, 0.0f, 0.0f)))
43383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											continue;
43393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										const bool isMirrored = tfResult.varying[vtxNdx].w() > 0.5f;
43413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										if (isMirrored)
43423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											mirroredEdgeVertices.insert(vtx);
43433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										else
43443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											nonMirroredEdgeVertices.insert(vtx);
43453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
43463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
43473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (m_primitiveType != TESSPRIMITIVETYPE_ISOLINES)
43493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
43503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									// Check that both endpoints are present. Note that endpoints aren't mirrored by the shader, since they belong to more than one edge.
43513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									Vec3 endpointA;
43533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									Vec3 endpointB;
43543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
43563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
43573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										endpointA = tcu::select(Vec3(1.0f), Vec3(0.0f), singleTrueMask<3>((edgeDesc.constantCoordinateIndex + 1) % 3));
43583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										endpointB = tcu::select(Vec3(1.0f), Vec3(0.0f), singleTrueMask<3>((edgeDesc.constantCoordinateIndex + 2) % 3));
43593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
43603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS)
43613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
43623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										endpointA.xy() = tcu::select(Vec2(edgeDesc.constantCoordinateValueChoices[0]), Vec2(0.0f), singleTrueMask<2>(edgeDesc.constantCoordinateIndex));
43633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										endpointB.xy() = tcu::select(Vec2(edgeDesc.constantCoordinateValueChoices[0]), Vec2(1.0f), singleTrueMask<2>(edgeDesc.constantCoordinateIndex));
43643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
43653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									else
43663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										DE_ASSERT(false);
43673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									if (!contains(nonMirroredEdgeVertices, endpointA) ||
43693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										!contains(nonMirroredEdgeVertices, endpointB))
43703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
43713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										log << TestLog::Message << "Failure: edge doesn't contain both endpoints, " << endpointA << " and " << endpointB << TestLog::EndMessage
43723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< TestLog::Message << "Note: non-mirrored vertices:\n" << containerStr(nonMirroredEdgeVertices, 5)
43733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< "\nmirrored vertices:\n" << containerStr(mirroredEdgeVertices, 5) << TestLog::EndMessage;
43743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
43753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										return STOP;
43763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
43773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									nonMirroredEdgeVertices.erase(endpointA);
43783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									nonMirroredEdgeVertices.erase(endpointB);
43793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
43803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (nonMirroredEdgeVertices != mirroredEdgeVertices)
43823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
43833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									log << TestLog::Message << "Failure: the set of mirrored edges isn't equal to the set of non-mirrored edges (ignoring endpoints and possible middle)" << TestLog::EndMessage
43843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< TestLog::Message << "Note: non-mirrored vertices:\n" << containerStr(nonMirroredEdgeVertices, 5)
43853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																<< "\nmirrored vertices:\n" << containerStr(mirroredEdgeVertices, 5) << TestLog::EndMessage;
43863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
43873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									return STOP;
43883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
43893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
43903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
43913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
43923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
43933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
43943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
43953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
43963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
43983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
43993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
44003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
44023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test invariance rule #4
44033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
44043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that the vertices on an outer edge don't depend on which of the
44053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * edges it is, other than with respect to component order.
44063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
44073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass OuterEdgeVertexSetIndexIndependenceCase : public TestCase
44083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
44093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
44103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OuterEdgeVertexSetIndexIndependenceCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode)
44113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase			(context, name, description)
44123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType	(primType)
44133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_spacing			(spacing)
44143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_winding			(winding)
44153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_usePointMode	(usePointMode)
44163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
44173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primType == TESSPRIMITIVETYPE_TRIANGLES || primType == TESSPRIMITIVETYPE_QUADS);
44183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
44193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									init		(void);
44213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									deinit		(void);
44223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult							iterate		(void);
44233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
44253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static vector<float>					generatePatchTessLevels (int numPatches, int constantOuterLevelIndex, float constantOuterLevel);
44263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int						RENDER_SIZE = 16;
44283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType					m_primitiveType;
44303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode						m_spacing;
44313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Winding							m_winding;
44323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool								m_usePointMode;
44333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const glu::ShaderProgram>		m_program;
44353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
44363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<float> OuterEdgeVertexSetIndexIndependenceCase::generatePatchTessLevels (int numPatches, int constantOuterLevelIndex, float constantOuterLevel)
44383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
44393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random rnd(123);
44403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return generateRandomPatchTessLevels(numPatches, constantOuterLevelIndex, constantOuterLevel, rnd);
44413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
44423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid OuterEdgeVertexSetIndexIndependenceCase::init (void)
44443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
44453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
44463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
44473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
44493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::VertexSource					("#version 310 es\n"
44503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_v_attr;\n"
44523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp float in_tc_attr;\n"
44533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
44553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
44563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_tc_attr = in_v_attr;\n"
44573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
44583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationControlSource		("#version 310 es\n"
44603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
44613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (vertices = 1) out;\n"
44633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_tc_attr[];\n"
44653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
44673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
44683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
44693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
44703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
44723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
44733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
44743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
44753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
44763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationEvaluationSource	("#version 310 es\n"
44783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
44793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing, m_winding, m_usePointMode) +
44813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec4 in_f_color;\n"
44833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec3 out_te_tessCoord;\n"
44843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
44863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
44873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	out_te_tessCoord = gl_TessCoord;"
44883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
44893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_f_color = vec4(1.0);\n"
44903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
44913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::FragmentSource					("#version 310 es\n"
44933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (location = 0) out mediump vec4 o_color;\n"
44953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp vec4 in_f_color;\n"
44973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
44983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
44993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
45003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	o_color = in_f_color;\n"
45013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
45023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackVarying		("out_te_tessCoord")
45043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)));
45053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
45073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
45083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
45093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
45103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid OuterEdgeVertexSetIndexIndependenceCase::deinit (void)
45123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
45133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
45143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
45153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45163c827367444ee418f129b2c238299f49d3264554Jarkko PoyryOuterEdgeVertexSetIndexIndependenceCase::IterateResult OuterEdgeVertexSetIndexIndependenceCase::iterate (void)
45173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
45183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<Vec3> TFHandler;
45193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&							log							= m_testCtx.getLog();
45213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&				renderCtx					= m_context.getRenderContext();
45223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport				viewport					(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
45233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&				gl							= renderCtx.getFunctions();
45243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32						programGL					= m_program->getProgram();
45253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float					singleOuterEdgeLevels[]		= { 1.0f, 1.2f, 1.9f, 2.3f, 2.8f, 3.3f, 3.8f, 10.2f, 1.6f, 24.4f, 24.7f, 63.0f };
45273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<OuterEdgeDescription>	edgeDescriptions			= outerEdgeDescriptions(m_primitiveType);
45283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
45303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
45313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 6);
45323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
45343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute the number vertices in the largest draw call, so we can allocate the TF buffer just once.
45353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int maxNumVerticesInDrawCall = 0;
45363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
45373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const vector<float> patchTessLevels = generatePatchTessLevels(1, 0 /* outer-edge index doesn't affect vertex count */, arrayMax(singleOuterEdgeLevels));
45383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxNumVerticesInDrawCall = referenceVertexCount(m_primitiveType, m_spacing, m_usePointMode, &patchTessLevels[0], &patchTessLevels[2]);
45393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
45403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
45423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler tfHandler(m_context.getRenderContext(), maxNumVerticesInDrawCall);
45433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int outerEdgeLevelCaseNdx = 0; outerEdgeLevelCaseNdx < DE_LENGTH_OF_ARRAY(singleOuterEdgeLevels); outerEdgeLevelCaseNdx++)
45453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
45463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				typedef std::set<Vec3, VecLexLessThan<3> > Vec3Set;
45473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Vec3Set firstEdgeVertices;
45493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int outerEdgeIndex = 0; outerEdgeIndex < (int)edgeDescriptions.size(); outerEdgeIndex++)
45513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
45523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const OuterEdgeDescription&		edgeDesc			= edgeDescriptions[outerEdgeIndex];
45533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const vector<float>				patchTessLevels		= generatePatchTessLevels(1, outerEdgeIndex, singleOuterEdgeLevels[outerEdgeLevelCaseNdx]);
45543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::VertexArrayBinding	bindings[]			= { glu::va::Float("in_v_attr", 1, (int)patchTessLevels.size(), 0, &patchTessLevels[0]) };
45553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Testing with outer tessellation level " << singleOuterEdgeLevels[outerEdgeLevelCaseNdx]
45573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< " for the " << edgeDesc.description() << " edge, and with various levels for other edges" << TestLog::EndMessage;
45583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
45603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const TFHandler::Result		tfResult		= tfHandler.renderAndGetPrimitives(programGL, outputPrimitiveTypeGL(m_primitiveType, m_usePointMode),
45613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																										DE_LENGTH_OF_ARRAY(bindings), &bindings[0], (int)patchTessLevels.size());
45623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const int					refNumVertices	= referenceVertexCount(m_primitiveType, m_spacing, m_usePointMode, &patchTessLevels[0], &patchTessLevels[2]);
45633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if ((int)tfResult.varying.size() != refNumVertices)
45653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
45663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "Failure: the number of vertices returned by transform feedback is "
45673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< tfResult.varying.size() << ", expected " << refNumVertices << TestLog::EndMessage
45683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< TestLog::Message << "Note: rendered 1 patch, tessellation levels are (in order [inner0, inner1, outer0, outer1, outer2, outer3]):\n"
45693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< containerStr(patchTessLevels, 6) << TestLog::EndMessage;
45703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
45723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							return STOP;
45733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
45743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
45763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							Vec3Set currentEdgeVertices;
45773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							// Get the vertices on the current outer edge.
45793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							for(int vtxNdx = 0; vtxNdx < refNumVertices; vtxNdx++)
45803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
45813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const Vec3& vtx = tfResult.varying[vtxNdx];
45823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (edgeDesc.contains(vtx))
45833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
45843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									// Swizzle components to match the order of the first edge.
45853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
45863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
45873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										currentEdgeVertices.insert(outerEdgeIndex == 0 ? vtx
45883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	: outerEdgeIndex == 1 ? vtx.swizzle(1, 0, 2)
45893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	: outerEdgeIndex == 2 ? vtx.swizzle(2, 1, 0)
45903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	: Vec3(-1.0f));
45913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
45923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS)
45933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									{
45943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										currentEdgeVertices.insert(Vec3(outerEdgeIndex == 0 ? vtx.y()
45953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		: outerEdgeIndex == 1 ? vtx.x()
45963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		: outerEdgeIndex == 2 ? vtx.y()
45973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		: outerEdgeIndex == 3 ? vtx.x()
45983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		: -1.0f,
45993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		0.0f, 0.0f));
46003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									}
46013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									else
46023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										DE_ASSERT(false);
46033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
46043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
46053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							if (outerEdgeIndex == 0)
46073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								firstEdgeVertices = currentEdgeVertices;
46083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							else
46093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
46103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								// Compare vertices of this edge to those of the first edge.
46113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (currentEdgeVertices != firstEdgeVertices)
46133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
46143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const char* const swizzleDesc = m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? (outerEdgeIndex == 1 ? "(y, x, z)"
46153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																													: outerEdgeIndex == 2 ? "(z, y, x)"
46163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																													: DE_NULL)
46173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	: m_primitiveType == TESSPRIMITIVETYPE_QUADS ? (outerEdgeIndex == 1 ? "(x, 0)"
46183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																												: outerEdgeIndex == 2 ? "(y, 0)"
46193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																												: outerEdgeIndex == 3 ? "(x, 0)"
46203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																												: DE_NULL)
46213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	: DE_NULL;
46223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									log << TestLog::Message << "Failure: the set of vertices on the " << edgeDesc.description() << " edge"
46243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															<< " doesn't match the set of vertices on the " << edgeDescriptions[0].description() << " edge" << TestLog::EndMessage
46253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< TestLog::Message << "Note: set of vertices on " << edgeDesc.description() << " edge, components swizzled like " << swizzleDesc
46263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															<< " to match component order on first edge:\n" << containerStr(currentEdgeVertices, 5)
46273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															<< "\non " << edgeDescriptions[0].description() << " edge:\n" << containerStr(firstEdgeVertices, 5) << TestLog::EndMessage;
46283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid set of vertices");
46293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									return STOP;
46303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
46313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
46323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
46333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
46343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
46353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
46363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
46373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
46403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
46413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
46423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
46443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test invariance rule #5
46453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
46463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that the set of triangles input to the TES only depends on the
46473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * tessellation levels, tessellation mode and spacing mode. Specifically,
46483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * winding doesn't change the set of triangles, though it can change the
46493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * order in which they are input to TES, and can (and will) change the
46503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * vertex order within a triangle.
46513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
46523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvariantTriangleSetCase : public PrimitiveSetInvarianceCase
46533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
46553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InvariantTriangleSetCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing)
46563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: PrimitiveSetInvarianceCase(context, name, description, primType, spacing, false, WINDINGUSAGE_VARY)
46573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primType == TESSPRIMITIVETYPE_TRIANGLES || primType == TESSPRIMITIVETYPE_QUADS);
46593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
46623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool compare (const vector<Vec3>& coordsA, const vector<Vec3>& coordsB, int) const
46633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return compareTriangleSets(coordsA, coordsB, m_testCtx.getLog());
46653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
46673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
46693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test invariance rule #6
46703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
46713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that the set of inner triangles input to the TES only depends on
46723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the inner tessellation levels, tessellation mode and spacing mode.
46733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
46743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvariantInnerTriangleSetCase : public PrimitiveSetInvarianceCase
46753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
46773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InvariantInnerTriangleSetCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing)
46783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: PrimitiveSetInvarianceCase(context, name, description, primType, spacing, false, WINDINGUSAGE_VARY)
46793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primType == TESSPRIMITIVETYPE_TRIANGLES || primType == TESSPRIMITIVETYPE_QUADS);
46813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
46843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual vector<LevelCase> genTessLevelCases (void) const
46853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					numSubCases		= 4;
46873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<LevelCase>		baseResults		= PrimitiveSetInvarianceCase::genTessLevelCases();
46883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<LevelCase>			result;
46893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random					rnd				(123);
46903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Generate variants with different values for irrelevant levels.
46923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int baseNdx = 0; baseNdx < (int)baseResults.size(); baseNdx++)
46933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
46943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessLevels&	base	= baseResults[baseNdx].levels[0];
46953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TessLevels			levels	= base;
46963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			LevelCase			levelCase;
46973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int subNdx = 0; subNdx < numSubCases; subNdx++)
46993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
47003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelCase.levels.push_back(levels);
47013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int i = 0; i < DE_LENGTH_OF_ARRAY(levels.outer); i++)
47033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levels.outer[i] = rnd.getFloat(2.0f, 16.0f);
47043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
47053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levels.inner[1] = rnd.getFloat(2.0f, 16.0f);
47063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
47073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result.push_back(levelCase);
47093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
47103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
47123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
47133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct IsInnerTriangleTriangle
47153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool operator() (const Vec3* vertices) const
47173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
47183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int v = 0; v < 3; v++)
47193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int c = 0; c < 3; c++)
47203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (vertices[v][c] == 0.0f)
47213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
47223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
47233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
47243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
47253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct IsInnerQuadTriangle
47273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool operator() (const Vec3* vertices) const
47293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
47303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int v = 0; v < 3; v++)
47313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int c = 0; c < 2; c++)
47323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (vertices[v][c] == 0.0f || vertices[v][c] == 1.0f)
47333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
47343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
47353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
47363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
47373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool compare (const vector<Vec3>& coordsA, const vector<Vec3>& coordsB, int) const
47393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
47413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return compareTriangleSets(coordsA, coordsB, m_testCtx.getLog(), IsInnerTriangleTriangle(), "outer triangles");
47423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS)
47433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return compareTriangleSets(coordsA, coordsB, m_testCtx.getLog(), IsInnerQuadTriangle(), "outer triangles");
47443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
47453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
47463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
47473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
47483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
47493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
47503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
47513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
47533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test invariance rule #7
47543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
47553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that the set of outer triangles input to the TES only depends on
47563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * tessellation mode, spacing mode and the inner and outer tessellation
47573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * levels corresponding to the inner and outer edges relevant to that
47583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * triangle.
47593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
47603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvariantOuterTriangleSetCase : public PrimitiveSetInvarianceCase
47613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
47623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
47633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InvariantOuterTriangleSetCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing)
47643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: PrimitiveSetInvarianceCase(context, name, description, primType, spacing, false, WINDINGUSAGE_VARY)
47653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(primType == TESSPRIMITIVETYPE_TRIANGLES || primType == TESSPRIMITIVETYPE_QUADS);
47673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
47683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
47703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual vector<LevelCase> genTessLevelCases (void) const
47713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					numSubCasesPerEdge	= 4;
47733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					numEdges			= m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES	? 3
47743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														: m_primitiveType == TESSPRIMITIVETYPE_QUADS		? 4
47753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														: -1;
47763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<LevelCase>		baseResult			= PrimitiveSetInvarianceCase::genTessLevelCases();
47773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<LevelCase>			result;
47783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random					rnd					(123);
47793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Generate variants with different values for irrelevant levels.
47813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int baseNdx = 0; baseNdx < (int)baseResult.size(); baseNdx++)
47823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
47833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessLevels& base = baseResult[baseNdx].levels[0];
47843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (base.inner[0] == 1.0f || (m_primitiveType == TESSPRIMITIVETYPE_QUADS && base.inner[1] == 1.0f))
47853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
47863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int edgeNdx = 0; edgeNdx < numEdges; edgeNdx++)
47883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
47893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TessLevels	levels = base;
47903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				LevelCase	levelCase;
47913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelCase.mem = edgeNdx;
47923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int subCaseNdx = 0; subCaseNdx < numSubCasesPerEdge; subCaseNdx++)
47943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
47953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levelCase.levels.push_back(levels);
47963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int i = 0; i < DE_LENGTH_OF_ARRAY(levels.outer); i++)
47983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
47993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (i != edgeNdx)
48003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							levels.outer[i] = rnd.getFloat(2.0f, 16.0f);
48013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
48023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
48043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						levels.inner[1] = rnd.getFloat(2.0f, 16.0f);
48053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
48063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.push_back(levelCase);
48083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
48093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
48103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
48123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
48133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	class IsTriangleTriangleOnOuterEdge
48153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
48163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	public:
48173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IsTriangleTriangleOnOuterEdge (int edgeNdx) : m_edgeNdx(edgeNdx) {}
48183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool operator() (const Vec3* vertices) const
48193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
48203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool touchesAppropriateEdge = false;
48213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int v = 0; v < 3; v++)
48223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (vertices[v][m_edgeNdx] == 0.0f)
48233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					touchesAppropriateEdge = true;
48243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (touchesAppropriateEdge)
48263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
48273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Vec3 avg = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
48283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return avg[m_edgeNdx] < avg[(m_edgeNdx+1)%3] &&
48293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   avg[m_edgeNdx] < avg[(m_edgeNdx+2)%3];
48303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
48313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
48323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
48333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	private:
48353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int m_edgeNdx;
48363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
48373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	class IsQuadTriangleOnOuterEdge
48393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
48403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	public:
48413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IsQuadTriangleOnOuterEdge (int edgeNdx) : m_edgeNdx(edgeNdx) {}
48423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool onEdge (const Vec3& v) const
48443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
48453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return v[m_edgeNdx%2] == (m_edgeNdx <= 1 ? 0.0f : 1.0f);
48463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
48473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static inline bool onAnyEdge (const Vec3& v)
48493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
48503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return v[0] == 0.0f || v[0] == 1.0f || v[1] == 0.0f || v[1] == 1.0f;
48513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
48523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool operator() (const Vec3* vertices) const
48543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
48553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int v = 0; v < 3; v++)
48563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
48573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Vec3& a = vertices[v];
48583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Vec3& b = vertices[(v+1)%3];
48593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Vec3& c = vertices[(v+2)%3];
48603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (onEdge(a) && onEdge(b))
48613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return true;
48623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (onEdge(c) && !onAnyEdge(a) && !onAnyEdge(b) && a[m_edgeNdx%2] == b[m_edgeNdx%2])
48633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return true;
48643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
48653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
48673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
48683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	private:
48703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int m_edgeNdx;
48713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
48723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool compare (const vector<Vec3>& coordsA, const vector<Vec3>& coordsB, int outerEdgeNdx) const
48743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
48753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
48763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
48773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return compareTriangleSets(coordsA, coordsB, m_testCtx.getLog(),
48783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   IsTriangleTriangleOnOuterEdge(outerEdgeNdx),
48793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   ("inner triangles, and outer triangles corresponding to other edge than edge "
48803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										+ outerEdgeDescriptions(m_primitiveType)[outerEdgeNdx].description()).c_str());
48813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
48823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_primitiveType == TESSPRIMITIVETYPE_QUADS)
48833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
48843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return compareTriangleSets(coordsA, coordsB, m_testCtx.getLog(),
48853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   IsQuadTriangleOnOuterEdge(outerEdgeNdx),
48863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   ("inner triangles, and outer triangles corresponding to other edge than edge "
48873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										+ outerEdgeDescriptions(m_primitiveType)[outerEdgeNdx].description()).c_str());
48883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
48893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
48903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
48913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
48933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
48943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
48953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
48973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Base class for testing individual components of tess coords
48983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
48993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Useful for testing parts of invariance rule #8.
49003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
49013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TessCoordComponentInvarianceCase : public TestCase
49023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
49033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
49043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TessCoordComponentInvarianceCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode)
49053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase			(context, name, description)
49063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType	(primType)
49073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_spacing			(spacing)
49083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_winding			(winding)
49093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_usePointMode	(usePointMode)
49103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
49113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
49123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									init		(void);
49143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									deinit		(void);
49153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult							iterate		(void);
49163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
49183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string							tessEvalOutputComponentStatements	(const char* tessCoordComponentName, const char* outputComponentName) const = 0;
49193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool							checkTessCoordComponent				(float component) const = 0;
49203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
49223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static vector<float>					genTessLevelCases (int numCases);
49233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int						RENDER_SIZE = 16;
49253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType					m_primitiveType;
49273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode						m_spacing;
49283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Winding							m_winding;
49293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool								m_usePointMode;
49303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const glu::ShaderProgram>		m_program;
49323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
49333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessCoordComponentInvarianceCase::init (void)
49353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
49363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
49373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
49383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
49403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::VertexSource					("#version 310 es\n"
49413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_v_attr;\n"
49433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp float in_tc_attr;\n"
49443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
49463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
49473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_tc_attr = in_v_attr;\n"
49483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
49493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationControlSource		("#version 310 es\n"
49513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
49523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (vertices = 1) out;\n"
49543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_tc_attr[];\n"
49563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
49583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
49593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
49603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
49613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
49633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
49643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
49653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
49663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
49673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationEvaluationSource	("#version 310 es\n"
49693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
49703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing, m_winding, m_usePointMode) +
49723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec4 in_f_color;\n"
49743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec3 out_te_output;\n"
49753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
49773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
49783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + tessEvalOutputComponentStatements("gl_TessCoord.x", "out_te_output.x")
49793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + tessEvalOutputComponentStatements("gl_TessCoord.y", "out_te_output.y")
49803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
49823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													tessEvalOutputComponentStatements("gl_TessCoord.z", "out_te_output.z") :
49833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													"	out_te_output.z = 0.0f;\n") +
49843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
49853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_f_color = vec4(1.0);\n"
49863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
49873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::FragmentSource					("#version 310 es\n"
49893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (location = 0) out mediump vec4 o_color;\n"
49913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp vec4 in_f_color;\n"
49933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
49943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
49953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
49963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	o_color = in_f_color;\n"
49973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
49983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackVarying		("out_te_output")
50003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)));
50013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
50033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
50043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
50053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
50063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessCoordComponentInvarianceCase::deinit (void)
50083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
50103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
50113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<float> TessCoordComponentInvarianceCase::genTessLevelCases (int numCases)
50133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random		rnd(123);
50153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>	result;
50163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < numCases; i++)
50183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int j = 0; j < 6; j++)
50193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result.push_back(rnd.getFloat(1.0f, 63.0f));
50203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
50223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
50233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessCoordComponentInvarianceCase::IterateResult TessCoordComponentInvarianceCase::iterate (void)
50253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<Vec3> TFHandler;
50273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log					= m_testCtx.getLog();
50293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx			= m_context.getRenderContext();
50303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport	viewport			(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
50313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= renderCtx.getFunctions();
50323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numTessLevelCases	= 32;
50333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<float>		tessLevels			= genTessLevelCases(numTessLevelCases);
50343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			programGL			= m_program->getProgram();
50353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
50373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
50383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 6);
50393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute the number vertices in the largest draw call, so we can allocate the TF buffer just once.
50423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int maxNumVerticesInDrawCall = 0;
50433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < numTessLevelCases; i++)
50443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxNumVerticesInDrawCall = de::max(maxNumVerticesInDrawCall, referenceVertexCount(m_primitiveType, m_spacing, m_usePointMode, &tessLevels[6*i+0], &tessLevels[6*i+2]));
50453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
50473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler tfHandler(m_context.getRenderContext(), maxNumVerticesInDrawCall);
50483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < numTessLevelCases; tessLevelCaseNdx++)
50503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
50513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Testing with tessellation levels: " << tessellationLevelsString(&tessLevels[6*tessLevelCaseNdx+0], &tessLevels[6*tessLevelCaseNdx+2]) << TestLog::EndMessage;
50523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glu::VertexArrayBinding bindings[] = { glu::va::Float("in_v_attr", 1, (int)6, 0, &tessLevels[6*tessLevelCaseNdx]) };
50543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const TFHandler::Result tfResult = tfHandler.renderAndGetPrimitives(programGL, outputPrimitiveTypeGL(m_primitiveType, m_usePointMode),
50553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																					DE_LENGTH_OF_ARRAY(bindings), &bindings[0], 6);
50563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int vtxNdx = 0; vtxNdx < (int)tfResult.varying.size(); vtxNdx++)
50583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
50593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const Vec3&		vec			= tfResult.varying[vtxNdx];
50603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int		numComps	= m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3 : 2;
50613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int compNdx = 0; compNdx < numComps; compNdx++)
50633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
50643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (!checkTessCoordComponent(vec[compNdx]))
50653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
50663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "Note: output value at index " << vtxNdx << " is "
50673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? de::toString(vec) : de::toString(vec.swizzle(0,1)))
50683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< TestLog::EndMessage;
50693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid tessellation coordinate component");
50703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							return STOP;
50713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
50723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
50733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
50743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
50753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
50763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
50793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
50803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
50813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
50833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test first part of invariance rule #8
50843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
50853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that all (relevant) components of tess coord are in [0,1].
50863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
50873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TessCoordComponentRangeCase : public TessCoordComponentInvarianceCase
50883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
50903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TessCoordComponentRangeCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode)
50913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TessCoordComponentInvarianceCase(context, name, description, primType, spacing, winding, usePointMode)
50923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
50963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string tessEvalOutputComponentStatements (const char* tessCoordComponentName, const char* outputComponentName) const
50973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return string() + "\t" + outputComponentName + " = " + tessCoordComponentName + ";\n";
50993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool checkTessCoordComponent (float component) const
51023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!de::inRange(component, 0.0f, 1.0f))
51043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
51053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << TestLog::Message << "Failure: tess coord component isn't in range [0,1]" << TestLog::EndMessage;
51063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
51073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
51083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
51093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
51113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
51133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test second part of invariance rule #8
51143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
51153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test that all (relevant) components of tess coord are in [0,1] and
51163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 1.0-c is exact for every such component c.
51173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
51183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass OneMinusTessCoordComponentCase : public TessCoordComponentInvarianceCase
51193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
51203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
51213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OneMinusTessCoordComponentCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode)
51223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TessCoordComponentInvarianceCase(context, name, description, primType, spacing, winding, usePointMode)
51233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
51273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string tessEvalOutputComponentStatements (const char* tessCoordComponentName, const char* outputComponentName) const
51283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return string() + "	{\n"
51303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  "		float oneMinusComp = 1.0 - " + tessCoordComponentName + ";\n"
51313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  "		" + outputComponentName + " = " + tessCoordComponentName + " + oneMinusComp;\n"
51323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  "	}\n";
51333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool checkTessCoordComponent (float component) const
51363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (component != 1.0f)
51383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
51393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << TestLog::Message << "Failure: comp + (1.0-comp) doesn't equal 1.0 for some component of tessellation coordinate" << TestLog::EndMessage;
51403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
51413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
51423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
51433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
51453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
51473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test that patch is discarded if relevant outer level <= 0.0
51483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
51493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Draws patches with different combinations of tessellation levels,
51503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * varying which levels are negative. Verifies by checking that colored
51513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * pixels exist inside the area of valid primitives, and only black pixels
51523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * exist inside the area of discarded primitives. An additional sanity
51533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * test is done, checking that the number of primitives written by TF is
51543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * correct.
51553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
51563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PrimitiveDiscardCase : public TestCase
51573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
51583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
51593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PrimitiveDiscardCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, SpacingMode spacing, Winding winding, bool usePointMode)
51603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase			(context, name, description)
51613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType	(primType)
51623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_spacing			(spacing)
51633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_winding			(winding)
51643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_usePointMode	(usePointMode)
51653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									init		(void);
51693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									deinit		(void);
51703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult							iterate		(void);
51713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
51733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static vector<float>					genAttributes (void);
51743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int						RENDER_SIZE = 256;
51763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType					m_primitiveType;
51783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const SpacingMode						m_spacing;
51793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Winding							m_winding;
51803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool								m_usePointMode;
51813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const glu::ShaderProgram>		m_program;
51833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
51843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PrimitiveDiscardCase::init (void)
51863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
51873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
51883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
51893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
51913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::VertexSource					("#version 310 es\n"
51923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
51933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_v_attr;\n"
51943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp float in_tc_attr;\n"
51953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
51963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
51973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
51983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_tc_attr = in_v_attr;\n"
51993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
52003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationControlSource		("#version 310 es\n"
52023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
52033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (vertices = 1) out;\n"
52053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_tc_attr[];\n"
52073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch out highp vec2 in_te_positionScale;\n"
52093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch out highp vec2 in_te_positionOffset;\n"
52103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
52123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
52133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_te_positionScale  = vec2(in_tc_attr[6], in_tc_attr[7]);\n"
52143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_te_positionOffset = vec2(in_tc_attr[8], in_tc_attr[9]);\n"
52153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
52173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
52183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
52203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
52213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
52223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
52233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
52243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationEvaluationSource	("#version 310 es\n"
52263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
52273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + getTessellationEvaluationInLayoutString(m_primitiveType, m_spacing, m_winding, m_usePointMode) +
52293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch in highp vec2 in_te_positionScale;\n"
52313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch in highp vec2 in_te_positionOffset;\n"
52323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec3 out_te_tessCoord;\n"
52343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
52363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
52373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	out_te_tessCoord = gl_TessCoord;\n"
52383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_Position = vec4(gl_TessCoord.xy*in_te_positionScale + in_te_positionOffset, 0.0, 1.0);\n"
52393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
52403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::FragmentSource					("#version 310 es\n"
52423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (location = 0) out mediump vec4 o_color;\n"
52443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
52453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
52463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
52473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	o_color = vec4(1.0);\n"
52483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
52493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackVarying		("out_te_tessCoord")
52513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)));
52523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
52543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
52553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
52563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
52573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PrimitiveDiscardCase::deinit (void)
52593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
52603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
52613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
52623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<float> PrimitiveDiscardCase::genAttributes (void)
52643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
52653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Generate input attributes (tessellation levels, and position scale and
52663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// offset) for a number of primitives. Each primitive has a different
52673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// combination of tessellatio levels; each level is either a valid
52683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// value or an "invalid" value (negative or zero, chosen from
52693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// invalidTessLevelChoices).
52703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note The attributes are generated in such an order that all of the
52723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 valid attribute tuples come before the first invalid one both
52733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 in the result vector, and when scanning the resulting 2d grid
52743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 of primitives is scanned in y-major order. This makes
52753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 verification somewhat simpler.
52763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float	baseTessLevels[6]			= { 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
52783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float	invalidTessLevelChoices[]	= { -0.42f, 0.0f };
52793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numChoices					= 1 + DE_LENGTH_OF_ARRAY(invalidTessLevelChoices);
52803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float				choices[6][numChoices];
52813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>		result;
52823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 0; levelNdx < 6; levelNdx++)
52843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int choiceNdx = 0; choiceNdx < numChoices; choiceNdx++)
52853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			choices[levelNdx][choiceNdx] = choiceNdx == 0 ? baseTessLevels[levelNdx] : invalidTessLevelChoices[choiceNdx-1];
52863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
52883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	numCols			= intPow(numChoices, 6/2); // sqrt(numChoices**6) == sqrt(number of primitives)
52893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	numRows			= numCols;
52903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			index			= 0;
52913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			i[6];
52923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// We could do this with some generic combination-generation function, but meh, it's not that bad.
52933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (i[2] = 0; i[2] < numChoices; i[2]++) // First  outer
52943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (i[3] = 0; i[3] < numChoices; i[3]++) // Second outer
52953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (i[4] = 0; i[4] < numChoices; i[4]++) // Third  outer
52963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (i[5] = 0; i[5] < numChoices; i[5]++) // Fourth outer
52973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (i[0] = 0; i[0] < numChoices; i[0]++) // First  inner
52983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (i[1] = 0; i[1] < numChoices; i[1]++) // Second inner
52993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
53003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int j = 0; j < 6; j++)
53013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.push_back(choices[j][i[j]]);
53023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
53043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int col = index % numCols;
53053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int row = index / numCols;
53063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Position scale.
53073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.push_back((float)2.0f / (float)numCols);
53083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.push_back((float)2.0f / (float)numRows);
53093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Position offset.
53103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.push_back((float)col / (float)numCols * 2.0f - 1.0f);
53113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.push_back((float)row / (float)numRows * 2.0f - 1.0f);
53123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
53133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			index++;
53153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
53163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
53173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
53193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
53203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53213c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPrimitiveDiscardCase::IterateResult PrimitiveDiscardCase::iterate (void)
53223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
53233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<Vec3> TFHandler;
53243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log						= m_testCtx.getLog();
53263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx				= m_context.getRenderContext();
53273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport	viewport				(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
53283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl						= renderCtx.getFunctions();
53293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<float>		attributes				= genAttributes();
53303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numAttribsPerPrimitive	= 6+2+2; // Tess levels, scale, offset.
53313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numPrimitives			= (int)attributes.size() / numAttribsPerPrimitive;
53323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			programGL				= m_program->getProgram();
53333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
53353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
53363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, numAttribsPerPrimitive);
53373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
53393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
53403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check the convenience assertion that all discarded patches come after the last non-discarded patch.
53423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
53433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool discardedPatchEncountered = false;
53443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int patchNdx = 0; patchNdx < numPrimitives; patchNdx++)
53453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
53463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool discard = isPatchDiscarded(m_primitiveType, &attributes[numAttribsPerPrimitive*patchNdx + 2]);
53473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(discard || !discardedPatchEncountered);
53483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			discardedPatchEncountered = discard;
53493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
53503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_UNREF(discardedPatchEncountered);
53513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
53523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
53543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int numVerticesInDrawCall = 0;
53553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int patchNdx = 0; patchNdx < numPrimitives; patchNdx++)
53563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numVerticesInDrawCall += referenceVertexCount(m_primitiveType, m_spacing, m_usePointMode, &attributes[numAttribsPerPrimitive*patchNdx+0], &attributes[numAttribsPerPrimitive*patchNdx+2]);
53573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Note: rendering " << numPrimitives << " patches; first patches have valid relevant outer levels, "
53593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< "but later patches have one or more invalid (i.e. less than or equal to 0.0) relevant outer levels" << TestLog::EndMessage;
53603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
53623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler					tfHandler	(m_context.getRenderContext(), numVerticesInDrawCall);
53633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::VertexArrayBinding	bindings[]	= { glu::va::Float("in_v_attr", 1, (int)attributes.size(), 0, &attributes[0]) };
53643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TFHandler::Result			tfResult	= tfHandler.renderAndGetPrimitives(programGL, outputPrimitiveTypeGL(m_primitiveType, m_usePointMode),
53653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																						   DE_LENGTH_OF_ARRAY(bindings), &bindings[0], (int)attributes.size());
53663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Surface				pixels		= getPixels(renderCtx, viewport);
53673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Image("RenderedImage", "Rendered image", pixels);
53693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if ((int)tfResult.varying.size() != numVerticesInDrawCall)
53713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
53723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Failure: expected " << numVerticesInDrawCall << " vertices from transform feedback, got " << tfResult.varying.size() << TestLog::EndMessage;
53733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Wrong number of tessellation coordinates");
53743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
53753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
53763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Check that white pixels are found around every non-discarded
53783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// patch, and that only black pixels are found after the last
53793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// non-discarded patch.
53803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
53813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int lastWhitePixelRow									= 0;
53823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int secondToLastWhitePixelRow							= 0;
53833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int	lastWhitePixelColumnOnSecondToLastWhitePixelRow		= 0;
53843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int patchNdx = 0; patchNdx < numPrimitives; patchNdx++)
53863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
53873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float* const	attr			= &attributes[numAttribsPerPrimitive*patchNdx];
53883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const bool			validLevels		= !isPatchDiscarded(m_primitiveType, &attr[2]);
53893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (validLevels)
53913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
53923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// Not a discarded patch; check that at least one white pixel is found in its area.
53933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float* const	scale		= &attr[6];
53953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float* const	offset		= &attr[8];
53963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const int			x0			= (int)((			offset[0] + 1.0f)*0.5f*(float)pixels.getWidth()) - 1;
53973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const int			x1			= (int)((scale[0] + offset[0] + 1.0f)*0.5f*(float)pixels.getWidth()) + 1;
53983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const int			y0			= (int)((			offset[1] + 1.0f)*0.5f*(float)pixels.getHeight()) - 1;
53993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const int			y1			= (int)((scale[1] + offset[1] + 1.0f)*0.5f*(float)pixels.getHeight()) + 1;
54003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const bool			isMSAA		= renderCtx.getRenderTarget().getNumSamples() > 1;
54013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						bool				pixelOk		= false;
54023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (y1 > lastWhitePixelRow)
54043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
54053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							secondToLastWhitePixelRow	= lastWhitePixelRow;
54063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							lastWhitePixelRow			= y1;
54073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
54083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						lastWhitePixelColumnOnSecondToLastWhitePixelRow = x1;
54093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int y = y0; y <= y1 && !pixelOk; y++)
54113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int x = x0; x <= x1 && !pixelOk; x++)
54123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
54133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							if (!de::inBounds(x, 0, pixels.getWidth()) || !de::inBounds(y, 0, pixels.getHeight()))
54143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								continue;
54153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							if (isMSAA)
54173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
54183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (pixels.getPixel(x, y) != tcu::RGBA::black)
54193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									pixelOk = true;
54203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
54213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							else
54223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
54233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (pixels.getPixel(x, y) == tcu::RGBA::white)
54243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									pixelOk = true;
54253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
54263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
54273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (!pixelOk)
54293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
54303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							log << TestLog::Message << "Failure: expected at least one " << (isMSAA ? "non-black" : "white") << " pixel in the rectangle "
54313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< "[x0=" << x0 << ", y0=" << y0 << ", x1=" << x1 << ", y1=" << y1 << "]" << TestLog::EndMessage
54323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< TestLog::Message << "Note: the rectangle approximately corresponds to the patch with these tessellation levels: "
54333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< tessellationLevelsString(&attr[0], &attr[1]) << TestLog::EndMessage;
54343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
54353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							return STOP;
54363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
54373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
54383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
54393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
54403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// First discarded primitive patch; the remaining are guaranteed to be discarded ones as well.
54413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int y = 0; y < pixels.getHeight(); y++)
54433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int x = 0; x < pixels.getWidth(); x++)
54443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
54453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							if (y > lastWhitePixelRow || (y > secondToLastWhitePixelRow && x > lastWhitePixelColumnOnSecondToLastWhitePixelRow))
54463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
54473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								if (pixels.getPixel(x, y) != tcu::RGBA::black)
54483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								{
54493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									log << TestLog::Message << "Failure: expected all pixels to be black in the area "
54503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															<< (lastWhitePixelColumnOnSecondToLastWhitePixelRow < pixels.getWidth()-1
54513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	? string() + "y > " + de::toString(lastWhitePixelRow) + " || (y > " + de::toString(secondToLastWhitePixelRow)
54523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			   + " && x > " + de::toString(lastWhitePixelColumnOnSecondToLastWhitePixelRow) + ")"
54533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	: string() + "y > " + de::toString(lastWhitePixelRow))
54543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															<< " (they all correspond to patches that should be discarded)" << TestLog::EndMessage
54553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										<< TestLog::Message << "Note: pixel " << tcu::IVec2(x, y) << " isn't black" << TestLog::EndMessage;
54563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
54573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									return STOP;
54583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								}
54593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
54603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
54613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
54633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
54643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
54653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
54663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
54673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
54683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
54703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
54713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
54723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
54743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Case testing user-defined IO between TCS and TES
54753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
54763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * TCS outputs various values to TES, including aggregates. The outputs
54773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * can be per-patch or per-vertex, and if per-vertex, they can also be in
54783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * an IO block. Per-vertex input array size can be left implicit (i.e.
54793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * inputArray[]) or explicit either by gl_MaxPatchVertices or an integer
54803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * literal whose value is queried from GL.
54813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
54823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The values output are generated in TCS and verified in TES against
54833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * similarly generated values. In case a verification of a value fails, the
54843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * index of the invalid value is output with TF.
54853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * As a sanity check, also the rendering result is verified (against pre-
54863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * rendered reference).
54873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
54883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass UserDefinedIOCase : public TestCase
54893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
54903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
54913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum IOType
54923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
54933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IO_TYPE_PER_PATCH = 0,
54943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IO_TYPE_PER_PATCH_ARRAY,
54958cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		IO_TYPE_PER_PATCH_BLOCK,
54968cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		IO_TYPE_PER_PATCH_BLOCK_ARRAY,
54973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IO_TYPE_PER_VERTEX,
54983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IO_TYPE_PER_VERTEX_BLOCK,
54993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IO_TYPE_LAST
55013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
55023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum VertexIOArraySize
55043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
55053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VERTEX_IO_ARRAY_SIZE_IMPLICIT = 0,
55063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN,		//!< Use gl_MaxPatchVertices as size for per-vertex input array.
55073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VERTEX_IO_ARRAY_SIZE_EXPLICIT_QUERY,				//!< Query GL_MAX_PATCH_VERTICES, and use that as size for per-vertex input array.
55083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VERTEX_IO_ARRAY_SIZE_LAST
55103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
55113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	UserDefinedIOCase (Context& context, const char* name, const char* description, TessPrimitiveType primType, IOType ioType, VertexIOArraySize vertexIOArraySize, const char* referenceImagePath)
55133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase				(context, name, description)
55143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_primitiveType		(primType)
55153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_ioType				(ioType)
55163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_vertexIOArraySize	(vertexIOArraySize)
55173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_referenceImagePath	(referenceImagePath)
55183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
55193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
55203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									init		(void);
55223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									deinit		(void);
55233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult							iterate		(void);
55243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
55263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef string (*BasicTypeVisitFunc)(const string& name, glu::DataType type, int indentationDepth); //!< See glslTraverseBasicTypes below.
55273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	class TopLevelObject
55293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
55303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	public:
55313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		virtual			~TopLevelObject					(void) {}
55323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		virtual string	name							(void) const = 0;
55348cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		virtual string	declare							(void) const = 0;
55358cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		virtual string	declareArray					(const string& arraySizeExpr) const = 0;
55368cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		virtual string	glslTraverseBasicTypeArray		(int numArrayElements, //!< If negative, traverse just array[gl_InvocationID], not all indices.
55373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 int indentationDepth,
55383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 BasicTypeVisitFunc) const = 0;
55398cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		virtual string	glslTraverseBasicType			(int indentationDepth,
55408cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry														 BasicTypeVisitFunc) const = 0;
55413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		virtual int		numBasicSubobjectsInElementType	(void) const = 0;
55423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		virtual string	basicSubobjectAtIndex			(int index, int arraySize) const = 0;
55433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
55443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	class Variable : public TopLevelObject
55463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
55473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	public:
55483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Variable (const string& name_, const glu::VarType& type, bool isArray)
55493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			: m_name		(name_)
55503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			, m_type		(type)
55513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			, m_isArray		(isArray)
55523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
55533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!type.isArrayType());
55543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
55553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string	name								(void) const { return m_name; }
55578cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	declare								(void) const;
55588cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	declareArray						(const string& arraySizeExpr) const;
55598cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	glslTraverseBasicTypeArray			(int numArrayElements, int indentationDepth, BasicTypeVisitFunc) const;
55608cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	glslTraverseBasicType				(int indentationDepth, BasicTypeVisitFunc) const;
55613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		numBasicSubobjectsInElementType		(void) const;
55623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string	basicSubobjectAtIndex				(int index, int arraySize) const;
55633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	private:
55653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string			m_name;
55663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::VarType	m_type; //!< If this Variable is an array element, m_type is the element type; otherwise just the variable type.
55673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		m_isArray;
55683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
55693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	class IOBlock : public TopLevelObject
55713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
55723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	public:
55733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		struct Member
55743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
55753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string			name;
55763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::VarType	type;
55773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Member (const string& n, const glu::VarType& t) : name(n), type(t) {}
55783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
55793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IOBlock (const string& blockName, const string& interfaceName, const vector<Member>& members)
55813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			: m_blockName		(blockName)
55823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			, m_interfaceName	(interfaceName)
55833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			, m_members			(members)
55843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
55853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
55863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string	name								(void) const { return m_interfaceName; }
55888cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	declare								(void) const;
55898cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	declareArray						(const string& arraySizeExpr) const;
55908cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	glslTraverseBasicTypeArray			(int numArrayElements, int indentationDepth, BasicTypeVisitFunc) const;
55918cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		string	glslTraverseBasicType				(int indentationDepth, BasicTypeVisitFunc) const;
55923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		numBasicSubobjectsInElementType		(void) const;
55933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string	basicSubobjectAtIndex				(int index, int arraySize) const;
55943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	private:
55963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string			m_blockName;
55973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string			m_interfaceName;
55983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<Member>	m_members;
55993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
56003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static string							glslTraverseBasicTypes				(const string&			rootName,
56023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				 const glu::VarType&	rootType,
56033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				 int					arrayNestingDepth,
56043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				 int					indentationDepth,
56053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				 BasicTypeVisitFunc		visit);
56063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static string							glslAssignBasicTypeObject			(const string& name, glu::DataType, int indentationDepth);
56083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static string							glslCheckBasicTypeObject			(const string& name, glu::DataType, int indentationDepth);
56093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static int								numBasicSubobjectsInElementType		(const vector<SharedPtr<TopLevelObject> >&);
56103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static string							basicSubobjectAtIndex				(int index, const vector<SharedPtr<TopLevelObject> >&, int topLevelArraySizes);
56113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56128cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	enum
56138cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	{
56148cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		RENDER_SIZE = 256
56158cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	};
56168cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	enum
56178cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	{
56188cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		NUM_OUTPUT_VERTICES = 5
56198cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	};
56208cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	enum
56218cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	{
56228cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		NUM_PER_PATCH_ARRAY_ELEMS = 3
56238cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	};
56248cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	enum
56258cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	{
56268cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		NUM_PER_PATCH_BLOCKS = 2
56278cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	};
56283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessPrimitiveType					m_primitiveType;
56303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const IOType							m_ioType;
56313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VertexIOArraySize					m_vertexIOArraySize;
56323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string							m_referenceImagePath;
56333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<glu::StructType>					m_structTypes;
56353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<SharedPtr<TopLevelObject> >		m_tcsOutputs;
56363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<SharedPtr<TopLevelObject> >		m_tesInputs;
56373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const glu::ShaderProgram>		m_program;
56393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
56403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
56423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Generate GLSL code to traverse (possibly aggregate) object
56433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
56443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Generates a string that represents GLSL code that traverses the
56453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * basic-type subobjects in a rootType-typed object named rootName. Arrays
56463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * are traversed with loops and struct members are each traversed
56473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * separately. The code for each basic-type subobject is generated with
56483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the function given as the 'visit' argument.
56493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
56503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring UserDefinedIOCase::glslTraverseBasicTypes (const string&			rootName,
56513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  const glu::VarType&	rootType,
56523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  int					arrayNestingDepth,
56533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  int					indentationDepth,
56543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  BasicTypeVisitFunc	visit)
56553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
56563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (rootType.isBasicType())
56573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return visit(rootName, rootType.getBasicType(), indentationDepth);
56583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (rootType.isArrayType())
56593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
56603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string indentation	= string(indentationDepth, '\t');
56613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string loopIndexName	= "i" + de::toString(arrayNestingDepth);
56623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string arrayLength	= de::toString(rootType.getArraySize());
56633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return indentation + "for (int " + loopIndexName + " = 0; " + loopIndexName + " < " + de::toString(rootType.getArraySize()) + "; " + loopIndexName + "++)\n" +
56643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   indentation + "{\n" +
56653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   glslTraverseBasicTypes(rootName + "[" + loopIndexName + "]", rootType.getElementType(), arrayNestingDepth+1, indentationDepth+1, visit) +
56663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   indentation + "}\n";
56673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
56683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (rootType.isStructType())
56693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
56703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::StructType&	structType = *rootType.getStructPtr();
56713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numMembers = structType.getNumMembers();
56723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string					result;
56733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int membNdx = 0; membNdx < numMembers; membNdx++)
56753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
56763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::StructMember& member = structType.getMember(membNdx);
56773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result += glslTraverseBasicTypes(rootName + "." + member.getName(), member.getType(), arrayNestingDepth, indentationDepth, visit);
56783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
56793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
56813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
56823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
56833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
56843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
56853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
56863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
56873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
56883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
56898cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::Variable::declare (void) const
56908cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry{
56918cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	DE_ASSERT(!m_isArray);
56928cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	return de::toString(glu::declare(m_type, m_name)) + ";\n";
56938cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry}
56948cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
56958cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::Variable::declareArray (const string& sizeExpr) const
56963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
56978cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	DE_ASSERT(m_isArray);
56988cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	return de::toString(glu::declare(m_type, m_name)) + "[" + sizeExpr + "];\n";
56993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
57003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57018cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::IOBlock::declare (void) const
57023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
57038cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	std::ostringstream buf;
57048cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57058cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	buf << m_blockName << "\n"
57068cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		<< "{\n";
57078cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < (int)m_members.size(); i++)
57098cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		buf << "\t" << glu::declare(m_members[i].type, m_members[i].name) << ";\n";
57108cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57118cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	buf << "} " << m_interfaceName << ";\n";
57128cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	return buf.str();
57138cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry}
57148cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57158cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::IOBlock::declareArray (const string& sizeExpr) const
57168cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry{
57178cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	std::ostringstream buf;
57188cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57198cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	buf << m_blockName << "\n"
57208cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		<< "{\n";
57218cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57228cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	for (int i = 0; i < (int)m_members.size(); i++)
57238cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		buf << "\t" << glu::declare(m_members[i].type, m_members[i].name) << ";\n";
57248cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57258cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	buf << "} " << m_interfaceName << "[" << sizeExpr << "];\n";
57268cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	return buf.str();
57273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
57283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57298cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::Variable::glslTraverseBasicTypeArray (int numArrayElements, int indentationDepth, BasicTypeVisitFunc visit) const
57303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
57318cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	DE_ASSERT(m_isArray);
57328cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57338cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	const bool				traverseAsArray		= numArrayElements >= 0;
57348cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	const string			traversedName		= m_name + (!traverseAsArray ? "[gl_InvocationID]" : "");
57353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VarType		type				= traverseAsArray ? glu::VarType(m_type, numArrayElements) : m_type;
57363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return UserDefinedIOCase::glslTraverseBasicTypes(traversedName, type, 0, indentationDepth, visit);
57383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
57393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57408cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::Variable::glslTraverseBasicType (int indentationDepth, BasicTypeVisitFunc visit) const
57418cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry{
57428cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	DE_ASSERT(!m_isArray);
57438cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57448cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	return UserDefinedIOCase::glslTraverseBasicTypes(m_name, m_type, 0, indentationDepth, visit);
57458cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry}
57468cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57478cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::IOBlock::glslTraverseBasicTypeArray (int numArrayElements, int indentationDepth, BasicTypeVisitFunc visit) const
57483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
57493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numArrayElements >= 0)
57503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
57513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	indentation			= string(indentationDepth, '\t');
57523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string			result				= indentation + "for (int i0 = 0; i0 < " + de::toString(numArrayElements) + "; i0++)\n" +
57533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  indentation + "{\n";
57543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < (int)m_members.size(); i++)
57553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result += UserDefinedIOCase::glslTraverseBasicTypes(m_interfaceName + "[i0]." + m_members[i].name, m_members[i].type, 1, indentationDepth+1, visit);
57563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += indentation + "}\n";
57573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
57583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
57593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
57603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
57613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string result;
57623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < (int)m_members.size(); i++)
57633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result += UserDefinedIOCase::glslTraverseBasicTypes(m_interfaceName + "[gl_InvocationID]." + m_members[i].name, m_members[i].type, 0, indentationDepth, visit);
57643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return result;
57653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
57663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
57673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57688cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57698cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyrystring UserDefinedIOCase::IOBlock::glslTraverseBasicType (int indentationDepth, BasicTypeVisitFunc visit) const
57708cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry{
57718cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	string result;
57728cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	for (int i = 0; i < (int)m_members.size(); i++)
57738cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		result += UserDefinedIOCase::glslTraverseBasicTypes(m_interfaceName + "." + m_members[i].name, m_members[i].type, 0, indentationDepth, visit);
57748cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	return result;
57758cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry}
57768cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
57773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint UserDefinedIOCase::Variable::numBasicSubobjectsInElementType (void) const
57783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
57793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numBasicSubobjects(m_type);
57803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
57813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint UserDefinedIOCase::IOBlock::numBasicSubobjectsInElementType (void) const
57833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
57843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int result = 0;
57853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < (int)m_members.size(); i++)
57863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += numBasicSubobjects(m_members[i].type);
57873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
57883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
57893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring UserDefinedIOCase::Variable::basicSubobjectAtIndex (int subobjectIndex, int arraySize) const
57913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
57923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VarType	type			= m_isArray ? glu::VarType(m_type, arraySize) : m_type;
57933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					currentIndex	= 0;
57943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
57953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (glu::BasicTypeIterator basicIt = glu::BasicTypeIterator::begin(&type);
57963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 basicIt != glu::BasicTypeIterator::end(&type);
57973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 ++basicIt)
57983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
57993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (currentIndex == subobjectIndex)
58003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return m_name + de::toString(glu::TypeAccessFormat(type, basicIt.getPath()));
58013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		currentIndex++;
58023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
58033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(false);
58043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_NULL;
58053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
58063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring UserDefinedIOCase::IOBlock::basicSubobjectAtIndex (int subobjectIndex, int arraySize) const
58083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
58093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int currentIndex = 0;
58103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int arrayNdx = 0; arrayNdx < arraySize; arrayNdx++)
58113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
58123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int memberNdx = 0; memberNdx < (int)m_members.size(); memberNdx++)
58133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
58143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::VarType& membType = m_members[memberNdx].type;
58153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (glu::BasicTypeIterator basicIt = glu::BasicTypeIterator::begin(&membType);
58163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 basicIt != glu::BasicTypeIterator::end(&membType);
58173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 ++basicIt)
58183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
58193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (currentIndex == subobjectIndex)
58203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return m_interfaceName + "[" + de::toString(arrayNdx) + "]." + m_members[memberNdx].name + de::toString(glu::TypeAccessFormat(membType, basicIt.getPath()));
58213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				currentIndex++;
58223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
58233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
58243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
58253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(false);
58263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_NULL;
58273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
58283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Used as the 'visit' argument for glslTraverseBasicTypes.
58303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring UserDefinedIOCase::glslAssignBasicTypeObject (const string& name, glu::DataType type, int indentationDepth)
58313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
58323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		scalarSize		= glu::getDataTypeScalarSize(type);
58333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	indentation		= string(indentationDepth, '\t');
58343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			result;
58353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result += indentation + name + " = ";
58373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type != glu::TYPE_FLOAT)
58393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += string() + glu::getDataTypeName(type) + "(";
58403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < scalarSize; i++)
58413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += (i > 0 ? ", v+" + de::floatToString(0.8f*(float)i, 1)
58423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						 : "v");
58433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type != glu::TYPE_FLOAT)
58443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += ")";
58453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result += ";\n" +
58463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  indentation + "v += 0.4;\n";
58473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
58483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
58493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Used as the 'visit' argument for glslTraverseBasicTypes.
58513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring UserDefinedIOCase::glslCheckBasicTypeObject (const string& name, glu::DataType type, int indentationDepth)
58523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
58533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		scalarSize		= glu::getDataTypeScalarSize(type);
58543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	indentation		= string(indentationDepth, '\t');
58553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			result;
58563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result += indentation + "allOk = allOk && compare_" + glu::getDataTypeName(type) + "(" + name + ", ";
58583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type != glu::TYPE_FLOAT)
58603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += string() + glu::getDataTypeName(type) + "(";
58613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < scalarSize; i++)
58623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += (i > 0 ? ", v+" + de::floatToString(0.8f*(float)i, 1)
58633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						 : "v");
58643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type != glu::TYPE_FLOAT)
58653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += ")";
58663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result += ");\n" +
58673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  indentation + "v += 0.4;\n" +
58683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  indentation + "if (allOk) firstFailedInputIndex++;\n";
58693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
58713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
58723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint UserDefinedIOCase::numBasicSubobjectsInElementType (const vector<SharedPtr<TopLevelObject> >& objects)
58743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
58753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int result = 0;
58763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < (int)objects.size(); i++)
58773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result += objects[i]->numBasicSubobjectsInElementType();
58783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
58793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
58803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring UserDefinedIOCase::basicSubobjectAtIndex (int subobjectIndex, const vector<SharedPtr<TopLevelObject> >& objects, int topLevelArraySize)
58823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
58833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int currentIndex	= 0;
58843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int objectIndex		= 0;
58853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (; currentIndex < subobjectIndex; objectIndex++)
58863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		currentIndex += objects[objectIndex]->numBasicSubobjectsInElementType() * topLevelArraySize;
58873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (currentIndex > subobjectIndex)
58883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
58893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		objectIndex--;
58903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		currentIndex -= objects[objectIndex]->numBasicSubobjectsInElementType() * topLevelArraySize;
58913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
58923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return objects[objectIndex]->basicSubobjectAtIndex(subobjectIndex - currentIndex, topLevelArraySize);
58943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
58953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
58963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid UserDefinedIOCase::init (void)
58973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
58983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
58993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
59003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59018cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	const bool			isPerPatchIO				= m_ioType == IO_TYPE_PER_PATCH				||
59028cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry													  m_ioType == IO_TYPE_PER_PATCH_ARRAY		||
59038cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry													  m_ioType == IO_TYPE_PER_PATCH_BLOCK		||
59048cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry													  m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY;
59058cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
59063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			isExplicitVertexArraySize	= m_vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN ||
59073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  m_vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_QUERY;
59083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string		vertexAttrArrayInputSize	= m_vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_IMPLICIT					? ""
59103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													: m_vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN	? "gl_MaxPatchVertices"
59113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													: m_vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_QUERY			? de::toString(m_context.getContextInfo().getInt(GL_MAX_PATCH_VERTICES))
59123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													: DE_NULL;
59133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	maybePatch					= isPerPatchIO ? "patch " : "";
59153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string		outMaybePatch				= string() + maybePatch + "out ";
59163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string		inMaybePatch				= string() + maybePatch + "in ";
59178cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	const bool			useBlock					= m_ioType == IO_TYPE_PER_VERTEX_BLOCK		||
59188cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry													  m_ioType == IO_TYPE_PER_PATCH_BLOCK		||
59198cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry													  m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY;
59203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				tcsDeclarations;
59223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				tcsStatements;
59233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				tesDeclarations;
59253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				tesStatements;
59263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
59283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_structTypes.push_back(glu::StructType("S"));
59293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VarType	highpFloat		(glu::TYPE_FLOAT, glu::PRECISION_HIGHP);
59313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::StructType&	structType		= m_structTypes.back();
59323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VarType	structVarType	(&structType);
593302238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry		bool				usedStruct		= false;
59343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		structType.addMember("x", glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP));
59363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		structType.addMember("y", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
593702238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry
593802238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry		if (useBlock)
593902238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry		{
594002238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry			// It is illegal to have a structure containing an array as an output variable
594102238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry			structType.addMember("z", glu::VarType(highpFloat, 2));
594202238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry		}
59433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (useBlock)
59453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
59468cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const bool				useLightweightBlock = (m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY); // use leaner block to make sure it is not larger than allowed (per-patch storage is very limited)
59478cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			vector<IOBlock::Member>	blockMembers;
59488cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
59498cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			if (!useLightweightBlock)
59508cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				blockMembers.push_back(IOBlock::Member("blockS",	structVarType));
59518cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
59523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			blockMembers.push_back(IOBlock::Member("blockFa",	glu::VarType(highpFloat, 3)));
59533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			blockMembers.push_back(IOBlock::Member("blockSa",	glu::VarType(structVarType, 2)));
59543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			blockMembers.push_back(IOBlock::Member("blockF",	highpFloat));
59553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_tcsOutputs.push_back	(SharedPtr<TopLevelObject>(new IOBlock("TheBlock", "tcBlock", blockMembers)));
59573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_tesInputs.push_back	(SharedPtr<TopLevelObject>(new IOBlock("TheBlock", "teBlock", blockMembers)));
595802238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry
595902238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry			usedStruct = true;
59603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
59613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
59623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
59633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Variable var0("in_te_s", structVarType,	m_ioType != IO_TYPE_PER_PATCH);
59643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Variable var1("in_te_f", highpFloat,		m_ioType != IO_TYPE_PER_PATCH);
59653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
596602238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry			if (m_ioType != IO_TYPE_PER_PATCH_ARRAY)
596702238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry			{
596802238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry				// Arrays of structures are disallowed, add struct cases only if not arrayed variable
596902238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry				m_tcsOutputs.push_back	(SharedPtr<TopLevelObject>(new Variable(var0)));
597002238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry				m_tesInputs.push_back	(SharedPtr<TopLevelObject>(new Variable(var0)));
597102238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry
597202238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry				usedStruct = true;
597302238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry			}
597402238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry
59753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_tcsOutputs.push_back	(SharedPtr<TopLevelObject>(new Variable(var1)));
59763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_tesInputs.push_back	(SharedPtr<TopLevelObject>(new Variable(var1)));
59773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
59783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59798cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		tcsDeclarations += "in " + Variable("in_tc_attr", highpFloat, true).declareArray(vertexAttrArrayInputSize);
598002238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry
598102238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry		if (usedStruct)
598202238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry			tcsDeclarations += de::toString(glu::declare(structType)) + ";\n";
598302238eb8729ed058f65776b86a8b08fba11ab9cdJarkko Pöyry
59843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcsStatements += "\t{\n"
59853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						 "\t\thighp float v = 1.3;\n";
59863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
59873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int tcsOutputNdx = 0; tcsOutputNdx < (int)m_tcsOutputs.size(); tcsOutputNdx++)
59883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
59898cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const TopLevelObject&	output		= *m_tcsOutputs[tcsOutputNdx];
59908cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const int				numElements	= !isPerPatchIO								? -1	//!< \note -1 means indexing with gl_InstanceID
59918cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH				? 1
59928cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH_ARRAY		? NUM_PER_PATCH_ARRAY_ELEMS
59938cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH_BLOCK		? 1
59948cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? NUM_PER_PATCH_BLOCKS
59958cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: -2;
59968cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const bool				isArray		= (numElements != 1);
59978cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
59988cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			DE_ASSERT(numElements != -2);
59998cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
60008cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			if (isArray)
6001aabcb3260e4d63ae9fff43a9d693d9273fd5993bJarkko Pöyry			{
6002aabcb3260e4d63ae9fff43a9d693d9273fd5993bJarkko Pöyry				// \note: TCS output arrays are always implicitly-sized
6003eeec8accefdba51359d238575ade720d02a90276Pyry Haulos				tcsDeclarations += outMaybePatch + output.declareArray(m_ioType == IO_TYPE_PER_PATCH_ARRAY			? de::toString(int(NUM_PER_PATCH_ARRAY_ELEMS))
6004eeec8accefdba51359d238575ade720d02a90276Pyry Haulos																	   : m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? de::toString(int(NUM_PER_PATCH_BLOCKS))
60058cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry																	   : "");
6006aabcb3260e4d63ae9fff43a9d693d9273fd5993bJarkko Pöyry			}
60078cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			else
60088cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				tcsDeclarations += outMaybePatch + output.declare();
60093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
60103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!isPerPatchIO)
60113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcsStatements += "\t\tv += float(gl_InvocationID)*" + de::floatToString(0.4f*output.numBasicSubobjectsInElementType(), 1) + ";\n";
60123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
60138cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			tcsStatements += "\n\t\t// Assign values to output " + output.name() + "\n";
60148cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			if (isArray)
60158cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				tcsStatements += output.glslTraverseBasicTypeArray(numElements, 2, glslAssignBasicTypeObject);
60168cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			else
60178cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				tcsStatements += output.glslTraverseBasicType(2, glslAssignBasicTypeObject);
60183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
60193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!isPerPatchIO)
6020eeec8accefdba51359d238575ade720d02a90276Pyry Haulos				tcsStatements += "\t\tv += float(" + de::toString(int(NUM_OUTPUT_VERTICES)) + "-gl_InvocationID-1)*" + de::floatToString(0.4f*output.numBasicSubobjectsInElementType(), 1) + ";\n";
60213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
60223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcsStatements += "\t}\n";
60233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
60248cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		if (usedStruct)
60258cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			tesDeclarations += de::toString(glu::declare(structType)) + ";\n";
60268cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
60273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tesStatements += "\tbool allOk = true;\n"
6028ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry						 "\thighp uint firstFailedInputIndex = 0u;\n"
60293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						 "\t{\n"
60303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						 "\t\thighp float v = 1.3;\n";
60313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int tesInputNdx = 0; tesInputNdx < (int)m_tesInputs.size(); tesInputNdx++)
60323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
60338cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const TopLevelObject&	input		= *m_tesInputs[tesInputNdx];
60348cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const int				numElements	= !isPerPatchIO								? (int)NUM_OUTPUT_VERTICES
60358cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH				? 1
60368cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH_BLOCK		? 1
60378cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH_ARRAY		? NUM_PER_PATCH_ARRAY_ELEMS
60388cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? NUM_PER_PATCH_BLOCKS
60398cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry												: -2;
60408cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const bool				isArray		= (numElements != 1);
60418cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
60428cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			DE_ASSERT(numElements != -2);
60438cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
60448cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			if (isArray)
6045eeec8accefdba51359d238575ade720d02a90276Pyry Haulos				tesDeclarations += inMaybePatch + input.declareArray(m_ioType == IO_TYPE_PER_PATCH_ARRAY			? de::toString(int(NUM_PER_PATCH_ARRAY_ELEMS))
6046eeec8accefdba51359d238575ade720d02a90276Pyry Haulos																	 : m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? de::toString(int(NUM_PER_PATCH_BLOCKS))
60478cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry																	 : isExplicitVertexArraySize					? de::toString(vertexAttrArrayInputSize)
60488cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry																	 : "");
60498cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			else
60508cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				tesDeclarations += inMaybePatch + input.declare();
60518cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
60528cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			tesStatements += "\n\t\t// Check values in input " + input.name() + "\n";
60538cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			if (isArray)
60548cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				tesStatements += input.glslTraverseBasicTypeArray(numElements, 2, glslCheckBasicTypeObject);
60558cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			else
60568cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				tesStatements += input.glslTraverseBasicType(2, glslCheckBasicTypeObject);
60573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
60583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tesStatements += "\t}\n";
60593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
60603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
60613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
60623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::VertexSource					("#version 310 es\n"
60633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp float in_v_attr;\n"
60653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp float in_tc_attr;\n"
60663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
60683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
60693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_tc_attr = in_v_attr;\n"
60703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
60713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
60723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationControlSource		("#version 310 es\n"
60733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
60743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
6075eeec8accefdba51359d238575ade720d02a90276Pyry Haulos												 "layout (vertices = " + de::toString(int(NUM_OUTPUT_VERTICES)) + ") out;\n"
60763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + tcsDeclarations +
60783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch out highp vec2 in_te_positionScale;\n"
60803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch out highp vec2 in_te_positionOffset;\n"
60813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
60833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
60843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + tcsStatements +
60853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_te_positionScale  = vec2(in_tc_attr[6], in_tc_attr[7]);\n"
60873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_te_positionOffset = vec2(in_tc_attr[8], in_tc_attr[9]);\n"
60883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
60903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
60913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
60923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
60933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
60943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
60953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
60963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
60973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
60983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationEvaluationSource	("#version 310 es\n"
60993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
61003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + getTessellationEvaluationInLayoutString(m_primitiveType) +
61023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + tesDeclarations +
61043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch in highp vec2 in_te_positionScale;\n"
61063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "patch in highp vec2 in_te_positionOffset;\n"
61073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec4 in_f_color;\n"
61093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "// Will contain the index of the first incorrect input,\n"
61103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "// or the number of inputs if all are correct\n"
61113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "flat out highp uint out_te_firstFailedInputIndex;\n"
61123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "bool compare_int   (int   a, int   b) { return a == b; }\n"
61143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "bool compare_float (float a, float b) { return abs(a - b) < 0.01f; }\n"
61153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "bool compare_vec4  (vec4  a, vec4  b) { return all(lessThan(abs(a - b), vec4(0.01f))); }\n"
61163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
61183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
61193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + tesStatements +
61203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_Position = vec4(gl_TessCoord.xy*in_te_positionScale + in_te_positionOffset, 0.0, 1.0);\n"
61223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_f_color = allOk ? vec4(0.0, 1.0, 0.0, 1.0)\n"
61233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	                   : vec4(1.0, 0.0, 0.0, 1.0);\n"
61243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	out_te_firstFailedInputIndex = firstFailedInputIndex;\n"
61253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
61263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::FragmentSource					("#version 310 es\n"
61283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (location = 0) out mediump vec4 o_color;\n"
61303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp vec4 in_f_color;\n"
61323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
61333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
61343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
61353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	o_color = in_f_color;\n"
61363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
61373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackVarying		("out_te_firstFailedInputIndex")
61393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TransformFeedbackMode			(GL_INTERLEAVED_ATTRIBS)));
61403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
61423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
61433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
61443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
61453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid UserDefinedIOCase::deinit (void)
61473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
61483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
61493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
61503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61513c827367444ee418f129b2c238299f49d3264554Jarkko PoyryUserDefinedIOCase::IterateResult UserDefinedIOCase::iterate (void)
61523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
61533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TransformFeedbackHandler<deUint32> TFHandler;
61543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log						= m_testCtx.getLog();
61563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx				= m_context.getRenderContext();
61573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport	viewport				(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
61583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl						= renderCtx.getFunctions();
61593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float		attributes[6+2+2]		= { /* inner */ 3.0f, 4.0f, /* outer */ 5.0f, 6.0f, 7.0f, 8.0f, /* pos. scale */ 1.2f, 1.3f, /* pos. offset */ -0.3f, -0.4f };
61603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			programGL				= m_program->getProgram();
61613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numVertices				= referenceVertexCount(m_primitiveType, SPACINGMODE_EQUAL, false, &attributes[0], &attributes[2]);
61623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TFHandler			tfHandler				(renderCtx, numVertices);
61638cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	tcu::ResultCollector	result;
61643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
61663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
61673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, DE_LENGTH_OF_ARRAY(attributes));
61683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
61703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
61713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
61733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding	bindings[]	= { glu::va::Float("in_v_attr", 1, DE_LENGTH_OF_ARRAY(attributes), 0, &attributes[0]) };
61743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const TFHandler::Result			tfResult	= tfHandler.renderAndGetPrimitives(programGL, outputPrimitiveTypeGL(m_primitiveType, false),
61753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																					   DE_LENGTH_OF_ARRAY(bindings), &bindings[0], DE_LENGTH_OF_ARRAY(attributes));
61763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
61783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Surface			pixels		= getPixels(renderCtx, viewport);
61793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::TextureLevel		reference	= getPNG(m_testCtx.getArchive(), m_referenceImagePath.c_str());
61803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					success		= tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", reference.getAccess(), pixels.getAccess(), 0.02f, tcu::COMPARE_LOG_RESULT);
61813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!success)
61838cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry				result.fail("Image comparison failed");
61843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
61853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
61863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((int)tfResult.varying.size() != numVertices)
61873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
61883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Failure: transform feedback returned " << tfResult.varying.size() << " vertices; expected " << numVertices << TestLog::EndMessage;
61898cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			result.fail("Wrong number of vertices");
61903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
61918cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		else
61923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
61938cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const int topLevelArraySize		= (m_ioType == IO_TYPE_PER_PATCH				? 1
61948cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry											 : m_ioType == IO_TYPE_PER_PATCH_ARRAY			? NUM_PER_PATCH_ARRAY_ELEMS
61958cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry											 : m_ioType == IO_TYPE_PER_PATCH_BLOCK			? 1
61968cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry											 : m_ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? NUM_PER_PATCH_BLOCKS
61978cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry											 : (int)NUM_OUTPUT_VERTICES);
61983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numTEInputs			= numBasicSubobjectsInElementType(m_tesInputs) * topLevelArraySize;
61993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vertexNdx = 0; vertexNdx < (int)numVertices; vertexNdx++)
62013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
62023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (tfResult.varying[vertexNdx] > (deUint32)numTEInputs)
62033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
62043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: out_te_firstFailedInputIndex has value " << tfResult.varying[vertexNdx]
62053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< ", should be in range [0, " << numTEInputs << "]" << TestLog::EndMessage;
62068cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry					result.fail("Invalid transform feedback output");
62073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
62083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (tfResult.varying[vertexNdx] != (deUint32)numTEInputs)
62093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
62103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failure: in tessellation evaluation shader, check for input "
62113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< basicSubobjectAtIndex(tfResult.varying[vertexNdx], m_tesInputs, topLevelArraySize) << " failed" << TestLog::EndMessage;
62128cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry					result.fail("Invalid input value in tessellation evaluation shader");
62133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
62143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
62153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
62163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
62173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62188cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry	result.setTestContextResult(m_testCtx);
62193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
62203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
62213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
62233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Pass gl_Position between VS and TCS, or between TCS and TES.
62243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
62253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * In TCS gl_Position is in the gl_out[] block and in TES in the gl_in[]
62263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * block, and has no special semantics in those. Arbitrary vec4 data can
62273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * thus be passed there.
62283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
62293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GLPositionCase : public TestCase
62303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
62313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
62323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum CaseType
62333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
62343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_VS_TO_TCS = 0,
62353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_TCS_TO_TES,
62363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_VS_TO_TCS_TO_TES,
62373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASETYPE_LAST
62393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
62403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLPositionCase (Context& context, const char* name, const char* description, CaseType caseType, const char* referenceImagePath)
62423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: TestCase				(context, name, description)
62433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_caseType			(caseType)
62443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_referenceImagePath	(referenceImagePath)
62453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
62463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
62473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									init				(void);
62493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void									deinit				(void);
62503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult							iterate				(void);
62513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*						getCaseTypeName		(CaseType type);
62533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
62553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int						RENDER_SIZE = 256;
62563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseType							m_caseType;
62583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string							m_referenceImagePath;
62593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SharedPtr<const glu::ShaderProgram>		m_program;
62613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
62623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* GLPositionCase::getCaseTypeName (CaseType type)
62643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
62653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
62663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
62673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_VS_TO_TCS:			return "gl_position_vs_to_tcs";
62683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_TCS_TO_TES:			return "gl_position_tcs_to_tes";
62693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CASETYPE_VS_TO_TCS_TO_TES:		return "gl_position_vs_to_tcs_to_tes";
62703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
62713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false); return DE_NULL;
62723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
62733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
62743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid GLPositionCase::init (void)
62763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
62773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkTessellationSupport(m_context);
62783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkRenderTargetSize(m_context.getRenderTarget(), RENDER_SIZE);
62793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		vsToTCS		= m_caseType == CASETYPE_VS_TO_TCS		|| m_caseType == CASETYPE_VS_TO_TCS_TO_TES;
62813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		tcsToTES	= m_caseType == CASETYPE_TCS_TO_TES		|| m_caseType == CASETYPE_VS_TO_TCS_TO_TES;
62823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	tesIn0		= tcsToTES ? "gl_in[0].gl_Position" : "in_te_attr[0]";
62843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	tesIn1		= tcsToTES ? "gl_in[1].gl_Position" : "in_te_attr[1]";
62853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	tesIn2		= tcsToTES ? "gl_in[2].gl_Position" : "in_te_attr[2]";
62863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = SharedPtr<const ShaderProgram>(new ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
62883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::VertexSource					("#version 310 es\n"
62893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
62903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp vec4 in_v_attr;\n"
62913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + string(!vsToTCS ? "out highp vec4 in_tc_attr;\n" : "") +
62923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
62933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
62943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
62953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	" + (vsToTCS ? "gl_Position" : "in_tc_attr") + " = in_v_attr;\n"
62963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
62973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationControlSource		("#version 310 es\n"
62993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
63003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (vertices = 3) out;\n"
63023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + string(!vsToTCS ? "in highp vec4 in_tc_attr[];\n" : "") +
63043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + (!tcsToTES ? "out highp vec4 in_te_attr[];\n" : "") +
63063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
63083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
63093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	" + (tcsToTES ? "gl_out[gl_InvocationID].gl_Position" : "in_te_attr[gl_InvocationID]") + " = "
63103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  + (vsToTCS ? "gl_in[gl_InvocationID].gl_Position" : "in_tc_attr[gl_InvocationID]") + ";\n"
63113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[0] = 2.0;\n"
63133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelInner[1] = 3.0;\n"
63143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[0] = 4.0;\n"
63163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[1] = 5.0;\n"
63173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[2] = 6.0;\n"
63183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_TessLevelOuter[3] = 7.0;\n"
63193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
63203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::TessellationEvaluationSource	("#version 310 es\n"
63223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "#extension GL_EXT_tessellation_shader : require\n"
63233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + getTessellationEvaluationInLayoutString(TESSPRIMITIVETYPE_TRIANGLES) +
63253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 + (!tcsToTES ? "in highp vec4 in_te_attr[];\n" : "") +
63273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "out highp vec4 in_f_color;\n"
63293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
63313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
63323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	highp vec2 xy = gl_TessCoord.x * " + tesIn0 + ".xy\n"
63333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	              + gl_TessCoord.y * " + tesIn1 + ".xy\n"
63343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	              + gl_TessCoord.z * " + tesIn2 + ".xy;\n"
63353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	gl_Position = vec4(xy, 0.0, 1.0);\n"
63363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	in_f_color = vec4(" + tesIn0 + ".z + " + tesIn1 + ".w,\n"
63373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	                  " + tesIn2 + ".z + " + tesIn0 + ".w,\n"
63383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	                  " + tesIn1 + ".z + " + tesIn2 + ".w,\n"
63393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	                  1.0);\n"
63403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")
63413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< glu::FragmentSource					("#version 310 es\n"
63433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "layout (location = 0) out mediump vec4 o_color;\n"
63453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "in highp vec4 in_f_color;\n"
63473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "\n"
63483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "void main (void)\n"
63493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "{\n"
63503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "	o_color = in_f_color;\n"
63513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 "}\n")));
63523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
63543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
63553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Program compilation failed");
63563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
63573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid GLPositionCase::deinit (void)
63593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
63603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
63613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
63623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryGLPositionCase::IterateResult GLPositionCase::iterate (void)
63643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
63653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log						= m_testCtx.getLog();
63663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx				= m_context.getRenderContext();
63673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RandomViewport	viewport				(renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()));
63683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl						= renderCtx.getFunctions();
63693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			programGL				= m_program->getProgram();
63703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float attributes[3*4] =
63723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
63733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-0.8f, -0.7f, 0.1f, 0.7f,
63743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-0.5f,  0.4f, 0.2f, 0.5f,
63753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 0.3f,  0.2f, 0.3f, 0.45f
63763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
63773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(programGL);
63793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setViewport(gl, viewport);
63803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 3);
63813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
63833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
63843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Message << "Note: input data for in_v_attr:\n" << arrayStr(attributes, 4) << TestLog::EndMessage;
63863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
63883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding bindings[] = { glu::va::Float("in_v_attr", 4, 3, 0, &attributes[0]) };
63893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(renderCtx, programGL, DE_LENGTH_OF_ARRAY(bindings), &bindings[0], glu::pr::Patches(3));
63903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
63923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Surface			pixels		= getPixels(renderCtx, viewport);
63933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::TextureLevel		reference	= getPNG(m_testCtx.getArchive(), m_referenceImagePath.c_str());
63943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					success		= tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", reference.getAccess(), pixels.getAccess(), 0.02f, tcu::COMPARE_LOG_RESULT);
63953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
63963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!success)
63973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
63983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
63993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
64003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
64013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
64023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
64033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
64043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
64053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
64063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
64073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6408c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass LimitQueryCase : public TestCase
6409c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6410c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6411c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						LimitQueryCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue);
6412c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6413c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate			(void);
6414c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6415c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	const glw::GLenum	m_target;
6416c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	const int			m_minValue;
6417c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6418c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6419c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryLimitQueryCase::LimitQueryCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue)
6420c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TestCase			(context, name, desc)
6421c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	, m_target			(target)
6422c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	, m_minValue		(minValue)
6423c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6424c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6425c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6426c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryLimitQueryCase::IterateResult LimitQueryCase::iterate (void)
6427c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6428c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6429c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6430c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6431c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6432c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6433c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6434c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_INTEGER);
6435c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6436c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6437c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Types", "Alternative queries");
6438c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_BOOLEAN);
6439c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_INTEGER64);
6440c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_FLOAT);
6441c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6442c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6443c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6444c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6445c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6446c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6447c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass CombinedUniformLimitCase : public TestCase
6448c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6449c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6450c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						CombinedUniformLimitCase	(Context& context, const char* name, const char* desc, glw::GLenum combined, glw::GLenum numBlocks, glw::GLenum defaultComponents);
6451c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6452c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate						(void);
6453c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6454c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	const glw::GLenum	m_combined;
6455c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	const glw::GLenum	m_numBlocks;
6456c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	const glw::GLenum	m_defaultComponents;
6457c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6458c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6459c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryCombinedUniformLimitCase::CombinedUniformLimitCase (Context& context, const char* name, const char* desc, glw::GLenum combined, glw::GLenum numBlocks, glw::GLenum defaultComponents)
6460c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TestCase				(context, name, desc)
6461c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	, m_combined			(combined)
6462c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	, m_numBlocks			(numBlocks)
6463c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	, m_defaultComponents	(defaultComponents)
6464c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6465c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6466c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6467c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryCombinedUniformLimitCase::IterateResult CombinedUniformLimitCase::iterate (void)
6468c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6469c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6470c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6471c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6472c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6473c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6474c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6475c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6476c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	m_testCtx.getLog()	<< tcu::TestLog::Message
6477c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						<< "The minimum value of " << glu::getGettableStateStr(m_combined)
6478c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						<< " is " << glu::getGettableStateStr(m_numBlocks)
6479c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						<< " x MAX_UNIFORM_BLOCK_SIZE / 4 + "
6480c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						<< glu::getGettableStateStr(m_defaultComponents)
6481c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						<< tcu::TestLog::EndMessage;
6482c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6483c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	StateQueryMemoryWriteGuard<glw::GLint> maxUniformBlocks;
6484c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.glGetIntegerv(m_numBlocks, &maxUniformBlocks);
6485c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGetIntegerv");
6486c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6487c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	StateQueryMemoryWriteGuard<glw::GLint> maxUniformBlockSize;
6488c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
6489c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGetIntegerv");
6490c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6491c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	StateQueryMemoryWriteGuard<glw::GLint> maxUniformComponents;
6492c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.glGetIntegerv(m_defaultComponents, &maxUniformComponents);
6493c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGetIntegerv");
6494c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6495c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	if (maxUniformBlocks.verifyValidity(result) && maxUniformBlockSize.verifyValidity(result) && maxUniformComponents.verifyValidity(result))
6496c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6497c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const int limit = ((int)maxUniformBlocks) * ((int)maxUniformBlockSize) / 4 + (int)maxUniformComponents;
6498c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateIntegerMin(result, gl, m_combined, limit, QUERY_INTEGER);
6499c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6500c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{
6501c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Types", "Alternative queries");
6502c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateIntegerMin(result, gl, m_combined, limit, QUERY_BOOLEAN);
6503c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateIntegerMin(result, gl, m_combined, limit, QUERY_INTEGER64);
6504c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateIntegerMin(result, gl, m_combined, limit, QUERY_FLOAT);
6505c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		}
6506c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6507c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6508c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6509c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6510c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6511c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6512c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass PatchVerticesStateCase : public TestCase
6513c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6514c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6515c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						PatchVerticesStateCase	(Context& context, const char* name, const char* desc);
6516c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6517c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate					(void);
6518c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6519c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6520c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryPatchVerticesStateCase::PatchVerticesStateCase (Context& context, const char* name, const char* desc)
6521c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TestCase(context, name, desc)
6522c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6523c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6524c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6525c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryPatchVerticesStateCase::IterateResult PatchVerticesStateCase::iterate (void)
6526c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6527c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6528c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6529c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6530c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6531c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6532c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6533c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6534c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	// initial
6535c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6536c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial value");
6537c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6538c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateInteger(result, gl, GL_PATCH_VERTICES, 3, QUERY_INTEGER);
6539c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6540c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6541c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	// bind
6542c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6543c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "set", "After set");
6544c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6545c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		gl.glPatchParameteri(GL_PATCH_VERTICES, 22);
6546c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glPatchParameteri");
6547c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6548c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateInteger(result, gl, GL_PATCH_VERTICES, 22, QUERY_INTEGER);
6549c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{
6550c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			const tcu::ScopedLogSection	subsection(m_testCtx.getLog(), "Types", "Alternative queries");
6551c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateIntegerMin(result, gl, GL_PATCH_VERTICES, 22, QUERY_BOOLEAN);
6552c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateIntegerMin(result, gl, GL_PATCH_VERTICES, 22, QUERY_INTEGER64);
6553c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateIntegerMin(result, gl, GL_PATCH_VERTICES, 22, QUERY_FLOAT);
6554c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		}
6555c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6556c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6557c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6558c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6559c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6560c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6561c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass PrimitiveRestartForPatchesSupportedCase : public TestCase
6562c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6563c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6564c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						PrimitiveRestartForPatchesSupportedCase	(Context& context, const char* name, const char* desc);
6565c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6566c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate									(void);
6567c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6568c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6569c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryPrimitiveRestartForPatchesSupportedCase::PrimitiveRestartForPatchesSupportedCase (Context& context, const char* name, const char* desc)
6570c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TestCase(context, name, desc)
6571c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6572c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6573c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6574c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryPrimitiveRestartForPatchesSupportedCase::IterateResult PrimitiveRestartForPatchesSupportedCase::iterate (void)
6575c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6576c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6577c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6578c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6579c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6580c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	QueriedState			state;
6581c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6582c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6583c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6584c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	queryState(result, gl, QUERY_BOOLEAN, GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED, state);
6585c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6586c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	if (!state.isUndefined())
6587c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6588c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection	subsection(m_testCtx.getLog(), "Types", "Alternative types");
6589c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateBoolean(result, gl, GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED, state.getBoolAccess(), QUERY_INTEGER);
6590c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateBoolean(result, gl, GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED, state.getBoolAccess(), QUERY_INTEGER64);
6591c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateBoolean(result, gl, GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED, state.getBoolAccess(), QUERY_FLOAT);
6592c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6593c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6594c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6595c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6596c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6597c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6598c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass TessProgramQueryCase : public TestCase
6599c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6600c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6601c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						TessProgramQueryCase	(Context& context, const char* name, const char* desc);
6602c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6603c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string			getVertexSource			(void) const;
6604c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string			getFragmentSource		(void) const;
6605c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string			getTessCtrlSource		(const char* globalLayouts) const;
6606c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string			getTessEvalSource		(const char* globalLayouts) const;
6607c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6608c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6609c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessProgramQueryCase::TessProgramQueryCase (Context& context, const char* name, const char* desc)
6610c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TestCase(context, name, desc)
6611c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6612c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6613c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6614c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string TessProgramQueryCase::getVertexSource (void) const
6615c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6616c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return	"#version 310 es\n"
6617c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
6618c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
6619c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_Position = vec4(float(gl_VertexID), float(gl_VertexID / 2), 0.0, 1.0);\n"
6620c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
6621c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6622c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6623c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string TessProgramQueryCase::getFragmentSource (void) const
6624c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6625c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return	"#version 310 es\n"
6626c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"layout (location = 0) out mediump vec4 o_color;\n"
6627c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
6628c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
6629c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
6630c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
6631c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6632c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6633c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string TessProgramQueryCase::getTessCtrlSource (const char* globalLayouts) const
6634c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6635c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return	"#version 310 es\n"
6636c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
6637c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			+ std::string(globalLayouts) + ";\n"
6638c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
6639c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
6640c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
6641c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n"
6642c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelInner[1] = 2.8;\n"
6643c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
6644c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
6645c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
6646c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[3] = 2.8;\n"
6647c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
6648c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6649c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6650c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string TessProgramQueryCase::getTessEvalSource (const char* globalLayouts) const
6651c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6652c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return	"#version 310 es\n"
6653c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
6654c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			+ std::string(globalLayouts) + ";\n"
6655c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
6656c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
6657c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_Position = gl_TessCoord.x * gl_in[0].gl_Position\n"
6658c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	            + gl_TessCoord.y * gl_in[1].gl_Position\n"
6659c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	            + gl_TessCoord.y * gl_in[2].gl_Position\n"
6660c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	            + gl_TessCoord.z * gl_in[3].gl_Position;\n"
6661c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
6662c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6663c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6664c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass TessControlOutputVerticesCase : public TessProgramQueryCase
6665c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6666c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6667c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						TessControlOutputVerticesCase	(Context& context, const char* name, const char* desc);
6668c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6669c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate							(void);
6670c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6671c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6672c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessControlOutputVerticesCase::TessControlOutputVerticesCase (Context& context, const char* name, const char* desc)
6673c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TessProgramQueryCase(context, name, desc)
6674c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6675c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6676c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6677c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessControlOutputVerticesCase::IterateResult TessControlOutputVerticesCase::iterate (void)
6678c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6679c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6680c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6681c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
6682c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																<< glu::VertexSource(getVertexSource())
6683c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																<< glu::FragmentSource(getFragmentSource())
6684c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																<< glu::TessellationControlSource(getTessCtrlSource("layout(vertices=4) out"))
6685c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																<< glu::TessellationEvaluationSource(getTessEvalSource("layout(triangles) in")));
6686c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6687c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	m_testCtx.getLog() << program;
6688c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	if (!program.isOk())
6689c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		throw tcu::TestError("failed to build program");
6690c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6691c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6692c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6693c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6694c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6695c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		gl.enableLogging(true);
6696c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 4, QUERY_PROGRAM_INTEGER);
6697c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6698c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		result.setTestContextResult(m_testCtx);
6699c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6700c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6701c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6702c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6703c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass TessGenModeQueryCase : public TessProgramQueryCase
6704c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6705c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6706c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						TessGenModeQueryCase	(Context& context, const char* name, const char* desc);
6707c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6708c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate					(void);
6709c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6710c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6711c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenModeQueryCase::TessGenModeQueryCase (Context& context, const char* name, const char* desc)
6712c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TessProgramQueryCase(context, name, desc)
6713c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6714c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6715c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6716c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenModeQueryCase::IterateResult TessGenModeQueryCase::iterate (void)
6717c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6718c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6719c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6720c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6721c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	static const struct
6722c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6723c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* description;
6724c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* layout;
6725c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glw::GLenum mode;
6726c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	} s_modes[] =
6727c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6728c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Triangles",	"layout(triangles) in",	GL_TRIANGLES	},
6729c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Isolines",	"layout(isolines) in",	GL_ISOLINES		},
6730c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Quads",		"layout(quads) in",		GL_QUADS		},
6731c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	};
6732c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6733c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6734c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6735c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6736c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_modes); ++ndx)
6737c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6738c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Type", s_modes[ndx].description);
6739c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6740c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
6741c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::VertexSource(getVertexSource())
6742c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::FragmentSource(getFragmentSource())
6743c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationControlSource(getTessCtrlSource("layout(vertices=6) out"))
6744c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationEvaluationSource(getTessEvalSource(s_modes[ndx].layout)));
6745c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6746c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		m_testCtx.getLog() << program;
6747c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		if (!program.isOk())
6748c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			result.fail("failed to build program");
6749c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		else
6750c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, s_modes[ndx].mode, QUERY_PROGRAM_INTEGER);
6751c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6752c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6753c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6754c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6755c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6756c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6757c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass TessGenSpacingQueryCase : public TessProgramQueryCase
6758c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6759c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6760c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						TessGenSpacingQueryCase	(Context& context, const char* name, const char* desc);
6761c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6762c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate					(void);
6763c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6764c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6765c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenSpacingQueryCase::TessGenSpacingQueryCase (Context& context, const char* name, const char* desc)
6766c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TessProgramQueryCase(context, name, desc)
6767c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6768c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6769c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6770c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenSpacingQueryCase::IterateResult TessGenSpacingQueryCase::iterate (void)
6771c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6772c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6773c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6774c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6775c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	static const struct
6776c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6777c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* description;
6778c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* layout;
6779c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glw::GLenum spacing;
6780c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	} s_modes[] =
6781c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6782c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Default spacing",			"layout(triangles) in",								GL_EQUAL			},
6783c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Equal spacing",				"layout(triangles, equal_spacing) in",				GL_EQUAL			},
6784c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Fractional even spacing",	"layout(triangles, fractional_even_spacing) in",	GL_FRACTIONAL_EVEN	},
6785c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Fractional odd spacing",		"layout(triangles, fractional_odd_spacing) in",		GL_FRACTIONAL_ODD	},
6786c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	};
6787c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6788c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6789c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6790c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6791c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_modes); ++ndx)
6792c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6793c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Type", s_modes[ndx].description);
6794c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6795c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
6796c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::VertexSource(getVertexSource())
6797c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::FragmentSource(getFragmentSource())
6798c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationControlSource(getTessCtrlSource("layout(vertices=6) out"))
6799c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationEvaluationSource(getTessEvalSource(s_modes[ndx].layout)));
6800c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6801c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		m_testCtx.getLog() << program;
6802c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		if (!program.isOk())
6803c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			result.fail("failed to build program");
6804c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		else
6805c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, s_modes[ndx].spacing, QUERY_PROGRAM_INTEGER);
6806c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6807c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6808c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6809c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6810c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6811c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6812c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass TessGenVertexOrderQueryCase : public TessProgramQueryCase
6813c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6814c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6815c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						TessGenVertexOrderQueryCase	(Context& context, const char* name, const char* desc);
6816c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6817c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate						(void);
6818c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6819c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6820c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenVertexOrderQueryCase::TessGenVertexOrderQueryCase (Context& context, const char* name, const char* desc)
6821c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TessProgramQueryCase(context, name, desc)
6822c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6823c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6824c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6825c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenVertexOrderQueryCase::IterateResult TessGenVertexOrderQueryCase::iterate (void)
6826c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6827c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6828c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6829c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6830c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	static const struct
6831c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6832c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* description;
6833c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* layout;
6834c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glw::GLenum order;
6835c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	} s_modes[] =
6836c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6837c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Default order",	"layout(triangles) in",			GL_CCW	},
6838c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "CW order",		"layout(triangles, cw) in",		GL_CW	},
6839c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "CCW order",		"layout(triangles, ccw) in",	GL_CCW	},
6840c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	};
6841c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6842c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6843c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6844c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6845c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_modes); ++ndx)
6846c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6847c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Type", s_modes[ndx].description);
6848c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6849c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
6850c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::VertexSource(getVertexSource())
6851c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::FragmentSource(getFragmentSource())
6852c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationControlSource(getTessCtrlSource("layout(vertices=6) out"))
6853c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationEvaluationSource(getTessEvalSource(s_modes[ndx].layout)));
6854c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6855c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		m_testCtx.getLog() << program;
6856c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		if (!program.isOk())
6857c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			result.fail("failed to build program");
6858c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		else
6859c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, s_modes[ndx].order, QUERY_PROGRAM_INTEGER);
6860c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6861c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6862c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6863c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6864c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6865c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6866c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass TessGenPointModeQueryCase : public TessProgramQueryCase
6867c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6868c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6869c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry						TessGenPointModeQueryCase	(Context& context, const char* name, const char* desc);
6870c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6871c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult		iterate						(void);
6872c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6873c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6874c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenPointModeQueryCase::TessGenPointModeQueryCase (Context& context, const char* name, const char* desc)
6875c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TessProgramQueryCase(context, name, desc)
6876c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6877c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6878c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6879c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryTessGenPointModeQueryCase::IterateResult TessGenPointModeQueryCase::iterate (void)
6880c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6881c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6882c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6883c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6884c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	static const struct
6885c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6886c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* description;
6887c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const char* layout;
6888c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glw::GLenum mode;
6889c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	} s_modes[] =
6890c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6891c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Default mode",	"layout(triangles) in",			GL_FALSE	},
6892c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{ "Point mode",		"layout(triangles, point_mode) in",		GL_TRUE		},
6893c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	};
6894c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6895c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6896c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6897c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6898c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_modes); ++ndx)
6899c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6900c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Type", s_modes[ndx].description);
6901c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6902c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
6903c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::VertexSource(getVertexSource())
6904c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::FragmentSource(getFragmentSource())
6905c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationControlSource(getTessCtrlSource("layout(vertices=6) out"))
6906c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationEvaluationSource(getTessEvalSource(s_modes[ndx].layout)));
6907c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6908c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		m_testCtx.getLog() << program;
6909c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		if (!program.isOk())
6910c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			result.fail("failed to build program");
6911c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		else
6912c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, s_modes[ndx].mode, QUERY_PROGRAM_INTEGER);
6913c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
6914c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6915c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
6916c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
6917c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6918c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6919c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass ReferencedByTessellationQueryCase : public TestCase
6920c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6921c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
6922c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					ReferencedByTessellationQueryCase	(Context& context, const char* name, const char* desc, bool isCtrlCase);
6923c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
6924c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	void			init								(void);
6925c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult	iterate								(void);
6926c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6927c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string		getVertexSource						(void) const;
6928c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string		getFragmentSource					(void) const;
6929c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string		getTessCtrlSource					(void) const;
6930c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::string		getTessEvalSource					(void) const;
6931c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6932c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	const bool		m_isCtrlCase;
6933c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
6934c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6935c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryReferencedByTessellationQueryCase::ReferencedByTessellationQueryCase (Context& context, const char* name, const char* desc, bool isCtrlCase)
6936c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TestCase		(context, name, desc)
6937c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	, m_isCtrlCase	(isCtrlCase)
6938c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6939c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6940c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6941c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryvoid ReferencedByTessellationQueryCase::init (void)
6942c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6943c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
6944c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
6945c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6946c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryReferencedByTessellationQueryCase::IterateResult ReferencedByTessellationQueryCase::iterate (void)
6947c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
6948c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
6949c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
6950c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::ShaderProgram		program	(m_context.getRenderContext(), glu::ProgramSources()
6951c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::VertexSource(getVertexSource())
6952c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::FragmentSource(getFragmentSource())
6953c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationControlSource(getTessCtrlSource())
6954c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationEvaluationSource(getTessEvalSource()));
6955c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6956c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
6957c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6958c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	m_testCtx.getLog() << program;
6959c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	if (!program.isOk())
6960c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		result.fail("failed to build program");
6961c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	else
6962c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
6963c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const deUint32 props[1] = { (deUint32)((m_isCtrlCase) ? (GL_REFERENCED_BY_TESS_CONTROL_SHADER) : (GL_REFERENCED_BY_TESS_EVALUATION_SHADER)) };
6964c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6965c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{
6966c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			const tcu::ScopedLogSection section		(m_testCtx.getLog(), "UnreferencedUniform", "Unreferenced uniform u_unreferenced");
6967c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			deUint32					resourcePos;
6968c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLsizei				length		= 0;
6969c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLint					referenced	= 0;
6970c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6971c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_unreferenced");
6972c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "u_unreferenced resource index: " << resourcePos << tcu::TestLog::EndMessage;
6973c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6974c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			if (resourcePos == GL_INVALID_INDEX)
6975c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				result.fail("resourcePos was GL_INVALID_INDEX");
6976c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			else
6977c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			{
6978c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced);
6979c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				m_testCtx.getLog()
6980c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::Message
6981c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< "Query " << glu::getProgramResourcePropertyStr(props[0])
6982c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< ", got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced)
6983c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::EndMessage;
6984c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6985c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "query resource");
6986c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6987c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				if (length == 0 || referenced != GL_FALSE)
6988c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					result.fail("expected GL_FALSE");
6989c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			}
6990c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		}
6991c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6992c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{
6993c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			const tcu::ScopedLogSection section		(m_testCtx.getLog(), "ReferencedUniform", "Referenced uniform u_referenced");
6994c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			deUint32					resourcePos;
6995c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLsizei				length		= 0;
6996c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLint					referenced	= 0;
6997c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
6998c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_referenced");
6999c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "u_referenced resource index: " << resourcePos << tcu::TestLog::EndMessage;
7000c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7001c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			if (resourcePos == GL_INVALID_INDEX)
7002c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				result.fail("resourcePos was GL_INVALID_INDEX");
7003c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			else
7004c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			{
7005c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced);
7006c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				m_testCtx.getLog()
7007c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::Message
7008c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< "Query " << glu::getProgramResourcePropertyStr(props[0])
7009c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< ", got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced)
7010c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::EndMessage;
7011c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7012c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource");
7013c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7014c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				if (length == 0 || referenced != GL_TRUE)
7015c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					result.fail("expected GL_TRUE");
7016c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			}
7017c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		}
7018c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
7019c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7020c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
7021c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
7022c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7023c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7024c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string ReferencedByTessellationQueryCase::getVertexSource (void) const
7025c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7026c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return	"#version 310 es\n"
7027c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
7028c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
7029c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_Position = vec4(float(gl_VertexID), float(gl_VertexID / 2), 0.0, 1.0);\n"
7030c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
7031c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7032c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7033c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string ReferencedByTessellationQueryCase::getFragmentSource (void) const
7034c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7035c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return	"#version 310 es\n"
7036c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"layout (location = 0) out mediump vec4 o_color;\n"
7037c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
7038c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
7039c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
7040c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
7041c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7042c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7043c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string ReferencedByTessellationQueryCase::getTessCtrlSource (void) const
7044c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7045c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::ostringstream buf;
7046c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	buf <<	"#version 310 es\n"
7047c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
7048c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"layout(vertices = 3) out;\n"
7049c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"uniform highp vec4 " << ((m_isCtrlCase) ? ("u_referenced") : ("u_unreferenced")) << ";\n"
7050c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
7051c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
7052c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	vec4 offset = " << ((m_isCtrlCase) ? ("u_referenced") : ("u_unreferenced")) << ";\n"
7053c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position + offset;\n"
7054c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n"
7055c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelInner[1] = 2.8;\n"
7056c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
7057c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
7058c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
7059c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_TessLevelOuter[3] = 2.8;\n"
7060c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
7061c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return buf.str();
7062c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7063c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7064c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrystd::string ReferencedByTessellationQueryCase::getTessEvalSource (void) const
7065c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7066c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	std::ostringstream buf;
7067c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	buf <<	"#version 310 es\n"
7068c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
7069c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"layout(triangles) in;\n"
7070c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"uniform highp vec4 " << ((m_isCtrlCase) ? ("u_unreferenced") : ("u_referenced")) << ";\n"
7071c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"void main (void)\n"
7072c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"{\n"
7073c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	vec4 offset = " << ((m_isCtrlCase) ? ("u_unreferenced") : ("u_referenced")) << ";\n"
7074c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	gl_Position = gl_TessCoord.x * gl_in[0].gl_Position\n"
7075c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	            + gl_TessCoord.y * gl_in[1].gl_Position\n"
7076c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	            + gl_TessCoord.z * gl_in[2].gl_Position\n"
7077c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"	            + offset;\n"
7078c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			"}\n";
7079c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7080c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return buf.str();
7081c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7082c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7083c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryclass IsPerPatchQueryCase : public TestCase
7084c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7085c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyrypublic:
7086c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					IsPerPatchQueryCase		(Context& context, const char* name, const char* desc);
7087c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryprivate:
7088c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	void			init					(void);
7089c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	IterateResult	iterate					(void);
7090c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry};
7091c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7092c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryIsPerPatchQueryCase::IsPerPatchQueryCase (Context& context, const char* name, const char* desc)
7093c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	: TestCase(context, name, desc)
7094c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7095c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7096c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7097c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyryvoid IsPerPatchQueryCase::init (void)
7098c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7099c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	checkTessellationSupport(m_context);
7100c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7101c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7102c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko PöyryIsPerPatchQueryCase::IterateResult IsPerPatchQueryCase::iterate (void)
7103c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry{
7104c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	static const char* const s_controlSource =	"#version 310 es\n"
7105c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"#extension GL_EXT_tessellation_shader : require\n"
7106c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"layout(vertices = 3) out;\n"
7107c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"patch out highp vec4 v_perPatch;\n"
7108c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"out highp vec4 v_perVertex[];\n"
7109c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"void main (void)\n"
7110c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"{\n"
7111c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
7112c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	v_perPatch = gl_in[0].gl_Position;\n"
7113c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	v_perVertex[gl_InvocationID] = -gl_in[gl_InvocationID].gl_Position;\n"
7114c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	gl_TessLevelInner[0] = 2.8;\n"
7115c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	gl_TessLevelInner[1] = 2.8;\n"
7116c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	gl_TessLevelOuter[0] = 2.8;\n"
7117c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	gl_TessLevelOuter[1] = 2.8;\n"
7118c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	gl_TessLevelOuter[2] = 2.8;\n"
7119c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"	gl_TessLevelOuter[3] = 2.8;\n"
7120c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry												"}\n";
7121c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
7122c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
7123c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	glu::ShaderProgram		program	(m_context.getRenderContext(), glu::ProgramSources()
7124c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::TessellationControlSource(s_controlSource)
7125c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry																	<< glu::ProgramSeparable(true));
7126c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7127c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	gl.enableLogging(true);
7128c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7129c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	m_testCtx.getLog() << program;
7130c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	if (!program.isOk())
7131c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		result.fail("failed to build program");
7132c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	else
7133c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
7134c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		const deUint32 props[1] = { GL_IS_PER_PATCH };
7135c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7136c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{
7137c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			const tcu::ScopedLogSection section		(m_testCtx.getLog(), "PerPatchOutput", "Per patch v_perPatch");
7138c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			deUint32					resourcePos;
7139c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLsizei				length		= 0;
7140c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLint					referenced	= 0;
7141c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7142c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_PROGRAM_OUTPUT, "v_perPatch");
7143c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "v_perPatch resource index: " << resourcePos << tcu::TestLog::EndMessage;
7144c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7145c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			if (resourcePos == GL_INVALID_INDEX)
7146c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				result.fail("resourcePos was GL_INVALID_INDEX");
7147c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			else
7148c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			{
7149c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				gl.glGetProgramResourceiv(program.getProgram(), GL_PROGRAM_OUTPUT, resourcePos, 1, props, 1, &length, &referenced);
7150c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				m_testCtx.getLog()
7151c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::Message
7152c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< "Query " << glu::getProgramResourcePropertyStr(props[0])
7153c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< ", got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced)
7154c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::EndMessage;
7155c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7156c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "query resource");
7157c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7158c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				if (length == 0 || referenced != GL_TRUE)
7159c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					result.fail("expected GL_TRUE");
7160c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			}
7161c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		}
7162c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7163c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		{
7164c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			const tcu::ScopedLogSection section		(m_testCtx.getLog(), "PerVertexhOutput", "Per vertex v_perVertex");
7165c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			deUint32					resourcePos;
7166c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLsizei				length		= 0;
7167c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			glw::GLint					referenced	= 0;
7168c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7169c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_PROGRAM_OUTPUT, "v_perVertex");
7170c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "v_perVertex resource index: " << resourcePos << tcu::TestLog::EndMessage;
7171c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7172c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			if (resourcePos == GL_INVALID_INDEX)
7173c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				result.fail("resourcePos was GL_INVALID_INDEX");
7174c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			else
7175c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			{
7176c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				gl.glGetProgramResourceiv(program.getProgram(), GL_PROGRAM_OUTPUT, resourcePos, 1, props, 1, &length, &referenced);
7177c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				m_testCtx.getLog()
7178c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::Message
7179c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< "Query " << glu::getProgramResourcePropertyStr(props[0])
7180c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< ", got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced)
7181c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					<< tcu::TestLog::EndMessage;
7182c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7183c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource");
7184c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7185c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry				if (length == 0 || referenced != GL_FALSE)
7186c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry					result.fail("expected GL_FALSE");
7187c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry			}
7188c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		}
7189c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
7190c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7191c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	result.setTestContextResult(m_testCtx);
7192c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	return STOP;
7193c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
7194c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
71953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
71963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
71973c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessellationTests::TessellationTests (Context& context)
71983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "tessellation", "Tessellation Tests")
71993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
72003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
72013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessellationTests::~TessellationTests (void)
72033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
72043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
72053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessellationTests::init (void)
72073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
72083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7209c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		tcu::TestCaseGroup* const queryGroup = new tcu::TestCaseGroup(m_testCtx, "state_query", "Query tests");
7210c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		addChild(queryGroup);
7211c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7212c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		// new limits
7213c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_patch_vertices",								"Test MAX_PATCH_VERTICES",								GL_MAX_PATCH_VERTICES,							32));
7214c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_gen_level",								"Test MAX_TESS_GEN_LEVEL",								GL_MAX_TESS_GEN_LEVEL,							64));
7215c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_uniform_components",				"Test MAX_TESS_CONTROL_UNIFORM_COMPONENTS",				GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS,			1024));
7216c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_uniform_components",			"Test MAX_TESS_EVALUATION_UNIFORM_COMPONENTS",			GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS,		1024));
7217c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_texture_image_units",				"Test MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS",			GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,		16));
7218c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_texture_image_units",			"Test MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS",			GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,		16));
7219c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_output_components",				"Test MAX_TESS_CONTROL_OUTPUT_COMPONENTS",				GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS,			128));
7220c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_patch_components",							"Test MAX_TESS_PATCH_COMPONENTS",						GL_MAX_TESS_PATCH_COMPONENTS,					120));
7221c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_total_output_components",			"Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS",		GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS,	4096));
7222c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_output_components",				"Test MAX_TESS_EVALUATION_OUTPUT_COMPONENTS",			GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS,		128));
7223c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_uniform_blocks",					"Test MAX_TESS_CONTROL_UNIFORM_BLOCKS",					GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,				12));
7224c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_uniform_blocks",				"Test MAX_TESS_EVALUATION_UNIFORM_BLOCKS",				GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,			12));
7225c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_input_components",					"Test MAX_TESS_CONTROL_INPUT_COMPONENTS",				GL_MAX_TESS_CONTROL_INPUT_COMPONENTS,			128));
7226c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_input_components",				"Test MAX_TESS_EVALUATION_INPUT_COMPONENTS",			GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS,		128));
7227c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_atomic_counter_buffers",			"Test MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS",			GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS,		0));
7228c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_atomic_counter_buffers",		"Test MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS",		GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS,	0));
7229c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_atomic_counters",					"Test MAX_TESS_CONTROL_ATOMIC_COUNTERS",				GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS,			0));
7230c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_atomic_counters",				"Test MAX_TESS_EVALUATION_ATOMIC_COUNTERS",				GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS,			0));
7231c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_image_uniforms",					"Test MAX_TESS_CONTROL_IMAGE_UNIFORMS",					GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS,				0));
7232c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_image_uniforms",				"Test MAX_TESS_EVALUATION_IMAGE_UNIFORMS",				GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS,			0));
7233c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_shader_storage_blocks",			"Test MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS",			GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,		0));
7234c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_shader_storage_blocks",			"Test MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS",		GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,	0));
7235c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7236c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		// modified limits
7237c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_uniform_buffer_bindings",						"Test MAX_UNIFORM_BUFFER_BINDINGS",						GL_MAX_UNIFORM_BUFFER_BINDINGS,					72));
7238c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_combined_uniform_blocks",						"Test MAX_COMBINED_UNIFORM_BLOCKS",						GL_MAX_COMBINED_UNIFORM_BLOCKS,					60));
7239c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new LimitQueryCase(m_context, "max_combined_texture_image_units",					"Test MAX_COMBINED_TEXTURE_IMAGE_UNITS",				GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,			96));
7240c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7241c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		// combined limits
7242c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new CombinedUniformLimitCase(m_context, "max_combined_tess_control_uniform_components",		"Test MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS",	GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS,		GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,		GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS));
7243c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new CombinedUniformLimitCase(m_context, "max_combined_tess_evaluation_uniform_components",		"Test MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS",	GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS,		GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,	GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS));
7244c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7245c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		// features
7246c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new PrimitiveRestartForPatchesSupportedCase(m_context, "primitive_restart_for_patches_supported", "Test PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"));
7247c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7248c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		// states
7249c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new PatchVerticesStateCase(m_context, "patch_vertices", "Test PATCH_VERTICES"));
7250c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7251c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		// program states
7252c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new TessControlOutputVerticesCase	(m_context, "tess_control_output_vertices",	"Test TESS_CONTROL_OUTPUT_VERTICES"));
7253c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new TessGenModeQueryCase			(m_context, "tess_gen_mode",				"Test TESS_GEN_MODE"));
7254c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new TessGenSpacingQueryCase		(m_context, "tess_gen_spacing",				"Test TESS_GEN_SPACING"));
7255c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new TessGenVertexOrderQueryCase	(m_context, "tess_gen_vertex_order",		"Test TESS_GEN_VERTEX_ORDER"));
7256c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new TessGenPointModeQueryCase		(m_context, "tess_gen_point_mode",			"Test TESS_GEN_POINT_MODE"));
7257c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7258c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		// resource queries
7259c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new ReferencedByTessellationQueryCase	(m_context, "referenced_by_tess_control_shader",	"Test REFERENCED_BY_TESS_CONTROL_SHADER",		true));
7260c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new ReferencedByTessellationQueryCase	(m_context, "referenced_by_tess_evaluation_shader",	"Test REFERENCED_BY_TESS_EVALUATION_SHADER",	false));
7261c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry		queryGroup->addChild(new IsPerPatchQueryCase				(m_context, "is_per_patch",							"Test IS_PER_PATCH"));
7262c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	}
7263c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
7264c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry	{
72653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const tessCoordGroup = new TestCaseGroup(m_context, "tesscoord", "Get tessellation coordinates with transform feedback and validate them");
72663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(tessCoordGroup);
72673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
72693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
72703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessPrimitiveType primitiveType = (TessPrimitiveType)primitiveTypeI;
72713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int spacingI = 0; spacingI < SPACINGMODE_LAST; spacingI++)
72733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tessCoordGroup->addChild(new TessCoordCase(m_context,
72743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   (string() + getTessPrimitiveTypeShaderName(primitiveType) + "_" + getSpacingModeShaderName((SpacingMode)spacingI)).c_str(), "",
72753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   primitiveType, (SpacingMode)spacingI));
72763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
72773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
72783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
72803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const windingGroup = new TestCaseGroup(m_context, "winding", "Test the cw and ccw input layout qualifiers");
72813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(windingGroup);
72823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
72843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
72853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessPrimitiveType primitiveType = (TessPrimitiveType)primitiveTypeI;
72863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (primitiveType == TESSPRIMITIVETYPE_ISOLINES)
72873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
72883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int windingI = 0; windingI < WINDING_LAST; windingI++)
72903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
72913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Winding winding = (Winding)windingI;
72923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				windingGroup->addChild(new WindingCase(m_context, (string() + getTessPrimitiveTypeShaderName(primitiveType) + "_" + getWindingShaderName(winding)).c_str(), "", primitiveType, winding));
72933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
72943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
72953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
72963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
72973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
72983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const shaderInputOutputGroup = new TestCaseGroup(m_context, "shader_input_output", "Test tessellation control and evaluation shader inputs and outputs");
72993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(shaderInputOutputGroup);
73003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
73023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			static const struct
73033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
73043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int inPatchSize;
73053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int outPatchSize;
73063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			} patchVertexCountCases[] =
73073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
73083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{  5, 10 },
73093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ 10,  5 }
73103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
73113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(patchVertexCountCases); caseNdx++)
73133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
73143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int inSize	= patchVertexCountCases[caseNdx].inPatchSize;
73153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int outSize	= patchVertexCountCases[caseNdx].outPatchSize;
73163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string caseName = "patch_vertices_" + de::toString(inSize) + "_in_" + de::toString(outSize) + "_out";
73183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				shaderInputOutputGroup->addChild(new PatchVertexCountCase(m_context, caseName.c_str(), "Test input and output patch vertex counts", inSize, outSize,
73203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		  ("data/tessellation/" + caseName + "_ref.png").c_str()));
73213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
73223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
73233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseTypeI = 0; caseTypeI < PerPatchDataCase::CASETYPE_LAST; caseTypeI++)
73253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
73263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const PerPatchDataCase::CaseType	caseType	= (PerPatchDataCase::CaseType)caseTypeI;
73273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* const					caseName	= PerPatchDataCase::getCaseTypeName(caseType);
73283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			shaderInputOutputGroup->addChild(new PerPatchDataCase(m_context, caseName, PerPatchDataCase::getCaseTypeDescription(caseType), caseType,
73303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  PerPatchDataCase::caseTypeUsesRefImageFromFile(caseType) ? (string() + "data/tessellation/" + caseName + "_ref.png").c_str() : DE_NULL));
73313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
73323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseTypeI = 0; caseTypeI < GLPositionCase::CASETYPE_LAST; caseTypeI++)
73343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
73353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const GLPositionCase::CaseType	caseType	= (GLPositionCase::CaseType)caseTypeI;
73363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* const				caseName	= GLPositionCase::getCaseTypeName(caseType);
73373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			shaderInputOutputGroup->addChild(new GLPositionCase(m_context, caseName, "", caseType, "data/tessellation/gl_position_ref.png"));
73393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
73403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shaderInputOutputGroup->addChild(new BarrierCase(m_context, "barrier", "Basic barrier usage", "data/tessellation/barrier_ref.png"));
73423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
73433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
73453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const miscDrawGroup = new TestCaseGroup(m_context, "misc_draw", "Miscellaneous draw-result-verifying cases");
73463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(miscDrawGroup);
73473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
73493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
73503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessPrimitiveType primitiveType = (TessPrimitiveType)primitiveTypeI;
73513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (primitiveType == TESSPRIMITIVETYPE_ISOLINES)
73523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
73533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* const primTypeName = getTessPrimitiveTypeShaderName(primitiveType);
73553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int spacingI = 0; spacingI < SPACINGMODE_LAST; spacingI++)
73573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
73583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string caseName = string() + "fill_cover_" + primTypeName + "_" + getSpacingModeShaderName((SpacingMode)spacingI);
73593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				miscDrawGroup->addChild(new BasicTriangleFillCoverCase(m_context,
73613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	   caseName.c_str(), "Check that there are no obvious gaps in the triangle-filled area of a tessellated shape",
73623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	   primitiveType, (SpacingMode)spacingI,
73633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	   ("data/tessellation/" + caseName + "_ref").c_str()));
73643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
73653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
73663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
73683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
73693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessPrimitiveType primitiveType = (TessPrimitiveType)primitiveTypeI;
73703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (primitiveType == TESSPRIMITIVETYPE_ISOLINES)
73713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
73723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* const primTypeName = getTessPrimitiveTypeShaderName(primitiveType);
73743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int spacingI = 0; spacingI < SPACINGMODE_LAST; spacingI++)
73763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
73773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string caseName = string() + "fill_overlap_" + primTypeName + "_" + getSpacingModeShaderName((SpacingMode)spacingI);
73783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				miscDrawGroup->addChild(new BasicTriangleFillNonOverlapCase(m_context,
73803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			caseName.c_str(), "Check that there are no obvious triangle overlaps in the triangle-filled area of a tessellated shape",
73813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			primitiveType, (SpacingMode)spacingI,
73823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			("data/tessellation/" + caseName + "_ref").c_str()));
73833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
73843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
73853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int spacingI = 0; spacingI < SPACINGMODE_LAST; spacingI++)
73873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
73883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string caseName = string() + "isolines_" + getSpacingModeShaderName((SpacingMode)spacingI);
73893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			miscDrawGroup->addChild(new IsolinesRenderCase(m_context,
73913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   caseName.c_str(), "Basic isolines render test",
73923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   (SpacingMode)spacingI,
73933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   ("data/tessellation/" + caseName + "_ref").c_str()));
73943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
73953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
73963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
73983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const commonEdgeGroup = new TestCaseGroup(m_context, "common_edge", "Draw multiple adjacent shapes and check that no cracks appear between them");
73993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(commonEdgeGroup);
74003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseTypeI = 0; caseTypeI < CommonEdgeCase::CASETYPE_LAST; caseTypeI++)
74023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
74033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
74043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
74053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const CommonEdgeCase::CaseType	caseType		= (CommonEdgeCase::CaseType)caseTypeI;
74063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const TessPrimitiveType			primitiveType	= (TessPrimitiveType)primitiveTypeI;
74073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (primitiveType == TESSPRIMITIVETYPE_ISOLINES)
74083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						continue;
74093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int spacingI = 0; spacingI < SPACINGMODE_LAST; spacingI++)
74113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
74123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const SpacingMode	spacing		= (SpacingMode)spacingI;
74133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const string		caseName	= (string() + getTessPrimitiveTypeShaderName(primitiveType)
74143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																+ "_" + getSpacingModeShaderName(spacing)
74153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																+ (caseType == CommonEdgeCase::CASETYPE_BASIC		? ""
74163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 : caseType == CommonEdgeCase::CASETYPE_PRECISE		? "_precise"
74173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 : DE_NULL));
74183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					commonEdgeGroup->addChild(new CommonEdgeCase(m_context, caseName.c_str(), "", primitiveType, spacing, caseType));
74203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
74213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
74223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
74233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
74243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
74263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const fractionalSpacingModeGroup = new TestCaseGroup(m_context, "fractional_spacing", "Test fractional spacing modes");
74273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(fractionalSpacingModeGroup);
74283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fractionalSpacingModeGroup->addChild(new FractionalSpacingModeCase(m_context, "odd",	"", SPACINGMODE_FRACTIONAL_ODD));
74303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fractionalSpacingModeGroup->addChild(new FractionalSpacingModeCase(m_context, "even",	"", SPACINGMODE_FRACTIONAL_EVEN));
74313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
74323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
74343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const primitiveDiscardGroup = new TestCaseGroup(m_context, "primitive_discard", "Test primitive discard with relevant outer tessellation level <= 0.0");
74353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(primitiveDiscardGroup);
74363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
74383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
74393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int spacingI = 0; spacingI < SPACINGMODE_LAST; spacingI++)
74403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
74413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int windingI = 0; windingI < WINDING_LAST; windingI++)
74423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
74433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int usePointModeI = 0; usePointModeI <= 1; usePointModeI++)
74443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
74453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const TessPrimitiveType		primitiveType	= (TessPrimitiveType)primitiveTypeI;
74463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const SpacingMode			spacing			= (SpacingMode)spacingI;
74473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const Winding				winding			= (Winding)windingI;
74483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const bool					usePointMode	= usePointModeI != 0;
74493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						primitiveDiscardGroup->addChild(new PrimitiveDiscardCase(m_context, (string() + getTessPrimitiveTypeShaderName(primitiveType)
74513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																									  + "_" + getSpacingModeShaderName(spacing)
74523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																									  + "_" + getWindingShaderName(winding)
74533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																									  + (usePointMode ? "_point_mode" : "")).c_str(), "",
74543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				 primitiveType, spacing, winding, usePointMode));
74553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
74563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
74573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
74583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
74593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
74603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
74623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const invarianceGroup							= new TestCaseGroup(m_context, "invariance",						"Test tessellation invariance rules");
74633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const invariantPrimitiveSetGroup					= new TestCaseGroup(m_context, "primitive_set",						"Test invariance rule #1");
74653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const invariantOuterEdgeGroup					= new TestCaseGroup(m_context, "outer_edge_division",				"Test invariance rule #2");
74663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const symmetricOuterEdgeGroup					= new TestCaseGroup(m_context, "outer_edge_symmetry",				"Test invariance rule #3");
74673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const outerEdgeVertexSetIndexIndependenceGroup	= new TestCaseGroup(m_context, "outer_edge_index_independence",		"Test invariance rule #4");
74683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const invariantTriangleSetGroup					= new TestCaseGroup(m_context, "triangle_set",						"Test invariance rule #5");
74693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const invariantInnerTriangleSetGroup				= new TestCaseGroup(m_context, "inner_triangle_set",				"Test invariance rule #6");
74703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const invariantOuterTriangleSetGroup				= new TestCaseGroup(m_context, "outer_triangle_set",				"Test invariance rule #7");
74713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const tessCoordComponentRangeGroup				= new TestCaseGroup(m_context, "tess_coord_component_range",		"Test invariance rule #8, first part");
74723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const oneMinusTessCoordComponentGroup			= new TestCaseGroup(m_context, "one_minus_tess_coord_component",	"Test invariance rule #8, second part");
74733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(invarianceGroup);
74753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(invariantPrimitiveSetGroup);
74763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(invariantOuterEdgeGroup);
74773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(symmetricOuterEdgeGroup);
74783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(outerEdgeVertexSetIndexIndependenceGroup);
74793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(invariantTriangleSetGroup);
74803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(invariantInnerTriangleSetGroup);
74813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(invariantOuterTriangleSetGroup);
74823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(tessCoordComponentRangeGroup);
74833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		invarianceGroup->addChild(oneMinusTessCoordComponentGroup);
74843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
74863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
74873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TessPrimitiveType		primitiveType	= (TessPrimitiveType)primitiveTypeI;
74883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string				primName		= getTessPrimitiveTypeShaderName(primitiveType);
74893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					triOrQuad		= primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS;
74903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int spacingI = 0; spacingI < SPACINGMODE_LAST; spacingI++)
74923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
74933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const SpacingMode	spacing			= (SpacingMode)spacingI;
74943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string		primSpacName	= primName + "_" + getSpacingModeShaderName(spacing);
74953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
74963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (triOrQuad)
74973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
74983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					invariantOuterEdgeGroup->addChild		(new InvariantOuterEdgeCase			(m_context, primSpacName.c_str(), "", primitiveType, spacing));
74993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					invariantTriangleSetGroup->addChild		(new InvariantTriangleSetCase		(m_context, primSpacName.c_str(), "", primitiveType, spacing));
75003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					invariantInnerTriangleSetGroup->addChild(new InvariantInnerTriangleSetCase	(m_context, primSpacName.c_str(), "", primitiveType, spacing));
75013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					invariantOuterTriangleSetGroup->addChild(new InvariantOuterTriangleSetCase	(m_context, primSpacName.c_str(), "", primitiveType, spacing));
75023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
75033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int windingI = 0; windingI < WINDING_LAST; windingI++)
75053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
75063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const Winding	winding				= (Winding)windingI;
75073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const string	primSpacWindName	= primSpacName + "_" + getWindingShaderName(winding);
75083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int usePointModeI = 0; usePointModeI <= 1; usePointModeI++)
75103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
75113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const bool		usePointMode			= usePointModeI != 0;
75123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const string	primSpacWindPointName	= primSpacWindName + (usePointMode ? "_point_mode" : "");
75133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						invariantPrimitiveSetGroup->addChild		(new InvariantPrimitiveSetCase			(m_context, primSpacWindPointName.c_str(), "", primitiveType, spacing, winding, usePointMode));
75153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						symmetricOuterEdgeGroup->addChild			(new SymmetricOuterEdgeCase				(m_context, primSpacWindPointName.c_str(), "", primitiveType, spacing, winding, usePointMode));
75163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						tessCoordComponentRangeGroup->addChild		(new TessCoordComponentRangeCase		(m_context, primSpacWindPointName.c_str(), "", primitiveType, spacing, winding, usePointMode));
75173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						oneMinusTessCoordComponentGroup->addChild	(new OneMinusTessCoordComponentCase		(m_context, primSpacWindPointName.c_str(), "", primitiveType, spacing, winding, usePointMode));
75183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (triOrQuad)
75203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							outerEdgeVertexSetIndexIndependenceGroup->addChild(new OuterEdgeVertexSetIndexIndependenceCase(m_context, primSpacWindPointName.c_str(), "",
75213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																														   primitiveType, spacing, winding, usePointMode));
75223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
75233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
75243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
75253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
75263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
75273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
75298cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		static const struct
75308cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		{
75318cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const char*					name;
75328cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			const char*					description;
75338cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			UserDefinedIOCase::IOType	ioType;
75348cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		} ioCases[] =
75358cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		{
75368cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			{ "per_patch",					"Per-patch TCS outputs",					UserDefinedIOCase::IO_TYPE_PER_PATCH				},
75378cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			{ "per_patch_array",			"Per-patch array TCS outputs",				UserDefinedIOCase::IO_TYPE_PER_PATCH_ARRAY			},
75388cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			{ "per_patch_block",			"Per-patch TCS outputs in IO block",		UserDefinedIOCase::IO_TYPE_PER_PATCH_BLOCK			},
75398cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			{ "per_patch_block_array",		"Per-patch TCS outputs in IO block array",	UserDefinedIOCase::IO_TYPE_PER_PATCH_BLOCK_ARRAY	},
75408cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			{ "per_vertex",					"Per-vertex TCS outputs",					UserDefinedIOCase::IO_TYPE_PER_VERTEX				},
75418cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			{ "per_vertex_block",			"Per-vertex TCS outputs in IO block",		UserDefinedIOCase::IO_TYPE_PER_VERTEX_BLOCK			},
75428cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		};
75438cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry
75443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup* const userDefinedIOGroup = new TestCaseGroup(m_context, "user_defined_io", "Test non-built-in per-patch and per-vertex inputs and outputs");
75453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(userDefinedIOGroup);
75463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75478cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(ioCases); ++ndx)
75483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
75498cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry			TestCaseGroup* const ioTypeGroup = new TestCaseGroup(m_context, ioCases[ndx].name, ioCases[ndx].description);
75503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			userDefinedIOGroup->addChild(ioTypeGroup);
75513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vertexArraySizeI = 0; vertexArraySizeI < UserDefinedIOCase::VERTEX_IO_ARRAY_SIZE_LAST; vertexArraySizeI++)
75533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
75543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const UserDefinedIOCase::VertexIOArraySize	vertexArraySize			= (UserDefinedIOCase::VertexIOArraySize)vertexArraySizeI;
75553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TestCaseGroup* const						vertexArraySizeGroup	= new TestCaseGroup(m_context,
75563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																										vertexArraySizeI == UserDefinedIOCase::VERTEX_IO_ARRAY_SIZE_IMPLICIT
75573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																											? "vertex_io_array_size_implicit"
75583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																									  : vertexArraySizeI == UserDefinedIOCase::VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN
75593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																											? "vertex_io_array_size_shader_builtin"
75603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																									  : vertexArraySizeI == UserDefinedIOCase::VERTEX_IO_ARRAY_SIZE_EXPLICIT_QUERY
75613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																											? "vertex_io_array_size_query"
75623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																									  : DE_NULL,
75633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																									    "");
75643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ioTypeGroup->addChild(vertexArraySizeGroup);
75653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int primitiveTypeI = 0; primitiveTypeI < TESSPRIMITIVETYPE_LAST; primitiveTypeI++)
75673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
75683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const TessPrimitiveType primitiveType = (TessPrimitiveType)primitiveTypeI;
75698cd63a217cae5f39d8d88b87e2cfdfb1a8325638Jarkko Pöyry					vertexArraySizeGroup->addChild(new UserDefinedIOCase(m_context, getTessPrimitiveTypeShaderName(primitiveType), "", primitiveType, ioCases[ndx].ioType, vertexArraySize,
75703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		 (string() + "data/tessellation/user_defined_io_" + getTessPrimitiveTypeShaderName(primitiveType) + "_ref.png").c_str()));
75713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
75723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
75733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
757418c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry
757518c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry		{
757618c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry			TestCaseGroup* const				negativeGroup	= new TestCaseGroup(m_context, "negative", "Negative cases");
757718c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry			gls::ShaderLibrary					shaderLibrary	(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
757818c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry			const std::vector<tcu::TestNode*>	children		= shaderLibrary.loadShaderFile("shaders/tessellation_negative_user_defined_io.test");
757918c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry
758018c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry			userDefinedIOGroup->addChild(negativeGroup);
758118c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry
758218c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry			for (int i = 0; i < (int)children.size(); i++)
758318c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry				negativeGroup->addChild(children[i]);
758418c15f928a710db86e7e374b478faea3b198afc3Jarkko Pöyry		}
75853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
75863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
75873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
75893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
75903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
7591