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