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 utilities
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fProgramInterfaceDefinitionUtil.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fProgramInterfaceDefinition.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarType.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarTypeUtil.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace ProgramInterfaceDefinition
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
483c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVariableSearchFilter VariableSearchFilter::intersection (const VariableSearchFilter& a, const VariableSearchFilter& b)
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool storageNonEmpty		= (a.m_storage == b.m_storage) || (a.m_storage == glu::STORAGE_LAST) || (b.m_storage == glu::STORAGE_LAST);
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool shaderTypeNonEmpty	= (a.m_shaderType == b.m_shaderType) || (a.m_shaderType == glu::SHADERTYPE_LAST) || (b.m_shaderType == glu::SHADERTYPE_LAST);
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return VariableSearchFilter((a.m_shaderType == glu::SHADERTYPE_LAST) ? (b.m_shaderType) : (a.m_shaderType),
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								(a.m_storage == glu::STORAGE_LAST) ? (b.m_storage) : (a.m_storage),
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								!storageNonEmpty || !shaderTypeNonEmpty || a.m_null || b.m_null);
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // ProgramInterfaceDefinition
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool incrementMultiDimensionIndex (std::vector<int>& index, const std::vector<int>& dimensions)
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int incrementDimensionNdx = (int)(index.size() - 1);
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (incrementDimensionNdx >= 0)
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (++index[incrementDimensionNdx] == dimensions[incrementDimensionNdx])
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			index[incrementDimensionNdx--] = 0;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (incrementDimensionNdx != -1);
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyryvoid generateVariableTypeResourceNames (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, deUint32 resourceNameGenerationFlags)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	DE_ASSERT((resourceNameGenerationFlags & (~RESOURCE_NAME_GENERATION_FLAG_MASK)) == 0);
7879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
7979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	// remove top-level flag from children
8079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	const deUint32 childFlags = resourceNameGenerationFlags & ~((deUint32)RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE);
8179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		resources.push_back(name);
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isStructType())
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::StructType* structType = type.getStructPtr();
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < structType->getNumMembers(); ++ndx)
8879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			generateVariableTypeResourceNames(resources, name + "." + structType->getMember(ndx).getName(), structType->getMember(ndx).getType(), childFlags);
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		// Bottom-level arrays of basic types of a transform feedback variable will produce only the first
9379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		// element but without the trailing "[0]"
9479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		if (type.getElementType().isBasicType() &&
9579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			(resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE) != 0)
9679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		{
9779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			resources.push_back(name);
9879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		}
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Bottom-level arrays of basic types and SSBO top-level arrays of any type procude only first element
10079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		else if (type.getElementType().isBasicType() ||
10179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				 (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) != 0)
10279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		{
10379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry			generateVariableTypeResourceNames(resources, name + "[0]", type.getElementType(), childFlags);
10479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		}
10579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		// Other arrays of aggregate types are expanded
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < type.getArraySize(); ++ndx)
10979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				generateVariableTypeResourceNames(resources, name + "[" + de::toString(ndx) + "]", type.getElementType(), childFlags);
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Program source generation
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing ProgramInterfaceDefinition::VariablePathComponent;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing ProgramInterfaceDefinition::VariableSearchFilter;
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getShaderTypeDeclarations (glu::ShaderType type)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_VERTEX:
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return	"";
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_FRAGMENT:
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return	"";
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_GEOMETRY:
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return	"layout(points) in;\n"
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"layout(points, max_vertices=3) out;\n";
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_TESSELLATION_CONTROL:
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return	"layout(vertices=1) out;\n";
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return	"layout(triangle, point_mode) in;\n";
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::SHADERTYPE_COMPUTE:
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return	"layout(local_size_x=1) in;\n";
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass StructNameEqualPredicate
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				StructNameEqualPredicate	(const char* name) : m_name(name) { }
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		operator()					(const glu::StructType* type) { return type->hasTypeName() && (deStringEqual(m_name, type->getTypeName()) == DE_TRUE); }
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*	m_name;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void collectNamedStructureDefinitions (std::vector<const glu::StructType*>& dst, const glu::VarType& type)
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return collectNamedStructureDefinitions(dst, type.getElementType());
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isStructType())
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (type.getStructPtr()->hasTypeName())
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// must be unique (may share the the same struct)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::vector<const glu::StructType*>::iterator where = std::find_if(dst.begin(), dst.end(), StructNameEqualPredicate(type.getStructPtr()->getTypeName()));
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (where != dst.end())
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(**where == *type.getStructPtr());
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// identical type has been added already, types of members must be added too
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Add types of members first
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			collectNamedStructureDefinitions(dst, type.getStructPtr()->getMember(ndx).getType());
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst.push_back(type.getStructPtr());
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeStructureDefinitions (std::ostringstream& buf, const ProgramInterfaceDefinition::DefaultBlock& defaultBlock)
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<const glu::StructType*> namedStructs;
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Collect all structs in post order
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)defaultBlock.variables.size(); ++ndx)
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		collectNamedStructureDefinitions(namedStructs, defaultBlock.variables[ndx].varType);
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < (int)defaultBlock.interfaceBlocks.size(); ++blockNdx)
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)defaultBlock.interfaceBlocks[blockNdx].variables.size(); ++ndx)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			collectNamedStructureDefinitions(namedStructs, defaultBlock.interfaceBlocks[blockNdx].variables[ndx].varType);
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Write
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int structNdx = 0; structNdx < (int)namedStructs.size(); ++structNdx)
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"struct " << namedStructs[structNdx]->getTypeName() << "\n"
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"{\n";
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int memberNdx = 0; memberNdx < namedStructs[structNdx]->getNumMembers(); ++memberNdx)
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << glu::indent(1) << glu::declare(namedStructs[structNdx]->getMember(memberNdx).getType(), namedStructs[structNdx]->getMember(memberNdx).getName(), 1) << ";\n";
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"};\n";
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!namedStructs.empty())
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\n";
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeInterfaceBlock (std::ostringstream& buf, const glu::InterfaceBlock& interfaceBlock)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << interfaceBlock.layout;
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (interfaceBlock.layout != glu::Layout())
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << " ";
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< glu::getStorageName(interfaceBlock.storage) << " " << interfaceBlock.interfaceName << "\n"
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n";
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)interfaceBlock.variables.size(); ++ndx)
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << glu::indent(1) << interfaceBlock.variables[ndx] << ";\n";
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "}";
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!interfaceBlock.instanceName.empty())
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << " " << interfaceBlock.instanceName;
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "[" << interfaceBlock.dimensions[dimensionNdx] << "]";
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << ";\n\n";
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeVariableReadAccumulateExpression (std::ostringstream& buf, const std::string& accumulatorName, const std::string& name, const glu::VarType& varType)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (varType.isBasicType())
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\t" << accumulatorName << " += ";
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeScalar(varType.getBasicType()))
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "vec4(float(" << name << "))";
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (glu::isDataTypeVector(varType.getBasicType()))
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "vec4(" << name << ".xyxy)";
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (glu::isDataTypeMatrix(varType.getBasicType()))
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "vec4(float(" << name << "[0][0]))";
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (glu::isDataTypeSamplerMultisample(varType.getBasicType()))
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "vec4(float(textureSize(" << name << ").x))";
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (glu::isDataTypeSampler(varType.getBasicType()))
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "vec4(float(textureSize(" << name << ", 0).x))";
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (glu::isDataTypeImage(varType.getBasicType()))
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "vec4(float(imageSize(" << name << ").x))";
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (varType.getBasicType() == glu::TYPE_UINT_ATOMIC_COUNTER)
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "vec4(float(atomicCounterIncrement(" << name << ")))";
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << ";\n";
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (varType.isStructType())
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeVariableReadAccumulateExpression(buf, accumulatorName, name + "." + varType.getStructPtr()->getMember(ndx).getName(), varType.getStructPtr()->getMember(ndx).getType());
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (varType.isArrayType())
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeVariableReadAccumulateExpression(buf, accumulatorName, name + "[" + de::toString(ndx) + "]", varType.getElementType());
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeVariableReadAccumulateExpression(buf, accumulatorName, name + "[8]", varType.getElementType());
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeInterfaceReadAccumulateExpression (std::ostringstream& buf, const std::string& accumulatorName, const glu::InterfaceBlock& block)
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (block.dimensions.empty())
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeVariableReadAccumulateExpression(buf, accumulatorName, prefix + block.variables[ndx].name, block.variables[ndx].varType);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<int> index(block.dimensions.size(), 0);
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (;;)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// access element
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::ostringstream name;
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << block.instanceName;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					name << "[" << index[dimensionNdx] << "]";
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					writeVariableReadAccumulateExpression(buf, accumulatorName, name.str() + "." + block.variables[ndx].name, block.variables[ndx].varType);
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// increment index
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!incrementMultiDimensionIndex(index, block.dimensions))
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeVariableWriteExpression (std::ostringstream& buf, const std::string& sourceVec4Name, const std::string& name, const glu::VarType& varType)
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (varType.isBasicType())
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\t" << name << " = ";
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeScalar(varType.getBasicType()))
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << sourceVec4Name << ".y)";
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (glu::isDataTypeVector(varType.getBasicType()) || glu::isDataTypeMatrix(varType.getBasicType()))
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << glu::getDataTypeName(glu::getDataTypeScalarType(varType.getBasicType())) << "(" << sourceVec4Name << ".y))";
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << ";\n";
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (varType.isStructType())
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeVariableWriteExpression(buf, sourceVec4Name, name + "." + varType.getStructPtr()->getMember(ndx).getName(), varType.getStructPtr()->getMember(ndx).getType());
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (varType.isArrayType())
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeVariableWriteExpression(buf, sourceVec4Name, name + "[" + de::toString(ndx) + "]", varType.getElementType());
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeVariableWriteExpression(buf, sourceVec4Name, name + "[9]", varType.getElementType());
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeInterfaceWriteExpression (std::ostringstream& buf, const std::string& sourceVec4Name, const glu::InterfaceBlock& block)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (block.dimensions.empty())
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeVariableWriteExpression(buf, sourceVec4Name, prefix + block.variables[ndx].name, block.variables[ndx].varType);
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<int> index(block.dimensions.size(), 0);
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (;;)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// access element
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::ostringstream name;
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << block.instanceName;
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					name << "[" << index[dimensionNdx] << "]";
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					writeVariableWriteExpression(buf, sourceVec4Name, name.str() + "." + block.variables[ndx].name, block.variables[ndx].varType);
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// increment index
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!incrementMultiDimensionIndex(index, block.dimensions))
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyrystatic bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const char* subPath, const glu::VarType& type)
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry	glu::VarTokenizer tokenizer(subPath);
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typePath.push_back(VariablePathComponent(&type));
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tokenizer.getToken() == glu::VarTokenizer::TOKEN_END)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isStructType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_PERIOD)
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tokenizer.advance();
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// malformed path
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_IDENTIFIER)
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (type.getStructPtr()->getMember(memberNdx).getName() == tokenizer.getIdentifier())
40879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getStructPtr()->getMember(memberNdx).getType());
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// malformed path, no such member
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET)
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tokenizer.advance();
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// malformed path
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_NUMBER)
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tokenizer.advance();
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_RIGHT_BRACKET)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getElementType());
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return false;
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const std::string& path, const glu::VariableDeclaration& var)
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (glu::parseVariableName(path.c_str()) != var.name)
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typePath.push_back(VariablePathComponent(&var));
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return traverseVariablePath(typePath, path.c_str() + var.name.length(), var.varType);
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool traverseShaderVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Shader* shader, const std::string& path, const VariableSearchFilter& filter)
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Default block variable?
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (filter.matchesFilter(shader->getDefaultBlock().variables[varNdx]))
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (traverseVariablePath(typePath, path, shader->getDefaultBlock().variables[varNdx]))
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// is variable an interface block variable?
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string blockName = glu::parseVariableName(path.c_str());
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!filter.matchesFilter(shader->getDefaultBlock().interfaceBlocks[interfaceNdx]))
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName)
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// resource is a member of a named interface block
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \note there is no array index specifier even if the interface is declared as an array of instances
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const std::string blockMemberPath = path.substr(blockName.size() + 1);
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const std::string blockMemeberName = glu::parseVariableName(blockMemberPath.c_str());
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return traverseVariablePath(typePath, blockMemberPath, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// terminate search
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].instanceName.empty())
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const std::string blockMemeberName = glu::parseVariableName(path.c_str());
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// unnamed block contains such variable?
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return traverseVariablePath(typePath, path, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// continue search
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return false;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool traverseProgramVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& path, const VariableSearchFilter& filter)
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (filter.matchesFilter(shader))
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note modifying output variable even when returning false
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			typePath.clear();
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (traverseShaderVariablePath(typePath, shader, path, filter))
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return false;
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool containsSubType (const glu::VarType& complexType, glu::DataType basicType)
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (complexType.isBasicType())
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return complexType.getBasicType() == basicType;
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (complexType.isArrayType())
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return containsSubType(complexType.getElementType(), basicType);
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (complexType.isStructType())
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (containsSubType(complexType.getStructPtr()->getMember(ndx).getType(), basicType))
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumShaderBlocks (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int retVal = 0;
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int numInstances = 1;
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal += numInstances;
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumAtomicCounterBuffers (const ProgramInterfaceDefinition::Shader* shader)
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::set<int> buffers;
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buffers.insert(shader->getDefaultBlock().variables[ndx].layout.binding);
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (int)buffers.size();
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <bool B>
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool dummyConstantTypeFilter (glu::DataType d)
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(d);
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return B;
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumTypeInstances (const glu::VarType& complexType, bool (*predicate)(glu::DataType))
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (complexType.isBasicType())
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (predicate(complexType.getBasicType()))
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 1;
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (complexType.isArrayType())
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int arraySize = (complexType.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (complexType.getArraySize());
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return arraySize * getNumTypeInstances(complexType.getElementType(), predicate);
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (complexType.isStructType())
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int sum = 0;
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sum += getNumTypeInstances(complexType.getStructPtr()->getMember(ndx).getType(), predicate);
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return sum;
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getMappedBasicTypeSum (const glu::VarType& complexType, int (*typeMap)(glu::DataType))
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (complexType.isBasicType())
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return typeMap(complexType.getBasicType());
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (complexType.isArrayType())
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int arraySize = (complexType.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (complexType.getArraySize());
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return arraySize * getMappedBasicTypeSum(complexType.getElementType(), typeMap);
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (complexType.isStructType())
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int sum = 0;
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sum += getMappedBasicTypeSum(complexType.getStructPtr()->getMember(ndx).getType(), typeMap);
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return sum;
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, bool (*predicate)(glu::DataType))
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int retVal = 0;
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int numInstances = 1;
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].variables.size(); ++varNdx)
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				retVal += numInstances * getNumTypeInstances(shader->getDefaultBlock().interfaceBlocks[ndx].variables[varNdx].varType, predicate);
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().variables[varNdx].storage == storage)
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal += getNumTypeInstances(shader->getDefaultBlock().variables[varNdx].varType, predicate);
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getMappedBasicTypeSum (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, int (*typeMap)(glu::DataType))
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int retVal = 0;
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int numInstances = 1;
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].variables.size(); ++varNdx)
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				retVal += numInstances * getMappedBasicTypeSum(shader->getDefaultBlock().interfaceBlocks[ndx].variables[varNdx].varType, typeMap);
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().variables[varNdx].storage == storage)
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal += getMappedBasicTypeSum(shader->getDefaultBlock().variables[varNdx].varType, typeMap);
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumDataTypeComponents (glu::DataType type)
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type))
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return glu::getDataTypeScalarSize(type);
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumDataTypeVectors (glu::DataType type)
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (glu::isDataTypeScalar(type))
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (glu::isDataTypeVector(type))
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (glu::isDataTypeMatrix(type))
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return glu::getDataTypeMatrixNumColumns(type);
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getMappedBasicTypeSum(shader, storage, getNumDataTypeComponents);
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumVectors (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getMappedBasicTypeSum(shader, storage, getNumDataTypeVectors);
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumDefaultBlockComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int retVal = 0;
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().variables[varNdx].storage == storage)
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal += getMappedBasicTypeSum(shader->getDefaultBlock().variables[varNdx].varType, getNumDataTypeComponents);
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getMaxBufferBinding (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int maxBinding = -1;
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	binding			= (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding);
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			numInstances	= 1;
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxBinding = de::max(maxBinding, binding + numInstances - 1);
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (int)maxBinding;
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getBufferTypeSize (glu::DataType type, glu::MatrixOrder order)
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// assume vec4 alignments, should produce values greater than or equal to the actual resource usage
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numVectors = 0;
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (glu::isDataTypeScalarOrVector(type))
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numVectors = 1;
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (glu::isDataTypeMatrix(type) && order == glu::MATRIXORDER_ROW_MAJOR)
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numVectors = glu::getDataTypeMatrixNumRows(type);
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (glu::isDataTypeMatrix(type) && order != glu::MATRIXORDER_ROW_MAJOR)
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numVectors = glu::getDataTypeMatrixNumColumns(type);
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 4 * numVectors;
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getBufferVariableSize (const glu::VarType& type, glu::MatrixOrder order)
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getBufferTypeSize(type.getBasicType(), order);
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int arraySize = (type.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (type.getArraySize());
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return arraySize * getBufferVariableSize(type.getElementType(), order);
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isStructType())
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int sum = 0;
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sum += getBufferVariableSize(type.getStructPtr()->getMember(ndx).getType(), order);
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return sum;
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getBufferSize (const glu::InterfaceBlock& block, glu::MatrixOrder blockOrder)
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int size = 0;
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		size += getBufferVariableSize(block.variables[ndx].varType, (block.variables[ndx].layout.matrixOrder == glu::MATRIXORDER_LAST) ? (blockOrder) : (block.variables[ndx].layout.matrixOrder));
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return size;
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getBufferMaxSize (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int maxSize = 0;
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxSize = de::max(maxSize, getBufferSize(shader->getDefaultBlock().interfaceBlocks[ndx], shader->getDefaultBlock().interfaceBlocks[ndx].layout.matrixOrder));
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (int)maxSize;
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getAtomicCounterMaxBinding (const ProgramInterfaceDefinition::Shader* shader)
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int maxBinding = -1;
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxBinding = de::max(maxBinding, shader->getDefaultBlock().variables[ndx].layout.binding);
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (int)maxBinding;
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getUniformMaxBinding (const ProgramInterfaceDefinition::Shader* shader, bool (*predicate)(glu::DataType))
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int maxBinding = -1;
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxBinding = de::max(maxBinding, shader->getDefaultBlock().variables[ndx].layout.binding + getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, predicate));
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (int)maxBinding;
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getAtomicCounterMaxBufferSize (const ProgramInterfaceDefinition::Shader* shader)
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::map<int, int>	bufferSizes;
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					maxSize			= 0;
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int bufferBinding	= shader->getDefaultBlock().variables[ndx].layout.binding;
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int offset		= (shader->getDefaultBlock().variables[ndx].layout.offset == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.offset);
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int size			= offset + 4 * getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, glu::isDataTypeAtomicCounter);
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (bufferSizes.find(bufferBinding) == bufferSizes.end())
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bufferSizes[bufferBinding] = size;
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bufferSizes[bufferBinding] = de::max<int>(bufferSizes[bufferBinding], size);
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::map<int, int>::iterator it = bufferSizes.begin(); it != bufferSizes.end(); ++it)
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxSize = de::max<int>(maxSize, it->second);
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return maxSize;
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumFeedbackVaryingComponents (const ProgramInterfaceDefinition::Program* program, const std::string& name)
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VariablePathComponent> path;
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (name == "gl_Position")
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 4;
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(deStringBeginsWith(name.c_str(), "gl_") == DE_FALSE);
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!traverseProgramVariablePath(path, program, name, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false); // Program failed validate, invalid operation
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getMappedBasicTypeSum(*path.back().getVariableType(), getNumDataTypeComponents);
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumXFBComponents (const ProgramInterfaceDefinition::Program* program)
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numComponents = 0;
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComponents += getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]);
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numComponents;
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumMaxXFBOutputComponents (const ProgramInterfaceDefinition::Program* program)
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numComponents = 0;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComponents = de::max(numComponents, getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]));
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numComponents;
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8969fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyrystatic int getFragmentOutputMaxLocation (const ProgramInterfaceDefinition::Shader* shader)
8979fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry{
8989fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	DE_ASSERT(shader->getType() == glu::SHADERTYPE_FRAGMENT);
8999fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
9009fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	int maxOutputLocation = -1;
9019fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
9029fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
9039fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	{
9049fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry		if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT)
9059fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry		{
9069fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry			// missing location qualifier means location == 0
9079fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry			const int outputLocation 		= (shader->getDefaultBlock().variables[ndx].layout.location == -1)
9089fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry												? (0)
9099fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry												: (shader->getDefaultBlock().variables[ndx].layout.location);
9109fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
9119fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry			// only basic types or arrays of basic types possible
9129fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry			DE_ASSERT(!shader->getDefaultBlock().variables[ndx].varType.isStructType());
9139fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
9149fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry			const int locationSlotsTaken	= (shader->getDefaultBlock().variables[ndx].varType.isArrayType())
9159fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry												? (shader->getDefaultBlock().variables[ndx].varType.getArraySize())
9169fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry												: (1);
9179fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
9189fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry			maxOutputLocation = de::max(maxOutputLocation, outputLocation + locationSlotsTaken - 1);
9199fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry		}
9209fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	}
9219fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
9229fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	return maxOutputLocation;
9239fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry}
9249fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::vector<std::string> getProgramInterfaceBlockMemberResourceList (const glu::InterfaceBlock& interfaceBlock)
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string			namePrefix					= (!interfaceBlock.instanceName.empty()) ? (interfaceBlock.interfaceName + ".") : ("");
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool					isTopLevelBufferVariable	= (interfaceBlock.storage == glu::STORAGE_BUFFER);
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<std::string>	resources;
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int variableNdx = 0; variableNdx < (int)interfaceBlock.variables.size(); ++variableNdx)
93479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry		generateVariableTypeResourceNames(resources,
93579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry										  namePrefix + interfaceBlock.variables[variableNdx].name,
93679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry										  interfaceBlock.variables[variableNdx].varType,
93779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry										  (isTopLevelBufferVariable) ?
93879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry											(RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) :
93979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry											(RESOURCE_NAME_GENERATION_FLAG_DEFAULT));
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return resources;
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::vector<std::string> getProgramInterfaceResourceList (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface)
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// The same {uniform (block), buffer (variable)} can exist in multiple shaders, remove duplicates but keep order
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool					removeDuplicated	= (interface == PROGRAMINTERFACE_UNIFORM)			||
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  (interface == PROGRAMINTERFACE_UNIFORM_BLOCK)		||
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  (interface == PROGRAMINTERFACE_BUFFER_VARIABLE)	||
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  (interface == PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<std::string>	resources;
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (interface)
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM:
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_BUFFER_VARIABLE:
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (shader->getDefaultBlock().variables[variableNdx].storage == storage)
96679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry						generateVariableTypeResourceNames(resources,
96779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry														  shader->getDefaultBlock().variables[variableNdx].name,
96879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry														  shader->getDefaultBlock().variables[variableNdx].varType,
96979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (interfaceBlock.storage == storage)
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_UNIFORM_BLOCK:
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (interfaceBlock.storage == storage)
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						std::vector<int> index(interfaceBlock.dimensions.size(), 0);
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (;;)
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							// add resource string for each element
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							{
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								std::ostringstream name;
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								name << interfaceBlock.interfaceName;
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									name << "[" << index[dimensionNdx] << "]";
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								resources.push_back(name.str());
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							}
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							// increment index
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							if (!incrementMultiDimensionIndex(index, interfaceBlock.dimensions))
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								break;
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_INPUT:
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_PROGRAM_OUTPUT:
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::Storage		storage		= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT);
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::ShaderType	shaderType	= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (program->getFirstStage()) : (program->getLastStage());
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (shader->getType() != shaderType)
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					continue;
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (shader->getDefaultBlock().variables[variableNdx].storage == storage)
103779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry						generateVariableTypeResourceNames(resources,
103879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry														  shader->getDefaultBlock().variables[variableNdx].name,
103979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry														  shader->getDefaultBlock().variables[variableNdx].varType,
104079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (interfaceBlock.storage == storage)
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			// built-ins
10548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (interface == PROGRAMINTERFACE_PROGRAM_INPUT)
10558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			{
10568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				if (shaderType == glu::SHADERTYPE_VERTEX && resources.empty())
10578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_VertexID"); // only read from when there are no other inputs
10588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
10598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_FragCoord"); // only read from when there are no other inputs
10608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_GEOMETRY && resources.empty())
10618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_in[0].gl_Position");
10628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
10638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
10648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const bool noInputs = resources.empty();
10658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_InvocationID");
10668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
10678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					if (noInputs)
10688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						resources.push_back("gl_in[0].gl_Position"); // only read from when there are no other inputs
10698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
10708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION && resources.empty())
10718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_in[0].gl_Position"); // only read from when there are no other inputs
10728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_COMPUTE && resources.empty())
10738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_NumWorkGroups"); // only read from when there are no other inputs
10748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			}
10758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			else if (interface == PROGRAMINTERFACE_PROGRAM_OUTPUT)
10768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			{
10778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				if (shaderType == glu::SHADERTYPE_VERTEX)
10788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_Position");
10798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
10808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_FragDepth"); // only written to when there are no other outputs
10818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_GEOMETRY)
10828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_Position");
10838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
10848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_out[0].gl_Position");
10858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
10868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					resources.push_back("gl_Position");
10878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			}
10888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
109679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				const std::string& varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (deStringBeginsWith(varyingName.c_str(), "gl_"))
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					resources.push_back(varyingName); // builtin
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
110179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				{
110279ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry					std::vector<VariablePathComponent> path;
110379ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
110479ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry					if (!traverseProgramVariablePath(path, program, varyingName, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
110579ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry						DE_ASSERT(false); // Program failed validate, invalid operation
110679ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry
110779ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry					generateVariableTypeResourceNames(resources,
110879ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry													  varyingName,
110979ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry													  *path.back().getVariableType(),
111079ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry													  RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
111179ec52223daa917719d5d0555e7d8020d6514951Jarkko Pöyry				}
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (removeDuplicated)
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::set<std::string>		addedVariables;
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<std::string>	uniqueResouces;
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)resources.size(); ++ndx)
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (addedVariables.find(resources[ndx]) == addedVariables.end())
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				addedVariables.insert(resources[ndx]);
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uniqueResouces.push_back(resources[ndx]);
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		uniqueResouces.swap(resources);
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return resources;
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ProgramSources generateProgramInterfaceProgramSources (const ProgramInterfaceDefinition::Program* program)
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ProgramSources sources;
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(program->isValid());
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ProgramInterfaceDefinition::Shader*	shader						= program->getShaders()[shaderNdx];
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool										containsUserDefinedOutputs	= false;
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool										containsUserDefinedInputs	= false;
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::ostringstream							sourceBuf;
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::ostringstream							usageBuf;
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sourceBuf	<< glu::getGLSLVersionDeclaration(shader->getVersion()) << "\n"
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< getShaderTypeDeclarations(shader->getType())
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\n";
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Struct definitions
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeStructureDefinitions(sourceBuf, shader->getDefaultBlock());
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// variables in the default scope
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sourceBuf << shader->getDefaultBlock().variables[ndx] << ";\n";
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!shader->getDefaultBlock().variables.empty())
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sourceBuf << "\n";
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Interface blocks
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeInterfaceBlock(sourceBuf, shader->getDefaultBlock().interfaceBlocks[ndx]);
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Use inputs and outputs so that they won't be removed by the optimizer
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		usageBuf <<	"highp vec4 readInputs()\n"
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"{\n"
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	highp vec4 retValue = vec4(0.0);\n";
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// User-defined inputs
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_IN ||
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_UNIFORM)
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeVariableReadAccumulateExpression(usageBuf, "retValue", shader->getDefaultBlock().variables[ndx].name, shader->getDefaultBlock().variables[ndx].varType);
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				containsUserDefinedInputs = true;
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (interface.storage == glu::STORAGE_UNIFORM ||
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_WRITEONLY_BIT) == 0))
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeInterfaceReadAccumulateExpression(usageBuf, "retValue", interface);
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				containsUserDefinedInputs = true;
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Built-in-inputs
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!containsUserDefinedInputs)
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (shader->getType() == glu::SHADERTYPE_VERTEX)
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	retValue += vec4(float(gl_VertexID));\n";
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	retValue += gl_FragCoord;\n";
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL)
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (shader->getType() == glu::SHADERTYPE_COMPUTE)
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	retValue += vec4(float(gl_NumWorkGroups.x));\n";
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		usageBuf <<	"	return retValue;\n"
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"}\n\n";
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		usageBuf <<	"void writeOutputs(in highp vec4 dummyValue)\n"
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"{\n";
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// User-defined outputs
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT)
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeVariableWriteExpression(usageBuf, "dummyValue", shader->getDefaultBlock().variables[ndx].name, shader->getDefaultBlock().variables[ndx].varType);
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				containsUserDefinedOutputs = true;
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_READONLY_BIT) == 0)
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeInterfaceWriteExpression(usageBuf, "dummyValue", interface);
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				containsUserDefinedOutputs = true;
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Builtin-outputs that must be written to
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getType() == glu::SHADERTYPE_VERTEX)
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			usageBuf << "	gl_Position = dummyValue;\n";
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			usageBuf << "	gl_Position = dummyValue;\n"
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						 "	EmitVertex();\n";
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL)
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			usageBuf << "	gl_out[gl_InvocationID].gl_Position = dummyValue;\n";
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			usageBuf << "	gl_Position = dummyValue;\n";
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Output to sink input data to
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!containsUserDefinedOutputs)
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	gl_FragDepth = dot(dummyValue.xy, dummyValue.xw);\n";
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (shader->getType() == glu::SHADERTYPE_COMPUTE)
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				usageBuf << "	dummyOutputBlock.dummyValue = dummyValue;\n";
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		usageBuf <<	"}\n\n"
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"void main()\n"
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"{\n"
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	writeOutputs(readInputs());\n"
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"}\n";
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Interface for dummy output
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getType() == glu::SHADERTYPE_COMPUTE && !containsUserDefinedOutputs)
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sourceBuf	<< "writeonly buffer DummyOutputInterface\n"
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "{\n"
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "	highp vec4 dummyValue;\n"
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "} dummyOutputBlock;\n\n";
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << glu::ShaderSource(shader->getType(), sourceBuf.str() + usageBuf.str());
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (program->isSeparable())
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << glu::ProgramSeparable(true);
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << glu::TransformFeedbackVarying(program->getTransformFeedbackVaryings()[ndx]);
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (program->getTransformFeedbackMode())
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources << glu::TransformFeedbackMode(program->getTransformFeedbackMode());
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sources;
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool findProgramVariablePathByPathName (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& pathName, const VariableSearchFilter& filter)
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VariablePathComponent> modifiedPath;
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!traverseProgramVariablePath(modifiedPath, program, pathName, filter))
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// modify param only on success
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typePath.swap(modifiedPath);
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13153c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramInterfaceDefinition::ShaderResourceUsage getShaderResourceUsage (const ProgramInterfaceDefinition::Shader* shader)
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramInterfaceDefinition::ShaderResourceUsage retVal;
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numInputs						= getNumTypeInstances(shader, glu::STORAGE_IN, dummyConstantTypeFilter<true>);
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numInputVectors					= getNumVectors(shader, glu::STORAGE_IN);
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numInputComponents				= getNumComponents(shader, glu::STORAGE_IN);
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numOutputs						= getNumTypeInstances(shader, glu::STORAGE_OUT, dummyConstantTypeFilter<true>);
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numOutputVectors					= getNumVectors(shader, glu::STORAGE_OUT);
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numOutputComponents				= getNumComponents(shader, glu::STORAGE_OUT);
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numDefaultBlockUniformComponents	= getNumDefaultBlockComponents(shader, glu::STORAGE_UNIFORM);
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numCombinedUniformComponents		= getNumComponents(shader, glu::STORAGE_UNIFORM);
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numUniformVectors				= getNumVectors(shader, glu::STORAGE_UNIFORM);
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numSamplers						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numImages						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numAtomicCounterBuffers			= getNumAtomicCounterBuffers(shader);
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numAtomicCounters				= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numUniformBlocks					= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numShaderStorageBlocks			= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13433c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramInterfaceDefinition::ProgramResourceUsage getCombinedProgramResourceUsage (const ProgramInterfaceDefinition::Program* program)
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProgramInterfaceDefinition::ProgramResourceUsage retVal;
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13479fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	retVal.uniformBufferMaxBinding				= -1; // max binding is inclusive upper bound. Allow 0 bindings by using negative value
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.uniformBufferMaxSize					= 0;
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numUniformBlocks						= 0;
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numCombinedVertexUniformComponents	= 0;
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numCombinedFragmentUniformComponents	= 0;
13529fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	retVal.shaderStorageBufferMaxBinding		= -1; // see above
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.shaderStorageBufferMaxSize			= 0;
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numShaderStorageBlocks				= 0;
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numVaryingComponents					= 0;
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numVaryingVectors					= 0;
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numCombinedSamplers					= 0;
13589fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	retVal.atomicCounterBufferMaxBinding		= -1; // see above
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.atomicCounterBufferMaxSize			= 0;
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numAtomicCounterBuffers				= 0;
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numAtomicCounters					= 0;
13629fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	retVal.maxImageBinding						= -1; // see above
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numCombinedImages					= 0;
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numCombinedOutputResources			= 0;
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numXFBInterleavedComponents			= 0;
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numXFBSeparateAttribs				= 0;
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	retVal.numXFBSeparateComponents				= 0;
13689fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry	retVal.fragmentOutputMaxBinding				= -1; // see above
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx];
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.uniformBufferMaxBinding		= de::max(retVal.uniformBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_UNIFORM));
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.uniformBufferMaxSize			= de::max(retVal.uniformBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_UNIFORM));
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numUniformBlocks				+= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getType() == glu::SHADERTYPE_VERTEX)
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal.numCombinedVertexUniformComponents += getNumComponents(shader, glu::STORAGE_UNIFORM);
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal.numCombinedFragmentUniformComponents += getNumComponents(shader, glu::STORAGE_UNIFORM);
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.shaderStorageBufferMaxBinding	= de::max(retVal.shaderStorageBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_BUFFER));
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.shaderStorageBufferMaxSize		= de::max(retVal.shaderStorageBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_BUFFER));
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numShaderStorageBlocks			+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getType() == glu::SHADERTYPE_VERTEX)
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal.numVaryingComponents += getNumComponents(shader, glu::STORAGE_OUT);
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal.numVaryingVectors	+= getNumVectors(shader, glu::STORAGE_OUT);
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numCombinedSamplers	+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.atomicCounterBufferMaxBinding	= de::max(retVal.atomicCounterBufferMaxBinding, getAtomicCounterMaxBinding(shader));
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.atomicCounterBufferMaxSize		= de::max(retVal.atomicCounterBufferMaxSize, getAtomicCounterMaxBufferSize(shader));
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numAtomicCounterBuffers			+= getNumAtomicCounterBuffers(shader);
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numAtomicCounters				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.maxImageBinding					= de::max(retVal.maxImageBinding, getUniformMaxBinding(shader, glu::isDataTypeImage));
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numCombinedImages				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numCombinedOutputResources		+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numCombinedOutputResources		+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
14059fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
14079fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry		{
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			retVal.numCombinedOutputResources += getNumVectors(shader, glu::STORAGE_OUT);
14099fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry			retVal.fragmentOutputMaxBinding = de::max(retVal.fragmentOutputMaxBinding, getFragmentOutputMaxLocation(shader));
14109fa944ae1829441ef58596701ddc9c3d07b50f04Jarkko Pöyry		}
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (program->getTransformFeedbackMode() == GL_INTERLEAVED_ATTRIBS)
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numXFBInterleavedComponents = getNumXFBComponents(program);
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (program->getTransformFeedbackMode() == GL_SEPARATE_ATTRIBS)
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numXFBSeparateAttribs	= (int)program->getTransformFeedbackVaryings().size();
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.numXFBSeparateComponents	= getNumMaxXFBOutputComponents(program);
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1427