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