13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL (ES) 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 Compiler test case.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderLibraryCase.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuStringTemplate.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluStrUtil.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSharedPtr.hpp"
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace std;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace tcu;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glu;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gls
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace sl
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VIEWPORT_WIDTH		= 128,
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VIEWPORT_HEIGHT		= 128
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool usesShaderInoutQualifiers (glu::GLSLVersion version)
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (version)
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::GLSL_VERSION_100_ES:
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::GLSL_VERSION_130:
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::GLSL_VERSION_140:
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::GLSL_VERSION_150:
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool supportsFragmentHighp (glu::GLSLVersion version)
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return version != glu::GLSL_VERSION_100_ES;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::ValueBlock::ValueBlock (void)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: arrayLength(0)
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::CaseRequirement::CaseRequirement (void)
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_type						(REQUIREMENTTYPE_LAST)
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_supportedExtensionNdx		(-1)
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_effectiveShaderStageFlags	(-1)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_enumName					(-1)
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_referenceValue				(-1)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::CaseRequirement ShaderCase::CaseRequirement::createAnyExtensionRequirement (const std::vector<std::string>& requirements, deUint32 effectiveShaderStageFlags)
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CaseRequirement retVal;
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.m_type = REQUIREMENTTYPE_EXTENSION;
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.m_extensions = requirements;
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.m_effectiveShaderStageFlags = effectiveShaderStageFlags;
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::CaseRequirement ShaderCase::CaseRequirement::createLimitRequirement (deUint32 enumName, int ref)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CaseRequirement retVal;
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.m_type = REQUIREMENTTYPE_IMPLEMENTATION_LIMIT;
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.m_enumName = enumName;
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.m_referenceValue = ref;
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::CaseRequirement::checkRequirements (glu::RenderContext& renderCtx, const glu::ContextInfo& contextInfo)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(renderCtx);
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_type)
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case REQUIREMENTTYPE_EXTENSION:
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < (int)m_extensions.size(); ++ndx)
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (contextInfo.isExtensionSupported(m_extensions[ndx].c_str()))
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_supportedExtensionNdx = ndx;
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// no extension(s). Make a nice output
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::ostringstream extensionList;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int ndx = 0; ndx < (int)m_extensions.size(); ++ndx)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!extensionList.str().empty())
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						extensionList << ", ";
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					extensionList << m_extensions[ndx];
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_extensions.size() == 1)
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw tcu::NotSupportedError("Test requires extension " + extensionList.str());
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw tcu::NotSupportedError("Test requires any extension of " + extensionList.str());
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// cannot be reached
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case REQUIREMENTTYPE_IMPLEMENTATION_LIMIT:
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::Functions&	gl		= renderCtx.getFunctions();
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glw::GLint				value	= 0;
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glw::GLenum				error;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getIntegerv(m_enumName, &value);
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			error = gl.getError();
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (error != GL_NO_ERROR)
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("Query for " + de::toString(glu::getGettableStateStr(m_enumName)) +  " generated " + de::toString(glu::getErrorStr(error)));
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!(value > m_referenceValue))
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::NotSupportedError("Test requires " + de::toString(glu::getGettableStateStr(m_enumName)) + " (" + de::toString(value) + ") > " + de::toString(m_referenceValue));
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::ShaderCaseSpecification::ShaderCaseSpecification (void)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: expectResult	(EXPECT_LAST)
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, targetVersion	(glu::GLSL_VERSION_LAST)
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, caseType		(CASETYPE_COMPLETE)
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::ShaderCaseSpecification ShaderCase::ShaderCaseSpecification::generateSharedSourceVertexCase (ExpectResult expectResult_, glu::GLSLVersion targetVersion_, const std::vector<ValueBlock>& values, const std::string& sharedSource)
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderCaseSpecification retVal;
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.expectResult		= expectResult_;
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.targetVersion	= targetVersion_;
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.caseType			= CASETYPE_VERTEX_ONLY;
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.valueBlocks		= values;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.vertexSources.push_back(sharedSource);
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::ShaderCaseSpecification ShaderCase::ShaderCaseSpecification::generateSharedSourceFragmentCase (ExpectResult expectResult_, glu::GLSLVersion targetVersion_, const std::vector<ValueBlock>& values, const std::string& sharedSource)
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderCaseSpecification retVal;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.expectResult		= expectResult_;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.targetVersion	= targetVersion_;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.caseType			= CASETYPE_FRAGMENT_ONLY;
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.valueBlocks		= values;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.fragmentSources.push_back(sharedSource);
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BeforeDrawValidator : public glu::DrawUtilCallback
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum TargetType
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TARGETTYPE_PROGRAM = 0,
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TARGETTYPE_PIPELINE,
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TARGETTYPE_LAST
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							BeforeDrawValidator	(const glw::Functions& gl, glw::GLuint target, TargetType targetType);
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					beforeDrawCall		(void);
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string&		getInfoLog			(void) const;
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLint				getValidateStatus	(void) const;
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	m_gl;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::GLuint		m_target;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TargetType		m_targetType;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLint				m_validateStatus;
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				m_logMessage;
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2403c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBeforeDrawValidator::BeforeDrawValidator (const glw::Functions& gl, glw::GLuint target, TargetType targetType)
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_gl				(gl)
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_target			(target)
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_targetType		(targetType)
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_validateStatus	(-1)
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(targetType < TARGETTYPE_LAST);
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BeforeDrawValidator::beforeDrawCall (void)
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLint					bytesWritten	= 0;
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLint					infoLogLength;
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<glw::GLchar>	logBuffer;
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							stringLength;
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// validate
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_targetType == TARGETTYPE_PROGRAM)
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.validateProgram(m_target);
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_targetType == TARGETTYPE_PIPELINE)
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.validateProgramPipeline(m_target);
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(m_gl.getError(), "validate");
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// check status
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_validateStatus = -1;
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_targetType == TARGETTYPE_PROGRAM)
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.getProgramiv(m_target, GL_VALIDATE_STATUS, &m_validateStatus);
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_targetType == TARGETTYPE_PIPELINE)
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.getProgramPipelineiv(m_target, GL_VALIDATE_STATUS, &m_validateStatus);
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(m_gl.getError(), "get validate status");
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(m_validateStatus == GL_TRUE || m_validateStatus == GL_FALSE);
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// read log
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	infoLogLength = 0;
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_targetType == TARGETTYPE_PROGRAM)
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.getProgramiv(m_target, GL_INFO_LOG_LENGTH, &infoLogLength);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_targetType == TARGETTYPE_PIPELINE)
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.getProgramPipelineiv(m_target, GL_INFO_LOG_LENGTH, &infoLogLength);
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(m_gl.getError(), "get info log length");
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (infoLogLength <= 0)
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_logMessage.clear();
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	logBuffer.resize(infoLogLength + 2, '0'); // +1 for zero terminator (infoLogLength should include it, but better play it safe), +1 to make sure buffer is always larger
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_targetType == TARGETTYPE_PROGRAM)
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.getProgramInfoLog(m_target, infoLogLength + 1, &bytesWritten, &logBuffer[0]);
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_targetType == TARGETTYPE_PIPELINE)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.getProgramPipelineInfoLog(m_target, infoLogLength + 1, &bytesWritten, &logBuffer[0]);
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// just ignore bytesWritten to be safe, find the null terminator
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stringLength = (int)(std::find(logBuffer.begin(), logBuffer.end(), '0') - logBuffer.begin());
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_logMessage.assign(&logBuffer[0], stringLength);
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst std::string& BeforeDrawValidator::getInfoLog (void) const
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_logMessage;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglw::GLint BeforeDrawValidator::getValidateStatus (void) const
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_validateStatus;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ShaderCase.
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::ShaderCase (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* name, const char* description, const ShaderCaseSpecification& specification)
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: tcu::TestCase				(testCtx, name, description)
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderCtx				(renderCtx)
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_contextInfo				(contextInfo)
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_caseType				(specification.caseType)
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_expectResult			(specification.expectResult)
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_targetVersion			(specification.targetVersion)
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_separatePrograms		(false)
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_valueBlocks				(specification.valueBlocks)
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_caseType == CASETYPE_VERTEX_ONLY)
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// case generated from "both" target, vertex case
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.vertexSources.size() == 1);
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.fragmentSources.empty());
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.tessCtrlSources.empty());
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.tessEvalSources.empty());
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.geometrySources.empty());
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_caseType == CASETYPE_FRAGMENT_ONLY)
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// case generated from "both" target, fragment case
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.vertexSources.empty());
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.fragmentSources.size() == 1);
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.tessCtrlSources.empty());
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.tessEvalSources.empty());
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(specification.geometrySources.empty());
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// single program object
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramObject program;
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.spec.requirements		= specification.requirements;
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.spec.vertexSources		= specification.vertexSources;
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.spec.fragmentSources	= specification.fragmentSources;
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.spec.tessCtrlSources	= specification.tessCtrlSources;
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.spec.tessEvalSources	= specification.tessEvalSources;
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.spec.geometrySources	= specification.geometrySources;
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_programs.push_back(program);
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::ShaderCase (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* name, const char* description, const PipelineCaseSpecification& specification)
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: tcu::TestCase				(testCtx, name, description)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderCtx				(renderCtx)
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_contextInfo				(contextInfo)
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_caseType				(specification.caseType)
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_expectResult			(specification.expectResult)
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_targetVersion			(specification.targetVersion)
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_separatePrograms		(true)
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_valueBlocks				(specification.valueBlocks)
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 totalActiveMask = 0;
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_caseType == CASETYPE_COMPLETE);
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// validate
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int pipelineProgramNdx = 0; pipelineProgramNdx < (int)specification.programs.size(); ++pipelineProgramNdx)
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// program with an active stage must contain executable code for that stage
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(((specification.programs[pipelineProgramNdx].activeStageBits & (1 << glu::SHADERTYPE_VERTEX))						== 0) || !specification.programs[pipelineProgramNdx].vertexSources.empty());
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(((specification.programs[pipelineProgramNdx].activeStageBits & (1 << glu::SHADERTYPE_FRAGMENT))					== 0) || !specification.programs[pipelineProgramNdx].fragmentSources.empty());
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(((specification.programs[pipelineProgramNdx].activeStageBits & (1 << glu::SHADERTYPE_TESSELLATION_CONTROL))		== 0) || !specification.programs[pipelineProgramNdx].tessCtrlSources.empty());
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(((specification.programs[pipelineProgramNdx].activeStageBits & (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION))	== 0) || !specification.programs[pipelineProgramNdx].tessEvalSources.empty());
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(((specification.programs[pipelineProgramNdx].activeStageBits & (1 << glu::SHADERTYPE_GEOMETRY))					== 0) || !specification.programs[pipelineProgramNdx].geometrySources.empty());
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// no two programs with with the same stage active
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT((totalActiveMask & specification.programs[pipelineProgramNdx].activeStageBits) == 0);
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalActiveMask |= specification.programs[pipelineProgramNdx].activeStageBits;
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// create ProgramObjects
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int pipelineProgramNdx = 0; pipelineProgramNdx < (int)specification.programs.size(); ++pipelineProgramNdx)
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ProgramObject program;
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		program.spec = specification.programs[pipelineProgramNdx];
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_programs.push_back(program);
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4073c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCase::~ShaderCase (void)
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::init (void)
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// If no value blocks given, use an empty one.
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_valueBlocks.empty())
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_valueBlocks.push_back(ValueBlock());
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Use first value block to specialize shaders.
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ValueBlock& valueBlock = m_valueBlocks[0];
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2010-04-01 petri] Check that all value blocks have matching values.
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// prepare programs
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int programNdx = 0; programNdx < (int)m_programs.size(); ++programNdx)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Check requirements
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)m_programs[programNdx].spec.requirements.size(); ++ndx)
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_programs[programNdx].spec.requirements[ndx].checkRequirements(m_renderCtx, m_contextInfo);
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Generate specialized shader sources.
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_caseType == CASETYPE_COMPLETE)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// all shaders specified separately
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			specializeVertexShaders		(m_programs[programNdx].programSources,	m_programs[programNdx].spec.vertexSources,		valueBlock,	m_programs[programNdx].spec.requirements);
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			specializeFragmentShaders	(m_programs[programNdx].programSources,	m_programs[programNdx].spec.fragmentSources,	valueBlock,	m_programs[programNdx].spec.requirements);
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			specializeGeometryShaders	(m_programs[programNdx].programSources,	m_programs[programNdx].spec.geometrySources,	valueBlock,	m_programs[programNdx].spec.requirements);
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			specializeTessControlShaders(m_programs[programNdx].programSources,	m_programs[programNdx].spec.tessCtrlSources,	valueBlock,	m_programs[programNdx].spec.requirements);
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			specializeTessEvalShaders	(m_programs[programNdx].programSources,	m_programs[programNdx].spec.tessEvalSources,	valueBlock,	m_programs[programNdx].spec.requirements);
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_caseType == CASETYPE_VERTEX_ONLY)
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(m_programs.size() == 1);
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!m_separatePrograms);
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// case generated from "both" target, vertex case
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_programs[0].programSources << glu::VertexSource(specializeVertexShader(m_programs[0].spec.vertexSources[0].c_str(), valueBlock));
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_programs[0].programSources << glu::FragmentSource(genFragmentShader(valueBlock));
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_caseType == CASETYPE_FRAGMENT_ONLY)
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(m_programs.size() == 1);
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!m_separatePrograms);
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// case generated from "both" target, fragment case
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_programs[0].programSources << glu::VertexSource(genVertexShader(valueBlock));
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_programs[0].programSources << glu::FragmentSource(specializeFragmentShader(m_programs[0].spec.fragmentSources[0].c_str(), valueBlock));
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_programs[programNdx].programSources << glu::ProgramSeparable(m_separatePrograms);
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// log the expected result
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_expectResult)
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_PASS:
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Don't write anything
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_COMPILE_FAIL:
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Expecting shader compilation to fail." << tcu::TestLog::EndMessage;
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_LINK_FAIL:
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Expecting program linking to fail." << tcu::TestLog::EndMessage;
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_COMPILE_LINK_FAIL:
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Expecting either shader compilation or program linking to fail." << tcu::TestLog::EndMessage;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_VALIDATION_FAIL:
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Expecting program validation to fail." << tcu::TestLog::EndMessage;
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void setUniformValue (const glw::Functions& gl, const std::vector<deUint32>& pipelinePrograms, const std::string& name, const ShaderCase::Value& val, int arrayNdx, tcu::TestLog& log)
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool foundAnyMatch = false;
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int programNdx = 0; programNdx < (int)pipelinePrograms.size(); ++programNdx)
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int scalarSize	= getDataTypeScalarSize(val.dataType);
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int loc			= gl.getUniformLocation(pipelinePrograms[programNdx], name.c_str());
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int elemNdx		= (val.arrayLength == 1) ? (0) : (arrayNdx * scalarSize);
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (loc == -1)
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		foundAnyMatch = true;
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_STATIC_ASSERT(sizeof(ShaderCase::Value::Element) == sizeof(glw::GLfloat));
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_STATIC_ASSERT(sizeof(ShaderCase::Value::Element) == sizeof(glw::GLint));
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram(pipelinePrograms[programNdx]);
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (val.dataType)
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT:		gl.uniform1fv(loc, 1, &val.elements[elemNdx].float32);						break;
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_VEC2:	gl.uniform2fv(loc, 1, &val.elements[elemNdx].float32);						break;
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_VEC3:	gl.uniform3fv(loc, 1, &val.elements[elemNdx].float32);						break;
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_VEC4:	gl.uniform4fv(loc, 1, &val.elements[elemNdx].float32);						break;
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT2:	gl.uniformMatrix2fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);		break;
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT3:	gl.uniformMatrix3fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);		break;
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT4:	gl.uniformMatrix4fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);		break;
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_INT:			gl.uniform1iv(loc, 1, &val.elements[elemNdx].int32);						break;
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_INT_VEC2:		gl.uniform2iv(loc, 1, &val.elements[elemNdx].int32);						break;
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_INT_VEC3:		gl.uniform3iv(loc, 1, &val.elements[elemNdx].int32);						break;
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_INT_VEC4:		gl.uniform4iv(loc, 1, &val.elements[elemNdx].int32);						break;
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_BOOL:			gl.uniform1iv(loc, 1, &val.elements[elemNdx].int32);						break;
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_BOOL_VEC2:	gl.uniform2iv(loc, 1, &val.elements[elemNdx].int32);						break;
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_BOOL_VEC3:	gl.uniform3iv(loc, 1, &val.elements[elemNdx].int32);						break;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_BOOL_VEC4:	gl.uniform4iv(loc, 1, &val.elements[elemNdx].int32);						break;
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_UINT:			gl.uniform1uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32);		break;
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_UINT_VEC2:	gl.uniform2uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32);		break;
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_UINT_VEC3:	gl.uniform3uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32);		break;
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_UINT_VEC4:	gl.uniform4uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32);		break;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT2X3:	gl.uniformMatrix2x3fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);	break;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT2X4:	gl.uniformMatrix2x4fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);	break;
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT3X2:	gl.uniformMatrix3x2fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);	break;
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT3X4:	gl.uniformMatrix3x4fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);	break;
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT4X2:	gl.uniformMatrix4x2fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);	break;
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_FLOAT_MAT4X3:	gl.uniformMatrix4x3fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32);	break;
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_SAMPLER_2D:
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case TYPE_SAMPLER_CUBE:
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!"implement!");
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!foundAnyMatch)
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << tcu::TestLog::Message << "WARNING // Uniform \"" << name << "\" location is not valid, location = -1. Cannot set value to the uniform." << tcu::TestLog::EndMessage;
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ShaderCase::isTessellationPresent (void) const
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_separatePrograms)
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32 tessellationBits =	(1 << glu::SHADERTYPE_TESSELLATION_CONTROL)		|
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											(1 << glu::SHADERTYPE_TESSELLATION_EVALUATION);
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int programNdx = 0; programNdx < (int)m_programs.size(); ++programNdx)
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_programs[programNdx].spec.activeStageBits & tessellationBits)
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return	!m_programs[0].programSources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].empty() ||
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				!m_programs[0].programSources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].empty();
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ShaderCase::checkPixels (Surface& surface, int minX, int maxX, int minY, int maxY)
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&	log				= m_testCtx.getLog();
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		allWhite		= true;
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		allBlack		= true;
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		anyUnexpected	= false;
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((maxX > minX) && (maxY > minY));
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = minY; y <= maxY; y++)
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = minX; x <= maxX; x++)
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			RGBA		pixel		 = surface.getPixel(x, y);
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Note: we really do not want to involve alpha in the check comparison
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \todo [2010-09-22 kalle] Do we know that alpha would be one? If yes, could use color constants white and black.
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool		isWhite		 = (pixel.getRed() == 255) && (pixel.getGreen() == 255) && (pixel.getBlue() == 255);
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool		isBlack		 = (pixel.getRed() == 0) && (pixel.getGreen() == 0) && (pixel.getBlue() == 0);
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			allWhite		= allWhite && isWhite;
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			allBlack		= allBlack && isBlack;
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			anyUnexpected	= anyUnexpected || (!isWhite && !isBlack);
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!allWhite)
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (anyUnexpected)
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "WARNING: expecting all rendered pixels to be white or black, but got other colors as well!" << TestLog::EndMessage;
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (!allBlack)
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "WARNING: got inconsistent results over the image, when all pixels should be the same color!" << TestLog::EndMessage;
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ShaderCase::execute (void)
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float										quadSize			= 1.0f;
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float								s_positions[4*4]	=
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-quadSize, -quadSize, 0.0f, 1.0f,
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-quadSize, +quadSize, 0.0f, 1.0f,
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+quadSize, -quadSize, 0.0f, 1.0f,
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+quadSize, +quadSize, 0.0f, 1.0f
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint16							s_indices[2*3]		=
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0, 1, 2,
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		1, 3, 2
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&										log					= m_testCtx.getLog();
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&							gl					= m_renderCtx.getFunctions();
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute viewport.
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RenderTarget&						renderTarget		= m_renderCtx.getRenderTarget();
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random										rnd					(deStringHash(getName()));
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int										width				= deMin32(renderTarget.getWidth(),	VIEWPORT_WIDTH);
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int										height				= deMin32(renderTarget.getHeight(),	VIEWPORT_HEIGHT);
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int										viewportX			= rnd.getInt(0, renderTarget.getWidth()  - width);
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int										viewportY			= rnd.getInt(0, renderTarget.getHeight() - height);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int										numVerticesPerDraw	= 4;
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool										tessellationPresent	= isTessellationPresent();
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool											allCompilesOk		= true;
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool											allLinksOk			= true;
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*										failReason			= DE_NULL;
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32										vertexProgramID		= -1;
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32>							pipelineProgramIDs;
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<de::SharedPtr<glu::ShaderProgram> >	programs;
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<glu::ProgramPipeline>				programPipeline;
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderCase::execute(): start");
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_separatePrograms)
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::SharedPtr<glu::ShaderProgram>	program		(new glu::ShaderProgram(m_renderCtx, m_programs[0].programSources));
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vertexProgramID = program->getProgram();
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pipelineProgramIDs.push_back(program->getProgram());
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		programs.push_back(program);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Check that compile/link results are what we expect.
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_STATIC_ASSERT(glu::SHADERTYPE_VERTEX == 0);
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage)
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (program->hasShader((glu::ShaderType)stage) && !program->getShaderInfo((glu::ShaderType)stage).compileOk)
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				allCompilesOk = false;
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!program->getProgramInfo().linkOk)
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			allLinksOk = false;
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << *program;
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Separate programs
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int programNdx = 0; programNdx < (int)m_programs.size(); ++programNdx)
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			de::SharedPtr<glu::ShaderProgram> program(new glu::ShaderProgram(m_renderCtx, m_programs[programNdx].programSources));
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_programs[programNdx].spec.activeStageBits & (1 << glu::SHADERTYPE_VERTEX))
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vertexProgramID = program->getProgram();
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			pipelineProgramIDs.push_back(program->getProgram());
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			programs.push_back(program);
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Check that compile/link results are what we expect.
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_STATIC_ASSERT(glu::SHADERTYPE_VERTEX == 0);
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage)
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (program->hasShader((glu::ShaderType)stage) && !program->getShaderInfo((glu::ShaderType)stage).compileOk)
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					allCompilesOk = false;
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!program->getProgramInfo().linkOk)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				allLinksOk = false;
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Log program and active stages
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection	section		(log, "Program", "Program " + de::toString(programNdx+1));
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::MessageBuilder			builder		(&log);
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool						firstStage	= true;
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "Pipeline uses stages: ";
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage)
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_programs[programNdx].spec.activeStageBits & (1 << stage))
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (!firstStage)
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							builder << ", ";
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						builder << glu::getShaderTypeName((glu::ShaderType)stage);
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						firstStage = true;
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << tcu::TestLog::EndMessage;
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << *program;
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_expectResult)
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_PASS:
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_VALIDATION_FAIL:
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!allCompilesOk)
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				failReason = "expected shaders to compile and link properly, but failed to compile.";
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (!allLinksOk)
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				failReason = "expected shaders to compile and link properly, but failed to link.";
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_COMPILE_FAIL:
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (allCompilesOk && !allLinksOk)
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				failReason = "expected compilation to fail, but shaders compiled and link failed.";
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (allCompilesOk)
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				failReason = "expected compilation to fail, but shaders compiled correctly.";
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_LINK_FAIL:
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!allCompilesOk)
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				failReason = "expected linking to fail, but unable to compile.";
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (allLinksOk)
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				failReason = "expected linking to fail, but passed.";
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case EXPECT_COMPILE_LINK_FAIL:
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (allCompilesOk && allLinksOk)
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				failReason = "expected compile or link to fail, but passed.";
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (failReason != DE_NULL)
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2010-06-07 petri] These should be handled in the test case?
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage;
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If implementation parses shader at link time, report it as quality warning.
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_expectResult == EXPECT_COMPILE_FAIL && allCompilesOk && !allLinksOk)
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, failReason);
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, failReason);
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Return if compile/link expected to fail.
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_expectResult == EXPECT_COMPILE_FAIL		||
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_expectResult == EXPECT_COMPILE_LINK_FAIL	||
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_expectResult == EXPECT_LINK_FAIL)
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (failReason == DE_NULL);
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Setup viewport.
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(viewportX, viewportY, width, height);
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_separatePrograms)
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		programPipeline = de::SharedPtr<glu::ProgramPipeline>(new glu::ProgramPipeline(m_renderCtx));
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Setup pipeline
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindProgramPipeline(programPipeline->getPipeline());
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int programNdx = 0; programNdx < (int)m_programs.size(); ++programNdx)
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32 shaderFlags = 0;
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage)
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_programs[programNdx].spec.activeStageBits & (1 << stage))
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					shaderFlags |= glu::getGLShaderTypeBit((glu::ShaderType)stage);
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			programPipeline->useProgramStages(shaderFlags, pipelineProgramIDs[programNdx]);
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		programPipeline->activeShaderProgram(vertexProgramID);
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "setup pipeline");
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Start using program
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram(vertexProgramID);
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram()");
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Fetch location for positions positions.
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int positionLoc = gl.getAttribLocation(vertexProgramID, "dEQP_Position");
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (positionLoc == -1)
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string errStr = string("no location found for attribute 'dEQP_Position'");
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL(errStr.c_str());
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Iterate all value blocks.
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < (int)m_valueBlocks.size(); blockNdx++)
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ValueBlock&	valueBlock		= m_valueBlocks[blockNdx];
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// always render at least one pass even if there is no input/output data
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numRenderPasses	= (valueBlock.arrayLength == 0) ? (1) : (valueBlock.arrayLength);
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Iterate all array sub-cases.
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int arrayNdx = 0; arrayNdx < numRenderPasses; arrayNdx++)
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int							numValues			= (int)valueBlock.values.size();
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<VertexArrayBinding>	vertexArrays;
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int							attribValueNdx		= 0;
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<vector<float> >		attribValues		(numValues);
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glw::GLenum					postDrawError;
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BeforeDrawValidator			beforeDrawValidator	(gl,
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 (m_separatePrograms) ? (programPipeline->getPipeline())			: (vertexProgramID),
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 (m_separatePrograms) ? (BeforeDrawValidator::TARGETTYPE_PIPELINE)	: (BeforeDrawValidator::TARGETTYPE_PROGRAM));
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vertexArrays.push_back(va::Float(positionLoc, 4, numVerticesPerDraw, 0, &s_positions[0]));
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Collect VA pointer for inputs
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int valNdx = 0; valNdx < numValues; valNdx++)
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const ShaderCase::Value&	val			= valueBlock.values[valNdx];
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const			valueName	= val.valueName.c_str();
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const DataType				dataType	= val.dataType;
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int					scalarSize	= getDataTypeScalarSize(val.dataType);
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (val.storageType == ShaderCase::Value::STORAGE_INPUT)
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Replicate values four times.
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					std::vector<float>& scalars = attribValues[attribValueNdx++];
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					scalars.resize(numVerticesPerDraw * scalarSize);
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (isDataTypeFloatOrVec(dataType) || isDataTypeMatrix(dataType))
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int repNdx = 0; repNdx < numVerticesPerDraw; repNdx++)
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							for (int ndx = 0; ndx < scalarSize; ndx++)
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								scalars[repNdx*scalarSize + ndx] = val.elements[arrayNdx*scalarSize + ndx].float32;
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// convert to floats.
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int repNdx = 0; repNdx < numVerticesPerDraw; repNdx++)
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							for (int ndx = 0; ndx < scalarSize; ndx++)
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								float v = (float)val.elements[arrayNdx*scalarSize + ndx].int32;
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								DE_ASSERT(val.elements[arrayNdx*scalarSize + ndx].int32 == (int)v);
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								scalars[repNdx*scalarSize + ndx] = v;
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Attribute name prefix.
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					string attribPrefix = "";
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// \todo [2010-05-27 petri] Should latter condition only apply for vertex cases (or actually non-fragment cases)?
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if ((m_caseType == CASETYPE_FRAGMENT_ONLY) || (getDataTypeScalarType(dataType) != TYPE_FLOAT))
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						attribPrefix = "a_";
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Input always given as attribute.
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					string attribName = attribPrefix + valueName;
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int attribLoc = gl.getAttribLocation(vertexProgramID, attribName.c_str());
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (attribLoc == -1)
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						log << TestLog::Message << "Warning: no location found for attribute '" << attribName << "'" << TestLog::EndMessage;
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						continue;
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (isDataTypeMatrix(dataType))
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						int numCols = getDataTypeMatrixNumColumns(dataType);
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						int numRows = getDataTypeMatrixNumRows(dataType);
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(scalarSize == numCols*numRows);
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int i = 0; i < numCols; i++)
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							vertexArrays.push_back(va::Float(attribLoc + i, numRows, numVerticesPerDraw, scalarSize*sizeof(float), &scalars[i * numRows]));
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(isDataTypeFloatOrVec(dataType) || isDataTypeIntOrIVec(dataType) || isDataTypeUintOrUVec(dataType) || isDataTypeBoolOrBVec(dataType));
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						vertexArrays.push_back(va::Float(attribLoc, scalarSize, numVerticesPerDraw, 0, &scalars[0]));
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GLU_EXPECT_NO_ERROR(gl.getError(), "set vertex attrib array");
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "before set uniforms");
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// set uniform values for outputs (refs).
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int valNdx = 0; valNdx < numValues; valNdx++)
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const ShaderCase::Value&	val			= valueBlock.values[valNdx];
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const			valueName	= val.valueName.c_str();
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (val.storageType == ShaderCase::Value::STORAGE_OUTPUT)
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Set reference value.
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					string refName = string("ref_") + valueName;
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					setUniformValue(gl, pipelineProgramIDs, refName, val, arrayNdx, m_testCtx.getLog());
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GLU_EXPECT_NO_ERROR(gl.getError(), "set reference uniforms");
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (val.storageType == ShaderCase::Value::STORAGE_UNIFORM)
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					setUniformValue(gl, pipelineProgramIDs, valueName, val, arrayNdx, m_testCtx.getLog());
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GLU_EXPECT_NO_ERROR(gl.getError(), "set uniforms");
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Clear.
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.clear(GL_COLOR_BUFFER_BIT);
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "clear buffer");
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Use program or pipeline
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_separatePrograms)
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.useProgram(0);
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.useProgram(vertexProgramID);
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Draw.
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (tessellationPresent)
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.patchParameteri(GL_PATCH_VERTICES, 3);
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "set patchParameteri(PATCH_VERTICES, 3)");
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			draw(m_renderCtx,
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 vertexProgramID,
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 (int)vertexArrays.size(),
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 &vertexArrays[0],
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 (tessellationPresent) ?
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					(pr::Patches(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0])) :
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					(pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0])),
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 (m_expectResult == EXPECT_VALIDATION_FAIL) ?
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					(&beforeDrawValidator) :
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					(DE_NULL));
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			postDrawError = gl.getError();
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_expectResult == EXPECT_PASS)
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Read back results.
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Surface			surface			(width, height);
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		w				= s_positions[3];
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minY			= deCeilFloatToInt32 (((-quadSize / w) * 0.5f + 0.5f) * height + 1.0f);
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxY			= deFloorFloatToInt32(((+quadSize / w) * 0.5f + 0.5f) * height - 0.5f);
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minX			= deCeilFloatToInt32 (((-quadSize / w) * 0.5f + 0.5f) * width + 1.0f);
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxX			= deFloorFloatToInt32(((+quadSize / w) * 0.5f + 0.5f) * width - 0.5f);
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(postDrawError, "draw");
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::readPixels(m_renderCtx, viewportX, viewportY, surface.getAccess());
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels");
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!checkPixels(surface, minX, maxX, minY, maxY))
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "INCORRECT RESULT for (value block " << (blockNdx+1) << " of " <<  (int)m_valueBlocks.size()
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< ", sub-case " << arrayNdx+1 << " of " << valueBlock.arrayLength << "):"
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< TestLog::EndMessage;
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Failing shader input/output values:" << TestLog::EndMessage;
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					dumpValues(valueBlock, arrayNdx);
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Dump image on failure.
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Image("Result", "Rendered result image", surface);
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.useProgram(0);
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_expectResult == EXPECT_VALIDATION_FAIL)
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log	<< TestLog::Message
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Draw call generated error: "
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::getErrorStr(postDrawError) << " "
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< ((postDrawError == GL_INVALID_OPERATION) ? ("(expected)") : ("(unexpected)")) << "\n"
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Validate status: "
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::getBooleanStr(beforeDrawValidator.getValidateStatus()) << " "
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< ((beforeDrawValidator.getValidateStatus() == GL_FALSE) ? ("(expected)") : ("(unexpected)")) << "\n"
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Info log: "
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< ((beforeDrawValidator.getInfoLog().empty()) ? ("[empty string]") : (beforeDrawValidator.getInfoLog())) << "\n"
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::EndMessage;
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// test result
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (postDrawError != GL_NO_ERROR && postDrawError != GL_INVALID_OPERATION)
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, ("Draw: got unexpected error: " + de::toString(glu::getErrorStr(postDrawError))).c_str());
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (beforeDrawValidator.getValidateStatus() == GL_TRUE)
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (postDrawError == GL_NO_ERROR)
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "expected validation and rendering to fail but validation and rendering succeeded");
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (postDrawError == GL_INVALID_OPERATION)
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "expected validation and rendering to fail but validation succeeded (rendering failed as expected)");
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(false);
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (beforeDrawValidator.getValidateStatus() == GL_FALSE && postDrawError == GL_NO_ERROR)
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "expected validation and rendering to fail but rendering succeeded (validation failed as expected)");
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (beforeDrawValidator.getValidateStatus() == GL_FALSE && postDrawError == GL_INVALID_OPERATION)
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Validation does not depend on input values, no need to test all values
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return true;
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(false);
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(0);
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_separatePrograms)
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindProgramPipeline(0);
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderCase::execute(): end");
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCase::IterateResult ShaderCase::iterate (void)
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize state to pass.
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool executeOk = execute();
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(executeOk ? m_testCtx.getTestResult() == QP_TEST_RESULT_PASS : m_testCtx.getTestResult() != QP_TEST_RESULT_PASS);
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(executeOk);
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return TestCase::STOP;
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void generateExtensionStatements (std::ostringstream& buf, const std::vector<ShaderCase::CaseRequirement>& requirements, glu::ShaderType type)
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)requirements.size(); ++ndx)
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (requirements[ndx].getType() == ShaderCase::CaseRequirement::REQUIREMENTTYPE_EXTENSION &&
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(requirements[ndx].getAffectedExtensionStageFlags() & (1 << (deUint32)type)) != 0)
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "#extension " << requirements[ndx].getSupportedExtension() << " : require\n";
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Injects #extension XXX : require lines after the last preprocessor directive in the shader code. Does not support line continuations
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string injectExtensionRequirements (const std::string& baseCode, glu::ShaderType shaderType, const std::vector<ShaderCase::CaseRequirement>& requirements)
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::istringstream	baseCodeBuf(baseCode);
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	resultBuf;
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			line;
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				firstNonPreprocessorLine = true;
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	extensions;
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateExtensionStatements(extensions, requirements, shaderType);
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// skip if no requirements
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (extensions.str().empty())
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return baseCode;
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (std::getline(baseCodeBuf, line))
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// begins with '#'?
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string::size_type	firstNonWhitespace		= line.find_first_not_of("\t ");
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool						isPreprocessorDirective	= (firstNonWhitespace != std::string::npos && line.at(firstNonWhitespace) == '#');
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Inject #extensions
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isPreprocessorDirective && firstNonPreprocessorLine)
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			firstNonPreprocessorLine = false;
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			resultBuf << extensions.str();
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		resultBuf << line << "\n";
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return resultBuf.str();
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This functions builds a matching vertex shader for a 'both' case, when
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// the fragment shader is being tested.
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// We need to build attributes and varyings for each 'input'.
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring ShaderCase::genVertexShader (const ValueBlock& valueBlock) const
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	res;
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		usesInout	= usesShaderInoutQualifiers(m_targetVersion);
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		vtxIn		= usesInout ? "in"	: "attribute";
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		vtxOut		= usesInout ? "out"	: "varying";
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << glu::getGLSLVersionDeclaration(m_targetVersion) << "\n";
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Declarations (position + attribute/varying for each input).
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "precision highp float;\n";
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "precision highp int;\n";
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "\n";
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << vtxIn << " highp vec4 dEQP_Position;\n";
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value& val = valueBlock.values[ndx];
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_INPUT)
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DataType	floatType	= getDataTypeFloatScalars(val.dataType);
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*	typeStr		= getDataTypeName(floatType);
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			res << vtxIn << " " << typeStr << " a_" << val.valueName << ";\n";
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				res << vtxOut << " " << typeStr << " " << val.valueName << ";\n";
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				res << vtxOut << " " << typeStr << " v_" << val.valueName << ";\n";
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "\n";
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Main function.
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// - gl_Position = dEQP_Position;
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// - for each input: write attribute directly to varying
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "void main()\n";
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "{\n";
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "	gl_Position = dEQP_Position;\n";
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value& val = valueBlock.values[ndx];
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_INPUT)
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string& name = val.valueName;
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				res << "	" << name << " = a_" << name << ";\n";
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				res << "	v_" << name << " = a_" << name << ";\n";
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res << "}\n";
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return res.str();
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void genCompareFunctions (ostringstream& stream, const ShaderCase::ValueBlock& valueBlock, bool useFloatTypes)
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool cmpTypeFound[TYPE_LAST];
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < TYPE_LAST; i++)
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		cmpTypeFound[i] = false;
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int valueNdx = 0; valueNdx < (int)valueBlock.values.size(); valueNdx++)
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value& val = valueBlock.values[valueNdx];
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_OUTPUT)
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			cmpTypeFound[(int)val.dataType] = true;
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useFloatTypes)
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL])		stream << "bool isOk (float a, bool b) { return ((a > 0.5) == b); }\n";
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL_VEC2])	stream << "bool isOk (vec2 a, bvec2 b) { return (greaterThan(a, vec2(0.5)) == b); }\n";
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL_VEC3])	stream << "bool isOk (vec3 a, bvec3 b) { return (greaterThan(a, vec3(0.5)) == b); }\n";
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL_VEC4])	stream << "bool isOk (vec4 a, bvec4 b) { return (greaterThan(a, vec4(0.5)) == b); }\n";
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT])			stream << "bool isOk (float a, int b)  { float atemp = a+0.5; return (float(b) <= atemp && atemp <= float(b+1)); }\n";
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT_VEC2])	stream << "bool isOk (vec2 a, ivec2 b) { return (ivec2(floor(a + 0.5)) == b); }\n";
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT_VEC3])	stream << "bool isOk (vec3 a, ivec3 b) { return (ivec3(floor(a + 0.5)) == b); }\n";
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT_VEC4])	stream << "bool isOk (vec4 a, ivec4 b) { return (ivec4(floor(a + 0.5)) == b); }\n";
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT])		stream << "bool isOk (float a, uint b) { float atemp = a+0.5; return (float(b) <= atemp && atemp <= float(b+1u)); }\n";
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT_VEC2])	stream << "bool isOk (vec2 a, uvec2 b) { return (uvec2(floor(a + 0.5)) == b); }\n";
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT_VEC3])	stream << "bool isOk (vec3 a, uvec3 b) { return (uvec3(floor(a + 0.5)) == b); }\n";
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT_VEC4])	stream << "bool isOk (vec4 a, uvec4 b) { return (uvec4(floor(a + 0.5)) == b); }\n";
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL])		stream << "bool isOk (bool a, bool b)   { return (a == b); }\n";
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL_VEC2])	stream << "bool isOk (bvec2 a, bvec2 b) { return (a == b); }\n";
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL_VEC3])	stream << "bool isOk (bvec3 a, bvec3 b) { return (a == b); }\n";
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_BOOL_VEC4])	stream << "bool isOk (bvec4 a, bvec4 b) { return (a == b); }\n";
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT])			stream << "bool isOk (int a, int b)     { return (a == b); }\n";
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT_VEC2])	stream << "bool isOk (ivec2 a, ivec2 b) { return (a == b); }\n";
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT_VEC3])	stream << "bool isOk (ivec3 a, ivec3 b) { return (a == b); }\n";
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_INT_VEC4])	stream << "bool isOk (ivec4 a, ivec4 b) { return (a == b); }\n";
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT])		stream << "bool isOk (uint a, uint b)   { return (a == b); }\n";
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT_VEC2])	stream << "bool isOk (uvec2 a, uvec2 b) { return (a == b); }\n";
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT_VEC3])	stream << "bool isOk (uvec3 a, uvec3 b) { return (a == b); }\n";
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpTypeFound[TYPE_UINT_VEC4])	stream << "bool isOk (uvec4 a, uvec4 b) { return (a == b); }\n";
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT])		stream << "bool isOk (float a, float b, float eps) { return (abs(a-b) <= (eps*abs(b) + eps)); }\n";
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_VEC2])	stream << "bool isOk (vec2 a, vec2 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n";
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_VEC3])	stream << "bool isOk (vec3 a, vec3 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n";
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_VEC4])	stream << "bool isOk (vec4 a, vec4 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n";
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT2])		stream << "bool isOk (mat2 a, mat2 b, float eps) { vec2 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec2(eps))); }\n";
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT2X3])	stream << "bool isOk (mat2x3 a, mat2x3 b, float eps) { vec3 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec3(eps))); }\n";
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT2X4])	stream << "bool isOk (mat2x4 a, mat2x4 b, float eps) { vec4 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec4(eps))); }\n";
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT3X2])	stream << "bool isOk (mat3x2 a, mat3x2 b, float eps) { vec2 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec2(eps))); }\n";
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT3])		stream << "bool isOk (mat3 a, mat3 b, float eps) { vec3 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec3(eps))); }\n";
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT3X4])	stream << "bool isOk (mat3x4 a, mat3x4 b, float eps) { vec4 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec4(eps))); }\n";
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT4X2])	stream << "bool isOk (mat4x2 a, mat4x2 b, float eps) { vec2 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec2(eps))); }\n";
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT4X3])	stream << "bool isOk (mat4x3 a, mat4x3 b, float eps) { vec3 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec3(eps))); }\n";
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (cmpTypeFound[TYPE_FLOAT_MAT4])		stream << "bool isOk (mat4 a, mat4 b, float eps) { vec4 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec4(eps))); }\n";
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void genCompareOp (ostringstream& output, const char* dstVec4Var, const ShaderCase::ValueBlock& valueBlock, const char* nonFloatNamePrefix, const char* checkVarName)
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool isFirstOutput = true;
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val			= valueBlock.values[ndx];
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					valueName	= val.valueName.c_str();
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_OUTPUT)
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Check if we're only interested in one variable (then skip if not the right one).
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (checkVarName && !deStringEqual(valueName, checkVarName))
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Prefix.
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isFirstOutput)
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				output << "bool RES = ";
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isFirstOutput = false;
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				output << "RES = RES && ";
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Generate actual comparison.
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				output << "isOk(" << valueName << ", ref_" << valueName << ", 0.05);\n";
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				output << "isOk(" << nonFloatNamePrefix << valueName << ", ref_" << valueName << ");\n";
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Uniforms are already declared in shader.
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isFirstOutput)
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		output << dstVec4Var << " = vec4(1.0);\n";	// \todo [petri] Should we give warning if not expect-failure case?
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n";
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring ShaderCase::genFragmentShader (const ValueBlock& valueBlock) const
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	shader;
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		usesInout		= usesShaderInoutQualifiers(m_targetVersion);
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		customColorOut	= usesInout;
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		fragIn			= usesInout ? "in" : "varying";
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		prec			= supportsFragmentHighp(m_targetVersion) ? "highp" : "mediump";
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << glu::getGLSLVersionDeclaration(m_targetVersion) << "\n";
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "precision " << prec << " float;\n";
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "precision " << prec << " int;\n";
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "\n";
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (customColorOut)
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shader << "\n";
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genCompareFunctions(shader, valueBlock, true);
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "\n";
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Declarations (varying, reference for each output).
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value& val = valueBlock.values[ndx];
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DataType	floatType		= getDataTypeFloatScalars(val.dataType);
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	floatTypeStr	= getDataTypeName(floatType);
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	refTypeStr		= getDataTypeName(val.dataType);
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_OUTPUT)
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				shader << fragIn << " " << floatTypeStr << " " << val.valueName << ";\n";
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				shader << fragIn << " " << floatTypeStr << " v_" << val.valueName << ";\n";
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			shader << "uniform " << refTypeStr << " ref_" << val.valueName << ";\n";
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "\n";
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "void main()\n";
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "{\n";
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "	";
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genCompareOp(shader, customColorOut ? "dEQP_FragColor" : "gl_FragColor", valueBlock, "v_", DE_NULL);
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	shader << "}\n";
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return shader.str();
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Specialize a shader for the vertex shader test case.
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring ShaderCase::specializeVertexShader (const char* src, const ValueBlock& valueBlock) const
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	decl;
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	setup;
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	output;
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		usesInout	= usesShaderInoutQualifiers(m_targetVersion);
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		vtxIn		= usesInout ? "in"	: "attribute";
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		vtxOut		= usesInout ? "out"	: "varying";
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// generated from "both" case
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_caseType == CASETYPE_VERTEX_ONLY);
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Output (write out position).
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	output << "gl_Position = dEQP_Position;\n";
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Declarations (position + attribute for each input, varying for each output).
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << vtxIn << " highp vec4 dEQP_Position;\n";
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value& val = valueBlock.values[ndx];
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	valueName		= val.valueName.c_str();
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DataType	floatType		= getDataTypeFloatScalars(val.dataType);
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	floatTypeStr	= getDataTypeName(floatType);
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	refTypeStr		= getDataTypeName(val.dataType);
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_INPUT)
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << vtxIn << " " << floatTypeStr << " " << valueName << ";\n";
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << vtxIn << " " << floatTypeStr << " a_" << valueName << ";\n";
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				setup << refTypeStr << " " << valueName << " = " << refTypeStr << "(a_" << valueName << ");\n";
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (val.storageType == ShaderCase::Value::STORAGE_OUTPUT)
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << vtxOut << " " << floatTypeStr << " " << valueName << ";\n";
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << vtxOut << " " << floatTypeStr << " v_" << valueName << ";\n";
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << refTypeStr << " " << valueName << ";\n";
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				output << "v_" << valueName << " = " << floatTypeStr << "(" << valueName << ");\n";
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Shader specialization.
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string> params;
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("DECLARATIONS", decl.str()));
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("SETUP", setup.str()));
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("OUTPUT", output.str()));
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position"));
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	StringTemplate	tmpl	(src);
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	baseSrc	= tmpl.specialize(params);
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	withExt	= injectExtensionRequirements(baseSrc, SHADERTYPE_VERTEX, m_programs[0].spec.requirements);
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return withExt;
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Specialize a shader for the fragment shader test case.
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring ShaderCase::specializeFragmentShader (const char* src, const ValueBlock& valueBlock) const
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	decl;
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	setup;
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream	output;
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		usesInout		= usesShaderInoutQualifiers(m_targetVersion);
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		customColorOut	= usesInout;
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		fragIn			= usesInout			? "in"				: "varying";
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		fragColor		= customColorOut	? "dEQP_FragColor"	: "gl_FragColor";
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// generated from "both" case
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_caseType == CASETYPE_FRAGMENT_ONLY);
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genCompareFunctions(decl, valueBlock, false);
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genCompareOp(output, fragColor, valueBlock, "", DE_NULL);
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (customColorOut)
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val				= valueBlock.values[ndx];
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					valueName		= val.valueName.c_str();
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DataType					floatType		= getDataTypeFloatScalars(val.dataType);
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					floatTypeStr	= getDataTypeName(floatType);
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					refTypeStr		= getDataTypeName(val.dataType);
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_INPUT)
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << fragIn << " " << floatTypeStr << " " << valueName << ";\n";
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << fragIn << " " << floatTypeStr << " v_" << valueName << ";\n";
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::string offset = isDataTypeIntOrIVec(val.dataType) ? " * 1.0025" : ""; // \todo [petri] bit of a hack to avoid errors in chop() due to varying interpolation
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				setup << refTypeStr << " " << valueName << " = " << refTypeStr << "(v_" << valueName << offset << ");\n";
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (val.storageType == ShaderCase::Value::STORAGE_OUTPUT)
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << "uniform " << refTypeStr << " ref_" << valueName << ";\n";
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << refTypeStr << " " << valueName << ";\n";
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* \todo [2010-04-01 petri] Check all outputs. */
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Shader specialization.
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string> params;
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("DECLARATIONS", decl.str()));
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("SETUP", setup.str()));
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("OUTPUT", output.str()));
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("POSITION_FRAG_COLOR", fragColor));
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	StringTemplate	tmpl	(src);
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	baseSrc	= tmpl.specialize(params);
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	withExt	= injectExtensionRequirements(baseSrc, SHADERTYPE_FRAGMENT, m_programs[0].spec.requirements);
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return withExt;
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic map<string, string> generateVertexSpecialization (glu::GLSLVersion targetVersion, const ShaderCase::ValueBlock& valueBlock)
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool				usesInout	= usesShaderInoutQualifiers(targetVersion);
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*				vtxIn		= usesInout ? "in" : "attribute";
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream			decl;
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream			setup;
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string>		params;
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << vtxIn << " highp vec4 dEQP_Position;\n";
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val		= valueBlock.values[ndx];
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					typeStr	= getDataTypeName(val.dataType);
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_INPUT)
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (getDataTypeScalarType(val.dataType) == TYPE_FLOAT)
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << vtxIn << " " << typeStr << " " << val.valueName << ";\n";
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DataType	floatType		= getDataTypeFloatScalars(val.dataType);
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char*	floatTypeStr	= getDataTypeName(floatType);
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				decl << vtxIn << " " << floatTypeStr << " a_" << val.valueName << ";\n";
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				setup << typeStr << " " << val.valueName << " = " << typeStr << "(a_" << val.valueName << ");\n";
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (val.storageType == ShaderCase::Value::STORAGE_UNIFORM &&
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					val.valueName.find('.') == string::npos)
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << "uniform " << typeStr << " " << val.valueName << ";\n";
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("VERTEX_DECLARATIONS",		decl.str()));
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("VERTEX_SETUP",				setup.str()));
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("VERTEX_OUTPUT",				string("gl_Position = dEQP_Position;\n")));
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return params;
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic map<string, string> generateFragmentSpecialization (glu::GLSLVersion targetVersion, const ShaderCase::ValueBlock& valueBlock)
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			usesInout		= usesShaderInoutQualifiers(targetVersion);
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			customColorOut	= usesInout;
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			fragColor		= customColorOut ? "dEQP_FragColor"	: "gl_FragColor";
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		decl;
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		output;
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string>	params;
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genCompareFunctions(decl, valueBlock, false);
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genCompareOp(output, fragColor, valueBlock, "", DE_NULL);
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (customColorOut)
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val				= valueBlock.values[ndx];
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					valueName		= val.valueName.c_str();
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					refTypeStr		= getDataTypeName(val.dataType);
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_OUTPUT)
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << "uniform " << refTypeStr << " ref_" << valueName << ";\n";
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << refTypeStr << " " << valueName << ";\n";
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (val.storageType == ShaderCase::Value::STORAGE_UNIFORM &&
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					val.valueName.find('.') == string::npos)
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << "uniform " << refTypeStr << " " << valueName << ";\n";
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("FRAGMENT_DECLARATIONS",		decl.str()));
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("FRAGMENT_OUTPUT",			output.str()));
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("FRAG_COLOR",				fragColor));
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return params;
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic map<string, string> generateGeometrySpecialization (glu::GLSLVersion targetVersion, const ShaderCase::ValueBlock& valueBlock)
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		decl;
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string>	params;
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(targetVersion);
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << "layout (triangles) in;\n";
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << "layout (triangle_strip, max_vertices=3) out;\n";
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << "\n";
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val				= valueBlock.values[ndx];
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					valueName		= val.valueName.c_str();
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					refTypeStr		= getDataTypeName(val.dataType);
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_UNIFORM &&
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			val.valueName.find('.') == string::npos)
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << "uniform " << refTypeStr << " " << valueName << ";\n";
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("GEOMETRY_DECLARATIONS",		decl.str()));
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return params;
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic map<string, string> generateTessControlSpecialization (glu::GLSLVersion targetVersion, const ShaderCase::ValueBlock& valueBlock)
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		decl;
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		output;
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string>	params;
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(targetVersion);
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << "layout (vertices=3) out;\n";
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << "\n";
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val				= valueBlock.values[ndx];
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					valueName		= val.valueName.c_str();
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					refTypeStr		= getDataTypeName(val.dataType);
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_UNIFORM &&
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			val.valueName.find('.') == string::npos)
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << "uniform " << refTypeStr << " " << valueName << ";\n";
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	output <<	"gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"gl_TessLevelInner[0] = 2.0;\n"
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"gl_TessLevelInner[1] = 2.0;\n"
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"gl_TessLevelOuter[0] = 2.0;\n"
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"gl_TessLevelOuter[1] = 2.0;\n"
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"gl_TessLevelOuter[2] = 2.0;\n"
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"gl_TessLevelOuter[3] = 2.0;";
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS",	decl.str()));
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT",		output.str()));
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return params;
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic map<string, string> generateTessEvalSpecialization (glu::GLSLVersion targetVersion, const ShaderCase::ValueBlock& valueBlock)
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		decl;
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream		output;
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string>	params;
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(targetVersion);
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << "layout (triangles) in;\n";
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << "\n";
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)valueBlock.values.size(); ndx++)
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val				= valueBlock.values[ndx];
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					valueName		= val.valueName.c_str();
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					refTypeStr		= getDataTypeName(val.dataType);
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == ShaderCase::Value::STORAGE_UNIFORM &&
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			val.valueName.find('.') == string::npos)
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decl << "uniform " << refTypeStr << " " << valueName << ";\n";
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	output <<	"gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n";
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS",	decl.str()));
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT",		output.str()));
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return params;
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void specializeShaders (glu::ProgramSources& dst, glu::ShaderType shaderType, const std::vector<std::string>& sources, const ShaderCase::ValueBlock& valueBlock, glu::GLSLVersion targetVersion, const std::vector<ShaderCase::CaseRequirement>& requirements, std::map<std::string, std::string> (*specializationGenerator)(glu::GLSLVersion, const ShaderCase::ValueBlock&))
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!sources.empty())
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::map<std::string, std::string> specializationParams = specializationGenerator(targetVersion, valueBlock);
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)sources.size(); ++ndx)
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const StringTemplate	tmpl			(sources[ndx]);
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::string		baseGLSLCode	= tmpl.specialize(specializationParams);
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::string		glslSource		= injectExtensionRequirements(baseGLSLCode, shaderType, requirements);
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst << glu::ShaderSource(shaderType, glslSource);
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::specializeVertexShaders (glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	specializeShaders(dst, glu::SHADERTYPE_VERTEX, sources, valueBlock, m_targetVersion, requirements, generateVertexSpecialization);
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::specializeFragmentShaders (glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	specializeShaders(dst, glu::SHADERTYPE_FRAGMENT, sources, valueBlock, m_targetVersion, requirements, generateFragmentSpecialization);
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::specializeGeometryShaders (glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	specializeShaders(dst, glu::SHADERTYPE_GEOMETRY, sources, valueBlock, m_targetVersion, requirements, generateGeometrySpecialization);
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::specializeTessControlShaders (glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	specializeShaders(dst, glu::SHADERTYPE_TESSELLATION_CONTROL, sources, valueBlock, m_targetVersion, requirements, generateTessControlSpecialization);
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::specializeTessEvalShaders (glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	specializeShaders(dst, glu::SHADERTYPE_TESSELLATION_EVALUATION, sources, valueBlock, m_targetVersion, requirements, generateTessEvalSpecialization);
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCase::dumpValues (const ValueBlock& valueBlock, int arrayNdx)
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numValues = (int)valueBlock.values.size();
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int valNdx = 0; valNdx < numValues; valNdx++)
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ShaderCase::Value&	val				= valueBlock.values[valNdx];
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*					valueName		= val.valueName.c_str();
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DataType					dataType		= val.dataType;
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							scalarSize		= getDataTypeScalarSize(val.dataType);
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream				result;
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result << "    ";
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (val.storageType == Value::STORAGE_INPUT)
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << "input ";
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (val.storageType == Value::STORAGE_UNIFORM)
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << "uniform ";
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (val.storageType == Value::STORAGE_OUTPUT)
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << "expected ";
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result << getDataTypeName(dataType) << " " << valueName << ":";
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isDataTypeScalar(dataType))
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << " ";
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isDataTypeVector(dataType))
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << " [ ";
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (isDataTypeMatrix(dataType))
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << "\n";
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isDataTypeScalarOrVector(dataType))
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int						elemNdx	= (val.arrayLength == 1) ? 0 : arrayNdx;
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Value::Element&	e		= val.elements[elemNdx*scalarSize + scalarNdx];
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result << ((scalarNdx != 0) ? ", " : "");
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (isDataTypeFloatOrVec(dataType))
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result << e.float32;
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (isDataTypeIntOrIVec(dataType))
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result << e.int32;
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (isDataTypeUintOrUVec(dataType))
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result << (deUint32)e.int32;
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (isDataTypeBoolOrBVec(dataType))
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result << (e.bool32 ? "true" : "false");
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (isDataTypeMatrix(dataType))
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int numRows = getDataTypeMatrixNumRows(dataType);
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int numCols = getDataTypeMatrixNumColumns(dataType);
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result << "       [ ";
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int colNdx = 0; colNdx < numCols; colNdx++)
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int		elemNdx = (val.arrayLength == 1) ? 0 : arrayNdx;
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					float	v		= val.elements[elemNdx*scalarSize + rowNdx*numCols + colNdx].float32;
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result << ((colNdx==0) ? "" : ", ") << v;
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result << " ]\n";
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isDataTypeScalar(dataType))
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << "\n";
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (isDataTypeVector(dataType))
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result << " ]\n";
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message << result.str() << TestLog::EndMessage;
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // sl
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gls
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1720