13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Invariance tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fShaderInvarianceTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuStringTemplate.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FormatArgumentList;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Vec4 genRandomVector (de::Random& rnd)
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 retVal;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.x() = rnd.getFloat(-1.0f, 1.0f);
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.y() = rnd.getFloat(-1.0f, 1.0f);
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.z() = rnd.getFloat(-1.0f, 1.0f);
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.w() = rnd.getFloat( 0.2f, 1.0f);
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FormatArgument
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						FormatArgument (const char* name, const std::string& value);
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	friend class FormatArgumentList;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	m_name;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string	m_value;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFormatArgument::FormatArgument (const char* name, const std::string& value)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_name	(name)
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_value	(value)
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FormatArgumentList
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												FormatArgumentList	(void);
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FormatArgumentList&							operator<<			(const FormatArgument&);
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::map<std::string, std::string>&	getArguments		(void) const;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::map<std::string, std::string>			m_formatArguments;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFormatArgumentList::FormatArgumentList (void)
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFormatArgumentList&	FormatArgumentList::operator<< (const FormatArgument& arg)
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_formatArguments[arg.m_name] = arg.m_value;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst std::map<std::string, std::string>& FormatArgumentList::getArguments (void) const
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_formatArguments;
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string formatGLSL (const char* templateString, const FormatArgumentList& args)
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::map<std::string, std::string>& params = args.getArguments();
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::StringTemplate(std::string(templateString)).specialize(params);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Vertex shader invariance test
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Test vertex shader invariance by drawing a test pattern two times, each
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * time with a different shader. Shaders have set identical values to
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * invariant gl_Position using identical expressions. No fragments from the
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * first pass using should remain visible.
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvarianceTest : public TestCase
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct ShaderPair
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::string vertexShaderSource0;
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::string fragmentShaderSource0;
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::string vertexShaderSource1;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::string fragmentShaderSource1;
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							InvarianceTest		(Context& ctx, const char* name, const char* desc);
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~InvarianceTest		(void);
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init				(void);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit				(void);
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate				(void);
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual ShaderPair		genShaders			(void) const = DE_NULL;
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					checkImage			(const tcu::Surface&) const;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_shader0;
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_shader1;
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint				m_arrayBuf;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_verticesInPattern;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_renderSize;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvarianceTest::InvarianceTest (Context& ctx, const char* name, const char* desc)
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase				(ctx, name, desc)
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shader0				(DE_NULL)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shader1				(DE_NULL)
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_arrayBuf			(0)
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_verticesInPattern	(0)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderSize			(256)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvarianceTest::~InvarianceTest (void)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InvarianceTest::init (void)
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Invariance tests require drawing to the screen and reading back results.
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Tests results are not reliable if the resolution is too small
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_context.getRenderTarget().getWidth()  < m_renderSize ||
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_context.getRenderTarget().getHeight() < m_renderSize)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_renderSize) + "x" + de::toString(m_renderSize));
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Gen shaders
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderPair vertexShaders = genShaders();
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_shader0 = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexShaders.vertexShaderSource0) << glu::FragmentSource(vertexShaders.fragmentShaderSource0));
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_shader0->isOk())
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << *m_shader0;
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("Test shader compile failed.");
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_shader1 = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexShaders.vertexShaderSource1) << glu::FragmentSource(vertexShaders.fragmentShaderSource1));
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_shader1->isOk())
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << *m_shader1;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("Test shader compile failed.");
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// log
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message << "Shader 1:" << tcu::TestLog::EndMessage
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< *m_shader0
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message << "Shader 2:" << tcu::TestLog::EndMessage
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< *m_shader1;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Gen test pattern
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numTriangles	= 72;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(123);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<tcu::Vec4>	triangles		(numTriangles * 3 * 2);
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Narrow triangle pattern
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int triNdx = 0; triNdx < numTriangles; ++triNdx)
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4 vertex1 = genRandomVector(rnd);
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4 vertex2 = genRandomVector(rnd);
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4 vertex3 = vertex2 + genRandomVector(rnd) * 0.01f; // generate narrow triangles
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			triangles[triNdx*3 + 0] = vertex1;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			triangles[triNdx*3 + 1] = vertex2;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			triangles[triNdx*3 + 2] = vertex3;
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Normal triangle pattern
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int triNdx = 0; triNdx < numTriangles; ++triNdx)
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			triangles[(numTriangles + triNdx)*3 + 0] = genRandomVector(rnd);
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			triangles[(numTriangles + triNdx)*3 + 1] = genRandomVector(rnd);
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			triangles[(numTriangles + triNdx)*3 + 2] = genRandomVector(rnd);
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// upload
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_arrayBuf);
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf);
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_ARRAY_BUFFER, (int)(triangles.size() * sizeof(tcu::Vec4)), &triangles[0], GL_STATIC_DRAW);
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "buffer gen");
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_verticesInPattern = numTriangles * 3;
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InvarianceTest::deinit (void)
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_shader0;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_shader1;
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_shader0 = DE_NULL;
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_shader1 = DE_NULL;
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_arrayBuf)
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_arrayBuf);
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_arrayBuf = 0;
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvarianceTest::IterateResult InvarianceTest::iterate (void)
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool				depthBufferExists	= m_context.getRenderTarget().getDepthBits() != 0;
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface			resultSurface		(m_renderSize, m_renderSize);
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					error				= false;
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Prepare draw
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor		(0.0f, 0.0f, 0.0f, 1.0f);
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear			(GL_COLOR_BUFFER_BIT);
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport			(0, 0, m_renderSize, m_renderSize);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer		(GL_ARRAY_BUFFER, m_arrayBuf);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR	(gl.getError(), "setup draw");
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Testing position invariance." << tcu::TestLog::EndMessage;
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Draw position check passes
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int passNdx = 0; passNdx < 2; ++passNdx)
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::ShaderProgram&	shader		= (passNdx == 0) ? (*m_shader0) : (*m_shader1);
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::GLint			positionLoc = gl.getAttribLocation(shader.getProgram(), "a_input");
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::GLint			colorLoc	= gl.getUniformLocation(shader.getProgram(), "u_color");
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4				red			= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4				green		= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4				color		= (passNdx == 0) ? (red) : (green);
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char* const			colorStr	= (passNdx == 0) ? ("red - purple") : ("green");
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Drawing position test pattern using shader " << (passNdx+1) << ". Primitive color: " << colorStr << "." << tcu::TestLog::EndMessage;
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram				(shader.getProgram());
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform4fv				(colorLoc, 1, color.getPtr());
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.enableVertexAttribArray	(positionLoc);
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), DE_NULL);
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.drawArrays				(GL_TRIANGLES, 0, m_verticesInPattern);
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.disableVertexAttribArray	(positionLoc);
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR			(gl.getError(), "draw pass");
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read result
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_context.getRenderContext(), 0, 0, resultSurface.getAccess());
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check there are no red pixels
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output. Expecting only green or background colored pixels." << tcu::TestLog::EndMessage;
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	error |= !checkImage(resultSurface);
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!depthBufferExists)
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Depth buffer not available, skipping z-test." << tcu::TestLog::EndMessage;
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Test with Z-test
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clearDepthf		(1.0f);
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear			(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.enable			(GL_DEPTH_TEST);
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Testing position invariance with z-test. Enabling GL_DEPTH_TEST." << tcu::TestLog::EndMessage;
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Draw position check passes
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int passNdx = 0; passNdx < 2; ++passNdx)
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::ShaderProgram&	shader			= (passNdx == 0) ? (*m_shader0) : (*m_shader1);
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::GLint			positionLoc		= gl.getAttribLocation(shader.getProgram(), "a_input");
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::GLint			colorLoc		= gl.getUniformLocation(shader.getProgram(), "u_color");
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4				red				= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4				green			= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4				color			= (passNdx == 0) ? (red) : (green);
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::GLenum			depthFunc		= (passNdx == 0) ? (GL_ALWAYS) : (GL_EQUAL);
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* const			depthFuncStr	= (passNdx == 0) ? ("GL_ALWAYS") : ("GL_EQUAL");
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* const			colorStr		= (passNdx == 0) ? ("red - purple") : ("green");
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Drawing Z-test pattern using shader " << (passNdx+1) << ". Primitive color: " << colorStr << ". DepthFunc: " << depthFuncStr << tcu::TestLog::EndMessage;
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.useProgram				(shader.getProgram());
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.uniform4fv				(colorLoc, 1, color.getPtr());
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.depthFunc				(depthFunc);
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.enableVertexAttribArray	(positionLoc);
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), DE_NULL);
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.drawArrays				(GL_TRIANGLES, m_verticesInPattern, m_verticesInPattern); // !< buffer contains 2 m_verticesInPattern-sized patterns
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.disableVertexAttribArray	(positionLoc);
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR			(gl.getError(), "draw pass");
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Read result
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::readPixels(m_context.getRenderContext(), 0, 0, resultSurface.getAccess());
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Check there are no red pixels
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output. Expecting only green or background colored pixels." << tcu::TestLog::EndMessage;
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		error |= !checkImage(resultSurface);
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Report result
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (error)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Detected variance between two invariant values");
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool InvarianceTest::checkImage (const tcu::Surface& surface) const
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec4	okColor		= tcu::IVec4(0, 255, 0, 255);
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		errColor	= tcu::RGBA(255, 0, 0, 255);
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				error		= false;
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface		errorMask	(m_renderSize, m_renderSize);
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask.getAccess(), okColor);
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < m_renderSize; ++y)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < m_renderSize; ++x)
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::RGBA col = surface.getPixel(x, y);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (col.getRed() != 0)
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			errorMask.setPixel(x, y, errColor);
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			error = true;
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// report error
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (error)
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixels found (fragments from first render pass found). Variance detected." << tcu::TestLog::EndMessage;
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::ImageSet("Results", "Result verification")
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Image("Result",		"Result",		surface)
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Image("Error mask",	"Error mask",	errorMask)
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndImageSet;
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "No variance found." << tcu::TestLog::EndMessage;
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::ImageSet("Results", "Result verification")
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Image("Result", "Result", surface)
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndImageSet;
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BasicInvarianceTest : public InvarianceTest
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								BasicInvarianceTest		(Context& ctx, const char* name, const char* desc, const std::string& vertexShader1, const std::string& vertexShader2);
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								BasicInvarianceTest		(Context& ctx, const char* name, const char* desc, const std::string& vertexShader1, const std::string& vertexShader2, const std::string& fragmentShader);
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderPair					genShaders				(void) const;
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string			m_vertexShader1;
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string			m_vertexShader2;
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string			m_fragmentShader;
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* const	s_basicFragmentShader;
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* const BasicInvarianceTest::s_basicFragmentShader =	"#version 300 es\n"
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"layout(location = 0) out mediump vec4 fragColor;\n"
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"uniform mediump vec4 u_color;\n"
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"in mediump vec4 v_unrelated;\n"
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"void main ()\n"
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"{\n"
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"	mediump float blue = dot(v_unrelated, vec4(1.0, 1.0, 1.0, 1.0));\n"
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"	fragColor = vec4(u_color.r, u_color.g, blue, u_color.a);\n"
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"}\n";
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4253c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBasicInvarianceTest::BasicInvarianceTest (Context& ctx, const char* name, const char* desc, const std::string& vertexShader1, const std::string& vertexShader2)
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: InvarianceTest	(ctx, name, desc)
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_vertexShader1	(vertexShader1)
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_vertexShader2	(vertexShader2)
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_fragmentShader	(s_basicFragmentShader)
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBasicInvarianceTest::BasicInvarianceTest (Context& ctx, const char* name, const char* desc, const std::string& vertexShader1, const std::string& vertexShader2, const std::string& fragmentShader)
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: InvarianceTest	(ctx, name, desc)
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_vertexShader1	(vertexShader1)
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_vertexShader2	(vertexShader2)
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_fragmentShader	(fragmentShader)
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBasicInvarianceTest::ShaderPair BasicInvarianceTest::genShaders (void) const
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderPair retVal;
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.vertexShaderSource0 = m_vertexShader1;
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.vertexShaderSource1 = m_vertexShader2;
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.fragmentShaderSource0 = m_fragmentShader;
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.fragmentShaderSource1 = m_fragmentShader;
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderInvarianceTests::ShaderInvarianceTests (Context& context)
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "invariance", "Invariance tests")
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4603c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderInvarianceTests::~ShaderInvarianceTests (void)
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderInvarianceTests::init (void)
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct PrecisionCase
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::Precision	prec;
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// set literals in the glsl to be in the representable range
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		highValue;		// !< highValue < maxValue
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		invHighValue;
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		mediumValue;	// !< mediumValue^2 < maxValue
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		lowValue;		// !< lowValue^4 < maxValue
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		invlowValue;
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				loopIterations;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				loopPartialIterations;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				loopNormalizationExponent;
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		loopNormalizationConstantLiteral;
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		loopMultiplier;
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		sumLoopNormalizationConstantLiteral;
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} precisions[] =
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ glu::PRECISION_HIGHP,		"highp",	"1.0e20",	"1.0e-20",	"1.0e14",	"1.0e9",	"1.0e-9",	14,	11,	2,	"1.0e4",	"1.9",	"1.0e3"	},
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ glu::PRECISION_MEDIUMP,	"mediump",	"1.0e4",	"1.0e-4",	"1.0e2",	"1.0e1",	"1.0e-1",	13,	11,	2,	"1.0e4",	"1.9",	"1.0e3"	},
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ glu::PRECISION_LOWP,		"lowp",		"0.9",		"1.1",		"1.1",		"1.15",		"0.87",		6,	2,	0,	"2.0",		"1.1",	"1.0"	},
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); ++precNdx)
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char* const			precisionName	= precisions[precNdx].name;
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision		precision		= precisions[precNdx].prec;
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const	group			= new tcu::TestCaseGroup(m_testCtx, precisionName, "Invariance tests using the given precision.");
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const FormatArgumentList	args			= FormatArgumentList()
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("VERSION",				"#version 300 es\n")
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("IN",						"in")
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("OUT",					"out")
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("IN_PREC",				precisionName)
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("HIGH_VALUE",				de::toString(precisions[precNdx].highValue))
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("HIGH_VALUE_INV",			de::toString(precisions[precNdx].invHighValue))
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("MEDIUM_VALUE",			de::toString(precisions[precNdx].mediumValue))
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("LOW_VALUE",				de::toString(precisions[precNdx].lowValue))
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("LOW_VALUE_INV",			de::toString(precisions[precNdx].invlowValue))
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("LOOP_ITERS",				de::toString(precisions[precNdx].loopIterations))
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("LOOP_ITERS_PARTIAL",		de::toString(precisions[precNdx].loopPartialIterations))
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("LOOP_NORM_FRACT_EXP",	de::toString(precisions[precNdx].loopNormalizationExponent))
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("LOOP_NORM_LITERAL",		precisions[precNdx].loopNormalizationConstantLiteral)
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("LOOP_MULTIPLIER",		precisions[precNdx].loopMultiplier)
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														<< FormatArgument("SUM_LOOP_NORM_LITERAL",	precisions[precNdx].sumLoopNormalizationConstantLiteral);
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(group);
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// subexpression cases
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// First shader shares "${HIGH_VALUE}*a_input.x*a_input.xxxx + ${HIGH_VALUE}*a_input.y*a_input.yyyy" with unrelated output variable. Reordering might result in accuracy loss
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// due to the high exponent. In the second shader, the high exponent may be removed during compilation.
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "common_subexpression_0", "Shader shares a subexpression with an unrelated variable.",
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = a_input.xzxz + (${HIGH_VALUE}*a_input.x*a_input.xxxx + ${HIGH_VALUE}*a_input.y*a_input.yyyy) * (1.08 * a_input.zyzy * a_input.xzxz) * ${HIGH_VALUE_INV} * (a_input.z * a_input.zzxz - a_input.z * a_input.zzxz) + (${HIGH_VALUE}*a_input.x*a_input.xxxx + ${HIGH_VALUE}*a_input.y*a_input.yyyy) / ${HIGH_VALUE};\n"
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + (${HIGH_VALUE}*a_input.x*a_input.xxxx + ${HIGH_VALUE}*a_input.y*a_input.yyyy) * ${HIGH_VALUE_INV};\n"
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + (${HIGH_VALUE}*a_input.x*a_input.xxxx + ${HIGH_VALUE}*a_input.y*a_input.yyyy) * ${HIGH_VALUE_INV};\n"
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// In the first shader, the unrelated variable "d" has mathematically the same expression as "e", but the different
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// order of calculation might cause different results.
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "common_subexpression_1", "Shader shares a subexpression with an unrelated variable.",
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 a = ${HIGH_VALUE} * a_input.zzxx + a_input.xzxy - ${HIGH_VALUE} * a_input.zzxx;\n"
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 b = ${HIGH_VALUE} * a_input.zzxx;\n"
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 c = b - ${HIGH_VALUE} * a_input.zzxx + a_input.xzxy;\n"
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 d = (${LOW_VALUE} * a_input.yzxx) * (${LOW_VALUE} * a_input.yzzw) * (1.1*${LOW_VALUE_INV} * a_input.yzxx) * (${LOW_VALUE_INV} * a_input.xzzy);\n"
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 e = ((${LOW_VALUE} * a_input.yzxx) * (1.1*${LOW_VALUE_INV} * a_input.yzxx)) * ((${LOW_VALUE_INV} * a_input.xzzy) * (${LOW_VALUE} * a_input.yzzw));\n"
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = a + b + c + d + e;\n"
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + fract(c) + e;\n"
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 b = ${HIGH_VALUE} * a_input.zzxx;\n"
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 c = b - ${HIGH_VALUE} * a_input.zzxx + a_input.xzxy;\n"
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 e = ((${LOW_VALUE} * a_input.yzxx) * (1.1*${LOW_VALUE_INV} * a_input.yzxx)) * ((${LOW_VALUE_INV} * a_input.xzzy) * (${LOW_VALUE} * a_input.yzzw));\n"
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + fract(c) + e;\n"
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Intermediate values used by an unrelated output variable
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "common_subexpression_2", "Shader shares a subexpression with an unrelated variable.",
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 a = ${MEDIUM_VALUE} * (a_input.xxxx + a_input.yyyy);\n"
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 b = (${MEDIUM_VALUE} * (a_input.xxxx + a_input.yyyy)) * (${MEDIUM_VALUE} * (a_input.xxxx + a_input.yyyy)) / ${MEDIUM_VALUE} / ${MEDIUM_VALUE};\n"
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 c = a * a;\n"
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 d = c / ${MEDIUM_VALUE} / ${MEDIUM_VALUE};\n"
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = a + b + c + d;\n"
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + d;\n"
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 a = ${MEDIUM_VALUE} * (a_input.xxxx + a_input.yyyy);\n"
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 c = a * a;\n"
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 d = c / ${MEDIUM_VALUE} / ${MEDIUM_VALUE};\n"
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + d;\n"
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Invariant value can be calculated using unrelated value
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "common_subexpression_3", "Shader shares a subexpression with an unrelated variable.",
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} float x = a_input.x * 0.2;\n"
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 a = a_input.xxyx * 0.7;\n"
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 b = a_input.yxyz * 0.7;\n"
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 c = a_input.zxyx * 0.5;\n"
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 f = x*a + x*b + x*c;\n"
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = f;\n"
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 g = x * (a + b + c);\n"
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + g;\n"
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} float x = a_input.x * 0.2;\n"
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 a = a_input.xxyx * 0.7;\n"
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 b = a_input.yxyz * 0.7;\n"
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 c = a_input.zxyx * 0.5;\n"
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 g = x * (a + b + c);\n"
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + g;\n"
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// shared subexpression of different precision
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precisionOther = glu::PRECISION_LOWP; precisionOther != glu::PRECISION_LAST; ++precisionOther)
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const		unrelatedPrec				= glu::getPrecisionName((glu::Precision)precisionOther);
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glu::Precision	minPrecision				= (precisionOther < (int)precision) ? ((glu::Precision)precisionOther) : (precision);
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const		multiplierStr				= (minPrecision == glu::PRECISION_LOWP) ? ("0.8, 0.4, -0.2, 0.3") : ("1.0e1, 5.0e2, 2.0e2, 1.0");
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const		normalizationStrUsed		= (minPrecision == glu::PRECISION_LOWP) ? ("vec4(fract(used2).xyz, 0.0)") : ("vec4(fract(used2 / 1.0e2).xyz - fract(used2 / 1.0e3).xyz, 0.0)");
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const		normalizationStrUnrelated	= (minPrecision == glu::PRECISION_LOWP) ? ("vec4(fract(unrelated2).xyz, 0.0)") : ("vec4(fract(unrelated2 / 1.0e2).xyz - fract(unrelated2 / 1.0e3).xyz, 0.0)");
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				group->addChild(new BasicInvarianceTest(m_context, ("subexpression_precision_" + std::string(unrelatedPrec)).c_str(), "Shader shares subexpression of different precision with an unrelated variable.",
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					formatGLSL(	"${VERSION}"
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"${IN} ${IN_PREC} vec4 a_input;\n"
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"${OUT} ${UNRELATED_PREC} vec4 v_unrelated;\n"
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"invariant gl_Position;\n"
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"void main ()\n"
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"{\n"
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${UNRELATED_PREC} vec4 unrelated0 = a_input + vec4(0.1, 0.2, 0.3, 0.4);\n"
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${UNRELATED_PREC} vec4 unrelated1 = vec4(${MULTIPLIER}) * unrelated0.xywz + unrelated0;\n"
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${UNRELATED_PREC} vec4 unrelated2 = refract(unrelated1, unrelated0, distance(unrelated0, unrelated1));\n"
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	v_unrelated = a_input + 0.02 * ${NORMALIZE_UNRELATED};\n"
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${IN_PREC} vec4 used0 = a_input + vec4(0.1, 0.2, 0.3, 0.4);\n"
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${IN_PREC} vec4 used1 = vec4(${MULTIPLIER}) * used0.xywz + used0;\n"
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${IN_PREC} vec4 used2 = refract(used1, used0, distance(used0, used1));\n"
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	gl_Position = a_input + 0.02 * ${NORMALIZE_USED};\n"
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"}\n", FormatArgumentList(args)
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("UNRELATED_PREC",			unrelatedPrec)
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("MULTIPLIER",				multiplierStr)
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("NORMALIZE_USED",			normalizationStrUsed)
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("NORMALIZE_UNRELATED",	normalizationStrUnrelated)),
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					formatGLSL(	"${VERSION}"
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"${IN} ${IN_PREC} vec4 a_input;\n"
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"${OUT} ${UNRELATED_PREC} vec4 v_unrelated;\n"
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"invariant gl_Position;\n"
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"void main ()\n"
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"{\n"
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${IN_PREC} vec4 used0 = a_input + vec4(0.1, 0.2, 0.3, 0.4);\n"
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${IN_PREC} vec4 used1 = vec4(${MULTIPLIER}) * used0.xywz + used0;\n"
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	${IN_PREC} vec4 used2 = refract(used1, used0, distance(used0, used1));\n"
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"	gl_Position = a_input + 0.02 * ${NORMALIZE_USED};\n"
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								"}\n", FormatArgumentList(args)
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("UNRELATED_PREC",			unrelatedPrec)
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("MULTIPLIER",				multiplierStr)
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("NORMALIZE_USED",			normalizationStrUsed)
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< FormatArgument("NORMALIZE_UNRELATED",	normalizationStrUnrelated))));
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// loops
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "loop_0", "Invariant value set using a loop",
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} highp vec4 v_unrelated;\n"
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		v_unrelated += value;\n"
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = vec4(value.xyz / ${LOOP_NORM_LITERAL} + a_input.xyz * 0.1, 1.0);\n"
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} highp vec4 v_unrelated;\n"
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = vec4(value.xyz / ${LOOP_NORM_LITERAL} + a_input.xyz * 0.1, 1.0);\n"
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "loop_1", "Invariant value set using a loop",
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		if (i == ${LOOP_ITERS_PARTIAL})\n"
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"			v_unrelated = value;\n"
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = vec4(value.xyz / ${LOOP_NORM_LITERAL} + a_input.xyz * 0.1, 1.0);\n"
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = vec4(value.xyz / ${LOOP_NORM_LITERAL} + a_input.xyz * 0.1, 1.0);\n"
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "loop_2", "Invariant value set using a loop",
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, -1.0, 1.0);\n"
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		if (i == ${LOOP_ITERS_PARTIAL})\n"
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"			gl_Position = a_input + 0.05 * vec4(fract(value.xyz / 1.0e${LOOP_NORM_FRACT_EXP}), 1.0);\n"
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		else\n"
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"			v_unrelated = value + a_input;\n"
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, -1.0, 1.0);\n"
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		if (i == ${LOOP_ITERS_PARTIAL})\n"
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"			gl_Position = a_input + 0.05 * vec4(fract(value.xyz / 1.0e${LOOP_NORM_FRACT_EXP}), 1.0);\n"
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		else\n"
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"			v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "loop_3", "Invariant value set using a loop",
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		gl_Position += vec4(value.xyz / ${SUM_LOOP_NORM_LITERAL} + a_input.xyz * 0.1, 1.0);\n"
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		v_unrelated = gl_Position.xyzx * a_input;\n"
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value = a_input;\n"
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value *= ${LOOP_MULTIPLIER};\n"
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		gl_Position += vec4(value.xyz / ${SUM_LOOP_NORM_LITERAL} + a_input.xyz * 0.1, 1.0);\n"
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(new BasicInvarianceTest(m_context, "loop_4", "Invariant value set using a loop",
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n"
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value1 = a_input;\n"
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value2 = a_input;\n"
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value1 *= ${LOOP_MULTIPLIER};\n"
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		v_unrelated = v_unrelated*1.3 + a_input.xyzx * value1.xyxw;\n"
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value2 *= ${LOOP_MULTIPLIER};\n"
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		position = position*1.3 + a_input.xyzx * value2.xyxw;\n"
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + 0.05 * vec4(fract(position.xyz / 1.0e${LOOP_NORM_FRACT_EXP}), 1.0);\n"
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args),
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				formatGLSL(	"${VERSION}"
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${IN} ${IN_PREC} vec4 a_input;\n"
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"${OUT} mediump vec4 v_unrelated;\n"
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"invariant gl_Position;\n"
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"void main ()\n"
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"{\n"
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n"
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	${IN_PREC} vec4 value2 = a_input;\n"
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	v_unrelated = vec4(0.0, 0.0, 0.0, 0.0);\n"
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	for (mediump int i = 0; i < ${LOOP_ITERS}; ++i)\n"
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	{\n"
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		value2 *= ${LOOP_MULTIPLIER};\n"
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"		position = position*1.3 + a_input.xyzx * value2.xyxw;\n"
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	}\n"
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"	gl_Position = a_input + 0.05 * vec4(fract(position.xyz / 1.0e${LOOP_NORM_FRACT_EXP}), 1.0);\n"
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							"}\n", args)));
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
862