1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Program interface
22 *//*--------------------------------------------------------------------*/
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"
40 namespace ProgramInterfaceDefinition
45 static const glu::ShaderType s_shaderStageOrder[] =
47 glu::SHADERTYPE_COMPUTE,
49 glu::SHADERTYPE_VERTEX,
50 glu::SHADERTYPE_TESSELLATION_CONTROL,
51 glu::SHADERTYPE_TESSELLATION_EVALUATION,
52 glu::SHADERTYPE_GEOMETRY,
53 glu::SHADERTYPE_FRAGMENT
56 // s_shaderStageOrder does not contain ShaderType_LAST
57 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_shaderStageOrder) == glu::SHADERTYPE_LAST);
59 static bool containsMatchingSubtype (const glu::VarType& varType, bool (*predicate)(glu::DataType))
61 if (varType.isBasicType() && predicate(varType.getBasicType()))
64 if (varType.isArrayType())
65 return containsMatchingSubtype(varType.getElementType(), predicate);
67 if (varType.isStructType())
68 for (int memberNdx = 0; memberNdx < varType.getStructPtr()->getNumMembers(); ++memberNdx)
69 if (containsMatchingSubtype(varType.getStructPtr()->getMember(memberNdx).getType(), predicate))
75 static bool containsMatchingSubtype (const std::vector<glu::VariableDeclaration>& decls, bool (*predicate)(glu::DataType))
77 for (int varNdx = 0; varNdx < (int)decls.size(); ++varNdx)
78 if (containsMatchingSubtype(decls[varNdx].varType, predicate))
83 static bool isOpaqueType (glu::DataType type)
85 return glu::isDataTypeAtomicCounter(type) ||
86 glu::isDataTypeImage(type) ||
87 glu::isDataTypeSampler(type);
90 static int getShaderStageIndex (glu::ShaderType stage)
92 const glu::ShaderType* const it = std::find(DE_ARRAY_BEGIN(s_shaderStageOrder), DE_ARRAY_END(s_shaderStageOrder), stage);
94 if (it == DE_ARRAY_END(s_shaderStageOrder))
98 const int index = (int)(it - DE_ARRAY_BEGIN(s_shaderStageOrder));
105 Shader::Shader (glu::ShaderType type, glu::GLSLVersion version)
106 : m_shaderType (type)
107 , m_version (version)
111 Shader::~Shader (void)
115 static bool isIllegalVertexInput (const glu::VarType& varType)
117 // booleans, opaque types, arrays, structs are not allowed as inputs
118 if (!varType.isBasicType())
120 if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
125 static bool isIllegalVertexOutput (const glu::VarType& varType, bool insideAStruct = false, bool insideAnArray = false)
127 // booleans, opaque types, arrays of arrays, arrays of structs, array in struct, struct struct are not allowed as vertex outputs
129 if (varType.isBasicType())
131 const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType());
133 if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
141 else if (varType.isArrayType())
143 if (insideAnArray || insideAStruct)
146 return isIllegalVertexOutput(varType.getElementType(), insideAStruct, true);
148 else if (varType.isStructType())
150 if (insideAnArray || insideAStruct)
153 for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
154 if (isIllegalVertexOutput(varType.getStructPtr()->getMember(ndx).getType(), true, insideAnArray))
166 static bool isIllegalFragmentInput (const glu::VarType& varType)
168 return isIllegalVertexOutput(varType);
171 static bool isIllegalFragmentOutput (const glu::VarType& varType, bool insideAnArray = false)
173 // booleans, opaque types, matrices, structs, arrays of arrays are not allowed as outputs
175 if (varType.isBasicType())
177 const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType());
179 if (glu::isDataTypeBoolOrBVec(varType.getBasicType()) || isOpaqueType || glu::isDataTypeMatrix(varType.getBasicType()))
183 else if (varType.isArrayType())
187 return isIllegalFragmentOutput(varType.getElementType(), true);
189 else if (varType.isStructType())
198 static bool isTypeIntegerOrContainsIntegers (const glu::VarType& varType)
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())
206 for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
207 if (isTypeIntegerOrContainsIntegers(varType.getStructPtr()->getMember(ndx).getType()))
218 bool Shader::isValid (void) const
220 // Default block variables
222 for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
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))
229 // atomic declaration in a struct
230 if (m_defaultBlock.variables[varNdx].varType.isStructType() &&
231 containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter))
234 // Unsupported layout qualifiers
236 if (m_defaultBlock.variables[varNdx].layout.matrixOrder != glu::MATRIXORDER_LAST)
239 if (containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeSampler))
241 const glu::Layout layoutWithLocationAndBinding(m_defaultBlock.variables[varNdx].layout.location, m_defaultBlock.variables[varNdx].layout.binding);
243 if (m_defaultBlock.variables[varNdx].layout != layoutWithLocationAndBinding)
251 for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
253 // ES31 disallows interface block array arrays
254 if (m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.size() > 1)
257 // Interface block arrays must have instance name
258 if (!m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty() && m_defaultBlock.interfaceBlocks[interfaceNdx].instanceName.empty())
261 // Opaque types in interface block
262 if (containsMatchingSubtype(m_defaultBlock.interfaceBlocks[interfaceNdx].variables, isOpaqueType))
267 // Shader type specific
269 if (m_shaderType == glu::SHADERTYPE_VERTEX)
271 for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
273 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalVertexInput(m_defaultBlock.variables[varNdx].varType))
275 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalVertexOutput(m_defaultBlock.variables[varNdx].varType))
277 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
280 for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
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)
290 else if (m_shaderType == glu::SHADERTYPE_FRAGMENT)
292 for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
294 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalFragmentInput(m_defaultBlock.variables[varNdx].varType))
296 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
298 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalFragmentOutput(m_defaultBlock.variables[varNdx].varType))
301 for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
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)
311 else if (m_shaderType == glu::SHADERTYPE_COMPUTE)
313 for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
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)
323 for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
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)
334 else if (m_shaderType == glu::SHADERTYPE_GEOMETRY)
336 for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
338 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN ||
339 m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
344 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
347 for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
349 if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN ||
350 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
355 if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
359 else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
361 for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
363 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN)
366 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
369 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && !m_defaultBlock.variables[varNdx].varType.isArrayType())
372 for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
374 if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN)
377 if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
380 if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
384 else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
386 for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
388 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
391 if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
394 for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
396 if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
399 if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
409 Program::Program (void)
410 : m_separable (false)
412 , m_geoNumOutputVertices (0)
413 , m_tessNumOutputVertices (0)
417 static void collectStructPtrs (std::set<const glu::StructType*>& dst, const glu::VarType& type)
419 if (type.isArrayType())
420 collectStructPtrs(dst, type.getElementType());
421 else if (type.isStructType())
423 dst.insert(type.getStructPtr());
425 for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
426 collectStructPtrs(dst, type.getStructPtr()->getMember(memberNdx).getType());
430 Program::~Program (void)
432 // delete shader struct types, need to be done by the program since shaders might share struct types
434 std::set<const glu::StructType*> structTypes;
436 for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
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);
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);
446 for (std::set<const glu::StructType*>::iterator it = structTypes.begin(); it != structTypes.end(); ++it)
450 for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
451 delete m_shaders[shaderNdx];
455 Shader* Program::addShader (glu::ShaderType type, glu::GLSLVersion version)
457 DE_ASSERT(type < glu::SHADERTYPE_LAST);
461 // make sure push_back() cannot throw
462 m_shaders.reserve(m_shaders.size() + 1);
464 shader = new Shader(type, version);
465 m_shaders.push_back(shader);
470 void Program::setSeparable (bool separable)
472 m_separable = separable;
475 bool Program::isSeparable (void) const
480 const std::vector<Shader*>& Program::getShaders (void) const
485 glu::ShaderType Program::getFirstStage (void) const
487 const int nullValue = DE_LENGTH_OF_ARRAY(s_shaderStageOrder);
488 int firstStage = nullValue;
490 for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
492 const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
494 firstStage = de::min(firstStage, index);
497 if (firstStage == nullValue)
498 return glu::SHADERTYPE_LAST;
500 return s_shaderStageOrder[firstStage];
503 glu::ShaderType Program::getLastStage (void) const
505 const int nullValue = -1;
506 int lastStage = nullValue;
508 for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
510 const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
512 lastStage = de::max(lastStage, index);
515 if (lastStage == nullValue)
516 return glu::SHADERTYPE_LAST;
518 return s_shaderStageOrder[lastStage];
521 bool Program::hasStage (glu::ShaderType stage) const
523 for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
525 if (m_shaders[shaderNdx]->getType() == stage)
531 void Program::addTransformFeedbackVarying (const std::string& varName)
533 m_xfbVaryings.push_back(varName);
536 const std::vector<std::string>& Program::getTransformFeedbackVaryings (void) const
538 return m_xfbVaryings;
541 void Program::setTransformFeedbackMode (deUint32 mode)
546 deUint32 Program::getTransformFeedbackMode (void) const
551 deUint32 Program::getGeometryNumOutputVertices (void) const
553 return m_geoNumOutputVertices;
556 void Program::setGeometryNumOutputVertices (deUint32 vertices)
558 m_geoNumOutputVertices = vertices;
561 deUint32 Program::getTessellationNumOutputPatchVertices (void) const
563 return m_tessNumOutputVertices;
566 void Program::setTessellationNumOutputPatchVertices (deUint32 vertices)
568 m_tessNumOutputVertices = vertices;
571 bool Program::isValid (void) const
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;
581 if (m_shaders.empty())
584 for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
585 if (!m_shaders[ndx]->isValid())
589 for (int ndx = 1; ndx < (int)m_shaders.size(); ++ndx)
590 if (m_shaders[0]->getVersion() != m_shaders[ndx]->getVersion())
593 for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
595 switch (m_shaders[ndx]->getType())
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;
608 // compute present -> no other stages present
610 const bool nonComputePresent = vertexPresent || fragmentPresent || tessControlPresent || tessEvalPresent || geometryPresent;
611 if (computePresent && nonComputePresent)
615 // must contain both vertex and fragment shaders
616 if (!computePresent && !m_separable)
618 if (!vertexPresent || !fragmentPresent)
622 // tess.Eval present <=> tess.Control present
625 if (tessEvalPresent != tessControlPresent)
629 if ((m_tessNumOutputVertices != 0) != (tessControlPresent || tessEvalPresent))
632 if ((m_geoNumOutputVertices != 0) != geometryPresent)
635 for (int ndx = 0; ndx < (int)m_xfbVaryings.size(); ++ndx)
638 if (!de::beginsWith(m_xfbVaryings[ndx], "gl_"))
640 std::vector<ProgramInterfaceDefinition::VariablePathComponent> path;
641 if (!findProgramVariablePathByPathName(path, this, m_xfbVaryings[ndx], VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(this), glu::STORAGE_OUT)))
643 if (!path.back().isVariableType())
646 // Khronos bug #12787 disallowed capturing whole structs in OpenGL ES.
647 if (path.back().getVariableType()->isStructType() && isOpenGLES)
655 } // ProgramInterfaceDefinition