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