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