Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Program interface
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fProgramInterfaceDefinition.hpp"
     25 #include "es31fProgramInterfaceDefinitionUtil.hpp"
     26 #include "gluVarType.hpp"
     27 #include "gluShaderProgram.hpp"
     28 #include "deSTLUtil.hpp"
     29 #include "deStringUtil.hpp"
     30 #include "glwEnums.hpp"
     31 
     32 #include <set>
     33 
     34 namespace deqp
     35 {
     36 namespace gles31
     37 {
     38 namespace Functional
     39 {
     40 namespace ProgramInterfaceDefinition
     41 {
     42 namespace
     43 {
     44 
     45 static const glu::ShaderType s_shaderStageOrder[] =
     46 {
     47 	glu::SHADERTYPE_COMPUTE,
     48 
     49 	glu::SHADERTYPE_VERTEX,
     50 	glu::SHADERTYPE_TESSELLATION_CONTROL,
     51 	glu::SHADERTYPE_TESSELLATION_EVALUATION,
     52 	glu::SHADERTYPE_GEOMETRY,
     53 	glu::SHADERTYPE_FRAGMENT
     54 };
     55 
     56 // s_shaderStageOrder does not contain ShaderType_LAST
     57 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_shaderStageOrder) == glu::SHADERTYPE_LAST);
     58 
     59 static bool containsMatchingSubtype (const glu::VarType& varType, bool (*predicate)(glu::DataType))
     60 {
     61 	if (varType.isBasicType() && predicate(varType.getBasicType()))
     62 		return true;
     63 
     64 	if (varType.isArrayType())
     65 		return containsMatchingSubtype(varType.getElementType(), predicate);
     66 
     67 	if (varType.isStructType())
     68 		for (int memberNdx = 0; memberNdx < varType.getStructPtr()->getNumMembers(); ++memberNdx)
     69 			if (containsMatchingSubtype(varType.getStructPtr()->getMember(memberNdx).getType(), predicate))
     70 				return true;
     71 
     72 	return false;
     73 }
     74 
     75 static bool containsMatchingSubtype (const std::vector<glu::VariableDeclaration>& decls, bool (*predicate)(glu::DataType))
     76 {
     77 	for (int varNdx = 0; varNdx < (int)decls.size(); ++varNdx)
     78 		if (containsMatchingSubtype(decls[varNdx].varType, predicate))
     79 			return true;
     80 	return false;
     81 }
     82 
     83 static bool isOpaqueType (glu::DataType type)
     84 {
     85 	return	glu::isDataTypeAtomicCounter(type)	||
     86 			glu::isDataTypeImage(type)			||
     87 			glu::isDataTypeSampler(type);
     88 }
     89 
     90 static int getShaderStageIndex (glu::ShaderType stage)
     91 {
     92 	const glu::ShaderType* const it = std::find(DE_ARRAY_BEGIN(s_shaderStageOrder), DE_ARRAY_END(s_shaderStageOrder), stage);
     93 
     94 	if (it == DE_ARRAY_END(s_shaderStageOrder))
     95 		return -1;
     96 	else
     97 	{
     98 		const int index = (int)(it - DE_ARRAY_BEGIN(s_shaderStageOrder));
     99 		return index;
    100 	}
    101 }
    102 
    103 } // anonymous
    104 
    105 Shader::Shader (glu::ShaderType type, glu::GLSLVersion version)
    106 	: m_shaderType	(type)
    107 	, m_version		(version)
    108 {
    109 }
    110 
    111 Shader::~Shader (void)
    112 {
    113 }
    114 
    115 static bool isIllegalVertexInput (const glu::VarType& varType)
    116 {
    117 	// booleans, opaque types, arrays, structs are not allowed as inputs
    118 	if (!varType.isBasicType())
    119 		return true;
    120 	if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
    121 		return true;
    122 	return false;
    123 }
    124 
    125 static bool isIllegalVertexOutput (const glu::VarType& varType, bool insideAStruct = false, bool insideAnArray = false)
    126 {
    127 	// booleans, opaque types, arrays of arrays, arrays of structs, array in struct, struct struct are not allowed as vertex outputs
    128 
    129 	if (varType.isBasicType())
    130 	{
    131 		const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType());
    132 
    133 		if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
    134 			return true;
    135 
    136 		if (isOpaqueType)
    137 			return true;
    138 
    139 		return false;
    140 	}
    141 	else if (varType.isArrayType())
    142 	{
    143 		if (insideAnArray || insideAStruct)
    144 			return true;
    145 
    146 		return isIllegalVertexOutput(varType.getElementType(), insideAStruct, true);
    147 	}
    148 	else if (varType.isStructType())
    149 	{
    150 		if (insideAnArray || insideAStruct)
    151 			return true;
    152 
    153 		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
    154 			if (isIllegalVertexOutput(varType.getStructPtr()->getMember(ndx).getType(), true, insideAnArray))
    155 				return true;
    156 
    157 		return false;
    158 	}
    159 	else
    160 	{
    161 		DE_ASSERT(false);
    162 		return true;
    163 	}
    164 }
    165 
    166 static bool isIllegalFragmentInput (const glu::VarType& varType)
    167 {
    168 	return isIllegalVertexOutput(varType);
    169 }
    170 
    171 static bool isIllegalFragmentOutput (const glu::VarType& varType, bool insideAnArray = false)
    172 {
    173 	// booleans, opaque types, matrices, structs, arrays of arrays are not allowed as outputs
    174 
    175 	if (varType.isBasicType())
    176 	{
    177 		const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType());
    178 
    179 		if (glu::isDataTypeBoolOrBVec(varType.getBasicType()) || isOpaqueType || glu::isDataTypeMatrix(varType.getBasicType()))
    180 			return true;
    181 		return false;
    182 	}
    183 	else if (varType.isArrayType())
    184 	{
    185 		if (insideAnArray)
    186 			return true;
    187 		return isIllegalFragmentOutput(varType.getElementType(), true);
    188 	}
    189 	else if (varType.isStructType())
    190 		return true;
    191 	else
    192 	{
    193 		DE_ASSERT(false);
    194 		return true;
    195 	}
    196 }
    197 
    198 static bool isTypeIntegerOrContainsIntegers (const glu::VarType& varType)
    199 {
    200 	if (varType.isBasicType())
    201 		return glu::isDataTypeIntOrIVec(varType.getBasicType()) || glu::isDataTypeUintOrUVec(varType.getBasicType());
    202 	else if (varType.isArrayType())
    203 		return isTypeIntegerOrContainsIntegers(varType.getElementType());
    204 	else if (varType.isStructType())
    205 	{
    206 		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
    207 			if (isTypeIntegerOrContainsIntegers(varType.getStructPtr()->getMember(ndx).getType()))
    208 				return true;
    209 		return false;
    210 	}
    211 	else
    212 	{
    213 		DE_ASSERT(false);
    214 		return true;
    215 	}
    216 }
    217 
    218 bool Shader::isValid (void) const
    219 {
    220 	// Default block variables
    221 	{
    222 		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
    223 		{
    224 			// atomic declaration in the default block without binding
    225 			if (m_defaultBlock.variables[varNdx].layout.binding == -1 &&
    226 				containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter))
    227 				return false;
    228 
    229 			// atomic declaration in a struct
    230 			if (m_defaultBlock.variables[varNdx].varType.isStructType() &&
    231 				containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter))
    232 				return false;
    233 
    234 			// Unsupported layout qualifiers
    235 
    236 			if (m_defaultBlock.variables[varNdx].layout.matrixOrder != glu::MATRIXORDER_LAST)
    237 				return false;
    238 
    239 			if (containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeSampler))
    240 			{
    241 				const glu::Layout layoutWithLocationAndBinding(m_defaultBlock.variables[varNdx].layout.location, m_defaultBlock.variables[varNdx].layout.binding);
    242 
    243 				if (m_defaultBlock.variables[varNdx].layout != layoutWithLocationAndBinding)
    244 					return false;
    245 			}
    246 		}
    247 	}
    248 
    249 	// Interface blocks
    250 	{
    251 		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    252 		{
    253 			// ES31 disallows interface block array arrays
    254 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.size() > 1)
    255 				return false;
    256 
    257 			// Interface block arrays must have instance name
    258 			if (!m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty() && m_defaultBlock.interfaceBlocks[interfaceNdx].instanceName.empty())
    259 				return false;
    260 
    261 			// Opaque types in interface block
    262 			if (containsMatchingSubtype(m_defaultBlock.interfaceBlocks[interfaceNdx].variables, isOpaqueType))
    263 				return false;
    264 		}
    265 	}
    266 
    267 	// Shader type specific
    268 
    269 	if (m_shaderType == glu::SHADERTYPE_VERTEX)
    270 	{
    271 		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
    272 		{
    273 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalVertexInput(m_defaultBlock.variables[varNdx].varType))
    274 				return false;
    275 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalVertexOutput(m_defaultBlock.variables[varNdx].varType))
    276 				return false;
    277 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
    278 				return false;
    279 		}
    280 		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    281 		{
    282 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN			||
    283 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
    284 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
    285 			{
    286 				return false;
    287 			}
    288 		}
    289 	}
    290 	else if (m_shaderType == glu::SHADERTYPE_FRAGMENT)
    291 	{
    292 		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
    293 		{
    294 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalFragmentInput(m_defaultBlock.variables[varNdx].varType))
    295 				return false;
    296 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
    297 				return false;
    298 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalFragmentOutput(m_defaultBlock.variables[varNdx].varType))
    299 				return false;
    300 		}
    301 		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    302 		{
    303 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
    304 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT		||
    305 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
    306 			{
    307 				return false;
    308 			}
    309 		}
    310 	}
    311 	else if (m_shaderType == glu::SHADERTYPE_COMPUTE)
    312 	{
    313 		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
    314 		{
    315 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN			||
    316 				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN	||
    317 				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT		||
    318 				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
    319 			{
    320 				return false;
    321 			}
    322 		}
    323 		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    324 		{
    325 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN			||
    326 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
    327 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT		||
    328 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
    329 			{
    330 				return false;
    331 			}
    332 		}
    333 	}
    334 	else if (m_shaderType == glu::SHADERTYPE_GEOMETRY)
    335 	{
    336 		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
    337 		{
    338 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN	||
    339 				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
    340 			{
    341 				return false;
    342 			}
    343 			// arrayed input
    344 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
    345 				return false;
    346 		}
    347 		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    348 		{
    349 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
    350 				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
    351 			{
    352 				return false;
    353 			}
    354 			// arrayed input
    355 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
    356 				return false;
    357 		}
    358 	}
    359 	else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
    360 	{
    361 		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
    362 		{
    363 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN)
    364 				return false;
    365 			// arrayed input
    366 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
    367 				return false;
    368 			// arrayed output
    369 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && !m_defaultBlock.variables[varNdx].varType.isArrayType())
    370 				return false;
    371 		}
    372 		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    373 		{
    374 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN)
    375 				return false;
    376 			// arrayed input
    377 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
    378 				return false;
    379 			// arrayed output
    380 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
    381 				return false;
    382 		}
    383 	}
    384 	else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
    385 	{
    386 		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
    387 		{
    388 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
    389 				return false;
    390 			// arrayed input
    391 			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
    392 				return false;
    393 		}
    394 		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    395 		{
    396 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
    397 				return false;
    398 			// arrayed input
    399 			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
    400 				return false;
    401 		}
    402 	}
    403 	else
    404 		DE_ASSERT(false);
    405 
    406 	return true;
    407 }
    408 
    409 Program::Program (void)
    410 	: m_separable				(false)
    411 	, m_xfbMode					(0)
    412 	, m_geoNumOutputVertices	(0)
    413 	, m_tessNumOutputVertices	(0)
    414 {
    415 }
    416 
    417 static void collectStructPtrs (std::set<const glu::StructType*>& dst, const glu::VarType& type)
    418 {
    419 	if (type.isArrayType())
    420 		collectStructPtrs(dst, type.getElementType());
    421 	else if (type.isStructType())
    422 	{
    423 		dst.insert(type.getStructPtr());
    424 
    425 		for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
    426 			collectStructPtrs(dst, type.getStructPtr()->getMember(memberNdx).getType());
    427 	}
    428 }
    429 
    430 Program::~Program (void)
    431 {
    432 	// delete shader struct types, need to be done by the program since shaders might share struct types
    433 	{
    434 		std::set<const glu::StructType*> structTypes;
    435 
    436 		for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
    437 		{
    438 			for (int varNdx = 0; varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.variables.size(); ++varNdx)
    439 				collectStructPtrs(structTypes, m_shaders[shaderNdx]->m_defaultBlock.variables[varNdx].varType);
    440 
    441 			for (int interfaceNdx = 0; interfaceNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
    442 				for (int varNdx = 0; varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
    443 					collectStructPtrs(structTypes, m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables[varNdx].varType);
    444 		}
    445 
    446 		for (std::set<const glu::StructType*>::iterator it = structTypes.begin(); it != structTypes.end(); ++it)
    447 			delete *it;
    448 	}
    449 
    450 	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
    451 		delete m_shaders[shaderNdx];
    452 	m_shaders.clear();
    453 }
    454 
    455 Shader* Program::addShader (glu::ShaderType type, glu::GLSLVersion version)
    456 {
    457 	DE_ASSERT(type < glu::SHADERTYPE_LAST);
    458 
    459 	Shader* shader;
    460 
    461 	// make sure push_back() cannot throw
    462 	m_shaders.reserve(m_shaders.size() + 1);
    463 
    464 	shader = new Shader(type, version);
    465 	m_shaders.push_back(shader);
    466 
    467 	return shader;
    468 }
    469 
    470 void Program::setSeparable (bool separable)
    471 {
    472 	m_separable = separable;
    473 }
    474 
    475 bool Program::isSeparable (void) const
    476 {
    477 	return m_separable;
    478 }
    479 
    480 const std::vector<Shader*>& Program::getShaders (void) const
    481 {
    482 	return m_shaders;
    483 }
    484 
    485 glu::ShaderType Program::getFirstStage (void) const
    486 {
    487 	const int	nullValue	= DE_LENGTH_OF_ARRAY(s_shaderStageOrder);
    488 	int			firstStage	= nullValue;
    489 
    490 	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
    491 	{
    492 		const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
    493 		if (index != -1)
    494 			firstStage = de::min(firstStage, index);
    495 	}
    496 
    497 	if (firstStage == nullValue)
    498 		return glu::SHADERTYPE_LAST;
    499 	else
    500 		return s_shaderStageOrder[firstStage];
    501 }
    502 
    503 glu::ShaderType Program::getLastStage (void) const
    504 {
    505 	const int	nullValue	= -1;
    506 	int			lastStage	= nullValue;
    507 
    508 	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
    509 	{
    510 		const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
    511 		if (index != -1)
    512 			lastStage = de::max(lastStage, index);
    513 	}
    514 
    515 	if (lastStage == nullValue)
    516 		return glu::SHADERTYPE_LAST;
    517 	else
    518 		return s_shaderStageOrder[lastStage];
    519 }
    520 
    521 bool Program::hasStage (glu::ShaderType stage) const
    522 {
    523 	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
    524 	{
    525 		if (m_shaders[shaderNdx]->getType() == stage)
    526 			return true;
    527 	}
    528 	return false;
    529 }
    530 
    531 void Program::addTransformFeedbackVarying (const std::string& varName)
    532 {
    533 	m_xfbVaryings.push_back(varName);
    534 }
    535 
    536 const std::vector<std::string>& Program::getTransformFeedbackVaryings (void) const
    537 {
    538 	return m_xfbVaryings;
    539 }
    540 
    541 void Program::setTransformFeedbackMode (deUint32 mode)
    542 {
    543 	m_xfbMode = mode;
    544 }
    545 
    546 deUint32 Program::getTransformFeedbackMode (void) const
    547 {
    548 	return m_xfbMode;
    549 }
    550 
    551 deUint32 Program::getGeometryNumOutputVertices (void) const
    552 {
    553 	return m_geoNumOutputVertices;
    554 }
    555 
    556 void Program::setGeometryNumOutputVertices (deUint32 vertices)
    557 {
    558 	m_geoNumOutputVertices = vertices;
    559 }
    560 
    561 deUint32 Program::getTessellationNumOutputPatchVertices (void) const
    562 {
    563 	return m_tessNumOutputVertices;
    564 }
    565 
    566 void Program::setTessellationNumOutputPatchVertices (deUint32 vertices)
    567 {
    568 	m_tessNumOutputVertices = vertices;
    569 }
    570 
    571 bool Program::isValid (void) const
    572 {
    573 	const bool	isOpenGLES			= (m_shaders.empty()) ? (false) : (glu::glslVersionIsES(m_shaders[0]->getVersion()));
    574 	bool		computePresent		= false;
    575 	bool		vertexPresent		= false;
    576 	bool		fragmentPresent		= false;
    577 	bool		tessControlPresent	= false;
    578 	bool		tessEvalPresent		= false;
    579 	bool		geometryPresent		= false;
    580 
    581 	if (m_shaders.empty())
    582 		return false;
    583 
    584 	for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
    585 		if (!m_shaders[ndx]->isValid())
    586 			return false;
    587 
    588 	// same version
    589 	for (int ndx = 1; ndx < (int)m_shaders.size(); ++ndx)
    590 		if (m_shaders[0]->getVersion() != m_shaders[ndx]->getVersion())
    591 			return false;
    592 
    593 	for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
    594 	{
    595 		switch (m_shaders[ndx]->getType())
    596 		{
    597 			case glu::SHADERTYPE_COMPUTE:					computePresent = true;		break;
    598 			case glu::SHADERTYPE_VERTEX:					vertexPresent = true;		break;
    599 			case glu::SHADERTYPE_FRAGMENT:					fragmentPresent = true;		break;
    600 			case glu::SHADERTYPE_TESSELLATION_CONTROL:		tessControlPresent = true;	break;
    601 			case glu::SHADERTYPE_TESSELLATION_EVALUATION:	tessEvalPresent = true;		break;
    602 			case glu::SHADERTYPE_GEOMETRY:					geometryPresent = true;		break;
    603 			default:
    604 				DE_ASSERT(false);
    605 				break;
    606 		}
    607 	}
    608 	// compute present -> no other stages present
    609 	{
    610 		const bool nonComputePresent = vertexPresent || fragmentPresent || tessControlPresent || tessEvalPresent || geometryPresent;
    611 		if (computePresent && nonComputePresent)
    612 			return false;
    613 	}
    614 
    615 	// must contain both vertex and fragment shaders
    616 	if (!computePresent && !m_separable)
    617 	{
    618 		if (!vertexPresent || !fragmentPresent)
    619 			return false;
    620 	}
    621 
    622 	// tess.Eval present <=> tess.Control present
    623 	if (!m_separable)
    624 	{
    625 		if (tessEvalPresent != tessControlPresent)
    626 			return false;
    627 	}
    628 
    629 	if ((m_tessNumOutputVertices != 0) != (tessControlPresent || tessEvalPresent))
    630 		return false;
    631 
    632 	if ((m_geoNumOutputVertices != 0) != geometryPresent)
    633 		return false;
    634 
    635 	for (int ndx = 0; ndx < (int)m_xfbVaryings.size(); ++ndx)
    636 	{
    637 		// user-defined
    638 		if (!de::beginsWith(m_xfbVaryings[ndx], "gl_"))
    639 		{
    640 			std::vector<ProgramInterfaceDefinition::VariablePathComponent> path;
    641 			if (!findProgramVariablePathByPathName(path, this, m_xfbVaryings[ndx], VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(this), glu::STORAGE_OUT)))
    642 				return false;
    643 			if (!path.back().isVariableType())
    644 				return false;
    645 
    646 			// Khronos bug #12787 disallowed capturing whole structs in OpenGL ES.
    647 			if (path.back().getVariableType()->isStructType() && isOpenGLES)
    648 				return false;
    649 		}
    650 	}
    651 
    652 	return true;
    653 }
    654 
    655 } // ProgramInterfaceDefinition
    656 } // Functional
    657 } // gles31
    658 } // deqp
    659