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 34namespace deqp 35{ 36namespace gles31 37{ 38namespace Functional 39{ 40namespace ProgramInterfaceDefinition 41{ 42namespace 43{ 44 45static 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 57DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_shaderStageOrder) == glu::SHADERTYPE_LAST); 58 59static 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 75static 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 83static bool isOpaqueType (glu::DataType type) 84{ 85 return glu::isDataTypeAtomicCounter(type) || 86 glu::isDataTypeImage(type) || 87 glu::isDataTypeSampler(type); 88} 89 90static 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 105Shader::Shader (glu::ShaderType type, glu::GLSLVersion version) 106 : m_shaderType (type) 107 , m_version (version) 108{ 109} 110 111Shader::~Shader (void) 112{ 113} 114 115static 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 125static 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 166static bool isIllegalFragmentInput (const glu::VarType& varType) 167{ 168 return isIllegalVertexOutput(varType); 169} 170 171static 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 198static 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 218bool 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 409Program::Program (void) 410 : m_separable (false) 411 , m_xfbMode (0) 412 , m_geoNumOutputVertices (0) 413 , m_tessNumOutputVertices (0) 414{ 415} 416 417static 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 430Program::~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 455Shader* 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 470void Program::setSeparable (bool separable) 471{ 472 m_separable = separable; 473} 474 475bool Program::isSeparable (void) const 476{ 477 return m_separable; 478} 479 480const std::vector<Shader*>& Program::getShaders (void) const 481{ 482 return m_shaders; 483} 484 485glu::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 503glu::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 521bool 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 531void Program::addTransformFeedbackVarying (const std::string& varName) 532{ 533 m_xfbVaryings.push_back(varName); 534} 535 536const std::vector<std::string>& Program::getTransformFeedbackVaryings (void) const 537{ 538 return m_xfbVaryings; 539} 540 541void Program::setTransformFeedbackMode (deUint32 mode) 542{ 543 m_xfbMode = mode; 544} 545 546deUint32 Program::getTransformFeedbackMode (void) const 547{ 548 return m_xfbMode; 549} 550 551deUint32 Program::getGeometryNumOutputVertices (void) const 552{ 553 return m_geoNumOutputVertices; 554} 555 556void Program::setGeometryNumOutputVertices (deUint32 vertices) 557{ 558 m_geoNumOutputVertices = vertices; 559} 560 561deUint32 Program::getTessellationNumOutputPatchVertices (void) const 562{ 563 return m_tessNumOutputVertices; 564} 565 566void Program::setTessellationNumOutputPatchVertices (deUint32 vertices) 567{ 568 m_tessNumOutputVertices = vertices; 569} 570 571bool 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