13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Program interface query test case
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fProgramInterfaceQueryTestCase.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fProgramInterfaceDefinitionUtil.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarTypeUtil.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluStrUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSTLUtil.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing ProgramInterfaceDefinition::VariablePathComponent;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing ProgramInterfaceDefinition::VariableSearchFilter;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool stringEndsWith (const std::string& str, const std::string& suffix)
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (suffix.length() > str.length())
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return str.substr(str.length() - suffix.length()) == suffix;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glw::GLenum getProgramDefaultBlockInterfaceFromStorage (glu::Storage storage)
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (storage)
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::STORAGE_IN:		return GL_PROGRAM_INPUT;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::STORAGE_OUT:		return GL_PROGRAM_OUTPUT;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::STORAGE_UNIFORM:	return GL_UNIFORM;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isBufferBackedInterfaceBlockStorage (glu::Storage storage)
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return storage == glu::STORAGE_BUFFER || storage == glu::STORAGE_UNIFORM;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getTypeSize (glu::DataType type)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type == glu::TYPE_FLOAT)
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 4;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type == glu::TYPE_INT || type == glu::TYPE_UINT)
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 4;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type == glu::TYPE_BOOL)
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 4; // uint
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(false);
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getVarTypeSize (const glu::VarType& type)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// return in basic machine units
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return glu::getDataTypeScalarSize(type.getBasicType()) * getTypeSize(glu::getDataTypeScalarType(type.getBasicType()));
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isStructType())
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int size = 0;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			size += getVarTypeSize(type.getStructPtr()->getMember(ndx).getType());
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return size;
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// unsized arrays are handled as if they had only one element
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (type.getArraySize() == glu::VarType::UNSIZED_ARRAY)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getVarTypeSize(type.getElementType());
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return type.getArraySize() * getVarTypeSize(type.getElementType());
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::MatrixOrder getMatrixOrderFromPath (const std::vector<VariablePathComponent>& path)
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::MatrixOrder order = glu::MATRIXORDER_LAST;
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// inherit majority
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int pathNdx = 0; pathNdx < (int)path.size(); ++pathNdx)
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::MatrixOrder matOrder;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (path[pathNdx].isInterfaceBlock())
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			matOrder = path[pathNdx].getInterfaceBlock()->layout.matrixOrder;
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (path[pathNdx].isDeclaration())
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			matOrder = path[pathNdx].getDeclaration()->layout.matrixOrder;
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (path[pathNdx].isVariableType())
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			matOrder = glu::MATRIXORDER_LAST;
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return glu::MATRIXORDER_LAST;
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (matOrder != glu::MATRIXORDER_LAST)
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			order = matOrder;
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return order;
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PropValidator
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									PropValidator					(Context& context, ProgramResourcePropFlags validationProp, const char* requiredExtension = "");
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual std::string				getHumanReadablePropertyString	(glw::GLint propVal) const;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void					validate						(const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const = 0;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							isSupported						(void) const;
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool							isSelected						(deUint32 caseFlags) const;
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							setError						(const std::string& err) const;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestContext&				m_testCtx;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&		m_renderContext;
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ContextInfo&			m_contextInfo;
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string				m_extension;
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ProgramResourcePropFlags	m_validationProp;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPropValidator::PropValidator (Context& context, ProgramResourcePropFlags validationProp, const char* requiredExtension)
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_testCtx			(context.getTestContext())
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderContext	(context.getRenderContext())
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_contextInfo		(context.getContextInfo())
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_extension		(requiredExtension)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_validationProp	(validationProp)
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string PropValidator::getHumanReadablePropertyString (glw::GLint propVal) const
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::toString(propVal);
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool PropValidator::isSupported (void) const
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_extension.empty() || m_contextInfo.isExtensionSupported(m_extension.c_str());
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool PropValidator::isSelected (deUint32 caseFlags) const
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (caseFlags & (deUint32)m_validationProp) != 0;
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PropValidator::setError (const std::string& err) const
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// don't overwrite earlier errors
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, err.c_str());
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SingleVariableValidator : public PropValidator
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					SingleVariableValidator	(Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension = "");
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			validate				(const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	validateSingleVariable	(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const = 0;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	validateBuiltinVariable	(const std::string& resource, glw::GLint propValue) const;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariableSearchFilter	m_filter;
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::GLuint			m_programID;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySingleVariableValidator::SingleVariableValidator (Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension)
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: PropValidator	(context, validationProp, requiredExtension)
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_filter		(filter)
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_programID	(programID)
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SingleVariableValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VariablePathComponent> path;
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (findProgramVariablePathByPathName(path, program, resource, m_filter))
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VarType* variable = (path.back().isVariableType()) ? (path.back().getVariableType()) : (DE_NULL);
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!variable || !variable->isBasicType())
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource name \"" << resource << "\" refers to a non-basic type." << tcu::TestLog::EndMessage;
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource not basic type");
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			validateSingleVariable(path, resource, propValue);
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// finding matching variable in any shader is sufficient
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (deStringBeginsWith(resource.c_str(), "gl_"))
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// special case for builtins
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		validateBuiltinVariable(resource, propValue);
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Error, could not find resource \"" << resource << "\" in the program" << tcu::TestLog::EndMessage;
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setError("could not find resource");
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SingleVariableValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(propValue);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Error, could not find builtin resource \"" << resource << "\" in the program" << tcu::TestLog::EndMessage;
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setError("could not find builtin resource");
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SingleBlockValidator : public PropValidator
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								SingleBlockValidator	(Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension = "");
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						validate				(const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const;
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void				validateSingleBlock		(const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue) const = 0;
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariableSearchFilter	m_filter;
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::GLuint			m_programID;
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2713c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySingleBlockValidator::SingleBlockValidator (Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension)
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: PropValidator	(context, validationProp, requiredExtension)
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_filter		(filter)
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_programID	(programID)
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SingleBlockValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::VarTokenizer	tokenizer		(resource.c_str());
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string	blockName		= tokenizer.getIdentifier();
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<int>	instanceIndex;
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tokenizer.advance();
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// array index
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET)
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tokenizer.advance();
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_NUMBER);
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		instanceIndex.push_back(tokenizer.getNumber());
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tokenizer.advance();
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_RIGHT_BRACKET);
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tokenizer.advance();
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// no trailing garbage
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_END);
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx];
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_filter.matchesFilter(shader))
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx)
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::InterfaceBlock& block = shader->getDefaultBlock().interfaceBlocks[blockNdx];
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_filter.matchesFilter(block) && block.interfaceName == blockName)
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// dimensions match
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(instanceIndex.size() == block.dimensions.size());
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				validateSingleBlock(block, instanceIndex, resource, propValue);
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Error, could not find resource \"" << resource << "\" in the program" << tcu::TestLog::EndMessage;
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setError("could not find resource");
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TypeValidator : public SingleVariableValidator
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TypeValidator					(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string	getHumanReadablePropertyString	(glw::GLint propVal) const;
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable			(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateBuiltinVariable			(const std::string& resource, glw::GLint propValue) const;
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3373c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTypeValidator::TypeValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_TYPE, programID, filter)
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string TypeValidator::getHumanReadablePropertyString (glw::GLint propVal) const
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::toString(glu::getShaderVarTypeStr(propVal));
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TypeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VarType* variable = path.back().getVariableType();
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(variable->getBasicType()) << tcu::TestLog::EndMessage;
3548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (variable->getBasicType() != glu::getDataTypeFromGLType(propValue))
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("resource type invalid");
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TypeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	static const struct
3658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
3668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const char*		name;
3678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		glu::DataType	type;
3688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	} builtins[] =
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ "gl_Position",			glu::TYPE_FLOAT_VEC4	},
3718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ "gl_FragCoord",			glu::TYPE_FLOAT_VEC4	},
3728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ "gl_in[0].gl_Position",	glu::TYPE_FLOAT_VEC4	},
3738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ "gl_VertexID",			glu::TYPE_INT			},
3748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ "gl_InvocationID",		glu::TYPE_INT			},
3758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ "gl_NumWorkGroups",		glu::TYPE_UINT_VEC3		},
3768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ "gl_FragDepth",			glu::TYPE_FLOAT			},
3778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	};
3788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
3798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtins); ++ndx)
3808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
3818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (resource == builtins[ndx].name)
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(builtins[ndx].type) << tcu::TestLog::EndMessage;
3848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
3858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (glu::getDataTypeFromGLType(propValue) != builtins[ndx].type)
3868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			{
3878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
3888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				setError("resource type invalid");
3898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			}
3908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			return;
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
3948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(false);
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ArraySizeValidator : public SingleVariableValidator
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ArraySizeValidator				(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable			(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
4028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	void		validateBuiltinVariable			(const std::string& resource, glw::GLint propValue) const;
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko PoyryArraySizeValidator::ArraySizeValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_ARRAY_SIZE, programID, filter)
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ArraySizeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent		nullComponent;
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	enclosingcomponent	= (path.size() > 1) ? (path[path.size()-2]) : (nullComponent);
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isArray				= enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType();
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						inUnsizedArray		= isArray && (enclosingcomponent.getVariableType()->getArraySize() == glu::VarType::UNSIZED_ARRAY);
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						arraySize			= (!isArray) ? (1) : (inUnsizedArray) ? (0) : (enclosingcomponent.getVariableType()->getArraySize());
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage;
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (arraySize != propValue)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("resource array size invalid");
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid ArraySizeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
4318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
4328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// support all built-ins that getProgramInterfaceResourceList supports
4338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (resource == "gl_Position"			||
4348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		resource == "gl_VertexID"			||
4358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		resource == "gl_FragCoord"			||
4368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		resource == "gl_in[0].gl_Position"	||
4378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		resource == "gl_InvocationID"		||
4388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		resource == "gl_NumWorkGroups"		||
4398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		resource == "gl_FragDepth")
4408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
4418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting 1" << tcu::TestLog::EndMessage;
4428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
4438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (propValue != 1)
4448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
4458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
4468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			setError("resource array size invalid");
4478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
4488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
4498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	else
4508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		DE_ASSERT(false);
4518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
4528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ArrayStrideValidator : public SingleVariableValidator
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ArrayStrideValidator			(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable			(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4603c827367444ee418f129b2c238299f49d3264554Jarkko PoyryArrayStrideValidator::ArrayStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_ARRAY_STRIDE, programID, filter)
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ArrayStrideValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent		nullComponent;
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	component			= path.back();
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	enclosingcomponent	= (path.size() > 1) ? (path[path.size()-2]) : (nullComponent);
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	firstComponent		= path.front();
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isBufferBlock		= firstComponent.isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage);
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isArray				= enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType();
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isAtomicCounter		= glu::isDataTypeAtomicCounter(component.getVariableType()->getBasicType()); // atomic counters are buffer backed with a stride of 4 basic machine units
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Layout tests will verify layouts of buffer backed arrays properly. Here we just check values are greater or equal to the element size
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isBufferBlock && isArray)
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int elementSize = glu::getDataTypeScalarSize(component.getVariableType()->getBasicType()) * getTypeSize(glu::getDataTypeScalarType(component.getVariableType()->getBasicType()));
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array stride, expecting greater or equal to " << elementSize << tcu::TestLog::EndMessage;
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue < elementSize)
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource array stride invalid");
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Atomics are buffer backed with stride of 4 even though they are not in an interface block
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int arrayStride = (isAtomicCounter && isArray) ? (4) : (!isBufferBlock && !isAtomicCounter) ? (-1) : (0);
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array stride, expecting " << arrayStride << tcu::TestLog::EndMessage;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (arrayStride != propValue)
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource array stride invalid");
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BlockIndexValidator : public SingleVariableValidator
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				BlockIndexValidator				(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable			(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5123c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBlockIndexValidator::BlockIndexValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_BLOCK_INDEX, programID, filter)
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BlockIndexValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent& firstComponent = path.front();
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!firstComponent.isInterfaceBlock())
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block index, expecting -1" << tcu::TestLog::EndMessage;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue != -1)
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource block index invalid");
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block index, expecting a valid block index" << tcu::TestLog::EndMessage;
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue == -1)
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource block index invalid");
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::Functions&	gl			= m_renderContext.getFunctions();
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::GLenum		interface	= (firstComponent.getInterfaceBlock()->storage == glu::STORAGE_UNIFORM) ? (GL_UNIFORM_BLOCK) :
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  (firstComponent.getInterfaceBlock()->storage == glu::STORAGE_BUFFER) ? (GL_SHADER_STORAGE_BLOCK) :
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  (0);
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glw::GLint				written		= 0;
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::vector<char>		nameBuffer	(firstComponent.getInterfaceBlock()->interfaceName.size() + 3 * firstComponent.getInterfaceBlock()->dimensions.size() + 2, '\0'); // +3 for appended "[N]", +1 for '\0' and +1 just for safety
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getProgramResourceName(m_programID, interface, propValue, (int)nameBuffer.size() - 1, &written, &nameBuffer[0]);
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "query block name");
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK(written < (int)nameBuffer.size());
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK(nameBuffer.back() == '\0');
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const std::string	blockName		(&nameBuffer[0], written);
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::ostringstream	expectedName;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				expectedName << firstComponent.getInterfaceBlock()->interfaceName;
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int dimensionNdx = 0; dimensionNdx < (int)firstComponent.getInterfaceBlock()->dimensions.size(); ++dimensionNdx)
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					expectedName << "[0]";
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Block name with index " << propValue << " is \"" << blockName << "\"" << tcu::TestLog::EndMessage;
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (blockName != expectedName.str())
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "\tError, expected " << expectedName.str() << tcu::TestLog::EndMessage;
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					setError("resource block index invalid");
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsRowMajorValidator : public SingleVariableValidator
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				IsRowMajorValidator				(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string getHumanReadablePropertyString	(glw::GLint propVal) const;
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable			(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5843c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIsRowMajorValidator::IsRowMajorValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, programID, filter)
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string IsRowMajorValidator::getHumanReadablePropertyString	(glw::GLint propVal) const
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::toString(glu::getBooleanStr(propVal));
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid IsRowMajorValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	component			= path.back();
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	firstComponent		= path.front();
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isBufferBlock		= firstComponent.isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage);
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isMatrix			= glu::isDataTypeMatrix(component.getVariableType()->getBasicType());
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						expected			= (isBufferBlock && isMatrix && getMatrixOrderFromPath(path) == glu::MATRIXORDER_ROW_MAJOR) ? (1) : (0);
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix order, expecting IS_ROW_MAJOR = " << expected << tcu::TestLog::EndMessage;
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (propValue != expected)
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("resource matrix order invalid");
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MatrixStrideValidator : public SingleVariableValidator
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				MatrixStrideValidator			(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable			(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6213c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMatrixStrideValidator::MatrixStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_MATRIX_STRIDE, programID, filter)
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MatrixStrideValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	component			= path.back();
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariablePathComponent&	firstComponent		= path.front();
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isBufferBlock		= firstComponent.isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage);
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool						isMatrix			= glu::isDataTypeMatrix(component.getVariableType()->getBasicType());
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Layout tests will verify layouts of buffer backed arrays properly. Here we just check the stride is is greater or equal to the row/column size
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isBufferBlock && isMatrix)
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool	columnMajor			= getMatrixOrderFromPath(path) != glu::MATRIXORDER_ROW_MAJOR;
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	numMajorElements	= (columnMajor) ? (glu::getDataTypeMatrixNumRows(component.getVariableType()->getBasicType())) : (glu::getDataTypeMatrixNumColumns(component.getVariableType()->getBasicType()));
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	majorSize			= numMajorElements * getTypeSize(glu::getDataTypeScalarType(component.getVariableType()->getBasicType()));
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix stride, expecting greater or equal to " << majorSize << tcu::TestLog::EndMessage;
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue < majorSize)
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource matrix stride invalid");
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int matrixStride = (!isBufferBlock && !glu::isDataTypeAtomicCounter(component.getVariableType()->getBasicType())) ? (-1) : (0);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix stride, expecting " << matrixStride << tcu::TestLog::EndMessage;
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (matrixStride != propValue)
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource matrix stride invalid");
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AtomicCounterBufferIndexVerifier : public SingleVariableValidator
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				AtomicCounterBufferIndexVerifier	(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable				(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6723c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAtomicCounterBufferIndexVerifier::AtomicCounterBufferIndexVerifier (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_ATOMIC_COUNTER_BUFFER_INDEX, programID, filter)
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid AtomicCounterBufferIndexVerifier::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType()))
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying atomic counter buffer index, expecting -1" << tcu::TestLog::EndMessage;
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue != -1)
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource atomic counter buffer index invalid");
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying atomic counter buffer index, expecting a valid index" << tcu::TestLog::EndMessage;
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue == -1)
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource atomic counter buffer index invalid");
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::Functions&	gl					= m_renderContext.getFunctions();
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glw::GLint				numActiveResources	= 0;
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getProgramInterfaceiv(m_programID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numActiveResources);
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramInterfaceiv(..., GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, ...)");
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (propValue >= numActiveResources)
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << ", GL_ACTIVE_RESOURCES = " << numActiveResources << tcu::TestLog::EndMessage;
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				setError("resource atomic counter buffer index invalid");
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LocationValidator : public SingleVariableValidator
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				LocationValidator		(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable	(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
7228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	void		validateBuiltinVariable	(const std::string& resource, glw::GLint propValue) const;
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7253c827367444ee418f129b2c238299f49d3264554Jarkko PoyryLocationValidator::LocationValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_LOCATION, programID, filter)
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getVariableLocationLength (const glu::VarType& type)
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeMatrix(type.getBasicType()))
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return glu::getDataTypeMatrixNumColumns(type.getBasicType());
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 1;
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isStructType())
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int size = 0;
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			size += getVariableLocationLength(type.getStructPtr()->getMember(ndx).getType());
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return size;
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return type.getArraySize() * getVariableLocationLength(type.getElementType());
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getIOSubVariableLocation (const std::vector<VariablePathComponent>& path, int startNdx, int currentLocation)
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (currentLocation == -1)
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (path[startNdx].getVariableType()->isBasicType())
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return currentLocation;
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (path[startNdx].getVariableType()->isArrayType())
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getIOSubVariableLocation(path, startNdx+1, currentLocation);
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (path[startNdx].getVariableType()->isStructType())
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < path[startNdx].getVariableType()->getStructPtr()->getNumMembers(); ++ndx)
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (&path[startNdx].getVariableType()->getStructPtr()->getMember(ndx).getType() == path[startNdx + 1].getVariableType())
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return getIOSubVariableLocation(path, startNdx + 1, currentLocation);
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (currentLocation != -1)
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				currentLocation += getVariableLocationLength(path[startNdx].getVariableType()->getStructPtr()->getMember(ndx).getType());
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// could not find member, never happens
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getIOBlockVariableLocation (const std::vector<VariablePathComponent>& path)
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::InterfaceBlock*	block			= path.front().getInterfaceBlock();
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							currentLocation	= block->layout.location;
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Find the block member
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int memberNdx = 0; memberNdx < (int)block->variables.size(); ++memberNdx)
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (&block->variables[memberNdx] == path[1].getDeclaration())
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (block->variables[memberNdx].layout.location != -1)
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			currentLocation = block->variables[memberNdx].layout.location;
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		currentLocation += getVariableLocationLength(block->variables[memberNdx].varType);
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Find subtype location in the complex type
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getIOSubVariableLocation(path, 2, currentLocation);
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getExplicitLocationFromPath (const std::vector<VariablePathComponent>& path)
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VariableDeclaration* varDecl = (path[0].isInterfaceBlock()) ? (path[1].getDeclaration()) : (path[0].getDeclaration());
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_UNIFORM)
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// inside uniform block
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (path.front().isInterfaceBlock() && (path.front().getInterfaceBlock()->storage == glu::STORAGE_IN || path.front().getInterfaceBlock()->storage == glu::STORAGE_OUT))
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// inside ioblock
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getIOBlockVariableLocation(path);
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (varDecl->storage == glu::STORAGE_UNIFORM)
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// default block uniform
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return varDecl->layout.location;
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (varDecl->storage == glu::STORAGE_IN || varDecl->storage == glu::STORAGE_OUT)
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// default block input/output
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getIOSubVariableLocation(path, 1, varDecl->layout.location);
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid LocationValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	isAtomicCounterUniform	= glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType());
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	isUniformBlockVariable	= path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_UNIFORM;
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	isVertexShader			= m_filter.getShaderTypeFilter() == glu::SHADERTYPE_VERTEX;
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	isFragmentShader		= m_filter.getShaderTypeFilter() == glu::SHADERTYPE_FRAGMENT;
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	isInputVariable			= (path.front().isInterfaceBlock()) ? (path.front().getInterfaceBlock()->storage == glu::STORAGE_IN) : (path.front().getDeclaration()->storage == glu::STORAGE_IN);
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	isOutputVariable		= (path.front().isInterfaceBlock()) ? (path.front().getInterfaceBlock()->storage == glu::STORAGE_OUT) : (path.front().getDeclaration()->storage == glu::STORAGE_OUT);
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	explicitLayoutLocation	= getExplicitLocationFromPath(path);
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		expectLocation;
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string	reasonStr;
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isAtomicCounterUniform)
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expectLocation = false;
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reasonStr = "Atomic counter uniforms have effective location of -1";
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isUniformBlockVariable)
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expectLocation = false;
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reasonStr = "Uniform block variables have effective location of -1";
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isInputVariable && !isVertexShader && explicitLayoutLocation == -1)
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expectLocation = false;
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reasonStr = "Inputs (except for vertex shader inputs) not declared with a location layout qualifier have effective location of -1";
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isOutputVariable && !isFragmentShader && explicitLayoutLocation == -1)
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expectLocation = false;
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reasonStr = "Outputs (except for fragment shader outputs) not declared with a location layout qualifier have effective location of -1";
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expectLocation = true;
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!expectLocation)
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying uniform location, expecting -1. (" << reasonStr << ")" << tcu::TestLog::EndMessage;
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue != -1)
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource location invalid");
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool locationOk;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (explicitLayoutLocation == -1)
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting a valid location" << tcu::TestLog::EndMessage;
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			locationOk = (propValue != -1);
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting " << explicitLayoutLocation << tcu::TestLog::EndMessage;
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			locationOk = (propValue == explicitLayoutLocation);
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!locationOk)
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("resource location invalid");
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariablePathComponent		nullComponent;
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariablePathComponent&	enclosingcomponent	= (path.size() > 1) ? (path[path.size()-2]) : (nullComponent);
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool						isArray				= enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType();
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::Functions&			gl					= m_renderContext.getFunctions();
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::Storage				storage				= (path.front().isInterfaceBlock()) ? (path.front().getInterfaceBlock()->storage) : (path.front().getDeclaration()->storage);
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::GLenum				interface			= getProgramDefaultBlockInterfaceFromStorage(storage);
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Comparing location to the values returned by GetProgramResourceLocation" << tcu::TestLog::EndMessage;
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Test all bottom-level array elements
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isArray)
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const std::string arrayResourceName = (resource.size() > 3) ? (resource.substr(0, resource.size() - 3)) : (""); // chop "[0]"
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int arrayElementNdx = 0; arrayElementNdx < enclosingcomponent.getVariableType()->getArraySize(); ++arrayElementNdx)
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const std::string	elementResourceName	= arrayResourceName + "[" + de::toString(arrayElementNdx) + "]";
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glw::GLint	location			= gl.getProgramResourceLocation(m_programID, interface, elementResourceName.c_str());
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (location != propValue+arrayElementNdx)
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.getLog()
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::TestLog::Message
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< "\tError, getProgramResourceLocation (resource=\"" << elementResourceName << "\") returned location " << location
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< ", expected " << (propValue+arrayElementNdx)
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::TestLog::EndMessage;
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						setError("resource location invalid");
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.getLog() << tcu::TestLog::Message << "\tLocation of \"" << elementResourceName << "\":\t" << location << tcu::TestLog::EndMessage;
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glw::GLint location = gl.getProgramResourceLocation(m_programID, interface, resource.c_str());
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (location != propValue)
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "\tError, getProgramResourceLocation returned location " << location << ", expected " << propValue << tcu::TestLog::EndMessage;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					setError("resource location invalid");
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid LocationValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
9578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
9588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_UNREF(resource);
9598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
9608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// built-ins have no location
9618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
9628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting -1" << tcu::TestLog::EndMessage;
9638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
9648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (propValue != -1)
9658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
9668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
9678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		setError("resource location invalid");
9688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
9698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
9708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VariableNameLengthValidator : public SingleVariableValidator
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				VariableNameLengthValidator	(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable		(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateBuiltinVariable		(const std::string& resource, glw::GLint propValue) const;
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateNameLength			(const std::string& resource, glw::GLint propValue) const;
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9803c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVariableNameLengthValidator::VariableNameLengthValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH, programID, filter)
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VariableNameLengthValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(path);
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	validateNameLength(resource, propValue);
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VariableNameLengthValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	validateNameLength(resource, propValue);
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VariableNameLengthValidator::validateNameLength (const std::string& resource, glw::GLint propValue) const
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int expected = (int)resource.length() + 1; // includes null byte
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " (" << (int)resource.length() << " for \"" << resource << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage;
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (propValue != expected)
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue << tcu::TestLog::EndMessage;
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("name length invalid");
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass OffsetValidator : public SingleVariableValidator
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				OffsetValidator			(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable	(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10153c827367444ee418f129b2c238299f49d3264554Jarkko PoyryOffsetValidator::OffsetValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_OFFSET, programID, filter)
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid OffsetValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool isAtomicCounterUniform		= glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType());
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool isBufferBackedBlockStorage	= path.front().isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(path.front().getInterfaceBlock()->storage);
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isAtomicCounterUniform && !isBufferBackedBlockStorage)
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Not buffer backed
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying offset, expecting -1" << tcu::TestLog::EndMessage;
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue != -1)
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid offset, got " << propValue << tcu::TestLog::EndMessage;
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("offset invalid");
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Expect a valid offset
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying offset, expecting a valid offset" << tcu::TestLog::EndMessage;
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue < 0)
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid offset, got " << propValue << tcu::TestLog::EndMessage;
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("offset invalid");
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VariableReferencedByShaderValidator : public PropValidator
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								VariableReferencedByShaderValidator	(Context& context, const VariableSearchFilter& searchFilter);
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string					getHumanReadablePropertyString		(glw::GLint propVal) const;
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						validate							(const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const;
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariableSearchFilter	m_filter;
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVariableReferencedByShaderValidator::VariableReferencedByShaderValidator (Context& context, const VariableSearchFilter& searchFilter)
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: PropValidator	(context, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER)
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_filter		(searchFilter)
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string VariableReferencedByShaderValidator::getHumanReadablePropertyString	(glw::GLint propVal) const
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::toString(glu::getBooleanStr(propVal));
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VariableReferencedByShaderValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VariablePathComponent>	dummyPath;
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool							referencedByShader = findProgramVariablePathByPathName(dummyPath, program, resource, m_filter);
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Verifying referenced by " << glu::getShaderTypeName(m_filter.getShaderTypeFilter()) << " shader, expecting "
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((referencedByShader) ? ("GL_TRUE") : ("GL_FALSE"))
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (propValue != ((referencedByShader) ? (1) : (0)))
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid referenced_by_" << glu::getShaderTypeName(m_filter.getShaderTypeFilter()) << ", got " << propValue << tcu::TestLog::EndMessage;
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("referenced_by_" + std::string(glu::getShaderTypeName(m_filter.getShaderTypeFilter())) + " invalid");
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BlockNameLengthValidator : public SingleBlockValidator
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BlockNameLengthValidator	(Context& context, const glw::GLuint programID, const VariableSearchFilter& filter);
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	validateSingleBlock			(const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue) const;
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBlockNameLengthValidator::BlockNameLengthValidator (Context& context, const glw::GLuint programID, const VariableSearchFilter& filter)
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleBlockValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH, programID, filter)
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BlockNameLengthValidator::validateSingleBlock (const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue) const
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(instanceIndex);
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(block);
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int expected = (int)resource.length() + 1; // includes null byte
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " (" << (int)resource.length() << " for \"" << resource << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage;
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (propValue != expected)
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue << tcu::TestLog::EndMessage;
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("name length invalid");
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BufferBindingValidator : public SingleBlockValidator
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BufferBindingValidator	(Context& context, const glw::GLuint programID, const VariableSearchFilter& filter);
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	validateSingleBlock		(const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue) const;
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferBindingValidator::BufferBindingValidator (Context& context, const glw::GLuint programID, const VariableSearchFilter& filter)
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleBlockValidator(context, PROGRAMRESOURCEPROP_BUFFER_BINDING, programID, filter)
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferBindingValidator::validateSingleBlock (const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue) const
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (block.layout.binding != -1)
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int flatIndex		= 0;
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int dimensionSize	= 1;
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int dimensionNdx = (int)(block.dimensions.size()) - 1; dimensionNdx >= 0; --dimensionNdx)
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			flatIndex += dimensionSize * instanceIndex[dimensionNdx];
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dimensionSize *= block.dimensions[dimensionNdx];
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int expected = (block.dimensions.empty()) ? (block.layout.binding) : (block.layout.binding + flatIndex);
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block binding, expecting " << expected << tcu::TestLog::EndMessage;
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue != expected)
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid buffer binding, got " << propValue << tcu::TestLog::EndMessage;
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("buffer binding invalid");
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying buffer binding, expecting a valid binding" << tcu::TestLog::EndMessage;
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue < 0)
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid buffer binding, got " << propValue << tcu::TestLog::EndMessage;
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("buffer binding invalid");
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BlockReferencedByShaderValidator : public PropValidator
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								BlockReferencedByShaderValidator	(Context& context, const VariableSearchFilter& searchFilter);
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string					getHumanReadablePropertyString		(glw::GLint propVal) const;
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						validate							(const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const;
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VariableSearchFilter	m_filter;
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11793c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBlockReferencedByShaderValidator::BlockReferencedByShaderValidator (Context& context, const VariableSearchFilter& searchFilter)
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: PropValidator	(context, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER)
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_filter		(searchFilter)
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string BlockReferencedByShaderValidator::getHumanReadablePropertyString	(glw::GLint propVal) const
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::toString(glu::getBooleanStr(propVal));
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BlockReferencedByShaderValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string	blockName			= glu::parseVariableName(resource.c_str());
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				referencedByShader	= false;
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx];
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_filter.matchesFilter(shader))
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx)
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::InterfaceBlock& block = shader->getDefaultBlock().interfaceBlocks[blockNdx];
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_filter.matchesFilter(block) && block.interfaceName == blockName)
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				referencedByShader = true;
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Verifying referenced by " << glu::getShaderTypeName(m_filter.getShaderTypeFilter()) << " shader, expecting "
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((referencedByShader) ? ("GL_TRUE") : ("GL_FALSE"))
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (propValue != ((referencedByShader) ? (1) : (0)))
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid referenced_by_" << glu::getShaderTypeName(m_filter.getShaderTypeFilter()) << ", got " << propValue << tcu::TestLog::EndMessage;
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("referenced_by_" + std::string(glu::getShaderTypeName(m_filter.getShaderTypeFilter())) + " invalid");
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TopLevelArraySizeValidator : public SingleVariableValidator
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TopLevelArraySizeValidator	(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable		(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12323c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTopLevelArraySizeValidator::TopLevelArraySizeValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_SIZE, programID, filter)
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TopLevelArraySizeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			expected;
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string	reason;
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_BUFFER);
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!path[1].getDeclaration()->varType.isArrayType())
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expected = 1;
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reason = "Top-level block member is not an array";
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (path[1].getDeclaration()->varType.getElementType().isBasicType())
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expected = 1;
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reason = "Top-level block member is not an array of an aggregate type";
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (path[1].getDeclaration()->varType.getArraySize() == glu::VarType::UNSIZED_ARRAY)
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expected = 0;
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reason = "Top-level block member is an unsized top-level array";
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		expected = path[1].getDeclaration()->varType.getArraySize();
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reason = "Top-level block member is a sized top-level array";
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array size, expecting " << expected << ". (" << reason << ")." << tcu::TestLog::EndMessage;
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (propValue != expected)
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid top level array size, got " << propValue << tcu::TestLog::EndMessage;
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("top level array size invalid");
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TopLevelArrayStrideValidator : public SingleVariableValidator
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TopLevelArrayStrideValidator	(Context& context, glw::GLuint programID, const VariableSearchFilter& filter);
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		validateSingleVariable			(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12823c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTopLevelArrayStrideValidator::TopLevelArrayStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter)
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: SingleVariableValidator(context, PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_STRIDE, programID, filter)
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TopLevelArrayStrideValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_BUFFER);
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(resource);
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!path[1].getDeclaration()->varType.isArrayType())
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array stride, expecting 0. (Top-level block member is not an array)." << tcu::TestLog::EndMessage;
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue != 0)
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, top level array stride, got " << propValue << tcu::TestLog::EndMessage;
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("top level array stride invalid");
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (path[1].getDeclaration()->varType.getElementType().isBasicType())
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array stride, expecting 0. (Top-level block member is not an array of an aggregate type)." << tcu::TestLog::EndMessage;
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue != 0)
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, top level array stride, got " << propValue << tcu::TestLog::EndMessage;
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("top level array stride invalid");
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int minimumStride = getVarTypeSize(path[1].getDeclaration()->varType.getElementType());
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array stride, expecting greater or equal to " << minimumStride << "." << tcu::TestLog::EndMessage;
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (propValue < minimumStride)
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid top level array stride, got " << propValue << tcu::TestLog::EndMessage;
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setError("top level array stride invalid");
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
132679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryclass TransformFeedbackResourceValidator : public PropValidator
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
132979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry					TransformFeedbackResourceValidator	(Context& context, ProgramResourcePropFlags validationProp);
133079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void			validate							(const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const;
133179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
133279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryprivate:
133379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	virtual void	validateBuiltinVariable				(const std::string& resource, glw::GLint propValue) const = 0;
133479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	virtual void	validateSingleVariable				(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const = 0;
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
133779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
133879ec52223daa917719d5d0555e7d8020d6514951Jarkko PöyryTransformFeedbackResourceValidator::TransformFeedbackResourceValidator (Context& context, ProgramResourcePropFlags validationProp)
133979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	: PropValidator(context, validationProp)
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
134379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackResourceValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (deStringBeginsWith(resource.c_str(), "gl_"))
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
134779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		validateBuiltinVariable(resource, propValue);
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
135179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		// Check resource name is a xfb output. (sanity check)
135279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry#if defined(DE_DEBUG)
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool generatorFound = false;
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
135579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		// Check the resource name is a valid transform feedback resource and find the name generating resource
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
135879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			const std::string					varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::vector<VariablePathComponent>	path;
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::vector<std::string>			resources;
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!findProgramVariablePathByPathName(path, program, varyingName, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// program does not contain feedback varying, not valid program
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return;
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
136979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			generateVariableTypeResourceNames(resources, varyingName, *path.back().getVariableType(), RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (de::contains(resources.begin(), resources.end(), resource))
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				generatorFound = true;
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
137879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		// resource name was not found, should never happen
137979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		DE_ASSERT(generatorFound);
138079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		DE_UNREF(generatorFound);
138179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry#endif
138279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
138379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		// verify resource
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
138579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			std::vector<VariablePathComponent> path;
138679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
138779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			if (!findProgramVariablePathByPathName(path, program, resource, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
138879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				DE_ASSERT(false);
138979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
139079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			validateSingleVariable(path, resource, propValue);
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
139379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
139479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
139579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryclass TransformFeedbackArraySizeValidator : public TransformFeedbackResourceValidator
139679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
139779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyrypublic:
139879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				TransformFeedbackArraySizeValidator	(Context& context);
139979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
140079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void		validateBuiltinVariable				(const std::string& resource, glw::GLint propValue) const;
140179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void		validateSingleVariable				(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
140279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry};
140379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
140479ec52223daa917719d5d0555e7d8020d6514951Jarkko PöyryTransformFeedbackArraySizeValidator::TransformFeedbackArraySizeValidator (Context& context)
140579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	: TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_ARRAY_SIZE)
140679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
140779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
140879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
140979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackArraySizeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
141079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
141179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	int arraySize = 0;
141279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
141379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	if (resource == "gl_Position")
141479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		arraySize = 1;
141579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	else
141679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		DE_ASSERT(false);
141779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
141879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage;
141979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	if (arraySize != propValue)
142079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	{
142179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
142279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		setError("resource array size invalid");
142379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	}
142479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
142579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
142679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackArraySizeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
142779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
142879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	DE_UNREF(resource);
142979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
143079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	const int arraySize = (path.back().getVariableType()->isArrayType()) ? (path.back().getVariableType()->getArraySize()) : (1);
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage;
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (arraySize != propValue)
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setError("resource array size invalid");
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
144079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryclass TransformFeedbackNameLengthValidator : public TransformFeedbackResourceValidator
144179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
144279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyrypublic:
144379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				TransformFeedbackNameLengthValidator	(Context& context);
144479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
144579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryprivate:
144679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void		validateBuiltinVariable					(const std::string& resource, glw::GLint propValue) const;
144779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void		validateSingleVariable					(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
144879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void		validateVariable						(const std::string& resource, glw::GLint propValue) const;
144979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry};
145079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
145179ec52223daa917719d5d0555e7d8020d6514951Jarkko PöyryTransformFeedbackNameLengthValidator::TransformFeedbackNameLengthValidator (Context& context)
145279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	: TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH)
145379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
145479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
145579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
145679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackNameLengthValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
145779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
145879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	validateVariable(resource, propValue);
145979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
146079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
146179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackNameLengthValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
146279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
146379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	DE_UNREF(path);
146479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	validateVariable(resource, propValue);
146579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
146679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
146779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackNameLengthValidator::validateVariable (const std::string& resource, glw::GLint propValue) const
146879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
146979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	const int expected = (int)resource.length() + 1; // includes null byte
147079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " (" << (int)resource.length() << " for \"" << resource << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage;
147179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
147279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	if (propValue != expected)
147379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	{
147479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue << tcu::TestLog::EndMessage;
147579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		setError("name length invalid");
147679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	}
147779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
147879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
147979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryclass TransformFeedbackTypeValidator : public TransformFeedbackResourceValidator
148079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
148179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyrypublic:
148279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				TransformFeedbackTypeValidator		(Context& context);
148379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
148479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void		validateBuiltinVariable				(const std::string& resource, glw::GLint propValue) const;
148579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	void		validateSingleVariable				(const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
148679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry};
148779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
148879ec52223daa917719d5d0555e7d8020d6514951Jarkko PöyryTransformFeedbackTypeValidator::TransformFeedbackTypeValidator (Context& context)
148979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	: TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_TYPE)
149079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
149179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
149279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
149379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackTypeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
149479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
149579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	glu::DataType varType = glu::TYPE_INVALID;
149679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
149779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	if (resource == "gl_Position")
149879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		varType = glu::TYPE_FLOAT_VEC4;
149979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	else
150079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		DE_ASSERT(false);
150179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
150279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(varType) << tcu::TestLog::EndMessage;
150379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	if (glu::getDataTypeFromGLType(propValue) != varType)
150479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	{
150579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
150679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		setError("resource type invalid");
150779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	}
150879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	return;
150979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
151079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
151179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid TransformFeedbackTypeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
151279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry{
151379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	DE_UNREF(resource);
151479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
151579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	// Unlike other interfaces, xfb program interface uses just variable name to refer to arrays of basic types. (Others use "variable[0]")
151679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	// Thus we might end up querying a type for an array. In this case, return the type of an array element.
151779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	const glu::VarType& variable    = *path.back().getVariableType();
151879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	const glu::VarType& elementType = (variable.isArrayType()) ? (variable.getElementType()) : (variable);
151979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
152079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	DE_ASSERT(elementType.isBasicType());
152179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
152279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(elementType.getBasicType()) << tcu::TestLog::EndMessage;
152379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	if (elementType.getBasicType() != glu::getDataTypeFromGLType(propValue))
152479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	{
152579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
152679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		setError("resource type invalid");
152779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	}
152879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry}
152979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15323c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramResourceQueryTestTarget::ProgramResourceQueryTestTarget (ProgramInterface interface_, deUint32 propFlags_)
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: interface(interface_)
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, propFlags(propFlags_)
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (interface)
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM:						DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_UNIFORM_INTERFACE_MASK)			== propFlags);	break;
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM_BLOCK:				DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_UNIFORM_BLOCK_INTERFACE_MASK)	== propFlags);	break;
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:			DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_SHADER_STORAGE_BLOCK_MASK)		== propFlags);	break;
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_INPUT:				DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_PROGRAM_INPUT_MASK)				== propFlags);	break;
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_OUTPUT:				DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_PROGRAM_OUTPUT_MASK)				== propFlags);	break;
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_BUFFER_VARIABLE:				DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_BUFFER_VARIABLE_MASK)			== propFlags);	break;
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:	DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_TRANSFORM_FEEDBACK_VARYING_MASK)	== propFlags);	break;
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15513c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramInterfaceQueryTestCase::ProgramInterfaceQueryTestCase (Context& context, const char* name, const char* description, ProgramResourceQueryTestTarget queryTarget)
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(context, name, description)
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_queryTarget	(queryTarget)
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15573c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramInterfaceQueryTestCase::~ProgramInterfaceQueryTestCase (void)
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramInterface ProgramInterfaceQueryTestCase::getTargetInterface (void) const
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_queryTarget.interface;
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glw::GLenum getGLInterfaceEnumValue (ProgramInterface interface)
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (interface)
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM:						return GL_UNIFORM;
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM_BLOCK:				return GL_UNIFORM_BLOCK;
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER:		return GL_ATOMIC_COUNTER_BUFFER;
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_INPUT:				return GL_PROGRAM_INPUT;
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_OUTPUT:				return GL_PROGRAM_OUTPUT;
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:	return GL_TRANSFORM_FEEDBACK_VARYING;
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_BUFFER_VARIABLE:				return GL_BUFFER_VARIABLE;
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:			return GL_SHADER_STORAGE_BLOCK;
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void queryAndValidateProps (tcu::TestContext& testCtx, const glw::Functions& gl, glw::GLuint programID, ProgramInterface interface, const char* targetResourceName, const ProgramInterfaceDefinition::Program* programDefinition, const std::vector<glw::GLenum>& props, const std::vector<const PropValidator*>& validators)
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::GLenum			glInterface		= getGLInterfaceEnumValue(interface);
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint					resourceNdx;
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLint					written			= -1;
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<glw::GLint>		propValues		(props.size() + 1, -2);	// prefill result buffer with an invalid value. -1 might be valid sometimes, avoid it. Make buffer one larger to allow detection of too many return values
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(props.size() == validators.size());
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// query
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	resourceNdx = gl.getProgramResourceIndex(programID, glInterface, targetResourceName);
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "get resource index");
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (resourceNdx == GL_INVALID_INDEX)
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		testCtx.getLog() << tcu::TestLog::Message << "getProgramResourceIndex returned GL_INVALID_INDEX for \"" << targetResourceName << "\"" << tcu::TestLog::EndMessage;
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "could not find target resource");
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// try to recover but keep the test result as failure
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::string	resourceName			= std::string(targetResourceName);
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::string			simplifiedResourceName;
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (stringEndsWith(resourceName, "[0]"))
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				simplifiedResourceName = resourceName.substr(0, resourceName.length() - 3);
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const size_t lastMember = resourceName.find_last_of('.');
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (lastMember != std::string::npos)
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					simplifiedResourceName = resourceName.substr(0, lastMember);
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (simplifiedResourceName.empty())
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return;
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			resourceNdx = gl.getProgramResourceIndex(programID, glInterface, simplifiedResourceName.c_str());
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "get resource index");
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (resourceNdx == GL_INVALID_INDEX)
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return;
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			testCtx.getLog() << tcu::TestLog::Message << "\tResource not found, continuing anyway using index obtained for resource \"" << simplifiedResourceName << "\"" << tcu::TestLog::EndMessage;
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getProgramResourceiv(programID, glInterface, resourceNdx, (int)props.size(), &props[0], (int)propValues.size(), &written, &propValues[0]);
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "get props");
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (written != (int)props.size())
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		testCtx.getLog() << tcu::TestLog::Message << "getProgramResourceiv returned unexpected number of values, expected " << (int)props.size() << ", got " << written << tcu::TestLog::EndMessage;
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "getProgramResourceiv returned unexpected number of values");
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (propValues.back() != -2)
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		testCtx.getLog() << tcu::TestLog::Message << "getProgramResourceiv post write buffer guard value was modified, too many return values" << tcu::TestLog::EndMessage;
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "getProgramResourceiv returned unexpected number of values");
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	propValues.pop_back();
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(validators.size() == propValues.size());
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// log
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::MessageBuilder message(&testCtx.getLog());
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		message << "For resource index " << resourceNdx << " (\"" << targetResourceName << "\") got following properties:\n";
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int propNdx = 0; propNdx < (int)propValues.size(); ++propNdx)
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			message << "\t" << glu::getProgramResourcePropertyName(props[propNdx]) << ":\t" << validators[propNdx]->getHumanReadablePropertyString(propValues[propNdx]) << "\n";
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		message << tcu::TestLog::EndMessage;
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// validate
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int propNdx = 0; propNdx < (int)propValues.size(); ++propNdx)
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		validators[propNdx]->validate(programDefinition, targetResourceName, propValues[propNdx]);
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramInterfaceQueryTestCase::IterateResult ProgramInterfaceQueryTestCase::iterate (void)
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct TestProperty
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLenum				prop;
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const PropValidator*	validator;
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ProgramInterfaceDefinition::Program*	programDefinition	= getProgramDefinition();
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::vector<std::string>				targetResources		= getQueryTargetResources();
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram							program				(m_context.getRenderContext(), generateProgramInterfaceProgramSources(programDefinition));
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(programDefinition->isValid());
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Log program
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program");
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Feedback varyings
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!programDefinition->getTransformFeedbackVaryings().empty())
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::MessageBuilder builder(&m_testCtx.getLog());
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			builder << "Transform feedback varyings: {";
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < (int)programDefinition->getTransformFeedbackVaryings().size(); ++ndx)
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ndx)
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					builder << ", ";
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "\"" << programDefinition->getTransformFeedbackVaryings()[ndx] << "\"";
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			builder << "}" << tcu::TestLog::EndMessage;
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << program;
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!program.isOk())
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Program build failed, checking if program exceeded implementation limits" << tcu::TestLog::EndMessage;
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			checkProgramResourceUsage(programDefinition, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// within limits
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("could not build program");
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check interface props
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_queryTarget.interface)
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM:
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableSearchFilter					uniformFilter						(glu::SHADERTYPE_LAST, glu::STORAGE_UNIFORM);
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TypeValidator							typeValidator						(m_context, program.getProgram(), uniformFilter);
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const ArraySizeValidator					arraySizeValidator					(m_context, program.getProgram(), uniformFilter);
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const ArrayStrideValidator					arrayStrideValidator				(m_context, program.getProgram(), uniformFilter);
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockIndexValidator					blockIndexValidator					(m_context, program.getProgram(), uniformFilter);
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const IsRowMajorValidator					isRowMajorValidator					(m_context, program.getProgram(), uniformFilter);
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const MatrixStrideValidator					matrixStrideValidator				(m_context, program.getProgram(), uniformFilter);
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const AtomicCounterBufferIndexVerifier		atomicCounterBufferIndexVerifier	(m_context, program.getProgram(), uniformFilter);
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const LocationValidator						locationValidator					(m_context, program.getProgram(), uniformFilter);
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableNameLengthValidator			nameLengthValidator					(m_context, program.getProgram(), uniformFilter);
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const OffsetValidator						offsetVerifier						(m_context, program.getProgram(), uniformFilter);
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByVertexVerifier			(m_context, VariableSearchFilter(glu::SHADERTYPE_VERTEX,	glu::STORAGE_UNIFORM));
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByFragmentVerifier		(m_context, VariableSearchFilter(glu::SHADERTYPE_FRAGMENT,	glu::STORAGE_UNIFORM));
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByComputeVerifier			(m_context, VariableSearchFilter(glu::SHADERTYPE_COMPUTE,	glu::STORAGE_UNIFORM));
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TestProperty allProperties[] =
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_ARRAY_SIZE,					&arraySizeValidator					},
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_ARRAY_STRIDE,					&arrayStrideValidator				},
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_ATOMIC_COUNTER_BUFFER_INDEX,	&atomicCounterBufferIndexVerifier	},
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_BLOCK_INDEX,					&blockIndexValidator				},
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_IS_ROW_MAJOR,					&isRowMajorValidator				},
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_LOCATION,						&locationValidator					},
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MATRIX_STRIDE,					&matrixStrideValidator				},
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_NAME_LENGTH,					&nameLengthValidator				},
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_OFFSET,						&offsetVerifier						},
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_VERTEX_SHADER,	&referencedByVertexVerifier			},
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_FRAGMENT_SHADER,	&referencedByFragmentVerifier		},
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_COMPUTE_SHADER,	&referencedByComputeVerifier		},
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_TYPE,							&typeValidator						},
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection			section			(m_testCtx.getLog(), "UniformResource", "Uniform resource \"" +  targetResources[targetResourceNdx] + "\"");
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glw::Functions&				gl				= m_context.getRenderContext().getFunctions();
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<glw::GLenum>			props;
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<const PropValidator*>	validators;
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						allProperties[propNdx].validator->isSupported())
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						props.push_back(allProperties[propNdx].prop);
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						validators.push_back(allProperties[propNdx].validator);
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!props.empty());
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM_BLOCK:
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::Storage						storage								= (m_queryTarget.interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableSearchFilter				blockFilter							(glu::SHADERTYPE_LAST, storage);
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockNameLengthValidator			nameLengthValidator					(m_context, program.getProgram(), blockFilter);
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockReferencedByShaderValidator	referencedByVertexVerifier			(m_context, VariableSearchFilter(glu::SHADERTYPE_VERTEX,	storage));
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockReferencedByShaderValidator	referencedByFragmentVerifier		(m_context, VariableSearchFilter(glu::SHADERTYPE_FRAGMENT,	storage));
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockReferencedByShaderValidator	referencedByComputeVerifier			(m_context, VariableSearchFilter(glu::SHADERTYPE_COMPUTE,	storage));
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferBindingValidator			bufferBindingValidator				(m_context, program.getProgram(), blockFilter);
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TestProperty allProperties[] =
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_NAME_LENGTH,					&nameLengthValidator				},
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_VERTEX_SHADER,	&referencedByVertexVerifier			},
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_FRAGMENT_SHADER,	&referencedByFragmentVerifier		},
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_COMPUTE_SHADER,	&referencedByComputeVerifier		},
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_BUFFER_BINDING,				&bufferBindingValidator				},
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection			section			(m_testCtx.getLog(), "BlockResource", "Interface block \"" +  targetResources[targetResourceNdx] + "\"");
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glw::Functions&				gl				= m_context.getRenderContext().getFunctions();
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<glw::GLenum>			props;
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<const PropValidator*>	validators;
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						allProperties[propNdx].validator->isSupported())
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						props.push_back(allProperties[propNdx].prop);
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						validators.push_back(allProperties[propNdx].validator);
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!props.empty());
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_INPUT:
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_OUTPUT:
18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::Storage							storage							= (m_queryTarget.interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT);
18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::ShaderType						shaderType						= (m_queryTarget.interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (programDefinition->getFirstStage()) : (programDefinition->getLastStage());
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableSearchFilter					variableFilter					(shaderType, storage);
18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TypeValidator							typeValidator					(m_context, program.getProgram(), variableFilter);
18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const ArraySizeValidator					arraySizeValidator				(m_context, program.getProgram(), variableFilter);
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const LocationValidator						locationValidator				(m_context, program.getProgram(), variableFilter);
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableNameLengthValidator			nameLengthValidator				(m_context, program.getProgram(), variableFilter);
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByVertexVerifier		(m_context, VariableSearchFilter::intersection(VariableSearchFilter(glu::SHADERTYPE_VERTEX,		storage), variableFilter));
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByFragmentVerifier	(m_context, VariableSearchFilter::intersection(VariableSearchFilter(glu::SHADERTYPE_FRAGMENT,	storage), variableFilter));
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByComputeVerifier		(m_context, VariableSearchFilter::intersection(VariableSearchFilter(glu::SHADERTYPE_COMPUTE,	storage), variableFilter));
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TestProperty allProperties[] =
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_ARRAY_SIZE,					&arraySizeValidator				},
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_LOCATION,						&locationValidator				},
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_NAME_LENGTH,					&nameLengthValidator			},
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_VERTEX_SHADER,	&referencedByVertexVerifier		},
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_FRAGMENT_SHADER,	&referencedByFragmentVerifier	},
18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_COMPUTE_SHADER,	&referencedByComputeVerifier	},
18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_TYPE,							&typeValidator					},
18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const std::string					resourceInterfaceName	= (m_queryTarget.interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? ("Input") : ("Output");
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection			section					(m_testCtx.getLog(), "BlockResource", resourceInterfaceName + " resource \"" +  targetResources[targetResourceNdx] + "\"");
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glw::Functions&				gl						= m_context.getRenderContext().getFunctions();
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<glw::GLenum>			props;
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<const PropValidator*>	validators;
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						allProperties[propNdx].validator->isSupported())
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						props.push_back(allProperties[propNdx].prop);
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						validators.push_back(allProperties[propNdx].validator);
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!props.empty());
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_BUFFER_VARIABLE:
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableSearchFilter					variableFilter					(glu::SHADERTYPE_LAST, glu::STORAGE_BUFFER);
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TypeValidator							typeValidator					(m_context, program.getProgram(), variableFilter);
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const ArraySizeValidator					arraySizeValidator				(m_context, program.getProgram(), variableFilter);
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const ArrayStrideValidator					arrayStrideValidator			(m_context, program.getProgram(), variableFilter);
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockIndexValidator					blockIndexValidator				(m_context, program.getProgram(), variableFilter);
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const IsRowMajorValidator					isRowMajorValidator				(m_context, program.getProgram(), variableFilter);
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const MatrixStrideValidator					matrixStrideValidator			(m_context, program.getProgram(), variableFilter);
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const OffsetValidator						offsetValidator					(m_context, program.getProgram(), variableFilter);
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableNameLengthValidator			nameLengthValidator				(m_context, program.getProgram(), variableFilter);
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByVertexVerifier		(m_context, VariableSearchFilter(glu::SHADERTYPE_VERTEX,	glu::STORAGE_BUFFER));
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByFragmentVerifier	(m_context, VariableSearchFilter(glu::SHADERTYPE_FRAGMENT,	glu::STORAGE_BUFFER));
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VariableReferencedByShaderValidator	referencedByComputeVerifier		(m_context, VariableSearchFilter(glu::SHADERTYPE_COMPUTE,	glu::STORAGE_BUFFER));
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TopLevelArraySizeValidator			topLevelArraySizeValidator		(m_context, program.getProgram(), variableFilter);
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TopLevelArrayStrideValidator			topLevelArrayStrideValidator	(m_context, program.getProgram(), variableFilter);
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TestProperty allProperties[] =
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_ARRAY_SIZE,					&arraySizeValidator				},
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_ARRAY_STRIDE,					&arrayStrideValidator			},
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_BLOCK_INDEX,					&blockIndexValidator			},
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_IS_ROW_MAJOR,					&isRowMajorValidator			},
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MATRIX_STRIDE,					&matrixStrideValidator			},
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_NAME_LENGTH,					&nameLengthValidator			},
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_OFFSET,						&offsetValidator				},
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_VERTEX_SHADER,	&referencedByVertexVerifier		},
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_FRAGMENT_SHADER,	&referencedByFragmentVerifier	},
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_REFERENCED_BY_COMPUTE_SHADER,	&referencedByComputeVerifier	},
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_TOP_LEVEL_ARRAY_SIZE,			&topLevelArraySizeValidator		},
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_TOP_LEVEL_ARRAY_STRIDE,		&topLevelArrayStrideValidator	},
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_TYPE,							&typeValidator					},
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection			section			(m_testCtx.getLog(), "BufferVariableResource", "Buffer variable \"" +  targetResources[targetResourceNdx] + "\"");
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glw::Functions&				gl				= m_context.getRenderContext().getFunctions();
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<glw::GLenum>			props;
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<const PropValidator*>	validators;
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						allProperties[propNdx].validator->isSupported())
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						props.push_back(allProperties[propNdx].prop);
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						validators.push_back(allProperties[propNdx].validator);
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!props.empty());
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
193679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			const TransformFeedbackTypeValidator		typeValidator			(m_context);
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TransformFeedbackArraySizeValidator	arraySizeValidator		(m_context);
193879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			const TransformFeedbackNameLengthValidator	nameLengthValidator		(m_context);
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const TestProperty allProperties[] =
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_ARRAY_SIZE,					&arraySizeValidator				},
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_NAME_LENGTH,					&nameLengthValidator			},
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_TYPE,							&typeValidator					},
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::ScopedLogSection			section			(m_testCtx.getLog(), "XFBVariableResource", "Transform feedback varying \"" +  targetResources[targetResourceNdx] + "\"");
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glw::Functions&				gl				= m_context.getRenderContext().getFunctions();
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<glw::GLenum>			props;
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::vector<const PropValidator*>	validators;
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						allProperties[propNdx].validator->isSupported())
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						props.push_back(allProperties[propNdx].prop);
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						validators.push_back(allProperties[propNdx].validator);
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(!props.empty());
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool checkLimit (glw::GLenum pname, int usage, const glw::Functions& gl, tcu::TestLog& log)
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (usage > 0)
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLint limit = 0;
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.getIntegerv(pname, &limit);
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "query limits");
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << tcu::TestLog::Message << "\t" << glu::getGettableStateStr(pname) << " = " << limit << ", test requires " << usage << tcu::TestLog::EndMessage;
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (limit < usage)
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << tcu::TestLog::Message << "\t\tLimit exceeded" << tcu::TestLog::EndMessage;
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool checkShaderResourceUsage (const ProgramInterfaceDefinition::Shader* shader, const glw::Functions& gl, tcu::TestLog& log)
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ProgramInterfaceDefinition::ShaderResourceUsage usage = getShaderResourceUsage(shader);
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (shader->getType())
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_VERTEX:
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const struct
20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glw::GLenum	pname;
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			usage;
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			} restrictions[] =
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_ATTRIBS,						usage.numInputVectors					},
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_UNIFORM_COMPONENTS,				usage.numDefaultBlockUniformComponents	},
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_UNIFORM_VECTORS,				usage.numUniformVectors					},
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_UNIFORM_BLOCKS,					usage.numUniformBlocks					},
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_OUTPUT_COMPONENTS,				usage.numOutputComponents				},
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,			usage.numSamplers						},
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS,			usage.numAtomicCounterBuffers			},
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_ATOMIC_COUNTERS,				usage.numAtomicCounters					},
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_IMAGE_UNIFORMS,					usage.numImages							},
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,	usage.numCombinedUniformComponents		},
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,			usage.numShaderStorageBlocks			},
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool allOk = true;
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << tcu::TestLog::Message << "Vertex shader:" << tcu::TestLog::EndMessage;
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return allOk;
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_FRAGMENT:
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const struct
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glw::GLenum	pname;
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			usage;
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			} restrictions[] =
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,			usage.numDefaultBlockUniformComponents		},
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_UNIFORM_VECTORS,				usage.numUniformVectors						},
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_UNIFORM_BLOCKS,				usage.numUniformBlocks						},
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_INPUT_COMPONENTS,				usage.numInputComponents					},
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_TEXTURE_IMAGE_UNITS,					usage.numSamplers							},
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS,		usage.numAtomicCounterBuffers				},
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_ATOMIC_COUNTERS,				usage.numAtomicCounters						},
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_IMAGE_UNIFORMS,				usage.numImages								},
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,	usage.numCombinedUniformComponents			},
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,		usage.numShaderStorageBlocks				},
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool allOk = true;
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << tcu::TestLog::Message << "Fragment shader:" << tcu::TestLog::EndMessage;
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return allOk;
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_COMPUTE:
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const struct
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glw::GLenum	pname;
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			usage;
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			} restrictions[] =
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMPUTE_UNIFORM_BLOCKS,				usage.numUniformBlocks					},
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS,			usage.numSamplers						},
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMPUTE_UNIFORM_COMPONENTS,			usage.numDefaultBlockUniformComponents	},
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS,		usage.numAtomicCounterBuffers			},
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMPUTE_ATOMIC_COUNTERS,				usage.numAtomicCounters					},
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMPUTE_IMAGE_UNIFORMS,				usage.numImages							},
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS,	usage.numCombinedUniformComponents		},
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS,			usage.numShaderStorageBlocks			},
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool allOk = true;
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << tcu::TestLog::Message << "Compute shader:" << tcu::TestLog::EndMessage;
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return allOk;
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool checkProgramCombinedResourceUsage (const ProgramInterfaceDefinition::Program* program, const glw::Functions& gl, tcu::TestLog& log)
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ProgramInterfaceDefinition::ProgramResourceUsage usage = getCombinedProgramResourceUsage(program);
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const struct
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLenum	pname;
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			usage;
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} restrictions[] =
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_UNIFORM_BUFFER_BINDINGS,						usage.uniformBufferMaxBinding+1				},
21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_UNIFORM_BLOCK_SIZE,							usage.uniformBufferMaxSize					},
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_UNIFORM_BLOCKS,						usage.numUniformBlocks						},
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,			usage.numCombinedVertexUniformComponents	},
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,			usage.numCombinedFragmentUniformComponents	},
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_VARYING_COMPONENTS,							usage.numVaryingComponents					},
21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_VARYING_VECTORS,								usage.numVaryingVectors						},
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,					usage.numCombinedSamplers					},
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES,				usage.numCombinedOutputResources			},
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,				usage.atomicCounterBufferMaxBinding+1		},
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE,					usage.atomicCounterBufferMaxSize			},
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS,				usage.numAtomicCounterBuffers				},
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_ATOMIC_COUNTERS,						usage.numAtomicCounters						},
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_IMAGE_UNITS,									usage.maxImageBinding						},
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_IMAGE_UNIFORMS,						usage.numCombinedImages						},
21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,				usage.shaderStorageBufferMaxBinding+1		},
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_SHADER_STORAGE_BLOCK_SIZE,						usage.shaderStorageBufferMaxSize			},
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS,				usage.numShaderStorageBlocks				},
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,		usage.numXFBInterleavedComponents			},
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,			usage.numXFBSeparateAttribs					},
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,		usage.numXFBSeparateComponents				},
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool allOk = true;
21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << tcu::TestLog::Message << "Program combined:" << tcu::TestLog::EndMessage;
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return allOk;
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid checkProgramResourceUsage (const ProgramInterfaceDefinition::Program* program, const glw::Functions& gl, tcu::TestLog& log)
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool limitExceeded = false;
21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		limitExceeded |= !checkShaderResourceUsage(program->getShaders()[shaderNdx], gl, log);
21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	limitExceeded |= !checkProgramCombinedResourceUsage(program, gl, log);
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (limitExceeded)
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << tcu::TestLog::Message << "One or more resource limits exceeded" << tcu::TestLog::EndMessage;
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("one or more resource limits exceeded");
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
2158