13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 2.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 Shader control statement performance tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es2pShaderControlStatementTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderPerformanceCase.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles2
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Performance
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glw; // GL types
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Writes the workload expression used in conditional tests.
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeConditionalWorkload (std::ostringstream& stream, const char* resultName, const char* operandName)
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int numMultiplications = 64;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream << resultName << " = ";
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < numMultiplications; i++)
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (i > 0)
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			stream << "*";
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		stream << operandName;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream << ";";
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Writes the workload expression used in loop tests (one iteration).
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeLoopWorkload (std::ostringstream& stream, const char* resultName, const char* operandName)
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int numMultiplications = 8;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream << resultName << " = ";
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < numMultiplications; i++)
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (i > 0)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			stream << " * ";
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		stream << "(" << resultName << " + " << operandName << ")";
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream << ";";
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// The type of decision to be made in a conditional expression.
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \note In fragment cases with DECISION_ATTRIBUTE, the value in the expression will actually be a varying.
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum DecisionType
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DECISION_STATIC = 0,
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DECISION_UNIFORM,
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DECISION_ATTRIBUTE,
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DECISION_LAST
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ControlStatementCase :  public ShaderPerformanceCase
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ControlStatementCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, gls::PerfCaseType caseType)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: ShaderPerformanceCase(testCtx, renderCtx, name, description, caseType)
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void init (void)
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message << "Using additive blending." << TestLog::EndMessage;
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderPerformanceCase::init();
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void setupRenderState (void)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions& gl = m_renderCtx.getFunctions();
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.enable(GL_BLEND);
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.blendEquation(GL_FUNC_ADD);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.blendFunc(GL_ONE, GL_ONE);
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ConditionalCase : public ControlStatementCase
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum BranchResult
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BRANCH_TRUE = 0,
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BRANCH_FALSE,
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BRANCH_MIXED,
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BRANCH_LAST
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum WorkloadDivision
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WORKLOAD_DIVISION_EVEN = 0,		//! Both true and false branches contain same amount of computation.
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WORKLOAD_DIVISION_TRUE_HEAVY,	//! True branch contains more computation.
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WORKLOAD_DIVISION_FALSE_HEAVY,	//! False branch contains more computation.
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WORKLOAD_DIVISION_LAST
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						ConditionalCase		(Context& context, const char* name, const char* description, DecisionType decisionType, BranchResult branchType, WorkloadDivision workloadDivision, bool isVertex);
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~ConditionalCase	(void);
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init				(void);
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				deinit				(void);
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				setupProgram		(deUint32 program);
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DecisionType		m_decisionType;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BranchResult		m_branchType;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	WorkloadDivision	m_workloadDivision;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>		m_comparisonValueArray; // Will contain per-vertex comparison values if using mixed branch type in vertex case.
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32			m_arrayBuffer;
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConditionalCase::ConditionalCase (Context& context, const char* name, const char* description, DecisionType decisionType, BranchResult branchType, WorkloadDivision workloadDivision, bool isVertex)
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: ControlStatementCase			(context.getTestContext(), context.getRenderContext(), name, description, isVertex ? CASETYPE_VERTEX : CASETYPE_FRAGMENT)
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_decisionType				(decisionType)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_branchType					(branchType)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_workloadDivision			(workloadDivision)
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_arrayBuffer					(0)
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConditionalCase::init (void)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isVertexCase		= m_caseType == CASETYPE_VERTEX;
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isStaticCase		= m_decisionType == DECISION_STATIC;
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isUniformCase		= m_decisionType == DECISION_UNIFORM;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isAttributeCase		= m_decisionType == DECISION_ATTRIBUTE;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isStaticCase || isUniformCase || isAttributeCase);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isConditionTrue		= m_branchType == BRANCH_TRUE;
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isConditionFalse	= m_branchType == BRANCH_FALSE;
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isConditionMixed	= m_branchType == BRANCH_MIXED;
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isConditionTrue || isConditionFalse || isConditionMixed);
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(isConditionFalse);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isAttributeCase || !isConditionMixed); // The branch taken can vary between executions only if using attribute input.
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		staticCompareValueStr	= isConditionTrue	? "1.0" : "-1.0";
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		compareValueStr			= isStaticCase		? staticCompareValueStr :
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  isUniformCase		? "u_compareValue" :
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  isVertexCase		? "a_compareValue" :
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  "v_compareValue";
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	vtx;
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	frag;
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream&	op		= isVertexCase ? vtx : frag;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "attribute highp vec4 a_position;\n";	// Position attribute.
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "attribute mediump vec4 a_value0;\n";	// Input for workload calculations of "true" branch.
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "attribute mediump vec4 a_value1;\n";	// Input for workload calculations of "false" branch.
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Value to be used in the conditional expression.
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isAttributeCase)
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "attribute mediump float a_compareValue;\n";
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isUniformCase)
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "uniform mediump float u_compareValue;\n";
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Varyings.
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "varying mediump vec4 v_color;\n";
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "varying mediump vec4 v_color;\n";
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "varying mediump vec4 v_value0;\n";
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "varying mediump vec4 v_value1;\n";
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "varying mediump vec4 v_value0;\n";
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "varying mediump vec4 v_value1;\n";
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isAttributeCase)
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vtx << "varying mediump float v_compareValue;\n";
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			frag << "varying mediump float v_compareValue;\n";
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "\n";
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "void main()\n";
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "{\n";
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "	gl_Position = a_position;\n";
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\n";
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "void main()\n";
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "{\n";
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	mediump vec4 res;\n";
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string condition;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isConditionMixed && !isVertexCase)
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		condition = string("") + "fract(" + compareValueStr + ") < 0.5"; // Comparison result varies with high frequency.
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		condition = string("") + compareValueStr + " > 0.0";
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	if (" << condition << ")\n";
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	{\n";
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\t\t";
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_workloadDivision == WORKLOAD_DIVISION_EVEN || m_workloadDivision == WORKLOAD_DIVISION_TRUE_HEAVY)
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeConditionalWorkload(op, "res", isVertexCase ? "a_value0" : "v_value0"); // Workload calculation for the "true" branch.
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "res = " << (isVertexCase ? "a_value0" : "v_value0") << ";";
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\n";
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	}\n";
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	else\n";
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	{\n";
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\t\t";
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_workloadDivision == WORKLOAD_DIVISION_EVEN || m_workloadDivision == WORKLOAD_DIVISION_FALSE_HEAVY)
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeConditionalWorkload(op, "res", isVertexCase ? "a_value1" : "v_value1"); // Workload calculations for the "false" branch.
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "res = " << (isVertexCase ? "a_value1" : "v_value1") << ";";
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\n";
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	}\n";
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Put result to color variable.
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_color = res;\n";
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	gl_FragColor = v_color;\n";
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Transfer inputs to fragment shader through varyings.
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isAttributeCase)
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vtx << "	v_compareValue = a_compareValue;\n";
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_value0 = a_value0;\n";
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_value1 = a_value1;\n";
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	gl_FragColor = res;\n"; // Put result to color variable.
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "}\n";
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "}\n";
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_vertShaderSource = vtx.str();
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fragShaderSource = frag.str();
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isAttributeCase)
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isConditionMixed)
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Every execution takes the same branch.
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float value = isConditionTrue ? +1.0f : -1.0f;
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_attributes.push_back(AttribSpec("a_compareValue",	Vec4(value, 0.0f, 0.0f, 0.0f),
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																Vec4(value, 0.0f, 0.0f, 0.0f),
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																Vec4(value, 0.0f, 0.0f, 0.0f),
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																Vec4(value, 0.0f, 0.0f, 0.0f)));
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (isVertexCase)
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Vertex case, not every execution takes the same branch.
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	numComponents	= 4;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			numVertices		= (getGridWidth() + 1) * (getGridHeight() + 1);
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// setupProgram() will later bind this array as an attribute.
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_comparisonValueArray.resize(numVertices * numComponents);
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Make every second vertex take the true branch, and every second the false branch.
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int i = 0; i < (int)m_comparisonValueArray.size(); i++)
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (i % numComponents == 0)
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_comparisonValueArray[i] = (i / numComponents) % 2 == 0 ? +1.0f : -1.0f;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_comparisonValueArray[i] = 0.0f;
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else // isConditionMixed && !isVertexCase
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Fragment case, not every execution takes the same branch.
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note fract(a_compareValue) < 0.5 will be true for every second column of fragments.
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float minValue = 0.0f;
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float maxValue = (float)getViewportWidth()*0.5f;
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_attributes.push_back(AttribSpec("a_compareValue",	Vec4(minValue, 0.0f, 0.0f, 0.0f),
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																Vec4(maxValue, 0.0f, 0.0f, 0.0f),
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																Vec4(minValue, 0.0f, 0.0f, 0.0f),
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																Vec4(maxValue, 0.0f, 0.0f, 0.0f)));
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_attributes.push_back(AttribSpec("a_value0",	Vec4(0.0f, 0.1f, 0.2f, 0.3f),
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.4f, 0.5f, 0.6f, 0.7f),
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.8f, 0.9f, 1.0f, 1.1f),
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(1.2f, 1.3f, 1.4f, 1.5f)));
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_attributes.push_back(AttribSpec("a_value1",	Vec4(0.0f, 0.1f, 0.2f, 0.3f),
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.4f, 0.5f, 0.6f, 0.7f),
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.8f, 0.9f, 1.0f, 1.1f),
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(1.2f, 1.3f, 1.4f, 1.5f)));
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ControlStatementCase::init();
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConditionalCase::setupProgram (deUint32 program)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_decisionType == DECISION_UNIFORM)
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int location = gl.getUniformLocation(program, "u_compareValue");
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(location, m_branchType == BRANCH_TRUE ? +1.0f : -1.0f);
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_decisionType == DECISION_ATTRIBUTE && m_branchType == BRANCH_MIXED && m_caseType == CASETYPE_VERTEX)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Setup per-vertex comparison values calculated in init().
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	numComponents			= 4;
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			compareAttribLocation	= gl.getAttribLocation(program, "a_compareValue");
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT((int)m_comparisonValueArray.size() == numComponents * (getGridWidth() + 1) * (getGridHeight() + 1));
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_arrayBuffer);
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(m_comparisonValueArray.size()*sizeof(float)), &m_comparisonValueArray[0], GL_STATIC_DRAW);
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.enableVertexAttribArray(compareAttribLocation);
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.vertexAttribPointer(compareAttribLocation, (GLint)numComponents, GL_FLOAT, GL_FALSE, 0, DE_NULL);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Setup program state");
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3743c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConditionalCase::~ConditionalCase (void)
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_arrayBuffer != 0)
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.deleteBuffers(1, &m_arrayBuffer);
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_arrayBuffer = 0;
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConditionalCase::deinit (void)
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_comparisonValueArray.clear();
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_arrayBuffer != 0)
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.deleteBuffers(1, &m_arrayBuffer);
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_arrayBuffer = 0;
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderPerformanceCase::deinit();
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LoopCase : public ControlStatementCase
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum LoopType
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOOP_FOR = 0,
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOOP_WHILE,
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOOP_DO_WHILE,
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LOOP_LAST
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					LoopCase			(Context& context, const char* name, const char* description, LoopType type, DecisionType decisionType, bool isLoopBoundStable, bool isVertex);
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~LoopCase			(void);
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			init				(void);
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			deinit				(void);
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			setupProgram		(deUint32 program);
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DecisionType	m_decisionType;
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LoopType		m_type;
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			m_isLoopBoundStable;	// Whether loop bound is same in all executions.
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>	m_boundArray;			// Will contain per-vertex loop bounds if using non-stable attribute in vertex case.
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32		m_arrayBuffer;
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4273c827367444ee418f129b2c238299f49d3264554Jarkko PoyryLoopCase::LoopCase (Context& context, const char* name, const char* description, LoopType type, DecisionType decisionType, bool isLoopBoundStable, bool isVertex)
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: ControlStatementCase	(context.getTestContext(), context.getRenderContext(), name, description, isVertex ? CASETYPE_VERTEX : CASETYPE_FRAGMENT)
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_decisionType		(decisionType)
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_type				(type)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_isLoopBoundStable	(isLoopBoundStable)
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_arrayBuffer			(0)
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid LoopCase::init (void)
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				isVertexCase	= m_caseType == CASETYPE_VERTEX;
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				isStaticCase	= m_decisionType == DECISION_STATIC;
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				isUniformCase	= m_decisionType == DECISION_UNIFORM;
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				isAttributeCase	= m_decisionType == DECISION_ATTRIBUTE;
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isStaticCase || isUniformCase || isAttributeCase);
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_type == LOOP_FOR		||
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  m_type == LOOP_WHILE		||
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  m_type == LOOP_DO_WHILE);
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isAttributeCase || m_isLoopBoundStable); // The loop bound count can vary between executions only if using attribute input.
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note The fractional part is .5 (instead of .0) so that these can be safely used as loop bounds.
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			loopBound				= 10.5f;
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			unstableBoundLow		= 5.5f;
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			unstableBoundHigh		= 15.5f;
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*	loopBoundStr			= "10.5";
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*	unstableBoundLowStr		= "5.5";
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*	unstableBoundHighStr	= "15.5";
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			boundValueStr		= isStaticCase			? loopBoundStr :
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  isUniformCase			? "u_bound" :
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  isVertexCase			? "a_bound" :
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  m_isLoopBoundStable	? "v_bound" :
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	  "loopBound";
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	vtx;
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	frag;
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream&	op		= isVertexCase ? vtx : frag;
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "attribute highp vec4 a_position;\n";	// Position attribute.
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "attribute mediump vec4 a_value;\n";		// Input for workload calculations.
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Value to be used as the loop iteration count.
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isAttributeCase)
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "attribute mediump float a_bound;\n";
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isUniformCase)
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "uniform mediump float u_bound;\n";
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Varyings.
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "varying mediump vec4 v_color;\n";
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "varying mediump vec4 v_color;\n";
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "varying mediump vec4 v_value;\n";
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "varying mediump vec4 v_value;\n";
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isAttributeCase)
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vtx << "varying mediump float v_bound;\n";
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			frag << "varying mediump float v_bound;\n";
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "\n";
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "void main()\n";
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "{\n";
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "	gl_Position = a_position;\n";
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\n";
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "void main()\n";
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "{\n";
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	mediump vec4 res = vec4(0.0);\n";
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_isLoopBoundStable && !isVertexCase)
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Choose the actual loop bound based on v_bound.
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Loop bound will vary with high frequency between fragment columns, given appropriate range for v_bound.
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "	mediump float loopBound = fract(v_bound) < 0.5 ? " << unstableBoundLowStr << " : " << unstableBoundHighStr << ";\n";
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Start a for, while or do-while loop.
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_type == LOOP_FOR)
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "	for (mediump float i = 0.0; i < " << boundValueStr << "; i++)\n";
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "	mediump float i = 0.0;\n";
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_type == LOOP_WHILE)
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op << "	while (i < " << boundValueStr << ")\n";
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else // LOOP_DO_WHILE
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op << "	do\n";
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "	{\n";
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Workload calculations inside the loop.
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\t\t";
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writeLoopWorkload(op, "res", isVertexCase ? "a_value" : "v_value");
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\n";
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Only "for" has counter increment in the loop head.
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_type != LOOP_FOR)
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "		i++;\n";
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// End the loop.
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_type == LOOP_DO_WHILE)
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "	} while (i < " << boundValueStr << ");\n";
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		op << "	}\n";
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Put result to color variable.
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_color = res;\n";
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	gl_FragColor = v_color;\n";
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Transfer inputs to fragment shader through varyings.
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isAttributeCase)
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vtx << "	v_bound = a_bound;\n";
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_value = a_value;\n";
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	gl_FragColor = res;\n"; // Put result to color variable.
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "}\n";
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "}\n";
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_vertShaderSource = vtx.str();
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fragShaderSource = frag.str();
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isAttributeCase)
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_isLoopBoundStable)
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Every execution has same number of iterations.
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_attributes.push_back(AttribSpec("a_bound",	Vec4(loopBound, 0.0f, 0.0f, 0.0f),
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															Vec4(loopBound, 0.0f, 0.0f, 0.0f),
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															Vec4(loopBound, 0.0f, 0.0f, 0.0f),
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															Vec4(loopBound, 0.0f, 0.0f, 0.0f)));
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (isVertexCase)
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Vertex case, with non-constant number of iterations.
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	numComponents	= 4;
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			numVertices		= (getGridWidth() + 1) * (getGridHeight() + 1);
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// setupProgram() will later bind this array as an attribute.
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_boundArray.resize(numVertices * numComponents);
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Vary between low and high loop bounds; they should average to loopBound however.
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int i = 0; i < (int)m_boundArray.size(); i++)
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (i % numComponents == 0)
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_boundArray[i] = (i / numComponents) % 2 == 0 ? unstableBoundLow : unstableBoundHigh;
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_boundArray[i] = 0.0f;
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else // !m_isLoopBoundStable && !isVertexCase
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Fragment case, with non-constant number of iterations.
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note fract(a_bound) < 0.5 will be true for every second fragment.
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float minValue = 0.0f;
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float maxValue = (float)getViewportWidth()*0.5f;
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_attributes.push_back(AttribSpec("a_bound",	Vec4(minValue, 0.0f, 0.0f, 0.0f),
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															Vec4(maxValue, 0.0f, 0.0f, 0.0f),
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															Vec4(minValue, 0.0f, 0.0f, 0.0f),
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															Vec4(maxValue, 0.0f, 0.0f, 0.0f)));
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_attributes.push_back(AttribSpec("a_value",	Vec4(0.0f, 0.1f, 0.2f, 0.3f),
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.4f, 0.5f, 0.6f, 0.7f),
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.8f, 0.9f, 1.0f, 1.1f),
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(1.2f, 1.3f, 1.4f, 1.5f)));
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ControlStatementCase::init();
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid LoopCase::setupProgram (deUint32 program)
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_decisionType == DECISION_UNIFORM)
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float loopBound = 10.5f;
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int location = gl.getUniformLocation(program, "u_bound");
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(location, loopBound);
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_decisionType == DECISION_ATTRIBUTE && !m_isLoopBoundStable && m_caseType == CASETYPE_VERTEX)
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Setup per-vertex loop bounds calculated in init().
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	numComponents		= 4;
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			boundAttribLocation	= gl.getAttribLocation(program, "a_bound");
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT((int)m_boundArray.size() == numComponents * (getGridWidth() + 1) * (getGridHeight() + 1));
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_arrayBuffer);
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(m_boundArray.size()*sizeof(float)), &m_boundArray[0], GL_STATIC_DRAW);
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.enableVertexAttribArray(boundAttribLocation);
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.vertexAttribPointer(boundAttribLocation, (GLint)numComponents, GL_FLOAT, GL_FALSE, 0, DE_NULL);
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Setup program state");
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryLoopCase::~LoopCase (void)
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_arrayBuffer)
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.deleteBuffers(1, &m_arrayBuffer);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_arrayBuffer = 0;
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid LoopCase::deinit (void)
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_boundArray.clear();
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_arrayBuffer)
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.deleteBuffers(1, &m_arrayBuffer);
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_arrayBuffer = 0;
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderPerformanceCase::deinit();
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// A reference case, same calculations as the actual tests but without control statements.
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass WorkloadReferenceCase : public ControlStatementCase
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							WorkloadReferenceCase		(Context& context, const char* name, const char* description, bool isVertex);
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init						(void);
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void			writeWorkload				(std::ostringstream& dst, const char* resultVariableName, const char* inputVariableName) const = 0;
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko PoyryWorkloadReferenceCase::WorkloadReferenceCase (Context& context, const char* name, const char* description, bool isVertex)
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: ControlStatementCase(context.getTestContext(), context.getRenderContext(), name, description, isVertex ? CASETYPE_VERTEX : CASETYPE_FRAGMENT)
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid WorkloadReferenceCase::init (void)
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool isVertexCase = m_caseType == CASETYPE_VERTEX;
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	vtx;
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	frag;
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream&	op			= isVertexCase ? vtx : frag;
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "attribute highp vec4 a_position;\n";	// Position attribute.
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "attribute mediump vec4 a_value;\n";		// Value for workload calculations.
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Varyings.
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "varying mediump vec4 v_color;\n";
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "varying mediump vec4 v_color;\n";
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "varying mediump vec4 v_value;\n";
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "varying mediump vec4 v_value;\n";
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "\n";
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "void main()\n";
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "{\n";
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "	gl_Position = a_position;\n";
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\n";
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "void main()\n";
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "{\n";
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	op << "\tmediump vec4 res;\n";
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writeWorkload(op, "res", isVertexCase ? "a_value" : "v_value");
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isVertexCase)
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Put result to color variable.
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_color = res;\n";
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	gl_FragColor = v_color;\n";
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vtx << "	v_value = a_value;\n";	// Transfer input to fragment shader through varying.
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		frag << "	gl_FragColor = res;\n";	// Put result to color variable.
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "}\n";
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "}\n";
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_vertShaderSource = vtx.str();
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fragShaderSource = frag.str();
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_attributes.push_back(AttribSpec("a_value",	Vec4(0.0f, 0.1f, 0.2f, 0.3f),
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.4f, 0.5f, 0.6f, 0.7f),
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(0.8f, 0.9f, 1.0f, 1.1f),
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vec4(1.2f, 1.3f, 1.4f, 1.5f)));
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ControlStatementCase::init();
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LoopWorkloadReferenceCase : public WorkloadReferenceCase
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LoopWorkloadReferenceCase (Context& context, const char* name, const char* description, bool isAttributeStable, bool isVertex)
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: WorkloadReferenceCase		(context, name, description, isVertex)
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_isAttributeStable		(isAttributeStable)
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void writeWorkload (std::ostringstream& dst, const char* resultVariableName, const char* inputVariableName) const;
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool m_isAttributeStable;
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid LoopWorkloadReferenceCase::writeWorkload (std::ostringstream& dst, const char* resultVariableName, const char* inputVariableName) const
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	loopIterations	= 11;
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		isVertexCase	= m_caseType == CASETYPE_VERTEX;
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst << "\t" << resultVariableName << " = vec4(0.0);\n";
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < loopIterations; i++)
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << "\t";
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeLoopWorkload(dst, resultVariableName, inputVariableName);
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << "\n";
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isVertexCase && !m_isAttributeStable)
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Corresponds to the fract() done in a real test's fragment case with non-stable attribute.
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << "	res.x = fract(res.x);\n";
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ConditionalWorkloadReferenceCase : public WorkloadReferenceCase
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ConditionalWorkloadReferenceCase (Context& context, const char* name, const char* description, bool isAttributeStable, bool isVertex)
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: WorkloadReferenceCase		(context, name, description, isVertex)
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_isAttributeStable		(isAttributeStable)
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void writeWorkload (std::ostringstream& dst, const char* resultVariableName, const char* inputVariableName) const;
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool m_isAttributeStable;
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConditionalWorkloadReferenceCase::writeWorkload (std::ostringstream& dst, const char* resultVariableName, const char* inputVariableName) const
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool isVertexCase = m_caseType == CASETYPE_VERTEX;
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst << "\t";
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writeConditionalWorkload(dst, resultVariableName, inputVariableName);
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst << "\n";
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isVertexCase && !m_isAttributeStable)
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Corresponds to the fract() done in a real test's fragment case with non-stable attribute.
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << "	res.x = fract(res.x);\n";
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// A workload reference case for e.g. a conditional case with a branch with no computation.
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass EmptyWorkloadReferenceCase : public WorkloadReferenceCase
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	EmptyWorkloadReferenceCase	(Context& context, const char* name, const char* description, bool isVertex)
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: WorkloadReferenceCase (context, name, description, isVertex)
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void writeWorkload (std::ostringstream& dst, const char* resultVariableName, const char* inputVariableName) const
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << "\t" << resultVariableName << " = " << inputVariableName << ";\n";
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderControlStatementTests::ShaderControlStatementTests (Context& context)
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "control_statement", "Control Statement Performance Tests")
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8403c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderControlStatementTests::~ShaderControlStatementTests (void)
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderControlStatementTests::init (void)
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Conditional cases (if-else).
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* ifElseGroup = new tcu::TestCaseGroup(m_testCtx, "if_else", "if-else Conditional Performance Tests");
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(ifElseGroup);
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int isFrag = 0; isFrag <= 1; isFrag++)
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool isVertex = isFrag == 0;
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderPerformanceCaseGroup* vertexOrFragmentGroup = new ShaderPerformanceCaseGroup(m_testCtx, isVertex ? "vertex" : "fragment", "");
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ifElseGroup->addChild(vertexOrFragmentGroup);
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_STATIC_ASSERT(DECISION_STATIC == 0);
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int decisionType = (int)DECISION_STATIC; decisionType < (int)DECISION_LAST; decisionType++)
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* decisionName = decisionType == (int)DECISION_STATIC		? "static" :
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										decisionType == (int)DECISION_UNIFORM	? "uniform" :
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										decisionType == (int)DECISION_ATTRIBUTE	? (isVertex ? "attribute" : "varying") :
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																					DE_NULL;
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(decisionName != DE_NULL);
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int workloadDivision = 0; workloadDivision < ConditionalCase::WORKLOAD_DIVISION_LAST; workloadDivision++)
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* workloadDivisionSuffix = workloadDivision == (int)ConditionalCase::WORKLOAD_DIVISION_EVEN			? "" :
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 workloadDivision == (int)ConditionalCase::WORKLOAD_DIVISION_TRUE_HEAVY		? "_with_heavier_true" :
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 workloadDivision == (int)ConditionalCase::WORKLOAD_DIVISION_FALSE_HEAVY	? "_with_heavier_false" :
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																																  DE_NULL;
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(workloadDivisionSuffix != DE_NULL);
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_STATIC_ASSERT(ConditionalCase::BRANCH_TRUE == 0);
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int branchResult = (int)ConditionalCase::BRANCH_TRUE; branchResult < (int)ConditionalCase::BRANCH_LAST; branchResult++)
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (decisionType != (int)DECISION_ATTRIBUTE && branchResult == (int)ConditionalCase::BRANCH_MIXED)
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						continue;
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const char* branchResultName = branchResult == (int)ConditionalCase::BRANCH_TRUE	? "true" :
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												   branchResult == (int)ConditionalCase::BRANCH_FALSE	? "false" :
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												   branchResult == (int)ConditionalCase::BRANCH_MIXED	? "mixed" :
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																										  DE_NULL;
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(branchResultName != DE_NULL);
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					string caseName = string("") + decisionName + "_" + branchResultName + workloadDivisionSuffix;
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vertexOrFragmentGroup->addChild(new ConditionalCase(m_context, caseName.c_str(), "",
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		(DecisionType)decisionType, (ConditionalCase::BranchResult)branchResult,
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		(ConditionalCase::WorkloadDivision)workloadDivision, isVertex));
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isVertex)
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vertexOrFragmentGroup->addChild(new ConditionalWorkloadReferenceCase(m_context, "reference", "", true, isVertex));
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Only fragment case with BRANCH_MIXED has an additional fract() call.
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vertexOrFragmentGroup->addChild(new ConditionalWorkloadReferenceCase(m_context, "reference_unmixed", "", true, isVertex));
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vertexOrFragmentGroup->addChild(new ConditionalWorkloadReferenceCase(m_context, "reference_mixed", "", false, isVertex));
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vertexOrFragmentGroup->addChild(new EmptyWorkloadReferenceCase(m_context, "reference_empty", "", isVertex));
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Loop cases.
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LoopCase::LoopType	type;
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*			name;
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*			description;
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} loopGroups[] =
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{LoopCase::LOOP_FOR,		"for",		"for Loop Performance Tests"},
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{LoopCase::LOOP_WHILE,		"while",	"while Loop Performance Tests"},
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{LoopCase::LOOP_DO_WHILE,	"do_while",	"do-while Loop Performance Tests"}
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(loopGroups); groupNdx++)
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* currentLoopGroup = new tcu::TestCaseGroup(m_testCtx, loopGroups[groupNdx].name, loopGroups[groupNdx].description);
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(currentLoopGroup);
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int isFrag = 0; isFrag <= 1; isFrag++)
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool isVertex = isFrag == 0;
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ShaderPerformanceCaseGroup* vertexOrFragmentGroup = new ShaderPerformanceCaseGroup(m_testCtx, isVertex ? "vertex" : "fragment", "");
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			currentLoopGroup->addChild(vertexOrFragmentGroup);
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_STATIC_ASSERT(DECISION_STATIC == 0);
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int decisionType = (int)DECISION_STATIC; decisionType < (int)DECISION_LAST; decisionType++)
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* decisionName = decisionType == (int)DECISION_STATIC		? "static" :
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   decisionType == (int)DECISION_UNIFORM	? "uniform" :
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   decisionType == (int)DECISION_ATTRIBUTE	? (isVertex ? "attribute" : "varying") :
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																					  DE_NULL;
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(decisionName != DE_NULL);
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (decisionType == (int)DECISION_ATTRIBUTE)
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vertexOrFragmentGroup->addChild(new LoopCase(m_context, (string(decisionName) + "_stable").c_str(), "", loopGroups[groupNdx].type, (DecisionType)decisionType, true, isVertex));
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vertexOrFragmentGroup->addChild(new LoopCase(m_context, (string(decisionName) + "_unstable").c_str(), "", loopGroups[groupNdx].type, (DecisionType)decisionType, false, isVertex));
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vertexOrFragmentGroup->addChild(new LoopCase(m_context, decisionName, "", loopGroups[groupNdx].type, (DecisionType)decisionType, true, isVertex));
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isVertex)
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexOrFragmentGroup->addChild(new LoopWorkloadReferenceCase(m_context, "reference", "", true, isVertex));
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Only fragment case with unstable attribute has an additional fract() call.
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexOrFragmentGroup->addChild(new LoopWorkloadReferenceCase(m_context, "reference_stable", "", true, isVertex));
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexOrFragmentGroup->addChild(new LoopWorkloadReferenceCase(m_context, "reference_unstable", "", false, isVertex));
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Performance
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles2
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
966