1 // 2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 // Copyright (C) 2012-2015 LunarG, Inc. 4 // Copyright (C) 2015-2018 Google, Inc. 5 // Copyright (C) 2017 ARM Limited. 6 // 7 // All rights reserved. 8 // 9 // Redistribution and use in source and binary forms, with or without 10 // modification, are permitted provided that the following conditions 11 // are met: 12 // 13 // Redistributions of source code must retain the above copyright 14 // notice, this list of conditions and the following disclaimer. 15 // 16 // Redistributions in binary form must reproduce the above 17 // copyright notice, this list of conditions and the following 18 // disclaimer in the documentation and/or other materials provided 19 // with the distribution. 20 // 21 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 22 // contributors may be used to endorse or promote products derived 23 // from this software without specific prior written permission. 24 // 25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 // POSSIBILITY OF SUCH DAMAGE. 37 // 38 39 #include "ParseHelper.h" 40 #include "Scan.h" 41 42 #include "../OSDependent/osinclude.h" 43 #include <algorithm> 44 45 #include "preprocessor/PpContext.h" 46 47 extern int yyparse(glslang::TParseContext*); 48 49 namespace glslang { 50 51 TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, 52 int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, 53 TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, 54 const TString* entryPoint) : 55 TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, 56 infoSink, forwardCompatible, messages, entryPoint), 57 inMain(false), 58 blockName(nullptr), 59 limits(resources.limits), 60 atomicUintOffsets(nullptr), anyIndexLimits(false) 61 { 62 // decide whether precision qualifiers should be ignored or respected 63 if (profile == EEsProfile || spvVersion.vulkan > 0) { 64 precisionManager.respectPrecisionQualifiers(); 65 if (! parsingBuiltins && language == EShLangFragment && profile != EEsProfile && spvVersion.vulkan > 0) 66 precisionManager.warnAboutDefaults(); 67 } 68 69 setPrecisionDefaults(); 70 71 globalUniformDefaults.clear(); 72 globalUniformDefaults.layoutMatrix = ElmColumnMajor; 73 globalUniformDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd140 : ElpShared; 74 75 globalBufferDefaults.clear(); 76 globalBufferDefaults.layoutMatrix = ElmColumnMajor; 77 globalBufferDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd430 : ElpShared; 78 79 // use storage buffer on SPIR-V 1.3 and up 80 if (spvVersion.spv >= EShTargetSpv_1_3) 81 intermediate.setUseStorageBuffer(); 82 83 globalInputDefaults.clear(); 84 globalOutputDefaults.clear(); 85 86 // "Shaders in the transform 87 // feedback capturing mode have an initial global default of 88 // layout(xfb_buffer = 0) out;" 89 if (language == EShLangVertex || 90 language == EShLangTessControl || 91 language == EShLangTessEvaluation || 92 language == EShLangGeometry) 93 globalOutputDefaults.layoutXfbBuffer = 0; 94 95 if (language == EShLangGeometry) 96 globalOutputDefaults.layoutStream = 0; 97 98 if (entryPoint != nullptr && entryPoint->size() > 0 && *entryPoint != "main") 99 infoSink.info.message(EPrefixError, "Source entry point must be \"main\""); 100 } 101 102 TParseContext::~TParseContext() 103 { 104 delete [] atomicUintOffsets; 105 } 106 107 // Set up all default precisions as needed by the current environment. 108 // Intended just as a TParseContext constructor helper. 109 void TParseContext::setPrecisionDefaults() 110 { 111 // Set all precision defaults to EpqNone, which is correct for all types 112 // when not obeying precision qualifiers, and correct for types that don't 113 // have defaults (thus getting an error on use) when obeying precision 114 // qualifiers. 115 116 for (int type = 0; type < EbtNumTypes; ++type) 117 defaultPrecision[type] = EpqNone; 118 119 for (int type = 0; type < maxSamplerIndex; ++type) 120 defaultSamplerPrecision[type] = EpqNone; 121 122 // replace with real precision defaults for those that have them 123 if (obeyPrecisionQualifiers()) { 124 if (profile == EEsProfile) { 125 // Most don't have defaults, a few default to lowp. 126 TSampler sampler; 127 sampler.set(EbtFloat, Esd2D); 128 defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; 129 sampler.set(EbtFloat, EsdCube); 130 defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; 131 sampler.set(EbtFloat, Esd2D); 132 sampler.external = true; 133 defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; 134 } 135 136 // If we are parsing built-in computational variables/functions, it is meaningful to record 137 // whether the built-in has no precision qualifier, as that ambiguity 138 // is used to resolve the precision from the supplied arguments/operands instead. 139 // So, we don't actually want to replace EpqNone with a default precision for built-ins. 140 if (! parsingBuiltins) { 141 if (profile == EEsProfile && language == EShLangFragment) { 142 defaultPrecision[EbtInt] = EpqMedium; 143 defaultPrecision[EbtUint] = EpqMedium; 144 } else { 145 defaultPrecision[EbtInt] = EpqHigh; 146 defaultPrecision[EbtUint] = EpqHigh; 147 defaultPrecision[EbtFloat] = EpqHigh; 148 } 149 150 if (profile != EEsProfile) { 151 // Non-ES profile 152 // All sampler precisions default to highp. 153 for (int type = 0; type < maxSamplerIndex; ++type) 154 defaultSamplerPrecision[type] = EpqHigh; 155 } 156 } 157 158 defaultPrecision[EbtSampler] = EpqLow; 159 defaultPrecision[EbtAtomicUint] = EpqHigh; 160 } 161 } 162 163 void TParseContext::setLimits(const TBuiltInResource& r) 164 { 165 resources = r; 166 167 anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing || 168 ! limits.generalConstantMatrixVectorIndexing || 169 ! limits.generalSamplerIndexing || 170 ! limits.generalUniformIndexing || 171 ! limits.generalVariableIndexing || 172 ! limits.generalVaryingIndexing; 173 174 intermediate.setLimits(resources); 175 176 // "Each binding point tracks its own current default offset for 177 // inheritance of subsequent variables using the same binding. The initial state of compilation is that all 178 // binding points have an offset of 0." 179 atomicUintOffsets = new int[resources.maxAtomicCounterBindings]; 180 for (int b = 0; b < resources.maxAtomicCounterBindings; ++b) 181 atomicUintOffsets[b] = 0; 182 } 183 184 // 185 // Parse an array of strings using yyparse, going through the 186 // preprocessor to tokenize the shader strings, then through 187 // the GLSL scanner. 188 // 189 // Returns true for successful acceptance of the shader, false if any errors. 190 // 191 bool TParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError) 192 { 193 currentScanner = &input; 194 ppContext.setInput(input, versionWillBeError); 195 yyparse(this); 196 197 finish(); 198 199 return numErrors == 0; 200 } 201 202 // This is called from bison when it has a parse (syntax) error 203 // Note though that to stop cascading errors, we set EOF, which 204 // will usually cause a syntax error, so be more accurate that 205 // compilation is terminating. 206 void TParseContext::parserError(const char* s) 207 { 208 if (! getScanner()->atEndOfInput() || numErrors == 0) 209 error(getCurrentLoc(), "", "", s, ""); 210 else 211 error(getCurrentLoc(), "compilation terminated", "", ""); 212 } 213 214 void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens) 215 { 216 if (pragmaCallback) 217 pragmaCallback(loc.line, tokens); 218 219 if (tokens.size() == 0) 220 return; 221 222 if (tokens[0].compare("optimize") == 0) { 223 if (tokens.size() != 4) { 224 error(loc, "optimize pragma syntax is incorrect", "#pragma", ""); 225 return; 226 } 227 228 if (tokens[1].compare("(") != 0) { 229 error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", ""); 230 return; 231 } 232 233 if (tokens[2].compare("on") == 0) 234 contextPragma.optimize = true; 235 else if (tokens[2].compare("off") == 0) 236 contextPragma.optimize = false; 237 else { 238 error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); 239 return; 240 } 241 242 if (tokens[3].compare(")") != 0) { 243 error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", ""); 244 return; 245 } 246 } else if (tokens[0].compare("debug") == 0) { 247 if (tokens.size() != 4) { 248 error(loc, "debug pragma syntax is incorrect", "#pragma", ""); 249 return; 250 } 251 252 if (tokens[1].compare("(") != 0) { 253 error(loc, "\"(\" expected after 'debug' keyword", "#pragma", ""); 254 return; 255 } 256 257 if (tokens[2].compare("on") == 0) 258 contextPragma.debug = true; 259 else if (tokens[2].compare("off") == 0) 260 contextPragma.debug = false; 261 else { 262 error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); 263 return; 264 } 265 266 if (tokens[3].compare(")") != 0) { 267 error(loc, "\")\" expected to end 'debug' pragma", "#pragma", ""); 268 return; 269 } 270 } else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) { 271 if (tokens.size() != 1) 272 error(loc, "extra tokens", "#pragma", ""); 273 intermediate.setUseStorageBuffer(); 274 } else if (spvVersion.spv > 0 && tokens[0].compare("use_vulkan_memory_model") == 0) { 275 if (tokens.size() != 1) 276 error(loc, "extra tokens", "#pragma", ""); 277 intermediate.setUseVulkanMemoryModel(); 278 } else if (tokens[0].compare("once") == 0) { 279 warn(loc, "not implemented", "#pragma once", ""); 280 } else if (tokens[0].compare("glslang_binary_double_output") == 0) 281 intermediate.setBinaryDoubleOutput(); 282 } 283 284 // 285 // Handle seeing a variable identifier in the grammar. 286 // 287 TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string) 288 { 289 TIntermTyped* node = nullptr; 290 291 // Error check for requiring specific extensions present. 292 if (symbol && symbol->getNumExtensions()) 293 requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); 294 295 if (symbol && symbol->isReadOnly()) { 296 // All shared things containing an unsized array must be copied up 297 // on first use, so that all future references will share its array structure, 298 // so that editing the implicit size will effect all nodes consuming it, 299 // and so that editing the implicit size won't change the shared one. 300 // 301 // If this is a variable or a block, check it and all it contains, but if this 302 // is a member of an anonymous block, check the whole block, as the whole block 303 // will need to be copied up if it contains an unsized array. 304 if (symbol->getType().containsUnsizedArray() || 305 (symbol->getAsAnonMember() && 306 symbol->getAsAnonMember()->getAnonContainer().getType().containsUnsizedArray())) 307 makeEditable(symbol); 308 } 309 310 const TVariable* variable; 311 const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; 312 if (anon) { 313 // It was a member of an anonymous container. 314 315 // The "getNumExtensions()" mechanism above doesn't yet work for block members 316 blockMemberExtensionCheck(loc, nullptr, *string); 317 318 // Create a subtree for its dereference. 319 variable = anon->getAnonContainer().getAsVariable(); 320 TIntermTyped* container = intermediate.addSymbol(*variable, loc); 321 TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc); 322 node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc); 323 324 node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); 325 if (node->getType().hiddenMember()) 326 error(loc, "member of nameless block was not redeclared", string->c_str(), ""); 327 } else { 328 // Not a member of an anonymous container. 329 330 // The symbol table search was done in the lexical phase. 331 // See if it was a variable. 332 variable = symbol ? symbol->getAsVariable() : nullptr; 333 if (variable) { 334 if ((variable->getType().getBasicType() == EbtBlock || 335 variable->getType().getBasicType() == EbtStruct) && variable->getType().getStruct() == nullptr) { 336 error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), ""); 337 variable = nullptr; 338 } 339 } else { 340 if (symbol) 341 error(loc, "variable name expected", string->c_str(), ""); 342 } 343 344 // Recovery, if it wasn't found or was not a variable. 345 if (! variable) 346 variable = new TVariable(string, TType(EbtVoid)); 347 348 if (variable->getType().getQualifier().isFrontEndConstant()) 349 node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc); 350 else 351 node = intermediate.addSymbol(*variable, loc); 352 } 353 354 if (variable->getType().getQualifier().isIo()) 355 intermediate.addIoAccessed(*string); 356 357 if (variable->getType().getBasicType() == EbtReference && 358 variable->getType().getQualifier().isMemory()) { 359 intermediate.setUseVulkanMemoryModel(); 360 } 361 362 return node; 363 } 364 365 // 366 // Handle seeing a base[index] dereference in the grammar. 367 // 368 TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) 369 { 370 int indexValue = 0; 371 if (index->getQualifier().isFrontEndConstant()) 372 indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); 373 374 // basic type checks... 375 variableCheck(base); 376 377 if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) { 378 if (base->getAsSymbolNode()) 379 error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); 380 else 381 error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); 382 383 // Insert dummy error-recovery result 384 return intermediate.addConstantUnion(0.0, EbtFloat, loc); 385 } 386 387 if (!base->isArray() && base->isVector()) { 388 if (base->getType().containsBasicType(EbtFloat16)) 389 requireFloat16Arithmetic(loc, "[", "does not operate on types containing float16"); 390 if (base->getType().contains16BitInt()) 391 requireInt16Arithmetic(loc, "[", "does not operate on types containing (u)int16"); 392 if (base->getType().contains8BitInt()) 393 requireInt8Arithmetic(loc, "[", "does not operate on types containing (u)int8"); 394 } 395 396 // check for constant folding 397 if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) { 398 // both base and index are front-end constants 399 checkIndex(loc, base->getType(), indexValue); 400 return intermediate.foldDereference(base, indexValue, loc); 401 } 402 403 // at least one of base and index is not a front-end constant variable... 404 TIntermTyped* result = nullptr; 405 if (index->getQualifier().isFrontEndConstant()) 406 checkIndex(loc, base->getType(), indexValue); 407 408 if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) 409 handleIoResizeArrayAccess(loc, base); 410 411 if (index->getQualifier().isFrontEndConstant()) { 412 if (base->getType().isUnsizedArray()) { 413 base->getWritableType().updateImplicitArraySize(indexValue + 1); 414 #ifdef NV_EXTENSIONS 415 // For 2D per-view builtin arrays, update the inner dimension size in parent type 416 if (base->getQualifier().isPerView() && base->getQualifier().builtIn != EbvNone) { 417 TIntermBinary* binaryNode = base->getAsBinaryNode(); 418 if (binaryNode) { 419 TType& leftType = binaryNode->getLeft()->getWritableType(); 420 TArraySizes& arraySizes = *leftType.getArraySizes(); 421 assert(arraySizes.getNumDims() == 2); 422 arraySizes.setDimSize(1, std::max(arraySizes.getDimSize(1), indexValue + 1)); 423 } 424 } 425 #endif 426 } else 427 checkIndex(loc, base->getType(), indexValue); 428 result = intermediate.addIndex(EOpIndexDirect, base, index, loc); 429 } else { 430 if (base->getType().isUnsizedArray()) { 431 // we have a variable index into an unsized array, which is okay, 432 // depending on the situation 433 if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) 434 error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable"); 435 else { 436 // it is okay for a run-time sized array 437 checkRuntimeSizable(loc, *base); 438 } 439 base->getWritableType().setArrayVariablyIndexed(); 440 } 441 if (base->getBasicType() == EbtBlock) { 442 if (base->getQualifier().storage == EvqBuffer) 443 requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array"); 444 else if (base->getQualifier().storage == EvqUniform) 445 profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, 446 "variable indexing uniform block array"); 447 else { 448 // input/output blocks either don't exist or can be variable indexed 449 } 450 } else if (language == EShLangFragment && base->getQualifier().isPipeOutput()) 451 requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader output array"); 452 else if (base->getBasicType() == EbtSampler && version >= 130) { 453 const char* explanation = "variable indexing sampler array"; 454 requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation); 455 profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation); 456 profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation); 457 } 458 459 result = intermediate.addIndex(EOpIndexIndirect, base, index, loc); 460 } 461 462 // Insert valid dereferenced result 463 TType newType(base->getType(), 0); // dereferenced type 464 if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) { 465 newType.getQualifier().storage = EvqConst; 466 // If base or index is a specialization constant, the result should also be a specialization constant. 467 if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) { 468 newType.getQualifier().makeSpecConstant(); 469 } 470 } else { 471 newType.getQualifier().makePartialTemporary(); 472 } 473 result->setType(newType); 474 475 // Propagate nonuniform 476 if (base->getQualifier().isNonUniform() || index->getQualifier().isNonUniform()) 477 result->getWritableType().getQualifier().nonUniform = true; 478 479 if (anyIndexLimits) 480 handleIndexLimits(loc, base, index); 481 482 return result; 483 } 484 485 // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms 486 void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index) 487 { 488 if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) || 489 (! limits.generalUniformIndexing && base->getQualifier().isUniformOrBuffer() && language != EShLangVertex) || 490 (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) || 491 (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) || 492 (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() && 493 ! base->getType().getQualifier().isPipeInput() && 494 ! base->getType().getQualifier().isPipeOutput() && 495 ! base->getType().getQualifier().isConstant()) || 496 (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || 497 base->getType().getQualifier().isPipeOutput()))) { 498 // it's too early to know what the inductive variables are, save it for post processing 499 needsIndexLimitationChecking.push_back(index); 500 } 501 } 502 503 // Make a shared symbol have a non-shared version that can be edited by the current 504 // compile, such that editing its type will not change the shared version and will 505 // effect all nodes sharing it. 506 void TParseContext::makeEditable(TSymbol*& symbol) 507 { 508 TParseContextBase::makeEditable(symbol); 509 510 // See if it's tied to IO resizing 511 if (isIoResizeArray(symbol->getType())) 512 ioArraySymbolResizeList.push_back(symbol); 513 } 514 515 // Return true if this is a geometry shader input array or tessellation control output array 516 // or mesh shader output array. 517 bool TParseContext::isIoResizeArray(const TType& type) const 518 { 519 return type.isArray() && 520 ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || 521 (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch) 522 #ifdef NV_EXTENSIONS 523 || 524 (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn && type.getQualifier().pervertexNV) || 525 (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut && !type.getQualifier().perTaskNV) 526 527 #endif 528 ); 529 } 530 531 // If an array is not isIoResizeArray() but is an io array, make sure it has the right size 532 void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type) 533 { 534 if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel()) 535 return; 536 537 assert(! isIoResizeArray(type)); 538 539 if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch) 540 return; 541 542 if (language == EShLangTessControl || language == EShLangTessEvaluation) { 543 if (type.getOuterArraySize() != resources.maxPatchVertices) { 544 if (type.isSizedArray()) 545 error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", ""); 546 type.changeOuterArraySize(resources.maxPatchVertices); 547 } 548 } 549 } 550 551 // Issue any errors if the non-array object is missing arrayness WRT 552 // shader I/O that has array requirements. 553 // All arrayness checking is handled in array paths, this is for 554 void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) 555 { 556 if (! type.isArray() && ! symbolTable.atBuiltInLevel()) { 557 if (type.getQualifier().isArrayedIo(language) 558 #ifdef NV_EXTENSIONS 559 && !type.getQualifier().layoutPassthrough 560 #endif 561 ) 562 error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str()); 563 } 564 } 565 566 // Handle a dereference of a geometry shader input array or tessellation control output array. 567 // See ioArraySymbolResizeList comment in ParseHelper.h. 568 // 569 void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base) 570 { 571 TIntermSymbol* symbolNode = base->getAsSymbolNode(); 572 assert(symbolNode); 573 if (! symbolNode) 574 return; 575 576 // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing) 577 if (symbolNode->getType().isUnsizedArray()) { 578 int newSize = getIoArrayImplicitSize(symbolNode->getType().getQualifier().isPerPrimitive()); 579 if (newSize > 0) 580 symbolNode->getWritableType().changeOuterArraySize(newSize); 581 } 582 } 583 584 // If there has been an input primitive declaration (geometry shader) or an output 585 // number of vertices declaration(tessellation shader), make sure all input array types 586 // match it in size. Types come either from nodes in the AST or symbols in the 587 // symbol table. 588 // 589 // Types without an array size will be given one. 590 // Types already having a size that is wrong will get an error. 591 // 592 void TParseContext::checkIoArraysConsistency(const TSourceLoc& loc, bool tailOnly, bool isPerPrimitive) 593 { 594 int requiredSize = getIoArrayImplicitSize(isPerPrimitive); 595 if (requiredSize == 0) 596 return; 597 598 const char* feature; 599 if (language == EShLangGeometry) 600 feature = TQualifier::getGeometryString(intermediate.getInputPrimitive()); 601 else if (language == EShLangTessControl 602 #ifdef NV_EXTENSIONS 603 || language == EShLangFragment 604 #endif 605 ) 606 607 feature = "vertices"; 608 #ifdef NV_EXTENSIONS 609 else if (language == EShLangMeshNV) { 610 feature = isPerPrimitive ? "max_primitives" : "max_vertices"; 611 } 612 #endif 613 else 614 feature = "unknown"; 615 616 if (tailOnly) { 617 checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName()); 618 return; 619 } 620 621 for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i) 622 checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName()); 623 } 624 625 int TParseContext::getIoArrayImplicitSize(bool isPerPrimitive) const 626 { 627 if (language == EShLangGeometry) 628 return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); 629 else if (language == EShLangTessControl) 630 return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; 631 #ifdef NV_EXTENSIONS 632 else if (language == EShLangFragment) 633 return 3; //Number of vertices for Fragment shader is always three. 634 else if (language == EShLangMeshNV) { 635 if (isPerPrimitive) { 636 return intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0; 637 } else { 638 return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; 639 } 640 } 641 #endif 642 643 else 644 return 0; 645 } 646 647 void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name) 648 { 649 if (type.isUnsizedArray()) 650 type.changeOuterArraySize(requiredSize); 651 else if (type.getOuterArraySize() != requiredSize) { 652 if (language == EShLangGeometry) 653 error(loc, "inconsistent input primitive for array size of", feature, name.c_str()); 654 else if (language == EShLangTessControl) 655 error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str()); 656 #ifdef NV_EXTENSIONS 657 else if (language == EShLangFragment) { 658 if (type.getOuterArraySize() > requiredSize) 659 error(loc, " cannot be greater than 3 for pervertexNV", feature, name.c_str()); 660 } 661 else if (language == EShLangMeshNV) 662 error(loc, "inconsistent output array size of", feature, name.c_str()); 663 #endif 664 else 665 assert(0); 666 } 667 } 668 669 // Handle seeing a binary node with a math operation. 670 // Returns nullptr if not semantically allowed. 671 TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right) 672 { 673 rValueErrorCheck(loc, str, left->getAsTyped()); 674 rValueErrorCheck(loc, str, right->getAsTyped()); 675 676 bool allowed = true; 677 switch (op) { 678 // TODO: Bring more source language-specific checks up from intermediate.cpp 679 // to the specific parse helpers for that source language. 680 case EOpLessThan: 681 case EOpGreaterThan: 682 case EOpLessThanEqual: 683 case EOpGreaterThanEqual: 684 if (! left->isScalar() || ! right->isScalar()) 685 allowed = false; 686 break; 687 default: 688 break; 689 } 690 691 if (((left->getType().containsBasicType(EbtFloat16) || right->getType().containsBasicType(EbtFloat16)) && !float16Arithmetic()) || 692 ((left->getType().contains16BitInt() || right->getType().contains16BitInt()) && !int16Arithmetic()) || 693 ((left->getType().contains8BitInt() || right->getType().contains8BitInt()) && !int8Arithmetic())) { 694 allowed = false; 695 } 696 697 TIntermTyped* result = nullptr; 698 if (allowed) 699 result = intermediate.addBinaryMath(op, left, right, loc); 700 701 if (result == nullptr) 702 binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString()); 703 704 return result; 705 } 706 707 // Handle seeing a unary node with a math operation. 708 TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* childNode) 709 { 710 rValueErrorCheck(loc, str, childNode); 711 712 bool allowed = true; 713 if ((childNode->getType().containsBasicType(EbtFloat16) && !float16Arithmetic()) || 714 (childNode->getType().contains16BitInt() && !int16Arithmetic()) || 715 (childNode->getType().contains8BitInt() && !int8Arithmetic())) { 716 allowed = false; 717 } 718 719 TIntermTyped* result = nullptr; 720 721 if (allowed) 722 result = intermediate.addUnaryMath(op, childNode, loc); 723 724 if (result) 725 return result; 726 else 727 unaryOpError(loc, str, childNode->getCompleteString()); 728 729 return childNode; 730 } 731 732 // 733 // Handle seeing a base.field dereference in the grammar. 734 // 735 TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field) 736 { 737 variableCheck(base); 738 739 // 740 // .length() can't be resolved until we later see the function-calling syntax. 741 // Save away the name in the AST for now. Processing is completed in 742 // handleLengthMethod(). 743 // 744 if (field == "length") { 745 if (base->isArray()) { 746 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, ".length"); 747 profileRequires(loc, EEsProfile, 300, nullptr, ".length"); 748 } else if (base->isVector() || base->isMatrix()) { 749 const char* feature = ".length() on vectors and matrices"; 750 requireProfile(loc, ~EEsProfile, feature); 751 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature); 752 } else { 753 error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str()); 754 755 return base; 756 } 757 758 return intermediate.addMethod(base, TType(EbtInt), &field, loc); 759 } 760 761 // It's not .length() if we get to here. 762 763 if (base->isArray()) { 764 error(loc, "cannot apply to an array:", ".", field.c_str()); 765 766 return base; 767 } 768 769 // It's neither an array nor .length() if we get here, 770 // leaving swizzles and struct/block dereferences. 771 772 TIntermTyped* result = base; 773 if ((base->isVector() || base->isScalar()) && 774 (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) { 775 if (base->isScalar()) { 776 const char* dotFeature = "scalar swizzle"; 777 requireProfile(loc, ~EEsProfile, dotFeature); 778 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature); 779 } 780 781 TSwizzleSelectors<TVectorSelector> selectors; 782 parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); 783 784 if (base->isVector() && selectors.size() != 1 && base->getType().containsBasicType(EbtFloat16)) 785 requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16"); 786 if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt()) 787 requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16"); 788 if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt()) 789 requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8"); 790 791 if (base->isScalar()) { 792 if (selectors.size() == 1) 793 return result; 794 else { 795 TType type(base->getBasicType(), EvqTemporary, selectors.size()); 796 // Swizzle operations propagate specialization-constantness 797 if (base->getQualifier().isSpecConstant()) 798 type.getQualifier().makeSpecConstant(); 799 return addConstructor(loc, base, type); 800 } 801 } 802 803 if (base->getType().getQualifier().isFrontEndConstant()) 804 result = intermediate.foldSwizzle(base, selectors, loc); 805 else { 806 if (selectors.size() == 1) { 807 TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); 808 result = intermediate.addIndex(EOpIndexDirect, base, index, loc); 809 result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision)); 810 } else { 811 TIntermTyped* index = intermediate.addSwizzle(selectors, loc); 812 result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); 813 result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); 814 } 815 // Swizzle operations propagate specialization-constantness 816 if (base->getType().getQualifier().isSpecConstant()) 817 result->getWritableType().getQualifier().makeSpecConstant(); 818 } 819 } else if (base->getBasicType() == EbtStruct || 820 base->getBasicType() == EbtBlock || 821 base->getBasicType() == EbtReference) { 822 const TTypeList* fields = base->getBasicType() == EbtReference ? 823 base->getType().getReferentType()->getStruct() : 824 base->getType().getStruct(); 825 bool fieldFound = false; 826 int member; 827 for (member = 0; member < (int)fields->size(); ++member) { 828 if ((*fields)[member].type->getFieldName() == field) { 829 fieldFound = true; 830 break; 831 } 832 } 833 if (fieldFound) { 834 if (base->getType().getQualifier().isFrontEndConstant()) 835 result = intermediate.foldDereference(base, member, loc); 836 else { 837 blockMemberExtensionCheck(loc, base, field); 838 TIntermTyped* index = intermediate.addConstantUnion(member, loc); 839 result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); 840 result->setType(*(*fields)[member].type); 841 if ((*fields)[member].type->getQualifier().isIo()) 842 intermediate.addIoAccessed(field); 843 } 844 } else 845 error(loc, "no such field in structure", field.c_str(), ""); 846 } else 847 error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str()); 848 849 // Propagate noContraction up the dereference chain 850 if (base->getQualifier().noContraction) 851 result->getWritableType().getQualifier().noContraction = true; 852 853 // Propagate nonuniform 854 if (base->getQualifier().isNonUniform()) 855 result->getWritableType().getQualifier().nonUniform = true; 856 857 return result; 858 } 859 860 void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* /*base*/, const TString& field) 861 { 862 if (profile == EEsProfile && field == "gl_PointSize") { 863 if (language == EShLangGeometry) 864 requireExtensions(loc, Num_AEP_geometry_point_size, AEP_geometry_point_size, "gl_PointSize"); 865 else if (language == EShLangTessControl || language == EShLangTessEvaluation) 866 requireExtensions(loc, Num_AEP_tessellation_point_size, AEP_tessellation_point_size, "gl_PointSize"); 867 } 868 } 869 870 // 871 // Handle seeing a function declarator in the grammar. This is the precursor 872 // to recognizing a function prototype or function definition. 873 // 874 TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype) 875 { 876 // ES can't declare prototypes inside functions 877 if (! symbolTable.atGlobalLevel()) 878 requireProfile(loc, ~EEsProfile, "local function declaration"); 879 880 // 881 // Multiple declarations of the same function name are allowed. 882 // 883 // If this is a definition, the definition production code will check for redefinitions 884 // (we don't know at this point if it's a definition or not). 885 // 886 // Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match. 887 // - except ES 100, which only allows a single prototype 888 // 889 // ES 100 does not allow redefining, but does allow overloading of built-in functions. 890 // ES 300 does not allow redefining or overloading of built-in functions. 891 // 892 bool builtIn; 893 TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); 894 if (symbol && symbol->getAsFunction() && builtIn) 895 requireProfile(loc, ~EEsProfile, "redefinition of built-in function"); 896 const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; 897 if (prevDec) { 898 if (prevDec->isPrototyped() && prototype) 899 profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function"); 900 if (prevDec->getType() != function.getType()) 901 error(loc, "overloaded functions must have the same return type", function.getName().c_str(), ""); 902 for (int i = 0; i < prevDec->getParamCount(); ++i) { 903 if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage) 904 error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1); 905 906 if ((*prevDec)[i].type->getQualifier().precision != function[i].type->getQualifier().precision) 907 error(loc, "overloaded functions must have the same parameter precision qualifiers for argument", function[i].type->getPrecisionQualifierString(), "%d", i+1); 908 } 909 } 910 911 arrayObjectCheck(loc, function.getType(), "array in function return type"); 912 913 if (prototype) { 914 // All built-in functions are defined, even though they don't have a body. 915 // Count their prototype as a definition instead. 916 if (symbolTable.atBuiltInLevel()) 917 function.setDefined(); 918 else { 919 if (prevDec && ! builtIn) 920 symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const 921 function.setPrototyped(); 922 } 923 } 924 925 // This insert won't actually insert it if it's a duplicate signature, but it will still check for 926 // other forms of name collisions. 927 if (! symbolTable.insert(function)) 928 error(loc, "function name is redeclaration of existing name", function.getName().c_str(), ""); 929 930 // 931 // If this is a redeclaration, it could also be a definition, 932 // in which case, we need to use the parameter names from this one, and not the one that's 933 // being redeclared. So, pass back this declaration, not the one in the symbol table. 934 // 935 return &function; 936 } 937 938 // 939 // Handle seeing the function prototype in front of a function definition in the grammar. 940 // The body is handled after this function returns. 941 // 942 TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function) 943 { 944 currentCaller = function.getMangledName(); 945 TSymbol* symbol = symbolTable.find(function.getMangledName()); 946 TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; 947 948 if (! prevDec) 949 error(loc, "can't find function", function.getName().c_str(), ""); 950 // Note: 'prevDec' could be 'function' if this is the first time we've seen function 951 // as it would have just been put in the symbol table. Otherwise, we're looking up 952 // an earlier occurrence. 953 954 if (prevDec && prevDec->isDefined()) { 955 // Then this function already has a body. 956 error(loc, "function already has a body", function.getName().c_str(), ""); 957 } 958 if (prevDec && ! prevDec->isDefined()) { 959 prevDec->setDefined(); 960 961 // Remember the return type for later checking for RETURN statements. 962 currentFunctionType = &(prevDec->getType()); 963 } else 964 currentFunctionType = new TType(EbtVoid); 965 functionReturnsValue = false; 966 967 // Check for entry point 968 if (function.getName().compare(intermediate.getEntryPointName().c_str()) == 0) { 969 intermediate.setEntryPointMangledName(function.getMangledName().c_str()); 970 intermediate.incrementEntryPointCount(); 971 inMain = true; 972 } else 973 inMain = false; 974 975 // 976 // Raise error message if main function takes any parameters or returns anything other than void 977 // 978 if (inMain) { 979 if (function.getParamCount() > 0) 980 error(loc, "function cannot take any parameter(s)", function.getName().c_str(), ""); 981 if (function.getType().getBasicType() != EbtVoid) 982 error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value"); 983 } 984 985 // 986 // New symbol table scope for body of function plus its arguments 987 // 988 symbolTable.push(); 989 990 // 991 // Insert parameters into the symbol table. 992 // If the parameter has no name, it's not an error, just don't insert it 993 // (could be used for unused args). 994 // 995 // Also, accumulate the list of parameters into the HIL, so lower level code 996 // knows where to find parameters. 997 // 998 TIntermAggregate* paramNodes = new TIntermAggregate; 999 for (int i = 0; i < function.getParamCount(); i++) { 1000 TParameter& param = function[i]; 1001 if (param.name != nullptr) { 1002 TVariable *variable = new TVariable(param.name, *param.type); 1003 1004 // Insert the parameters with name in the symbol table. 1005 if (! symbolTable.insert(*variable)) 1006 error(loc, "redefinition", variable->getName().c_str(), ""); 1007 else { 1008 // Transfer ownership of name pointer to symbol table. 1009 param.name = nullptr; 1010 1011 // Add the parameter to the HIL 1012 paramNodes = intermediate.growAggregate(paramNodes, 1013 intermediate.addSymbol(*variable, loc), 1014 loc); 1015 } 1016 } else 1017 paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); 1018 } 1019 intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); 1020 loopNestingLevel = 0; 1021 statementNestingLevel = 0; 1022 controlFlowNestingLevel = 0; 1023 postEntryPointReturn = false; 1024 1025 return paramNodes; 1026 } 1027 1028 // 1029 // Handle seeing function call syntax in the grammar, which could be any of 1030 // - .length() method 1031 // - constructor 1032 // - a call to a built-in function mapped to an operator 1033 // - a call to a built-in function that will remain a function call (e.g., texturing) 1034 // - user function 1035 // - subroutine call (not implemented yet) 1036 // 1037 TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments) 1038 { 1039 TIntermTyped* result = nullptr; 1040 1041 if (function->getBuiltInOp() == EOpArrayLength) 1042 result = handleLengthMethod(loc, function, arguments); 1043 else if (function->getBuiltInOp() != EOpNull) { 1044 // 1045 // Then this should be a constructor. 1046 // Don't go through the symbol table for constructors. 1047 // Their parameters will be verified algorithmically. 1048 // 1049 TType type(EbtVoid); // use this to get the type back 1050 if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) { 1051 // 1052 // It's a constructor, of type 'type'. 1053 // 1054 result = addConstructor(loc, arguments, type); 1055 if (result == nullptr) 1056 error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), ""); 1057 } 1058 } else { 1059 // 1060 // Find it in the symbol table. 1061 // 1062 const TFunction* fnCandidate; 1063 bool builtIn; 1064 fnCandidate = findFunction(loc, *function, builtIn); 1065 if (fnCandidate) { 1066 // This is a declared function that might map to 1067 // - a built-in operator, 1068 // - a built-in function not mapped to an operator, or 1069 // - a user function. 1070 1071 // Error check for a function requiring specific extensions present. 1072 if (builtIn && fnCandidate->getNumExtensions()) 1073 requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); 1074 1075 if (builtIn && fnCandidate->getType().containsBasicType(EbtFloat16)) 1076 requireFloat16Arithmetic(loc, "built-in function", "float16 types can only be in uniform block or buffer storage"); 1077 if (builtIn && fnCandidate->getType().contains16BitInt()) 1078 requireInt16Arithmetic(loc, "built-in function", "(u)int16 types can only be in uniform block or buffer storage"); 1079 if (builtIn && fnCandidate->getType().contains8BitInt()) 1080 requireInt8Arithmetic(loc, "built-in function", "(u)int8 types can only be in uniform block or buffer storage"); 1081 1082 if (arguments != nullptr) { 1083 // Make sure qualifications work for these arguments. 1084 TIntermAggregate* aggregate = arguments->getAsAggregate(); 1085 for (int i = 0; i < fnCandidate->getParamCount(); ++i) { 1086 // At this early point there is a slight ambiguity between whether an aggregate 'arguments' 1087 // is the single argument itself or its children are the arguments. Only one argument 1088 // means take 'arguments' itself as the one argument. 1089 TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments); 1090 TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier(); 1091 if (formalQualifier.isParamOutput()) { 1092 if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped())) 1093 error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", ""); 1094 } 1095 TQualifier& argQualifier = arg->getAsTyped()->getQualifier(); 1096 if (argQualifier.isMemory()) { 1097 const char* message = "argument cannot drop memory qualifier when passed to formal parameter"; 1098 if (argQualifier.volatil && ! formalQualifier.volatil) 1099 error(arguments->getLoc(), message, "volatile", ""); 1100 if (argQualifier.coherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent)) 1101 error(arguments->getLoc(), message, "coherent", ""); 1102 if (argQualifier.devicecoherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent)) 1103 error(arguments->getLoc(), message, "devicecoherent", ""); 1104 if (argQualifier.queuefamilycoherent && ! (formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent)) 1105 error(arguments->getLoc(), message, "queuefamilycoherent", ""); 1106 if (argQualifier.workgroupcoherent && ! (formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent)) 1107 error(arguments->getLoc(), message, "workgroupcoherent", ""); 1108 if (argQualifier.subgroupcoherent && ! (formalQualifier.subgroupcoherent || formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent)) 1109 error(arguments->getLoc(), message, "subgroupcoherent", ""); 1110 if (argQualifier.readonly && ! formalQualifier.readonly) 1111 error(arguments->getLoc(), message, "readonly", ""); 1112 if (argQualifier.writeonly && ! formalQualifier.writeonly) 1113 error(arguments->getLoc(), message, "writeonly", ""); 1114 } 1115 1116 if (builtIn && arg->getAsTyped()->getType().containsBasicType(EbtFloat16)) 1117 requireFloat16Arithmetic(arguments->getLoc(), "built-in function", "float16 types can only be in uniform block or buffer storage"); 1118 if (builtIn && arg->getAsTyped()->getType().contains16BitInt()) 1119 requireInt16Arithmetic(arguments->getLoc(), "built-in function", "(u)int16 types can only be in uniform block or buffer storage"); 1120 if (builtIn && arg->getAsTyped()->getType().contains8BitInt()) 1121 requireInt8Arithmetic(arguments->getLoc(), "built-in function", "(u)int8 types can only be in uniform block or buffer storage"); 1122 1123 // TODO 4.5 functionality: A shader will fail to compile 1124 // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or 1125 // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the 1126 // memargument of an atomic memory function, as long as the underlying array or vector is a buffer or 1127 // shared variable. 1128 } 1129 1130 // Convert 'in' arguments 1131 addInputArgumentConversions(*fnCandidate, arguments); // arguments may be modified if it's just a single argument node 1132 } 1133 1134 if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) { 1135 // A function call mapped to a built-in operation. 1136 result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate); 1137 } else { 1138 // This is a function call not mapped to built-in operator. 1139 // It could still be a built-in function, but only if PureOperatorBuiltins == false. 1140 result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc); 1141 TIntermAggregate* call = result->getAsAggregate(); 1142 call->setName(fnCandidate->getMangledName()); 1143 1144 // this is how we know whether the given function is a built-in function or a user-defined function 1145 // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also 1146 // if builtIn == true, it's definitely a built-in function with EOpNull 1147 if (! builtIn) { 1148 call->setUserDefined(); 1149 if (symbolTable.atGlobalLevel()) { 1150 requireProfile(loc, ~EEsProfile, "calling user function from global scope"); 1151 intermediate.addToCallGraph(infoSink, "main(", fnCandidate->getMangledName()); 1152 } else 1153 intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName()); 1154 } 1155 1156 if (builtIn) 1157 nonOpBuiltInCheck(loc, *fnCandidate, *call); 1158 else 1159 userFunctionCallCheck(loc, *call); 1160 } 1161 1162 // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. 1163 // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. 1164 // Also, build the qualifier list for user function calls, which are always called with an aggregate. 1165 if (result->getAsAggregate()) { 1166 TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); 1167 for (int i = 0; i < fnCandidate->getParamCount(); ++i) { 1168 TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; 1169 qualifierList.push_back(qual); 1170 } 1171 result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate()); 1172 } 1173 } 1174 } 1175 1176 // generic error recovery 1177 // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades 1178 if (result == nullptr) 1179 result = intermediate.addConstantUnion(0.0, EbtFloat, loc); 1180 1181 return result; 1182 } 1183 1184 TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode* arguments, 1185 const TFunction& function) 1186 { 1187 checkLocation(loc, function.getBuiltInOp()); 1188 TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(), 1189 function.getParamCount() == 1, 1190 arguments, function.getType()); 1191 if (obeyPrecisionQualifiers()) 1192 computeBuiltinPrecisions(*result, function); 1193 1194 if (result == nullptr) { 1195 if (arguments == nullptr) 1196 error(loc, " wrong operand type", "Internal Error", 1197 "built in unary operator function. Type: %s", ""); 1198 else 1199 error(arguments->getLoc(), " wrong operand type", "Internal Error", 1200 "built in unary operator function. Type: %s", 1201 static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str()); 1202 } else if (result->getAsOperator()) 1203 builtInOpCheck(loc, function, *result->getAsOperator()); 1204 1205 return result; 1206 } 1207 1208 // "The operation of a built-in function can have a different precision 1209 // qualification than the precision qualification of the resulting value. 1210 // These two precision qualifications are established as follows. 1211 // 1212 // The precision qualification of the operation of a built-in function is 1213 // based on the precision qualification of its input arguments and formal 1214 // parameters: When a formal parameter specifies a precision qualifier, 1215 // that is used, otherwise, the precision qualification of the calling 1216 // argument is used. The highest precision of these will be the precision 1217 // qualification of the operation of the built-in function. Generally, 1218 // this is applied across all arguments to a built-in function, with the 1219 // exceptions being: 1220 // - bitfieldExtract and bitfieldInsert ignore the 'offset' and 'bits' 1221 // arguments. 1222 // - interpolateAt* functions only look at the 'interpolant' argument. 1223 // 1224 // The precision qualification of the result of a built-in function is 1225 // determined in one of the following ways: 1226 // 1227 // - For the texture sampling, image load, and image store functions, 1228 // the precision of the return type matches the precision of the 1229 // sampler type 1230 // 1231 // Otherwise: 1232 // 1233 // - For prototypes that do not specify a resulting precision qualifier, 1234 // the precision will be the same as the precision of the operation. 1235 // 1236 // - For prototypes that do specify a resulting precision qualifier, 1237 // the specified precision qualifier is the precision qualification of 1238 // the result." 1239 // 1240 void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction& function) 1241 { 1242 TPrecisionQualifier operationPrecision = EpqNone; 1243 TPrecisionQualifier resultPrecision = EpqNone; 1244 1245 TIntermOperator* opNode = node.getAsOperator(); 1246 if (opNode == nullptr) 1247 return; 1248 1249 if (TIntermUnary* unaryNode = node.getAsUnaryNode()) { 1250 operationPrecision = std::max(function[0].type->getQualifier().precision, 1251 unaryNode->getOperand()->getType().getQualifier().precision); 1252 if (function.getType().getBasicType() != EbtBool) 1253 resultPrecision = function.getType().getQualifier().precision == EpqNone ? 1254 operationPrecision : 1255 function.getType().getQualifier().precision; 1256 } else if (TIntermAggregate* agg = node.getAsAggregate()) { 1257 TIntermSequence& sequence = agg->getSequence(); 1258 unsigned int numArgs = (unsigned int)sequence.size(); 1259 switch (agg->getOp()) { 1260 case EOpBitfieldExtract: 1261 numArgs = 1; 1262 break; 1263 case EOpBitfieldInsert: 1264 numArgs = 2; 1265 break; 1266 case EOpInterpolateAtCentroid: 1267 case EOpInterpolateAtOffset: 1268 case EOpInterpolateAtSample: 1269 numArgs = 1; 1270 break; 1271 default: 1272 break; 1273 } 1274 // find the maximum precision from the arguments and parameters 1275 for (unsigned int arg = 0; arg < numArgs; ++arg) { 1276 operationPrecision = std::max(operationPrecision, sequence[arg]->getAsTyped()->getQualifier().precision); 1277 operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision); 1278 } 1279 // compute the result precision 1280 #ifdef AMD_EXTENSIONS 1281 if (agg->isSampling() || 1282 agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore || 1283 agg->getOp() == EOpImageLoadLod || agg->getOp() == EOpImageStoreLod) 1284 #else 1285 if (agg->isSampling() || agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore) 1286 #endif 1287 resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision; 1288 else if (function.getType().getBasicType() != EbtBool) 1289 resultPrecision = function.getType().getQualifier().precision == EpqNone ? 1290 operationPrecision : 1291 function.getType().getQualifier().precision; 1292 } 1293 1294 // Propagate precision through this node and its children. That algorithm stops 1295 // when a precision is found, so start by clearing this subroot precision 1296 opNode->getQualifier().precision = EpqNone; 1297 if (operationPrecision != EpqNone) { 1298 opNode->propagatePrecision(operationPrecision); 1299 opNode->setOperationPrecision(operationPrecision); 1300 } 1301 // Now, set the result precision, which might not match 1302 opNode->getQualifier().precision = resultPrecision; 1303 } 1304 1305 TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value) 1306 { 1307 storage16BitAssignmentCheck(loc, value->getType(), "return"); 1308 1309 functionReturnsValue = true; 1310 if (currentFunctionType->getBasicType() == EbtVoid) { 1311 error(loc, "void function cannot return a value", "return", ""); 1312 return intermediate.addBranch(EOpReturn, loc); 1313 } else if (*currentFunctionType != value->getType()) { 1314 TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value); 1315 if (converted) { 1316 if (*currentFunctionType != converted->getType()) 1317 error(loc, "cannot convert return value to function return type", "return", ""); 1318 if (version < 420) 1319 warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", ""); 1320 return intermediate.addBranch(EOpReturn, converted, loc); 1321 } else { 1322 error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); 1323 return intermediate.addBranch(EOpReturn, value, loc); 1324 } 1325 } else 1326 return intermediate.addBranch(EOpReturn, value, loc); 1327 } 1328 1329 // See if the operation is being done in an illegal location. 1330 void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op) 1331 { 1332 switch (op) { 1333 case EOpBarrier: 1334 if (language == EShLangTessControl) { 1335 if (controlFlowNestingLevel > 0) 1336 error(loc, "tessellation control barrier() cannot be placed within flow control", "", ""); 1337 if (! inMain) 1338 error(loc, "tessellation control barrier() must be in main()", "", ""); 1339 else if (postEntryPointReturn) 1340 error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", ""); 1341 } 1342 break; 1343 default: 1344 break; 1345 } 1346 } 1347 1348 // Finish processing object.length(). This started earlier in handleDotDereference(), where 1349 // the ".length" part was recognized and semantically checked, and finished here where the 1350 // function syntax "()" is recognized. 1351 // 1352 // Return resulting tree node. 1353 TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction* function, TIntermNode* intermNode) 1354 { 1355 int length = 0; 1356 1357 if (function->getParamCount() > 0) 1358 error(loc, "method does not accept any arguments", function->getName().c_str(), ""); 1359 else { 1360 const TType& type = intermNode->getAsTyped()->getType(); 1361 if (type.isArray()) { 1362 if (type.isUnsizedArray()) { 1363 if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) { 1364 // We could be between a layout declaration that gives a built-in io array implicit size and 1365 // a user redeclaration of that array, meaning we have to substitute its implicit size here 1366 // without actually redeclaring the array. (It is an error to use a member before the 1367 // redeclaration, but not an error to use the array name itself.) 1368 const TString& name = intermNode->getAsSymbolNode()->getName(); 1369 if (name == "gl_in" || name == "gl_out" 1370 #ifdef NV_EXTENSIONS 1371 || name == "gl_MeshVerticesNV" 1372 || name == "gl_MeshPrimitivesNV" 1373 #endif 1374 ) 1375 { 1376 length = getIoArrayImplicitSize(type.getQualifier().isPerPrimitive()); 1377 } 1378 } 1379 if (length == 0) { 1380 if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) 1381 error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); 1382 else if (isRuntimeLength(*intermNode->getAsTyped())) { 1383 // Create a unary op and let the back end handle it 1384 return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); 1385 } else 1386 error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); 1387 } 1388 } else if (type.getOuterArrayNode()) { 1389 // If the array's outer size is specified by an intermediate node, it means the array's length 1390 // was specified by a specialization constant. In such a case, we should return the node of the 1391 // specialization constants to represent the length. 1392 return type.getOuterArrayNode(); 1393 } else 1394 length = type.getOuterArraySize(); 1395 } else if (type.isMatrix()) 1396 length = type.getMatrixCols(); 1397 else if (type.isVector()) 1398 length = type.getVectorSize(); 1399 else { 1400 // we should not get here, because earlier semantic checking should have prevented this path 1401 error(loc, ".length()", "unexpected use of .length()", ""); 1402 } 1403 } 1404 1405 if (length == 0) 1406 length = 1; 1407 1408 return intermediate.addConstantUnion(length, loc); 1409 } 1410 1411 // 1412 // Add any needed implicit conversions for function-call arguments to input parameters. 1413 // 1414 void TParseContext::addInputArgumentConversions(const TFunction& function, TIntermNode*& arguments) const 1415 { 1416 TIntermAggregate* aggregate = arguments->getAsAggregate(); 1417 1418 // Process each argument's conversion 1419 for (int i = 0; i < function.getParamCount(); ++i) { 1420 // At this early point there is a slight ambiguity between whether an aggregate 'arguments' 1421 // is the single argument itself or its children are the arguments. Only one argument 1422 // means take 'arguments' itself as the one argument. 1423 TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped()); 1424 if (*function[i].type != arg->getType()) { 1425 if (function[i].type->getQualifier().isParamInput()) { 1426 // In-qualified arguments just need an extra node added above the argument to 1427 // convert to the correct type. 1428 arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg); 1429 if (arg) { 1430 if (function.getParamCount() == 1) 1431 arguments = arg; 1432 else { 1433 if (aggregate) 1434 aggregate->getSequence()[i] = arg; 1435 else 1436 arguments = arg; 1437 } 1438 } 1439 } 1440 } 1441 } 1442 } 1443 1444 // 1445 // Add any needed implicit output conversions for function-call arguments. This 1446 // can require a new tree topology, complicated further by whether the function 1447 // has a return value. 1448 // 1449 // Returns a node of a subtree that evaluates to the return value of the function. 1450 // 1451 TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const 1452 { 1453 TIntermSequence& arguments = intermNode.getSequence(); 1454 1455 // Will there be any output conversions? 1456 bool outputConversions = false; 1457 for (int i = 0; i < function.getParamCount(); ++i) { 1458 if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().isParamOutput()) { 1459 outputConversions = true; 1460 break; 1461 } 1462 } 1463 1464 if (! outputConversions) 1465 return &intermNode; 1466 1467 // Setup for the new tree, if needed: 1468 // 1469 // Output conversions need a different tree topology. 1470 // Out-qualified arguments need a temporary of the correct type, with the call 1471 // followed by an assignment of the temporary to the original argument: 1472 // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...) 1473 // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet) 1474 // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment. 1475 TIntermTyped* conversionTree = nullptr; 1476 TVariable* tempRet = nullptr; 1477 if (intermNode.getBasicType() != EbtVoid) { 1478 // do the "tempRet = function(...), " bit from above 1479 tempRet = makeInternalVariable("tempReturn", intermNode.getType()); 1480 TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); 1481 conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc()); 1482 } else 1483 conversionTree = &intermNode; 1484 1485 conversionTree = intermediate.makeAggregate(conversionTree); 1486 1487 // Process each argument's conversion 1488 for (int i = 0; i < function.getParamCount(); ++i) { 1489 if (*function[i].type != arguments[i]->getAsTyped()->getType()) { 1490 if (function[i].type->getQualifier().isParamOutput()) { 1491 // Out-qualified arguments need to use the topology set up above. 1492 // do the " ...(tempArg, ...), arg = tempArg" bit from above 1493 TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type); 1494 tempArg->getWritableType().getQualifier().makeTemporary(); 1495 TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc()); 1496 TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc()); 1497 conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc()); 1498 // replace the argument with another node for the same tempArg variable 1499 arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc()); 1500 } 1501 } 1502 } 1503 1504 // Finalize the tree topology (see bigger comment above). 1505 if (tempRet) { 1506 // do the "..., tempRet" bit from above 1507 TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); 1508 conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc()); 1509 } 1510 conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc()); 1511 1512 return conversionTree; 1513 } 1514 1515 void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode) 1516 { 1517 const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence(); 1518 1519 //const int gl_SemanticsRelaxed = 0x0; 1520 const int gl_SemanticsAcquire = 0x2; 1521 const int gl_SemanticsRelease = 0x4; 1522 const int gl_SemanticsAcquireRelease = 0x8; 1523 const int gl_SemanticsMakeAvailable = 0x2000; 1524 const int gl_SemanticsMakeVisible = 0x4000; 1525 1526 //const int gl_StorageSemanticsNone = 0x0; 1527 const int gl_StorageSemanticsBuffer = 0x40; 1528 const int gl_StorageSemanticsShared = 0x100; 1529 const int gl_StorageSemanticsImage = 0x800; 1530 const int gl_StorageSemanticsOutput = 0x1000; 1531 1532 1533 unsigned int semantics = 0, storageClassSemantics = 0; 1534 unsigned int semantics2 = 0, storageClassSemantics2 = 0; 1535 1536 // Grab the semantics and storage class semantics from the operands, based on opcode 1537 switch (callNode.getOp()) { 1538 case EOpAtomicAdd: 1539 case EOpAtomicMin: 1540 case EOpAtomicMax: 1541 case EOpAtomicAnd: 1542 case EOpAtomicOr: 1543 case EOpAtomicXor: 1544 case EOpAtomicExchange: 1545 case EOpAtomicStore: 1546 storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1547 semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1548 break; 1549 case EOpAtomicLoad: 1550 storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1551 semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1552 break; 1553 case EOpAtomicCompSwap: 1554 storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1555 semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1556 storageClassSemantics2 = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1557 semantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1558 break; 1559 1560 case EOpImageAtomicAdd: 1561 case EOpImageAtomicMin: 1562 case EOpImageAtomicMax: 1563 case EOpImageAtomicAnd: 1564 case EOpImageAtomicOr: 1565 case EOpImageAtomicXor: 1566 case EOpImageAtomicExchange: 1567 case EOpImageAtomicStore: 1568 storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1569 semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1570 break; 1571 case EOpImageAtomicLoad: 1572 storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1573 semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1574 break; 1575 case EOpImageAtomicCompSwap: 1576 storageClassSemantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1577 semantics = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1578 storageClassSemantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1579 semantics2 = (*argp)[8]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1580 break; 1581 1582 case EOpBarrier: 1583 storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1584 semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1585 break; 1586 case EOpMemoryBarrier: 1587 storageClassSemantics = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1588 semantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1589 break; 1590 default: 1591 break; 1592 } 1593 1594 if ((semantics & gl_SemanticsAcquire) && 1595 (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore)) { 1596 error(loc, "gl_SemanticsAcquire must not be used with (image) atomic store", 1597 fnCandidate.getName().c_str(), ""); 1598 } 1599 if ((semantics & gl_SemanticsRelease) && 1600 (callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpImageAtomicLoad)) { 1601 error(loc, "gl_SemanticsRelease must not be used with (image) atomic load", 1602 fnCandidate.getName().c_str(), ""); 1603 } 1604 if ((semantics & gl_SemanticsAcquireRelease) && 1605 (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore || 1606 callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpImageAtomicLoad)) { 1607 error(loc, "gl_SemanticsAcquireRelease must not be used with (image) atomic load/store", 1608 fnCandidate.getName().c_str(), ""); 1609 } 1610 if (((semantics | semantics2) & ~(gl_SemanticsAcquire | 1611 gl_SemanticsRelease | 1612 gl_SemanticsAcquireRelease | 1613 gl_SemanticsMakeAvailable | 1614 gl_SemanticsMakeVisible))) { 1615 error(loc, "Invalid semantics value", fnCandidate.getName().c_str(), ""); 1616 } 1617 if (((storageClassSemantics | storageClassSemantics2) & ~(gl_StorageSemanticsBuffer | 1618 gl_StorageSemanticsShared | 1619 gl_StorageSemanticsImage | 1620 gl_StorageSemanticsOutput))) { 1621 error(loc, "Invalid storage class semantics value", fnCandidate.getName().c_str(), ""); 1622 } 1623 1624 if (callNode.getOp() == EOpMemoryBarrier) { 1625 if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { 1626 error(loc, "Semantics must include exactly one of gl_SemanticsRelease, gl_SemanticsAcquire, or " 1627 "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), ""); 1628 } 1629 } else { 1630 if (semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) { 1631 if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { 1632 error(loc, "Semantics must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or " 1633 "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), ""); 1634 } 1635 } 1636 if (semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) { 1637 if (!IsPow2(semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { 1638 error(loc, "semUnequal must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or " 1639 "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), ""); 1640 } 1641 } 1642 } 1643 if (callNode.getOp() == EOpMemoryBarrier) { 1644 if (storageClassSemantics == 0) { 1645 error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), ""); 1646 } 1647 } 1648 if (callNode.getOp() == EOpBarrier && semantics != 0 && storageClassSemantics == 0) { 1649 error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), ""); 1650 } 1651 if ((callNode.getOp() == EOpAtomicCompSwap || callNode.getOp() == EOpImageAtomicCompSwap) && 1652 (semantics2 & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { 1653 error(loc, "semUnequal must not be gl_SemanticsRelease or gl_SemanticsAcquireRelease", 1654 fnCandidate.getName().c_str(), ""); 1655 } 1656 if ((semantics & gl_SemanticsMakeAvailable) && 1657 !(semantics & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { 1658 error(loc, "gl_SemanticsMakeAvailable requires gl_SemanticsRelease or gl_SemanticsAcquireRelease", 1659 fnCandidate.getName().c_str(), ""); 1660 } 1661 if ((semantics & gl_SemanticsMakeVisible) && 1662 !(semantics & (gl_SemanticsAcquire | gl_SemanticsAcquireRelease))) { 1663 error(loc, "gl_SemanticsMakeVisible requires gl_SemanticsAcquire or gl_SemanticsAcquireRelease", 1664 fnCandidate.getName().c_str(), ""); 1665 } 1666 1667 } 1668 1669 1670 // 1671 // Do additional checking of built-in function calls that is not caught 1672 // by normal semantic checks on argument type, extension tagging, etc. 1673 // 1674 // Assumes there has been a semantically correct match to a built-in function prototype. 1675 // 1676 void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode) 1677 { 1678 // Set up convenience accessors to the argument(s). There is almost always 1679 // multiple arguments for the cases below, but when there might be one, 1680 // check the unaryArg first. 1681 const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference 1682 const TIntermTyped* unaryArg = nullptr; 1683 const TIntermTyped* arg0 = nullptr; 1684 if (callNode.getAsAggregate()) { 1685 argp = &callNode.getAsAggregate()->getSequence(); 1686 if (argp->size() > 0) 1687 arg0 = (*argp)[0]->getAsTyped(); 1688 } else { 1689 assert(callNode.getAsUnaryNode()); 1690 unaryArg = callNode.getAsUnaryNode()->getOperand(); 1691 arg0 = unaryArg; 1692 } 1693 1694 TString featureString; 1695 const char* feature = nullptr; 1696 switch (callNode.getOp()) { 1697 case EOpTextureGather: 1698 case EOpTextureGatherOffset: 1699 case EOpTextureGatherOffsets: 1700 { 1701 // Figure out which variants are allowed by what extensions, 1702 // and what arguments must be constant for which situations. 1703 1704 featureString = fnCandidate.getName(); 1705 featureString += "(...)"; 1706 feature = featureString.c_str(); 1707 profileRequires(loc, EEsProfile, 310, nullptr, feature); 1708 int compArg = -1; // track which argument, if any, is the constant component argument 1709 switch (callNode.getOp()) { 1710 case EOpTextureGather: 1711 // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, 1712 // otherwise, need GL_ARB_texture_gather. 1713 if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { 1714 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1715 if (! fnCandidate[0].type->getSampler().shadow) 1716 compArg = 2; 1717 } else 1718 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 1719 break; 1720 case EOpTextureGatherOffset: 1721 // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument 1722 if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) 1723 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 1724 else 1725 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1726 if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) 1727 profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, 1728 "non-constant offset argument"); 1729 if (! fnCandidate[0].type->getSampler().shadow) 1730 compArg = 3; 1731 break; 1732 case EOpTextureGatherOffsets: 1733 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1734 if (! fnCandidate[0].type->getSampler().shadow) 1735 compArg = 3; 1736 // check for constant offsets 1737 if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) 1738 error(loc, "must be a compile-time constant:", feature, "offsets argument"); 1739 break; 1740 default: 1741 break; 1742 } 1743 1744 if (compArg > 0 && compArg < fnCandidate.getParamCount()) { 1745 if ((*argp)[compArg]->getAsConstantUnion()) { 1746 int value = (*argp)[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1747 if (value < 0 || value > 3) 1748 error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); 1749 } else 1750 error(loc, "must be a compile-time constant:", feature, "component argument"); 1751 } 1752 1753 #ifdef AMD_EXTENSIONS 1754 bool bias = false; 1755 if (callNode.getOp() == EOpTextureGather) 1756 bias = fnCandidate.getParamCount() > 3; 1757 else if (callNode.getOp() == EOpTextureGatherOffset || 1758 callNode.getOp() == EOpTextureGatherOffsets) 1759 bias = fnCandidate.getParamCount() > 4; 1760 1761 if (bias) { 1762 featureString = fnCandidate.getName(); 1763 featureString += "with bias argument"; 1764 feature = featureString.c_str(); 1765 profileRequires(loc, ~EEsProfile, 450, nullptr, feature); 1766 requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); 1767 } 1768 #endif 1769 1770 break; 1771 } 1772 1773 #ifdef AMD_EXTENSIONS 1774 case EOpSparseTextureGather: 1775 case EOpSparseTextureGatherOffset: 1776 case EOpSparseTextureGatherOffsets: 1777 { 1778 bool bias = false; 1779 if (callNode.getOp() == EOpSparseTextureGather) 1780 bias = fnCandidate.getParamCount() > 4; 1781 else if (callNode.getOp() == EOpSparseTextureGatherOffset || 1782 callNode.getOp() == EOpSparseTextureGatherOffsets) 1783 bias = fnCandidate.getParamCount() > 5; 1784 1785 if (bias) { 1786 featureString = fnCandidate.getName(); 1787 featureString += "with bias argument"; 1788 feature = featureString.c_str(); 1789 profileRequires(loc, ~EEsProfile, 450, nullptr, feature); 1790 requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); 1791 } 1792 1793 break; 1794 } 1795 1796 case EOpSparseTextureGatherLod: 1797 case EOpSparseTextureGatherLodOffset: 1798 case EOpSparseTextureGatherLodOffsets: 1799 { 1800 requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str()); 1801 break; 1802 } 1803 1804 case EOpSwizzleInvocations: 1805 { 1806 if (! (*argp)[1]->getAsConstantUnion()) 1807 error(loc, "argument must be compile-time constant", "offset", ""); 1808 else { 1809 unsigned offset[4] = {}; 1810 offset[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); 1811 offset[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst(); 1812 offset[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst(); 1813 offset[3] = (*argp)[1]->getAsConstantUnion()->getConstArray()[3].getUConst(); 1814 if (offset[0] > 3 || offset[1] > 3 || offset[2] > 3 || offset[3] > 3) 1815 error(loc, "components must be in the range [0, 3]", "offset", ""); 1816 } 1817 1818 break; 1819 } 1820 1821 case EOpSwizzleInvocationsMasked: 1822 { 1823 if (! (*argp)[1]->getAsConstantUnion()) 1824 error(loc, "argument must be compile-time constant", "mask", ""); 1825 else { 1826 unsigned mask[3] = {}; 1827 mask[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); 1828 mask[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst(); 1829 mask[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst(); 1830 if (mask[0] > 31 || mask[1] > 31 || mask[2] > 31) 1831 error(loc, "components must be in the range [0, 31]", "mask", ""); 1832 } 1833 1834 break; 1835 } 1836 #endif 1837 1838 case EOpTextureOffset: 1839 case EOpTextureFetchOffset: 1840 case EOpTextureProjOffset: 1841 case EOpTextureLodOffset: 1842 case EOpTextureProjLodOffset: 1843 case EOpTextureGradOffset: 1844 case EOpTextureProjGradOffset: 1845 { 1846 // Handle texture-offset limits checking 1847 // Pick which argument has to hold constant offsets 1848 int arg = -1; 1849 switch (callNode.getOp()) { 1850 case EOpTextureOffset: arg = 2; break; 1851 case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().dim != EsdRect) ? 3 : 2; break; 1852 case EOpTextureProjOffset: arg = 2; break; 1853 case EOpTextureLodOffset: arg = 3; break; 1854 case EOpTextureProjLodOffset: arg = 3; break; 1855 case EOpTextureGradOffset: arg = 4; break; 1856 case EOpTextureProjGradOffset: arg = 4; break; 1857 default: 1858 assert(0); 1859 break; 1860 } 1861 1862 if (arg > 0) { 1863 1864 #ifdef AMD_EXTENSIONS 1865 bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && arg0->getType().getSampler().shadow; 1866 if (f16ShadowCompare) 1867 ++arg; 1868 #endif 1869 if (! (*argp)[arg]->getAsConstantUnion()) 1870 error(loc, "argument must be compile-time constant", "texel offset", ""); 1871 else { 1872 const TType& type = (*argp)[arg]->getAsTyped()->getType(); 1873 for (int c = 0; c < type.getVectorSize(); ++c) { 1874 int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); 1875 if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) 1876 error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); 1877 } 1878 } 1879 } 1880 1881 break; 1882 } 1883 1884 #ifdef NV_EXTENSIONS 1885 case EOpTraceNV: 1886 if (!(*argp)[10]->getAsConstantUnion()) 1887 error(loc, "argument must be compile-time constant", "payload number", ""); 1888 break; 1889 case EOpExecuteCallableNV: 1890 if (!(*argp)[1]->getAsConstantUnion()) 1891 error(loc, "argument must be compile-time constant", "callable data number", ""); 1892 break; 1893 #endif 1894 1895 case EOpTextureQuerySamples: 1896 case EOpImageQuerySamples: 1897 // GL_ARB_shader_texture_image_samples 1898 profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); 1899 break; 1900 1901 case EOpImageAtomicAdd: 1902 case EOpImageAtomicMin: 1903 case EOpImageAtomicMax: 1904 case EOpImageAtomicAnd: 1905 case EOpImageAtomicOr: 1906 case EOpImageAtomicXor: 1907 case EOpImageAtomicExchange: 1908 case EOpImageAtomicCompSwap: 1909 case EOpImageAtomicLoad: 1910 case EOpImageAtomicStore: 1911 { 1912 // Make sure the image types have the correct layout() format and correct argument types 1913 const TType& imageType = arg0->getType(); 1914 if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { 1915 if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui) 1916 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); 1917 } else { 1918 if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) 1919 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); 1920 else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile) 1921 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); 1922 } 1923 1924 const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4; 1925 if (argp->size() > maxArgs) { 1926 requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str()); 1927 memorySemanticsCheck(loc, fnCandidate, callNode); 1928 } 1929 1930 break; 1931 } 1932 1933 case EOpAtomicAdd: 1934 case EOpAtomicMin: 1935 case EOpAtomicMax: 1936 case EOpAtomicAnd: 1937 case EOpAtomicOr: 1938 case EOpAtomicXor: 1939 case EOpAtomicExchange: 1940 case EOpAtomicCompSwap: 1941 case EOpAtomicLoad: 1942 case EOpAtomicStore: 1943 { 1944 if (argp->size() > 3) { 1945 requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str()); 1946 memorySemanticsCheck(loc, fnCandidate, callNode); 1947 } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) { 1948 #ifdef NV_EXTENSIONS 1949 const char* const extensions[2] = { E_GL_NV_shader_atomic_int64, 1950 E_GL_EXT_shader_atomic_int64 }; 1951 requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str()); 1952 #else 1953 requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_int64, fnCandidate.getName().c_str()); 1954 #endif 1955 } 1956 break; 1957 } 1958 1959 case EOpInterpolateAtCentroid: 1960 case EOpInterpolateAtSample: 1961 case EOpInterpolateAtOffset: 1962 #ifdef AMD_EXTENSIONS 1963 case EOpInterpolateAtVertex: 1964 #endif 1965 // Make sure the first argument is an interpolant, or an array element of an interpolant 1966 if (arg0->getType().getQualifier().storage != EvqVaryingIn) { 1967 // It might still be an array element. 1968 // 1969 // We could check more, but the semantics of the first argument are already met; the 1970 // only way to turn an array into a float/vec* is array dereference and swizzle. 1971 // 1972 // ES and desktop 4.3 and earlier: swizzles may not be used 1973 // desktop 4.4 and later: swizzles may be used 1974 bool swizzleOkay = (profile != EEsProfile) && (version >= 440); 1975 const TIntermTyped* base = TIntermediate::findLValueBase(arg0, swizzleOkay); 1976 if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn) 1977 error(loc, "first argument must be an interpolant, or interpolant-array element", fnCandidate.getName().c_str(), ""); 1978 } 1979 1980 #ifdef AMD_EXTENSIONS 1981 if (callNode.getOp() == EOpInterpolateAtVertex) { 1982 if (!arg0->getType().getQualifier().isExplicitInterpolation()) 1983 error(loc, "argument must be qualified as __explicitInterpAMD in", "interpolant", ""); 1984 else { 1985 if (! (*argp)[1]->getAsConstantUnion()) 1986 error(loc, "argument must be compile-time constant", "vertex index", ""); 1987 else { 1988 unsigned vertexIdx = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); 1989 if (vertexIdx > 2) 1990 error(loc, "must be in the range [0, 2]", "vertex index", ""); 1991 } 1992 } 1993 } 1994 #endif 1995 1996 break; 1997 1998 case EOpEmitStreamVertex: 1999 case EOpEndStreamPrimitive: 2000 intermediate.setMultiStream(); 2001 break; 2002 2003 case EOpSubgroupClusteredAdd: 2004 case EOpSubgroupClusteredMul: 2005 case EOpSubgroupClusteredMin: 2006 case EOpSubgroupClusteredMax: 2007 case EOpSubgroupClusteredAnd: 2008 case EOpSubgroupClusteredOr: 2009 case EOpSubgroupClusteredXor: 2010 // The <clusterSize> as used in the subgroupClustered<op>() operations must be: 2011 // - An integral constant expression. 2012 // - At least 1. 2013 // - A power of 2. 2014 if ((*argp)[1]->getAsConstantUnion() == nullptr) 2015 error(loc, "argument must be compile-time constant", "cluster size", ""); 2016 else { 2017 int size = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst(); 2018 if (size < 1) 2019 error(loc, "argument must be at least 1", "cluster size", ""); 2020 else if (!IsPow2(size)) 2021 error(loc, "argument must be a power of 2", "cluster size", ""); 2022 } 2023 break; 2024 2025 case EOpSubgroupBroadcast: 2026 // <id> must be an integral constant expression. 2027 if ((*argp)[1]->getAsConstantUnion() == nullptr) 2028 error(loc, "argument must be compile-time constant", "id", ""); 2029 break; 2030 2031 case EOpBarrier: 2032 case EOpMemoryBarrier: 2033 if (argp->size() > 0) { 2034 requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str()); 2035 memorySemanticsCheck(loc, fnCandidate, callNode); 2036 } 2037 break; 2038 2039 default: 2040 break; 2041 } 2042 2043 // Texture operations on texture objects (aside from texelFetch on a 2044 // textureBuffer) require EXT_samplerless_texture_functions. 2045 switch (callNode.getOp()) { 2046 case EOpTextureQuerySize: 2047 case EOpTextureQueryLevels: 2048 case EOpTextureQuerySamples: 2049 case EOpTextureFetch: 2050 case EOpTextureFetchOffset: 2051 { 2052 const TSampler& sampler = fnCandidate[0].type->getSampler(); 2053 2054 const bool isTexture = sampler.isTexture() && !sampler.isCombined(); 2055 const bool isBuffer = sampler.dim == EsdBuffer; 2056 const bool isFetch = callNode.getOp() == EOpTextureFetch || callNode.getOp() == EOpTextureFetchOffset; 2057 2058 if (isTexture && (!isBuffer || !isFetch)) 2059 requireExtensions(loc, 1, &E_GL_EXT_samplerless_texture_functions, fnCandidate.getName().c_str()); 2060 2061 break; 2062 } 2063 2064 default: 2065 break; 2066 } 2067 2068 if (callNode.getOp() > EOpSubgroupGuardStart && callNode.getOp() < EOpSubgroupGuardStop) { 2069 // these require SPIR-V 1.3 2070 if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_3) 2071 error(loc, "requires SPIR-V 1.3", "subgroup op", ""); 2072 } 2073 } 2074 2075 extern bool PureOperatorBuiltins; 2076 2077 // Deprecated! Use PureOperatorBuiltins == true instead, in which case this 2078 // functionality is handled in builtInOpCheck() instead of here. 2079 // 2080 // Do additional checking of built-in function calls that were not mapped 2081 // to built-in operations (e.g., texturing functions). 2082 // 2083 // Assumes there has been a semantically correct match to a built-in function. 2084 // 2085 void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode) 2086 { 2087 // Further maintenance of this function is deprecated, because the "correct" 2088 // future-oriented design is to not have to do string compares on function names. 2089 2090 // If PureOperatorBuiltins == true, then all built-ins should be mapped 2091 // to a TOperator, and this function would then never get called. 2092 2093 assert(PureOperatorBuiltins == false); 2094 2095 // built-in texturing functions get their return value precision from the precision of the sampler 2096 if (fnCandidate.getType().getQualifier().precision == EpqNone && 2097 fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler) 2098 callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision; 2099 2100 if (fnCandidate.getName().compare(0, 7, "texture") == 0) { 2101 if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) { 2102 TString featureString = fnCandidate.getName() + "(...)"; 2103 const char* feature = featureString.c_str(); 2104 profileRequires(loc, EEsProfile, 310, nullptr, feature); 2105 2106 int compArg = -1; // track which argument, if any, is the constant component argument 2107 if (fnCandidate.getName().compare("textureGatherOffset") == 0) { 2108 // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument 2109 if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) 2110 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 2111 else 2112 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 2113 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; 2114 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) 2115 profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, 2116 "non-constant offset argument"); 2117 if (! fnCandidate[0].type->getSampler().shadow) 2118 compArg = 3; 2119 } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) { 2120 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 2121 if (! fnCandidate[0].type->getSampler().shadow) 2122 compArg = 3; 2123 // check for constant offsets 2124 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; 2125 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) 2126 error(loc, "must be a compile-time constant:", feature, "offsets argument"); 2127 } else if (fnCandidate.getName().compare("textureGather") == 0) { 2128 // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, 2129 // otherwise, need GL_ARB_texture_gather. 2130 if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { 2131 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 2132 if (! fnCandidate[0].type->getSampler().shadow) 2133 compArg = 2; 2134 } else 2135 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 2136 } 2137 2138 if (compArg > 0 && compArg < fnCandidate.getParamCount()) { 2139 if (callNode.getSequence()[compArg]->getAsConstantUnion()) { 2140 int value = callNode.getSequence()[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); 2141 if (value < 0 || value > 3) 2142 error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); 2143 } else 2144 error(loc, "must be a compile-time constant:", feature, "component argument"); 2145 } 2146 } else { 2147 // this is only for functions not starting "textureGather"... 2148 if (fnCandidate.getName().find("Offset") != TString::npos) { 2149 2150 // Handle texture-offset limits checking 2151 int arg = -1; 2152 if (fnCandidate.getName().compare("textureOffset") == 0) 2153 arg = 2; 2154 else if (fnCandidate.getName().compare("texelFetchOffset") == 0) 2155 arg = 3; 2156 else if (fnCandidate.getName().compare("textureProjOffset") == 0) 2157 arg = 2; 2158 else if (fnCandidate.getName().compare("textureLodOffset") == 0) 2159 arg = 3; 2160 else if (fnCandidate.getName().compare("textureProjLodOffset") == 0) 2161 arg = 3; 2162 else if (fnCandidate.getName().compare("textureGradOffset") == 0) 2163 arg = 4; 2164 else if (fnCandidate.getName().compare("textureProjGradOffset") == 0) 2165 arg = 4; 2166 2167 if (arg > 0) { 2168 if (! callNode.getSequence()[arg]->getAsConstantUnion()) 2169 error(loc, "argument must be compile-time constant", "texel offset", ""); 2170 else { 2171 const TType& type = callNode.getSequence()[arg]->getAsTyped()->getType(); 2172 for (int c = 0; c < type.getVectorSize(); ++c) { 2173 int offset = callNode.getSequence()[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); 2174 if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) 2175 error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); 2176 } 2177 } 2178 } 2179 } 2180 } 2181 } 2182 2183 // GL_ARB_shader_texture_image_samples 2184 if (fnCandidate.getName().compare(0, 14, "textureSamples") == 0 || fnCandidate.getName().compare(0, 12, "imageSamples") == 0) 2185 profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); 2186 2187 if (fnCandidate.getName().compare(0, 11, "imageAtomic") == 0) { 2188 const TType& imageType = callNode.getSequence()[0]->getAsTyped()->getType(); 2189 if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { 2190 if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui) 2191 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); 2192 } else { 2193 if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) 2194 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); 2195 else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile) 2196 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); 2197 } 2198 } 2199 } 2200 2201 // 2202 // Do any extra checking for a user function call. 2203 // 2204 void TParseContext::userFunctionCallCheck(const TSourceLoc& loc, TIntermAggregate& callNode) 2205 { 2206 TIntermSequence& arguments = callNode.getSequence(); 2207 2208 for (int i = 0; i < (int)arguments.size(); ++i) 2209 samplerConstructorLocationCheck(loc, "call argument", arguments[i]); 2210 } 2211 2212 // 2213 // Emit an error if this is a sampler constructor 2214 // 2215 void TParseContext::samplerConstructorLocationCheck(const TSourceLoc& loc, const char* token, TIntermNode* node) 2216 { 2217 if (node->getAsOperator() && node->getAsOperator()->getOp() == EOpConstructTextureSampler) 2218 error(loc, "sampler constructor must appear at point of use", token, ""); 2219 } 2220 2221 // 2222 // Handle seeing a built-in constructor in a grammar production. 2223 // 2224 TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType) 2225 { 2226 TType type(publicType); 2227 type.getQualifier().precision = EpqNone; 2228 2229 if (type.isArray()) { 2230 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed constructor"); 2231 profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor"); 2232 } 2233 2234 TOperator op = intermediate.mapTypeToConstructorOp(type); 2235 2236 if (op == EOpNull) { 2237 error(loc, "cannot construct this type", type.getBasicString(), ""); 2238 op = EOpConstructFloat; 2239 TType errorType(EbtFloat); 2240 type.shallowCopy(errorType); 2241 } 2242 2243 TString empty(""); 2244 2245 return new TFunction(&empty, type, op); 2246 } 2247 2248 // Handle seeing a precision qualifier in the grammar. 2249 void TParseContext::handlePrecisionQualifier(const TSourceLoc& /*loc*/, TQualifier& qualifier, TPrecisionQualifier precision) 2250 { 2251 if (obeyPrecisionQualifiers()) 2252 qualifier.precision = precision; 2253 } 2254 2255 // Check for messages to give on seeing a precision qualifier used in a 2256 // declaration in the grammar. 2257 void TParseContext::checkPrecisionQualifier(const TSourceLoc& loc, TPrecisionQualifier) 2258 { 2259 if (precisionManager.shouldWarnAboutDefaults()) { 2260 warn(loc, "all default precisions are highp; use precision statements to quiet warning, e.g.:\n" 2261 " \"precision mediump int; precision highp float;\"", "", ""); 2262 precisionManager.defaultWarningGiven(); 2263 } 2264 } 2265 2266 // 2267 // Same error message for all places assignments don't work. 2268 // 2269 void TParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right) 2270 { 2271 error(loc, "", op, "cannot convert from '%s' to '%s'", 2272 right.c_str(), left.c_str()); 2273 } 2274 2275 // 2276 // Same error message for all places unary operations don't work. 2277 // 2278 void TParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand) 2279 { 2280 error(loc, " wrong operand type", op, 2281 "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)", 2282 op, operand.c_str()); 2283 } 2284 2285 // 2286 // Same error message for all binary operations don't work. 2287 // 2288 void TParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right) 2289 { 2290 error(loc, " wrong operand types:", op, 2291 "no operation '%s' exists that takes a left-hand operand of type '%s' and " 2292 "a right operand of type '%s' (or there is no acceptable conversion)", 2293 op, left.c_str(), right.c_str()); 2294 } 2295 2296 // 2297 // A basic type of EbtVoid is a key that the name string was seen in the source, but 2298 // it was not found as a variable in the symbol table. If so, give the error 2299 // message and insert a dummy variable in the symbol table to prevent future errors. 2300 // 2301 void TParseContext::variableCheck(TIntermTyped*& nodePtr) 2302 { 2303 TIntermSymbol* symbol = nodePtr->getAsSymbolNode(); 2304 if (! symbol) 2305 return; 2306 2307 if (symbol->getType().getBasicType() == EbtVoid) { 2308 const char *extraInfoFormat = ""; 2309 if (spvVersion.vulkan != 0 && symbol->getName() == "gl_VertexID") { 2310 extraInfoFormat = "(Did you mean gl_VertexIndex?)"; 2311 } else if (spvVersion.vulkan != 0 && symbol->getName() == "gl_InstanceID") { 2312 extraInfoFormat = "(Did you mean gl_InstanceIndex?)"; 2313 } 2314 error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), extraInfoFormat); 2315 2316 // Add to symbol table to prevent future error messages on the same name 2317 if (symbol->getName().size() > 0) { 2318 TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat)); 2319 symbolTable.insert(*fakeVariable); 2320 2321 // substitute a symbol node for this new variable 2322 nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc()); 2323 } 2324 } else { 2325 switch (symbol->getQualifier().storage) { 2326 case EvqPointCoord: 2327 profileRequires(symbol->getLoc(), ENoProfile, 120, nullptr, "gl_PointCoord"); 2328 break; 2329 default: break; // some compilers want this 2330 } 2331 } 2332 } 2333 2334 // 2335 // Both test and if necessary, spit out an error, to see if the node is really 2336 // an l-value that can be operated on this way. 2337 // 2338 // Returns true if there was an error. 2339 // 2340 bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) 2341 { 2342 TIntermBinary* binaryNode = node->getAsBinaryNode(); 2343 2344 if (binaryNode) { 2345 bool errorReturn = false; 2346 2347 switch(binaryNode->getOp()) { 2348 case EOpIndexDirect: 2349 case EOpIndexIndirect: 2350 // ... tessellation control shader ... 2351 // If a per-vertex output variable is used as an l-value, it is a 2352 // compile-time or link-time error if the expression indicating the 2353 // vertex index is not the identifier gl_InvocationID. 2354 if (language == EShLangTessControl) { 2355 const TType& leftType = binaryNode->getLeft()->getType(); 2356 if (leftType.getQualifier().storage == EvqVaryingOut && ! leftType.getQualifier().patch && binaryNode->getLeft()->getAsSymbolNode()) { 2357 // we have a per-vertex output 2358 const TIntermSymbol* rightSymbol = binaryNode->getRight()->getAsSymbolNode(); 2359 if (! rightSymbol || rightSymbol->getQualifier().builtIn != EbvInvocationId) 2360 error(loc, "tessellation-control per-vertex output l-value must be indexed with gl_InvocationID", "[]", ""); 2361 } 2362 } 2363 2364 break; // left node is checked by base class 2365 case EOpIndexDirectStruct: 2366 break; // left node is checked by base class 2367 case EOpVectorSwizzle: 2368 errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft()); 2369 if (!errorReturn) { 2370 int offset[4] = {0,0,0,0}; 2371 2372 TIntermTyped* rightNode = binaryNode->getRight(); 2373 TIntermAggregate *aggrNode = rightNode->getAsAggregate(); 2374 2375 for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 2376 p != aggrNode->getSequence().end(); p++) { 2377 int value = (*p)->getAsTyped()->getAsConstantUnion()->getConstArray()[0].getIConst(); 2378 offset[value]++; 2379 if (offset[value] > 1) { 2380 error(loc, " l-value of swizzle cannot have duplicate components", op, "", ""); 2381 2382 return true; 2383 } 2384 } 2385 } 2386 2387 return errorReturn; 2388 default: 2389 break; 2390 } 2391 2392 if (errorReturn) { 2393 error(loc, " l-value required", op, "", ""); 2394 return true; 2395 } 2396 } 2397 2398 if (binaryNode && binaryNode->getOp() == EOpIndexDirectStruct && 2399 binaryNode->getLeft()->getBasicType() == EbtReference) 2400 return false; 2401 2402 // Let the base class check errors 2403 if (TParseContextBase::lValueErrorCheck(loc, op, node)) 2404 return true; 2405 2406 const char* symbol = nullptr; 2407 TIntermSymbol* symNode = node->getAsSymbolNode(); 2408 if (symNode != nullptr) 2409 symbol = symNode->getName().c_str(); 2410 2411 const char* message = nullptr; 2412 switch (node->getQualifier().storage) { 2413 case EvqVaryingIn: message = "can't modify shader input"; break; 2414 case EvqInstanceId: message = "can't modify gl_InstanceID"; break; 2415 case EvqVertexId: message = "can't modify gl_VertexID"; break; 2416 case EvqFace: message = "can't modify gl_FrontFace"; break; 2417 case EvqFragCoord: message = "can't modify gl_FragCoord"; break; 2418 case EvqPointCoord: message = "can't modify gl_PointCoord"; break; 2419 case EvqFragDepth: 2420 intermediate.setDepthReplacing(); 2421 // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader." 2422 if (profile == EEsProfile && intermediate.getEarlyFragmentTests()) 2423 message = "can't modify gl_FragDepth if using early_fragment_tests"; 2424 break; 2425 2426 default: 2427 break; 2428 } 2429 2430 if (message == nullptr && binaryNode == nullptr && symNode == nullptr) { 2431 error(loc, " l-value required", op, "", ""); 2432 2433 return true; 2434 } 2435 2436 // 2437 // Everything else is okay, no error. 2438 // 2439 if (message == nullptr) 2440 return false; 2441 2442 // 2443 // If we get here, we have an error and a message. 2444 // 2445 if (symNode) 2446 error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); 2447 else 2448 error(loc, " l-value required", op, "(%s)", message); 2449 2450 return true; 2451 } 2452 2453 // Test for and give an error if the node can't be read from. 2454 void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) 2455 { 2456 // Let the base class check errors 2457 TParseContextBase::rValueErrorCheck(loc, op, node); 2458 2459 #ifdef AMD_EXTENSIONS 2460 TIntermSymbol* symNode = node->getAsSymbolNode(); 2461 if (!(symNode && symNode->getQualifier().writeonly)) // base class checks 2462 if (symNode && symNode->getQualifier().explicitInterp) 2463 error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str()); 2464 #endif 2465 } 2466 2467 // 2468 // Both test, and if necessary spit out an error, to see if the node is really 2469 // a constant. 2470 // 2471 void TParseContext::constantValueCheck(TIntermTyped* node, const char* token) 2472 { 2473 if (! node->getQualifier().isConstant()) 2474 error(node->getLoc(), "constant expression required", token, ""); 2475 } 2476 2477 // 2478 // Both test, and if necessary spit out an error, to see if the node is really 2479 // an integer. 2480 // 2481 void TParseContext::integerCheck(const TIntermTyped* node, const char* token) 2482 { 2483 if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar()) 2484 return; 2485 2486 error(node->getLoc(), "scalar integer expression required", token, ""); 2487 } 2488 2489 // 2490 // Both test, and if necessary spit out an error, to see if we are currently 2491 // globally scoped. 2492 // 2493 void TParseContext::globalCheck(const TSourceLoc& loc, const char* token) 2494 { 2495 if (! symbolTable.atGlobalLevel()) 2496 error(loc, "not allowed in nested scope", token, ""); 2497 } 2498 2499 // 2500 // Reserved errors for GLSL. 2501 // 2502 void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& identifier) 2503 { 2504 // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be 2505 // declared in a shader; this results in a compile-time error." 2506 if (! symbolTable.atBuiltInLevel()) { 2507 if (builtInName(identifier)) 2508 error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), ""); 2509 2510 // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification: 2511 // "In addition, all identifiers containing two consecutive underscores (__) are 2512 // reserved; using such a name does not itself result in an error, but may result 2513 // in undefined behavior." 2514 // however, before that, ES tests required an error. 2515 if (identifier.find("__") != TString::npos) { 2516 if (profile == EEsProfile && version <= 300) 2517 error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version <= 300", identifier.c_str(), ""); 2518 else 2519 warn(loc, "identifiers containing consecutive underscores (\"__\") are reserved", identifier.c_str(), ""); 2520 } 2521 } 2522 } 2523 2524 // 2525 // Reserved errors for the preprocessor. 2526 // 2527 void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* identifier, const char* op) 2528 { 2529 // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification: 2530 // "All macro names containing two consecutive underscores ( __ ) are reserved; 2531 // defining such a name does not itself result in an error, but may result in 2532 // undefined behavior. All macro names prefixed with "GL_" ("GL" followed by a 2533 // single underscore) are also reserved, and defining such a name results in a 2534 // compile-time error." 2535 // however, before that, ES tests required an error. 2536 if (strncmp(identifier, "GL_", 3) == 0) 2537 ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier); 2538 else if (strncmp(identifier, "defined", 8) == 0) 2539 ppError(loc, "\"defined\" can't be (un)defined:", op, identifier); 2540 else if (strstr(identifier, "__") != 0) { 2541 if (profile == EEsProfile && version >= 300 && 2542 (strcmp(identifier, "__LINE__") == 0 || 2543 strcmp(identifier, "__FILE__") == 0 || 2544 strcmp(identifier, "__VERSION__") == 0)) 2545 ppError(loc, "predefined names can't be (un)defined:", op, identifier); 2546 else { 2547 if (profile == EEsProfile && version <= 300) 2548 ppError(loc, "names containing consecutive underscores are reserved, and an error if version <= 300:", op, identifier); 2549 else 2550 ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier); 2551 } 2552 } 2553 } 2554 2555 // 2556 // See if this version/profile allows use of the line-continuation character '\'. 2557 // 2558 // Returns true if a line continuation should be done. 2559 // 2560 bool TParseContext::lineContinuationCheck(const TSourceLoc& loc, bool endOfComment) 2561 { 2562 const char* message = "line continuation"; 2563 2564 bool lineContinuationAllowed = (profile == EEsProfile && version >= 300) || 2565 (profile != EEsProfile && (version >= 420 || extensionTurnedOn(E_GL_ARB_shading_language_420pack))); 2566 2567 if (endOfComment) { 2568 if (lineContinuationAllowed) 2569 warn(loc, "used at end of comment; the following line is still part of the comment", message, ""); 2570 else 2571 warn(loc, "used at end of comment, but this version does not provide line continuation", message, ""); 2572 2573 return lineContinuationAllowed; 2574 } 2575 2576 if (relaxedErrors()) { 2577 if (! lineContinuationAllowed) 2578 warn(loc, "not allowed in this version", message, ""); 2579 return true; 2580 } else { 2581 profileRequires(loc, EEsProfile, 300, nullptr, message); 2582 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, message); 2583 } 2584 2585 return lineContinuationAllowed; 2586 } 2587 2588 bool TParseContext::builtInName(const TString& identifier) 2589 { 2590 return identifier.compare(0, 3, "gl_") == 0; 2591 } 2592 2593 // 2594 // Make sure there is enough data and not too many arguments provided to the 2595 // constructor to build something of the type of the constructor. Also returns 2596 // the type of the constructor. 2597 // 2598 // Part of establishing type is establishing specialization-constness. 2599 // We don't yet know "top down" whether type is a specialization constant, 2600 // but a const constructor can becomes a specialization constant if any of 2601 // its children are, subject to KHR_vulkan_glsl rules: 2602 // 2603 // - int(), uint(), and bool() constructors for type conversions 2604 // from any of the following types to any of the following types: 2605 // * int 2606 // * uint 2607 // * bool 2608 // - vector versions of the above conversion constructors 2609 // 2610 // Returns true if there was an error in construction. 2611 // 2612 bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, TOperator op, TType& type) 2613 { 2614 type.shallowCopy(function.getType()); 2615 2616 bool constructingMatrix = false; 2617 switch(op) { 2618 case EOpConstructTextureSampler: 2619 return constructorTextureSamplerError(loc, function); 2620 case EOpConstructMat2x2: 2621 case EOpConstructMat2x3: 2622 case EOpConstructMat2x4: 2623 case EOpConstructMat3x2: 2624 case EOpConstructMat3x3: 2625 case EOpConstructMat3x4: 2626 case EOpConstructMat4x2: 2627 case EOpConstructMat4x3: 2628 case EOpConstructMat4x4: 2629 case EOpConstructDMat2x2: 2630 case EOpConstructDMat2x3: 2631 case EOpConstructDMat2x4: 2632 case EOpConstructDMat3x2: 2633 case EOpConstructDMat3x3: 2634 case EOpConstructDMat3x4: 2635 case EOpConstructDMat4x2: 2636 case EOpConstructDMat4x3: 2637 case EOpConstructDMat4x4: 2638 case EOpConstructF16Mat2x2: 2639 case EOpConstructF16Mat2x3: 2640 case EOpConstructF16Mat2x4: 2641 case EOpConstructF16Mat3x2: 2642 case EOpConstructF16Mat3x3: 2643 case EOpConstructF16Mat3x4: 2644 case EOpConstructF16Mat4x2: 2645 case EOpConstructF16Mat4x3: 2646 case EOpConstructF16Mat4x4: 2647 constructingMatrix = true; 2648 break; 2649 default: 2650 break; 2651 } 2652 2653 // 2654 // Walk the arguments for first-pass checks and collection of information. 2655 // 2656 2657 int size = 0; 2658 bool constType = true; 2659 bool specConstType = false; // value is only valid if constType is true 2660 bool full = false; 2661 bool overFull = false; 2662 bool matrixInMatrix = false; 2663 bool arrayArg = false; 2664 bool floatArgument = false; 2665 for (int arg = 0; arg < function.getParamCount(); ++arg) { 2666 if (function[arg].type->isArray()) { 2667 if (function[arg].type->isUnsizedArray()) { 2668 // Can't construct from an unsized array. 2669 error(loc, "array argument must be sized", "constructor", ""); 2670 return true; 2671 } 2672 arrayArg = true; 2673 } 2674 if (constructingMatrix && function[arg].type->isMatrix()) 2675 matrixInMatrix = true; 2676 2677 // 'full' will go to true when enough args have been seen. If we loop 2678 // again, there is an extra argument. 2679 if (full) { 2680 // For vectors and matrices, it's okay to have too many components 2681 // available, but not okay to have unused arguments. 2682 overFull = true; 2683 } 2684 2685 size += function[arg].type->computeNumComponents(); 2686 if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) 2687 full = true; 2688 2689 if (! function[arg].type->getQualifier().isConstant()) 2690 constType = false; 2691 if (function[arg].type->getQualifier().isSpecConstant()) 2692 specConstType = true; 2693 if (function[arg].type->isFloatingDomain()) 2694 floatArgument = true; 2695 if (type.isStruct()) { 2696 if (function[arg].type->containsBasicType(EbtFloat16)) { 2697 requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type"); 2698 } 2699 if (function[arg].type->containsBasicType(EbtUint16) || 2700 function[arg].type->containsBasicType(EbtInt16)) { 2701 requireInt16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type"); 2702 } 2703 if (function[arg].type->containsBasicType(EbtUint8) || 2704 function[arg].type->containsBasicType(EbtInt8)) { 2705 requireInt8Arithmetic(loc, "constructor", "can't construct structure containing 8-bit type"); 2706 } 2707 } 2708 } 2709 2710 switch (op) { 2711 case EOpConstructFloat16: 2712 case EOpConstructF16Vec2: 2713 case EOpConstructF16Vec3: 2714 case EOpConstructF16Vec4: 2715 if (type.isArray()) 2716 requireFloat16Arithmetic(loc, "constructor", "16-bit arrays not supported"); 2717 if (type.isVector() && function.getParamCount() != 1) 2718 requireFloat16Arithmetic(loc, "constructor", "16-bit vectors only take vector types"); 2719 break; 2720 case EOpConstructUint16: 2721 case EOpConstructU16Vec2: 2722 case EOpConstructU16Vec3: 2723 case EOpConstructU16Vec4: 2724 case EOpConstructInt16: 2725 case EOpConstructI16Vec2: 2726 case EOpConstructI16Vec3: 2727 case EOpConstructI16Vec4: 2728 if (type.isArray()) 2729 requireInt16Arithmetic(loc, "constructor", "16-bit arrays not supported"); 2730 if (type.isVector() && function.getParamCount() != 1) 2731 requireInt16Arithmetic(loc, "constructor", "16-bit vectors only take vector types"); 2732 break; 2733 case EOpConstructUint8: 2734 case EOpConstructU8Vec2: 2735 case EOpConstructU8Vec3: 2736 case EOpConstructU8Vec4: 2737 case EOpConstructInt8: 2738 case EOpConstructI8Vec2: 2739 case EOpConstructI8Vec3: 2740 case EOpConstructI8Vec4: 2741 if (type.isArray()) 2742 requireInt8Arithmetic(loc, "constructor", "8-bit arrays not supported"); 2743 if (type.isVector() && function.getParamCount() != 1) 2744 requireInt8Arithmetic(loc, "constructor", "8-bit vectors only take vector types"); 2745 break; 2746 default: 2747 break; 2748 } 2749 2750 // inherit constness from children 2751 if (constType) { 2752 bool makeSpecConst; 2753 // Finish pinning down spec-const semantics 2754 if (specConstType) { 2755 switch (op) { 2756 case EOpConstructInt8: 2757 case EOpConstructUint8: 2758 case EOpConstructInt16: 2759 case EOpConstructUint16: 2760 case EOpConstructInt: 2761 case EOpConstructUint: 2762 case EOpConstructInt64: 2763 case EOpConstructUint64: 2764 case EOpConstructBool: 2765 case EOpConstructBVec2: 2766 case EOpConstructBVec3: 2767 case EOpConstructBVec4: 2768 case EOpConstructI8Vec2: 2769 case EOpConstructI8Vec3: 2770 case EOpConstructI8Vec4: 2771 case EOpConstructU8Vec2: 2772 case EOpConstructU8Vec3: 2773 case EOpConstructU8Vec4: 2774 case EOpConstructI16Vec2: 2775 case EOpConstructI16Vec3: 2776 case EOpConstructI16Vec4: 2777 case EOpConstructU16Vec2: 2778 case EOpConstructU16Vec3: 2779 case EOpConstructU16Vec4: 2780 case EOpConstructIVec2: 2781 case EOpConstructIVec3: 2782 case EOpConstructIVec4: 2783 case EOpConstructUVec2: 2784 case EOpConstructUVec3: 2785 case EOpConstructUVec4: 2786 case EOpConstructI64Vec2: 2787 case EOpConstructI64Vec3: 2788 case EOpConstructI64Vec4: 2789 case EOpConstructU64Vec2: 2790 case EOpConstructU64Vec3: 2791 case EOpConstructU64Vec4: 2792 // This was the list of valid ones, if they aren't converting from float 2793 // and aren't making an array. 2794 makeSpecConst = ! floatArgument && ! type.isArray(); 2795 break; 2796 default: 2797 // anything else wasn't white-listed in the spec as a conversion 2798 makeSpecConst = false; 2799 break; 2800 } 2801 } else 2802 makeSpecConst = false; 2803 2804 if (makeSpecConst) 2805 type.getQualifier().makeSpecConstant(); 2806 else if (specConstType) 2807 type.getQualifier().makeTemporary(); 2808 else 2809 type.getQualifier().storage = EvqConst; 2810 } 2811 2812 if (type.isArray()) { 2813 if (function.getParamCount() == 0) { 2814 error(loc, "array constructor must have at least one argument", "constructor", ""); 2815 return true; 2816 } 2817 2818 if (type.isUnsizedArray()) { 2819 // auto adapt the constructor type to the number of arguments 2820 type.changeOuterArraySize(function.getParamCount()); 2821 } else if (type.getOuterArraySize() != function.getParamCount()) { 2822 error(loc, "array constructor needs one argument per array element", "constructor", ""); 2823 return true; 2824 } 2825 2826 if (type.isArrayOfArrays()) { 2827 // Types have to match, but we're still making the type. 2828 // Finish making the type, and the comparison is done later 2829 // when checking for conversion. 2830 TArraySizes& arraySizes = *type.getArraySizes(); 2831 2832 // At least the dimensionalities have to match. 2833 if (! function[0].type->isArray() || 2834 arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) { 2835 error(loc, "array constructor argument not correct type to construct array element", "constructor", ""); 2836 return true; 2837 } 2838 2839 if (arraySizes.isInnerUnsized()) { 2840 // "Arrays of arrays ..., and the size for any dimension is optional" 2841 // That means we need to adopt (from the first argument) the other array sizes into the type. 2842 for (int d = 1; d < arraySizes.getNumDims(); ++d) { 2843 if (arraySizes.getDimSize(d) == UnsizedArraySize) { 2844 arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1)); 2845 } 2846 } 2847 } 2848 } 2849 } 2850 2851 if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { 2852 error(loc, "constructing non-array constituent from array argument", "constructor", ""); 2853 return true; 2854 } 2855 2856 if (matrixInMatrix && ! type.isArray()) { 2857 profileRequires(loc, ENoProfile, 120, nullptr, "constructing matrix from matrix"); 2858 2859 // "If a matrix argument is given to a matrix constructor, 2860 // it is a compile-time error to have any other arguments." 2861 if (function.getParamCount() != 1) 2862 error(loc, "matrix constructed from matrix can only have one argument", "constructor", ""); 2863 return false; 2864 } 2865 2866 if (overFull) { 2867 error(loc, "too many arguments", "constructor", ""); 2868 return true; 2869 } 2870 2871 if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) { 2872 error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); 2873 return true; 2874 } 2875 2876 if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) || 2877 (op == EOpConstructStruct && size < type.computeNumComponents())) { 2878 error(loc, "not enough data provided for construction", "constructor", ""); 2879 return true; 2880 } 2881 2882 TIntermTyped* typed = node->getAsTyped(); 2883 if (typed == nullptr) { 2884 error(loc, "constructor argument does not have a type", "constructor", ""); 2885 return true; 2886 } 2887 if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) { 2888 error(loc, "cannot convert a sampler", "constructor", ""); 2889 return true; 2890 } 2891 if (op != EOpConstructStruct && typed->getBasicType() == EbtAtomicUint) { 2892 error(loc, "cannot convert an atomic_uint", "constructor", ""); 2893 return true; 2894 } 2895 if (typed->getBasicType() == EbtVoid) { 2896 error(loc, "cannot convert a void", "constructor", ""); 2897 return true; 2898 } 2899 2900 return false; 2901 } 2902 2903 // Verify all the correct semantics for constructing a combined texture/sampler. 2904 // Return true if the semantics are incorrect. 2905 bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function) 2906 { 2907 TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change 2908 const char* token = constructorName.c_str(); 2909 2910 // exactly two arguments needed 2911 if (function.getParamCount() != 2) { 2912 error(loc, "sampler-constructor requires two arguments", token, ""); 2913 return true; 2914 } 2915 2916 // For now, not allowing arrayed constructors, the rest of this function 2917 // is set up to allow them, if this test is removed: 2918 if (function.getType().isArray()) { 2919 error(loc, "sampler-constructor cannot make an array of samplers", token, ""); 2920 return true; 2921 } 2922 2923 // first argument 2924 // * the constructor's first argument must be a texture type 2925 // * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array) 2926 // of the texture type must match that of the constructed sampler type 2927 // (that is, the suffixes of the type of the first argument and the 2928 // type of the constructor will be spelled the same way) 2929 if (function[0].type->getBasicType() != EbtSampler || 2930 ! function[0].type->getSampler().isTexture() || 2931 function[0].type->isArray()) { 2932 error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, ""); 2933 return true; 2934 } 2935 // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=() 2936 TSampler texture = function.getType().getSampler(); 2937 texture.combined = false; 2938 texture.shadow = false; 2939 if (texture != function[0].type->getSampler()) { 2940 error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, ""); 2941 return true; 2942 } 2943 2944 // second argument 2945 // * the constructor's second argument must be a scalar of type 2946 // *sampler* or *samplerShadow* 2947 if ( function[1].type->getBasicType() != EbtSampler || 2948 ! function[1].type->getSampler().isPureSampler() || 2949 function[1].type->isArray()) { 2950 error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, ""); 2951 return true; 2952 } 2953 2954 return false; 2955 } 2956 2957 // Checks to see if a void variable has been declared and raise an error message for such a case 2958 // 2959 // returns true in case of an error 2960 // 2961 bool TParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType) 2962 { 2963 if (basicType == EbtVoid) { 2964 error(loc, "illegal use of type 'void'", identifier.c_str(), ""); 2965 return true; 2966 } 2967 2968 return false; 2969 } 2970 2971 // Checks to see if the node (for the expression) contains a scalar boolean expression or not 2972 void TParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type) 2973 { 2974 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) 2975 error(loc, "boolean expression expected", "", ""); 2976 } 2977 2978 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not 2979 void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType) 2980 { 2981 if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) 2982 error(loc, "boolean expression expected", "", ""); 2983 } 2984 2985 void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/) 2986 { 2987 // Check that the appropriate extension is enabled if external sampler is used. 2988 // There are two extensions. The correct one must be used based on GLSL version. 2989 if (type.getBasicType() == EbtSampler && type.getSampler().external) { 2990 if (version < 300) { 2991 requireExtensions(loc, 1, &E_GL_OES_EGL_image_external, "samplerExternalOES"); 2992 } else { 2993 requireExtensions(loc, 1, &E_GL_OES_EGL_image_external_essl3, "samplerExternalOES"); 2994 } 2995 } 2996 2997 if (type.getQualifier().storage == EvqUniform) 2998 return; 2999 3000 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler)) 3001 error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str()); 3002 else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) { 3003 // non-uniform sampler 3004 // not yet: okay if it has an initializer 3005 // if (! initializer) 3006 error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); 3007 } 3008 } 3009 3010 void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) 3011 { 3012 if (type.getQualifier().storage == EvqUniform) 3013 return; 3014 3015 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAtomicUint)) 3016 error(loc, "non-uniform struct contains an atomic_uint:", type.getBasicTypeString().c_str(), identifier.c_str()); 3017 else if (type.getBasicType() == EbtAtomicUint && type.getQualifier().storage != EvqUniform) 3018 error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); 3019 } 3020 #ifdef NV_EXTENSIONS 3021 void TParseContext::accStructNVCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) 3022 { 3023 if (type.getQualifier().storage == EvqUniform) 3024 return; 3025 3026 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStructNV)) 3027 error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str()); 3028 else if (type.getBasicType() == EbtAccStructNV && type.getQualifier().storage != EvqUniform) 3029 error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:", 3030 type.getBasicTypeString().c_str(), identifier.c_str()); 3031 3032 } 3033 #endif 3034 3035 void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) 3036 { 3037 if (parsingBuiltins) 3038 return; 3039 3040 if (type.getQualifier().storage != EvqUniform) 3041 return; 3042 3043 if (type.containsNonOpaque()) { 3044 // Vulkan doesn't allow transparent uniforms outside of blocks 3045 if (spvVersion.vulkan > 0) 3046 vulkanRemoved(loc, "non-opaque uniforms outside a block"); 3047 // OpenGL wants locations on these (unless they are getting automapped) 3048 if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations()) 3049 error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), ""); 3050 } 3051 } 3052 3053 // 3054 // Qualifier checks knowing the qualifier and that it is a member of a struct/block. 3055 // 3056 void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType) 3057 { 3058 globalQualifierFixCheck(publicType.loc, publicType.qualifier); 3059 checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers); 3060 if (publicType.qualifier.isNonUniform()) { 3061 error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", ""); 3062 publicType.qualifier.nonUniform = false; 3063 } 3064 } 3065 3066 // 3067 // Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. 3068 // 3069 void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier) 3070 { 3071 bool nonuniformOkay = false; 3072 3073 // move from parameter/unknown qualifiers to pipeline in/out qualifiers 3074 switch (qualifier.storage) { 3075 case EvqIn: 3076 profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs"); 3077 profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs"); 3078 qualifier.storage = EvqVaryingIn; 3079 nonuniformOkay = true; 3080 break; 3081 case EvqOut: 3082 profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs"); 3083 profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs"); 3084 qualifier.storage = EvqVaryingOut; 3085 break; 3086 case EvqInOut: 3087 qualifier.storage = EvqVaryingIn; 3088 error(loc, "cannot use 'inout' at global scope", "", ""); 3089 break; 3090 case EvqGlobal: 3091 case EvqTemporary: 3092 nonuniformOkay = true; 3093 break; 3094 default: 3095 break; 3096 } 3097 3098 if (!nonuniformOkay && qualifier.nonUniform) 3099 error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", ""); 3100 3101 invariantCheck(loc, qualifier); 3102 } 3103 3104 // 3105 // Check a full qualifier and type (no variable yet) at global level. 3106 // 3107 void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TPublicType& publicType) 3108 { 3109 if (! symbolTable.atGlobalLevel()) 3110 return; 3111 3112 if (!(publicType.userDef && publicType.userDef->getBasicType() == EbtReference)) { 3113 if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) { 3114 error(loc, "memory qualifiers cannot be used on this type", "", ""); 3115 } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) { 3116 error(loc, "memory qualifiers cannot be used on this type", "", ""); 3117 } 3118 } 3119 3120 if (qualifier.storage == EvqBuffer && 3121 publicType.basicType != EbtBlock && 3122 !qualifier.layoutBufferReference) 3123 error(loc, "buffers can be declared only as blocks", "buffer", ""); 3124 3125 if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) 3126 return; 3127 3128 if (publicType.shaderQualifiers.blendEquation) 3129 error(loc, "can only be applied to a standalone 'out'", "blend equation", ""); 3130 3131 // now, knowing it is a shader in/out, do all the in/out semantic checks 3132 3133 if (publicType.basicType == EbtBool && !parsingBuiltins) { 3134 error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), ""); 3135 return; 3136 } 3137 3138 if (isTypeInt(publicType.basicType) || publicType.basicType == EbtDouble) 3139 profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output"); 3140 3141 if (!qualifier.flat 3142 #ifdef AMD_EXTENSIONS 3143 && !qualifier.explicitInterp 3144 #endif 3145 #ifdef NV_EXTENSIONS 3146 && !qualifier.pervertexNV 3147 #endif 3148 ) { 3149 if (isTypeInt(publicType.basicType) || 3150 publicType.basicType == EbtDouble || 3151 (publicType.userDef && (publicType.userDef->containsBasicType(EbtInt8) || 3152 publicType.userDef->containsBasicType(EbtUint8) || 3153 publicType.userDef->containsBasicType(EbtInt16) || 3154 publicType.userDef->containsBasicType(EbtUint16) || 3155 publicType.userDef->containsBasicType(EbtInt) || 3156 publicType.userDef->containsBasicType(EbtUint) || 3157 publicType.userDef->containsBasicType(EbtInt64) || 3158 publicType.userDef->containsBasicType(EbtUint64) || 3159 publicType.userDef->containsBasicType(EbtDouble)))) { 3160 if (qualifier.storage == EvqVaryingIn && language == EShLangFragment) 3161 error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); 3162 else if (qualifier.storage == EvqVaryingOut && language == EShLangVertex && version == 300) 3163 error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); 3164 } 3165 } 3166 3167 if (qualifier.patch && qualifier.isInterpolation()) 3168 error(loc, "cannot use interpolation qualifiers with patch", "patch", ""); 3169 3170 #ifdef NV_EXTENSIONS 3171 if (qualifier.perTaskNV && publicType.basicType != EbtBlock) 3172 error(loc, "taskNV variables can be declared only as blocks", "taskNV", ""); 3173 #endif 3174 3175 if (qualifier.storage == EvqVaryingIn) { 3176 switch (language) { 3177 case EShLangVertex: 3178 if (publicType.basicType == EbtStruct) { 3179 error(loc, "cannot be a structure or array", GetStorageQualifierString(qualifier.storage), ""); 3180 return; 3181 } 3182 if (publicType.arraySizes) { 3183 requireProfile(loc, ~EEsProfile, "vertex input arrays"); 3184 profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); 3185 } 3186 if (publicType.basicType == EbtDouble) 3187 profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input"); 3188 if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant) 3189 error(loc, "vertex input cannot be further qualified", "", ""); 3190 break; 3191 3192 case EShLangTessControl: 3193 if (qualifier.patch) 3194 error(loc, "can only use on output in tessellation-control shader", "patch", ""); 3195 break; 3196 3197 case EShLangTessEvaluation: 3198 break; 3199 3200 case EShLangGeometry: 3201 break; 3202 3203 case EShLangFragment: 3204 if (publicType.userDef) { 3205 profileRequires(loc, EEsProfile, 300, nullptr, "fragment-shader struct input"); 3206 profileRequires(loc, ~EEsProfile, 150, nullptr, "fragment-shader struct input"); 3207 if (publicType.userDef->containsStructure()) 3208 requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing structure"); 3209 if (publicType.userDef->containsArray()) 3210 requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing an array"); 3211 } 3212 break; 3213 3214 case EShLangCompute: 3215 if (! symbolTable.atBuiltInLevel()) 3216 error(loc, "global storage input qualifier cannot be used in a compute shader", "in", ""); 3217 break; 3218 3219 default: 3220 break; 3221 } 3222 } else { 3223 // qualifier.storage == EvqVaryingOut 3224 switch (language) { 3225 case EShLangVertex: 3226 if (publicType.userDef) { 3227 profileRequires(loc, EEsProfile, 300, nullptr, "vertex-shader struct output"); 3228 profileRequires(loc, ~EEsProfile, 150, nullptr, "vertex-shader struct output"); 3229 if (publicType.userDef->containsStructure()) 3230 requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing structure"); 3231 if (publicType.userDef->containsArray()) 3232 requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing an array"); 3233 } 3234 3235 break; 3236 3237 case EShLangTessControl: 3238 break; 3239 3240 case EShLangTessEvaluation: 3241 if (qualifier.patch) 3242 error(loc, "can only use on input in tessellation-evaluation shader", "patch", ""); 3243 break; 3244 3245 case EShLangGeometry: 3246 break; 3247 3248 case EShLangFragment: 3249 profileRequires(loc, EEsProfile, 300, nullptr, "fragment shader output"); 3250 if (publicType.basicType == EbtStruct) { 3251 error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), ""); 3252 return; 3253 } 3254 if (publicType.matrixRows > 0) { 3255 error(loc, "cannot be a matrix", GetStorageQualifierString(qualifier.storage), ""); 3256 return; 3257 } 3258 if (qualifier.isAuxiliary()) 3259 error(loc, "can't use auxiliary qualifier on a fragment output", "centroid/sample/patch", ""); 3260 if (qualifier.isInterpolation()) 3261 error(loc, "can't use interpolation qualifier on a fragment output", "flat/smooth/noperspective", ""); 3262 if (publicType.basicType == EbtDouble || publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64) 3263 error(loc, "cannot contain a double, int64, or uint64", GetStorageQualifierString(qualifier.storage), ""); 3264 break; 3265 3266 case EShLangCompute: 3267 error(loc, "global storage output qualifier cannot be used in a compute shader", "out", ""); 3268 break; 3269 3270 default: 3271 break; 3272 } 3273 } 3274 } 3275 3276 // 3277 // Merge characteristics of the 'src' qualifier into the 'dst'. 3278 // If there is duplication, issue error messages, unless 'force' 3279 // is specified, which means to just override default settings. 3280 // 3281 // Also, when force is false, it will be assumed that 'src' follows 3282 // 'dst', for the purpose of error checking order for versions 3283 // that require specific orderings of qualifiers. 3284 // 3285 void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, const TQualifier& src, bool force) 3286 { 3287 // Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers') 3288 if (src.isAuxiliary() && dst.isAuxiliary()) 3289 error(loc, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", ""); 3290 3291 // Multiple interpolation qualifiers (mostly done later by 'individual qualifiers') 3292 if (src.isInterpolation() && dst.isInterpolation()) 3293 #ifdef AMD_EXTENSIONS 3294 error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective, __explicitInterpAMD)", "", ""); 3295 #else 3296 error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", ""); 3297 #endif 3298 3299 // Ordering 3300 if (! force && ((profile != EEsProfile && version < 420) || 3301 (profile == EEsProfile && version < 310)) 3302 && ! extensionTurnedOn(E_GL_ARB_shading_language_420pack)) { 3303 // non-function parameters 3304 if (src.noContraction && (dst.invariant || dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) 3305 error(loc, "precise qualifier must appear first", "", ""); 3306 if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) 3307 error(loc, "invariant qualifier must appear before interpolation, storage, and precision qualifiers ", "", ""); 3308 else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) 3309 error(loc, "interpolation qualifiers must appear before storage and precision qualifiers", "", ""); 3310 else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone)) 3311 error(loc, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", ""); 3312 else if (src.storage != EvqTemporary && (dst.precision != EpqNone)) 3313 error(loc, "precision qualifier must appear as last qualifier", "", ""); 3314 3315 // function parameters 3316 if (src.noContraction && (dst.storage == EvqConst || dst.storage == EvqIn || dst.storage == EvqOut)) 3317 error(loc, "precise qualifier must appear first", "", ""); 3318 if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut)) 3319 error(loc, "in/out must appear before const", "", ""); 3320 } 3321 3322 // Storage qualification 3323 if (dst.storage == EvqTemporary || dst.storage == EvqGlobal) 3324 dst.storage = src.storage; 3325 else if ((dst.storage == EvqIn && src.storage == EvqOut) || 3326 (dst.storage == EvqOut && src.storage == EvqIn)) 3327 dst.storage = EvqInOut; 3328 else if ((dst.storage == EvqIn && src.storage == EvqConst) || 3329 (dst.storage == EvqConst && src.storage == EvqIn)) 3330 dst.storage = EvqConstReadOnly; 3331 else if (src.storage != EvqTemporary && 3332 src.storage != EvqGlobal) 3333 error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), ""); 3334 3335 // Precision qualifiers 3336 if (! force && src.precision != EpqNone && dst.precision != EpqNone) 3337 error(loc, "only one precision qualifier allowed", GetPrecisionQualifierString(src.precision), ""); 3338 if (dst.precision == EpqNone || (force && src.precision != EpqNone)) 3339 dst.precision = src.precision; 3340 3341 if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || 3342 (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || 3343 (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || 3344 (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent)) || 3345 (src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent)))) { 3346 error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent qualifier allowed", GetPrecisionQualifierString(src.precision), ""); 3347 } 3348 // Layout qualifiers 3349 mergeObjectLayoutQualifiers(dst, src, false); 3350 3351 // individual qualifiers 3352 bool repeated = false; 3353 #define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field; 3354 MERGE_SINGLETON(invariant); 3355 MERGE_SINGLETON(noContraction); 3356 MERGE_SINGLETON(centroid); 3357 MERGE_SINGLETON(smooth); 3358 MERGE_SINGLETON(flat); 3359 MERGE_SINGLETON(nopersp); 3360 #ifdef AMD_EXTENSIONS 3361 MERGE_SINGLETON(explicitInterp); 3362 #endif 3363 #ifdef NV_EXTENSIONS 3364 MERGE_SINGLETON(perPrimitiveNV); 3365 MERGE_SINGLETON(perViewNV); 3366 MERGE_SINGLETON(perTaskNV); 3367 #endif 3368 MERGE_SINGLETON(patch); 3369 MERGE_SINGLETON(sample); 3370 MERGE_SINGLETON(coherent); 3371 MERGE_SINGLETON(devicecoherent); 3372 MERGE_SINGLETON(queuefamilycoherent); 3373 MERGE_SINGLETON(workgroupcoherent); 3374 MERGE_SINGLETON(subgroupcoherent); 3375 MERGE_SINGLETON(nonprivate); 3376 MERGE_SINGLETON(volatil); 3377 MERGE_SINGLETON(restrict); 3378 MERGE_SINGLETON(readonly); 3379 MERGE_SINGLETON(writeonly); 3380 MERGE_SINGLETON(specConstant); 3381 MERGE_SINGLETON(nonUniform); 3382 3383 if (repeated) 3384 error(loc, "replicated qualifiers", "", ""); 3385 } 3386 3387 void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publicType, TPrecisionQualifier qualifier) 3388 { 3389 TBasicType basicType = publicType.basicType; 3390 3391 if (basicType == EbtSampler) { 3392 defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)] = qualifier; 3393 3394 return; // all is well 3395 } 3396 3397 if (basicType == EbtInt || basicType == EbtFloat) { 3398 if (publicType.isScalar()) { 3399 defaultPrecision[basicType] = qualifier; 3400 if (basicType == EbtInt) { 3401 defaultPrecision[EbtUint] = qualifier; 3402 precisionManager.explicitIntDefaultSeen(); 3403 } else 3404 precisionManager.explicitFloatDefaultSeen(); 3405 3406 return; // all is well 3407 } 3408 } 3409 3410 if (basicType == EbtAtomicUint) { 3411 if (qualifier != EpqHigh) 3412 error(loc, "can only apply highp to atomic_uint", "precision", ""); 3413 3414 return; 3415 } 3416 3417 error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), ""); 3418 } 3419 3420 // used to flatten the sampler type space into a single dimension 3421 // correlates with the declaration of defaultSamplerPrecision[] 3422 int TParseContext::computeSamplerTypeIndex(TSampler& sampler) 3423 { 3424 int arrayIndex = sampler.arrayed ? 1 : 0; 3425 int shadowIndex = sampler.shadow ? 1 : 0; 3426 int externalIndex = sampler.external? 1 : 0; 3427 int imageIndex = sampler.image ? 1 : 0; 3428 int msIndex = sampler.ms ? 1 : 0; 3429 3430 int flattened = EsdNumDims * (EbtNumTypes * (2 * (2 * (2 * (2 * arrayIndex + msIndex) + imageIndex) + shadowIndex) + 3431 externalIndex) + sampler.type) + sampler.dim; 3432 assert(flattened < maxSamplerIndex); 3433 3434 return flattened; 3435 } 3436 3437 TPrecisionQualifier TParseContext::getDefaultPrecision(TPublicType& publicType) 3438 { 3439 if (publicType.basicType == EbtSampler) 3440 return defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)]; 3441 else 3442 return defaultPrecision[publicType.basicType]; 3443 } 3444 3445 void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType baseType, TQualifier& qualifier) 3446 { 3447 // Built-in symbols are allowed some ambiguous precisions, to be pinned down 3448 // later by context. 3449 if (! obeyPrecisionQualifiers() || parsingBuiltins) 3450 return; 3451 3452 if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh) 3453 error(loc, "atomic counters can only be highp", "atomic_uint", ""); 3454 3455 if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) { 3456 if (qualifier.precision == EpqNone) { 3457 if (relaxedErrors()) 3458 warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "substituting 'mediump'"); 3459 else 3460 error(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), ""); 3461 qualifier.precision = EpqMedium; 3462 defaultPrecision[baseType] = EpqMedium; 3463 } 3464 } else if (qualifier.precision != EpqNone) 3465 error(loc, "type cannot have precision qualifier", TType::getBasicString(baseType), ""); 3466 } 3467 3468 void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type) 3469 { 3470 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque()) 3471 error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), ""); 3472 3473 if (!parsingBuiltins && type.containsBasicType(EbtFloat16)) 3474 requireFloat16Arithmetic(loc, type.getBasicTypeString().c_str(), "float16 types can only be in uniform block or buffer storage"); 3475 if (!parsingBuiltins && type.contains16BitInt()) 3476 requireInt16Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int16 types can only be in uniform block or buffer storage"); 3477 if (!parsingBuiltins && type.contains8BitInt()) 3478 requireInt8Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int8 types can only be in uniform block or buffer storage"); 3479 } 3480 3481 bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType basicType) 3482 { 3483 if (type.getBasicType() == basicType) 3484 return true; 3485 3486 if (type.getBasicType() == EbtStruct) { 3487 const TTypeList& structure = *type.getStruct(); 3488 for (unsigned int i = 0; i < structure.size(); ++i) { 3489 if (containsFieldWithBasicType(*structure[i].type, basicType)) 3490 return true; 3491 } 3492 } 3493 3494 return false; 3495 } 3496 3497 // 3498 // Do size checking for an array type's size. 3499 // 3500 void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair) 3501 { 3502 bool isConst = false; 3503 sizePair.node = nullptr; 3504 3505 int size = 1; 3506 3507 TIntermConstantUnion* constant = expr->getAsConstantUnion(); 3508 if (constant) { 3509 // handle true (non-specialization) constant 3510 size = constant->getConstArray()[0].getIConst(); 3511 isConst = true; 3512 } else { 3513 // see if it's a specialization constant instead 3514 if (expr->getQualifier().isSpecConstant()) { 3515 isConst = true; 3516 sizePair.node = expr; 3517 TIntermSymbol* symbol = expr->getAsSymbolNode(); 3518 if (symbol && symbol->getConstArray().size() > 0) 3519 size = symbol->getConstArray()[0].getIConst(); 3520 } 3521 } 3522 3523 sizePair.size = size; 3524 3525 if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) { 3526 error(loc, "array size must be a constant integer expression", "", ""); 3527 return; 3528 } 3529 3530 if (size <= 0) { 3531 error(loc, "array size must be a positive integer", "", ""); 3532 return; 3533 } 3534 } 3535 3536 // 3537 // See if this qualifier can be an array. 3538 // 3539 // Returns true if there is an error. 3540 // 3541 bool TParseContext::arrayQualifierError(const TSourceLoc& loc, const TQualifier& qualifier) 3542 { 3543 if (qualifier.storage == EvqConst) { 3544 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "const array"); 3545 profileRequires(loc, EEsProfile, 300, nullptr, "const array"); 3546 } 3547 3548 if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) { 3549 requireProfile(loc, ~EEsProfile, "vertex input arrays"); 3550 profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); 3551 } 3552 3553 return false; 3554 } 3555 3556 // 3557 // See if this qualifier and type combination can be an array. 3558 // Assumes arrayQualifierError() was also called to catch the type-invariant tests. 3559 // 3560 // Returns true if there is an error. 3561 // 3562 bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type) 3563 { 3564 if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) { 3565 if (type.isArrayOfArrays()) 3566 requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output"); 3567 else if (type.isStruct()) 3568 requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output"); 3569 } 3570 if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) { 3571 if (type.isArrayOfArrays()) 3572 requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input"); 3573 else if (type.isStruct()) 3574 requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input"); 3575 } 3576 if (type.getQualifier().storage == EvqVaryingOut && language == EShLangFragment) { 3577 if (type.isArrayOfArrays()) 3578 requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array output"); 3579 } 3580 3581 return false; 3582 } 3583 3584 // 3585 // Require array to be completely sized 3586 // 3587 void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes) 3588 { 3589 if (arraySizes.hasUnsized()) 3590 error(loc, "array size required", "", ""); 3591 } 3592 3593 void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type) 3594 { 3595 const TTypeList& structure = *type.getStruct(); 3596 for (int m = 0; m < (int)structure.size(); ++m) { 3597 const TType& member = *structure[m].type; 3598 if (member.isArray()) 3599 arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes()); 3600 } 3601 } 3602 3603 void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes, 3604 const TIntermTyped* initializer, bool lastMember) 3605 { 3606 assert(arraySizes); 3607 3608 // always allow special built-in ins/outs sized to topologies 3609 if (parsingBuiltins) 3610 return; 3611 3612 // initializer must be a sized array, in which case 3613 // allow the initializer to set any unknown array sizes 3614 if (initializer != nullptr) { 3615 if (initializer->getType().isUnsizedArray()) 3616 error(loc, "array initializer must be sized", "[]", ""); 3617 return; 3618 } 3619 3620 // No environment allows any non-outer-dimension to be implicitly sized 3621 if (arraySizes->isInnerUnsized()) { 3622 error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", ""); 3623 arraySizes->clearInnerUnsized(); 3624 } 3625 3626 if (arraySizes->isInnerSpecialization()) 3627 error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", ""); 3628 3629 // desktop always allows outer-dimension-unsized variable arrays, 3630 if (profile != EEsProfile) 3631 return; 3632 3633 // for ES, if size isn't coming from an initializer, it has to be explicitly declared now, 3634 // with very few exceptions 3635 3636 // last member of ssbo block exception: 3637 if (qualifier.storage == EvqBuffer && lastMember) 3638 return; 3639 3640 // implicitly-sized io exceptions: 3641 switch (language) { 3642 case EShLangGeometry: 3643 if (qualifier.storage == EvqVaryingIn) 3644 if ((profile == EEsProfile && version >= 320) || 3645 extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader)) 3646 return; 3647 break; 3648 case EShLangTessControl: 3649 if ( qualifier.storage == EvqVaryingIn || 3650 (qualifier.storage == EvqVaryingOut && ! qualifier.patch)) 3651 if ((profile == EEsProfile && version >= 320) || 3652 extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) 3653 return; 3654 break; 3655 case EShLangTessEvaluation: 3656 if ((qualifier.storage == EvqVaryingIn && ! qualifier.patch) || 3657 qualifier.storage == EvqVaryingOut) 3658 if ((profile == EEsProfile && version >= 320) || 3659 extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) 3660 return; 3661 break; 3662 #ifdef NV_EXTENSIONS 3663 case EShLangMeshNV: 3664 if (qualifier.storage == EvqVaryingOut) 3665 if ((profile == EEsProfile && version >= 320) || 3666 extensionTurnedOn(E_GL_NV_mesh_shader)) 3667 return; 3668 break; 3669 #endif 3670 default: 3671 break; 3672 } 3673 3674 arraySizeRequiredCheck(loc, *arraySizes); 3675 } 3676 3677 void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc, const TArraySizes* sizes) 3678 { 3679 if (sizes == nullptr || sizes->getNumDims() == 1) 3680 return; 3681 3682 const char* feature = "arrays of arrays"; 3683 3684 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); 3685 profileRequires(loc, EEsProfile, 310, nullptr, feature); 3686 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); 3687 } 3688 3689 // 3690 // Do all the semantic checking for declaring or redeclaring an array, with and 3691 // without a size, and make the right changes to the symbol table. 3692 // 3693 void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol) 3694 { 3695 if (symbol == nullptr) { 3696 bool currentScope; 3697 symbol = symbolTable.find(identifier, nullptr, ¤tScope); 3698 3699 if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) { 3700 // bad shader (errors already reported) trying to redeclare a built-in name as an array 3701 symbol = nullptr; 3702 return; 3703 } 3704 if (symbol == nullptr || ! currentScope) { 3705 // 3706 // Successfully process a new definition. 3707 // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations) 3708 // 3709 symbol = new TVariable(&identifier, type); 3710 symbolTable.insert(*symbol); 3711 if (symbolTable.atGlobalLevel()) 3712 trackLinkage(*symbol); 3713 3714 if (! symbolTable.atBuiltInLevel()) { 3715 if (isIoResizeArray(type)) { 3716 ioArraySymbolResizeList.push_back(symbol); 3717 checkIoArraysConsistency(loc, true, type.getQualifier().isPerPrimitive()); 3718 } else 3719 fixIoArraySize(loc, symbol->getWritableType()); 3720 } 3721 3722 return; 3723 } 3724 if (symbol->getAsAnonMember()) { 3725 error(loc, "cannot redeclare a user-block member array", identifier.c_str(), ""); 3726 symbol = nullptr; 3727 return; 3728 } 3729 } 3730 3731 // 3732 // Process a redeclaration. 3733 // 3734 3735 if (symbol == nullptr) { 3736 error(loc, "array variable name expected", identifier.c_str(), ""); 3737 return; 3738 } 3739 3740 // redeclareBuiltinVariable() should have already done the copyUp() 3741 TType& existingType = symbol->getWritableType(); 3742 3743 if (! existingType.isArray()) { 3744 error(loc, "redeclaring non-array as array", identifier.c_str(), ""); 3745 return; 3746 } 3747 3748 if (! existingType.sameElementType(type)) { 3749 error(loc, "redeclaration of array with a different element type", identifier.c_str(), ""); 3750 return; 3751 } 3752 3753 if (! existingType.sameInnerArrayness(type)) { 3754 error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), ""); 3755 return; 3756 } 3757 3758 if (existingType.isSizedArray()) { 3759 // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size 3760 if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize())) 3761 error(loc, "redeclaration of array with size", identifier.c_str(), ""); 3762 return; 3763 } 3764 3765 arrayLimitCheck(loc, identifier, type.getOuterArraySize()); 3766 3767 existingType.updateArraySizes(type); 3768 3769 if (isIoResizeArray(type)) 3770 checkIoArraysConsistency(loc, false, type.getQualifier().isPerPrimitive()); 3771 } 3772 3773 // Policy and error check for needing a runtime sized array. 3774 void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermTyped& base) 3775 { 3776 // runtime length implies runtime sizeable, so no problem 3777 if (isRuntimeLength(base)) 3778 return; 3779 3780 // Check for last member of a bufferreference type, which is runtime sizeable 3781 // but doesn't support runtime length 3782 if (base.getType().getQualifier().storage == EvqBuffer) { 3783 const TIntermBinary* binary = base.getAsBinaryNode(); 3784 if (binary != nullptr && 3785 binary->getOp() == EOpIndexDirectStruct && 3786 binary->getLeft()->getBasicType() == EbtReference) { 3787 3788 const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); 3789 const int memberCount = (int)binary->getLeft()->getType().getReferentType()->getStruct()->size(); 3790 if (index == memberCount - 1) 3791 return; 3792 } 3793 } 3794 3795 // check for additional things allowed by GL_EXT_nonuniform_qualifier 3796 if (base.getBasicType() == EbtSampler || 3797 (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer())) 3798 requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index"); 3799 else 3800 error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable"); 3801 } 3802 3803 // Policy decision for whether a run-time .length() is allowed. 3804 bool TParseContext::isRuntimeLength(const TIntermTyped& base) const 3805 { 3806 if (base.getType().getQualifier().storage == EvqBuffer) { 3807 // in a buffer block 3808 const TIntermBinary* binary = base.getAsBinaryNode(); 3809 if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) { 3810 // is it the last member? 3811 const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); 3812 3813 if (binary->getLeft()->getBasicType() == EbtReference) 3814 return false; 3815 3816 const int memberCount = (int)binary->getLeft()->getType().getStruct()->size(); 3817 if (index == memberCount - 1) 3818 return true; 3819 } 3820 } 3821 3822 return false; 3823 } 3824 3825 #ifdef NV_EXTENSIONS 3826 // Fix mesh view output array dimension 3827 void TParseContext::resizeMeshViewDimension(const TSourceLoc& loc, TType& type) 3828 { 3829 // see if member is a per-view attribute 3830 if (type.getQualifier().isPerView()) { 3831 // since we don't have the maxMeshViewCountNV set during parsing builtins, we hardcode the value 3832 int maxViewCount = parsingBuiltins ? 4 : resources.maxMeshViewCountNV; 3833 3834 if (! type.isArray()) { 3835 error(loc, "requires an view array dimension", "perviewNV", ""); 3836 } 3837 else if (!type.isUnsizedArray() && type.getOuterArraySize() != maxViewCount) { 3838 error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", ""); 3839 } 3840 else if (type.isUnsizedArray()) { 3841 type.changeOuterArraySize(maxViewCount); 3842 } 3843 } 3844 } 3845 #endif 3846 3847 // Returns true if the first argument to the #line directive is the line number for the next line. 3848 // 3849 // Desktop, pre-version 3.30: "After processing this directive 3850 // (including its new-line), the implementation will behave as if it is compiling at line number line+1 and 3851 // source string number source-string-number." 3852 // 3853 // Desktop, version 3.30 and later, and ES: "After processing this directive 3854 // (including its new-line), the implementation will behave as if it is compiling at line number line and 3855 // source string number source-string-number. 3856 bool TParseContext::lineDirectiveShouldSetNextLine() const 3857 { 3858 return profile == EEsProfile || version >= 330; 3859 } 3860 3861 // 3862 // Enforce non-initializer type/qualifier rules. 3863 // 3864 void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier, TType& type) 3865 { 3866 // 3867 // Make the qualifier make sense, given that there is not an initializer. 3868 // 3869 if (type.getQualifier().storage == EvqConst || 3870 type.getQualifier().storage == EvqConstReadOnly) { 3871 type.getQualifier().makeTemporary(); 3872 error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); 3873 } 3874 } 3875 3876 // 3877 // See if the identifier is a built-in symbol that can be redeclared, and if so, 3878 // copy the symbol table's read-only built-in variable to the current 3879 // global level, where it can be modified based on the passed in type. 3880 // 3881 // Returns nullptr if no redeclaration took place; meaning a normal declaration still 3882 // needs to occur for it, not necessarily an error. 3883 // 3884 // Returns a redeclared and type-modified variable if a redeclarated occurred. 3885 // 3886 TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier, 3887 const TQualifier& qualifier, const TShaderQualifiers& publicType) 3888 { 3889 if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel()) 3890 return nullptr; 3891 3892 bool nonEsRedecls = (profile != EEsProfile && (version >= 130 || identifier == "gl_TexCoord")); 3893 bool esRedecls = (profile == EEsProfile && 3894 (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks))); 3895 if (! esRedecls && ! nonEsRedecls) 3896 return nullptr; 3897 3898 // Special case when using GL_ARB_separate_shader_objects 3899 bool ssoPre150 = false; // means the only reason this variable is redeclared is due to this combination 3900 if (profile != EEsProfile && version <= 140 && extensionTurnedOn(E_GL_ARB_separate_shader_objects)) { 3901 if (identifier == "gl_Position" || 3902 identifier == "gl_PointSize" || 3903 identifier == "gl_ClipVertex" || 3904 identifier == "gl_FogFragCoord") 3905 ssoPre150 = true; 3906 } 3907 3908 // Potentially redeclaring a built-in variable... 3909 3910 if (ssoPre150 || 3911 (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) || 3912 (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) || 3913 identifier == "gl_ClipDistance" || 3914 identifier == "gl_CullDistance" || 3915 identifier == "gl_FrontColor" || 3916 identifier == "gl_BackColor" || 3917 identifier == "gl_FrontSecondaryColor" || 3918 identifier == "gl_BackSecondaryColor" || 3919 identifier == "gl_SecondaryColor" || 3920 (identifier == "gl_Color" && language == EShLangFragment) || 3921 (identifier == "gl_FragStencilRefARB" && (nonEsRedecls && version >= 140) 3922 && language == EShLangFragment) || 3923 #ifdef NV_EXTENSIONS 3924 identifier == "gl_SampleMask" || 3925 identifier == "gl_Layer" || 3926 #endif 3927 identifier == "gl_TexCoord") { 3928 3929 // Find the existing symbol, if any. 3930 bool builtIn; 3931 TSymbol* symbol = symbolTable.find(identifier, &builtIn); 3932 3933 // If the symbol was not found, this must be a version/profile/stage 3934 // that doesn't have it. 3935 if (! symbol) 3936 return nullptr; 3937 3938 // If it wasn't at a built-in level, then it's already been redeclared; 3939 // that is, this is a redeclaration of a redeclaration; reuse that initial 3940 // redeclaration. Otherwise, make the new one. 3941 if (builtIn) 3942 makeEditable(symbol); 3943 3944 // Now, modify the type of the copy, as per the type of the current redeclaration. 3945 3946 TQualifier& symbolQualifier = symbol->getWritableType().getQualifier(); 3947 if (ssoPre150) { 3948 if (intermediate.inIoAccessed(identifier)) 3949 error(loc, "cannot redeclare after use", identifier.c_str(), ""); 3950 if (qualifier.hasLayout()) 3951 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); 3952 if (qualifier.isMemory() || qualifier.isAuxiliary() || (language == EShLangVertex && qualifier.storage != EvqVaryingOut) || 3953 (language == EShLangFragment && qualifier.storage != EvqVaryingIn)) 3954 error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); 3955 if (! qualifier.smooth) 3956 error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str()); 3957 } else if (identifier == "gl_FrontColor" || 3958 identifier == "gl_BackColor" || 3959 identifier == "gl_FrontSecondaryColor" || 3960 identifier == "gl_BackSecondaryColor" || 3961 identifier == "gl_SecondaryColor" || 3962 identifier == "gl_Color") { 3963 symbolQualifier.flat = qualifier.flat; 3964 symbolQualifier.smooth = qualifier.smooth; 3965 symbolQualifier.nopersp = qualifier.nopersp; 3966 if (qualifier.hasLayout()) 3967 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); 3968 if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage) 3969 error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); 3970 } else if (identifier == "gl_TexCoord" || 3971 identifier == "gl_ClipDistance" || 3972 identifier == "gl_CullDistance") { 3973 if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() || 3974 qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || 3975 symbolQualifier.storage != qualifier.storage) 3976 error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str()); 3977 } else if (identifier == "gl_FragCoord") { 3978 if (intermediate.inIoAccessed("gl_FragCoord")) 3979 error(loc, "cannot redeclare after use", "gl_FragCoord", ""); 3980 if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || 3981 qualifier.isMemory() || qualifier.isAuxiliary()) 3982 error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); 3983 if (qualifier.storage != EvqVaryingIn) 3984 error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str()); 3985 if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() || 3986 publicType.originUpperLeft != intermediate.getOriginUpperLeft())) 3987 error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str()); 3988 if (publicType.pixelCenterInteger) 3989 intermediate.setPixelCenterInteger(); 3990 if (publicType.originUpperLeft) 3991 intermediate.setOriginUpperLeft(); 3992 } else if (identifier == "gl_FragDepth") { 3993 if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || 3994 qualifier.isMemory() || qualifier.isAuxiliary()) 3995 error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); 3996 if (qualifier.storage != EvqVaryingOut) 3997 error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); 3998 if (publicType.layoutDepth != EldNone) { 3999 if (intermediate.inIoAccessed("gl_FragDepth")) 4000 error(loc, "cannot redeclare after use", "gl_FragDepth", ""); 4001 if (! intermediate.setDepth(publicType.layoutDepth)) 4002 error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str()); 4003 } 4004 } 4005 else if (identifier == "gl_FragStencilRefARB") { 4006 if (qualifier.hasLayout()) 4007 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); 4008 if (qualifier.storage != EvqVaryingOut) 4009 error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); 4010 } 4011 #ifdef NV_EXTENSIONS 4012 else if (identifier == "gl_SampleMask") { 4013 if (!publicType.layoutOverrideCoverage) { 4014 error(loc, "redeclaration only allowed for override_coverage layout", "redeclaration", symbol->getName().c_str()); 4015 } 4016 intermediate.setLayoutOverrideCoverage(); 4017 } 4018 else if (identifier == "gl_Layer") { 4019 if (!qualifier.layoutViewportRelative && qualifier.layoutSecondaryViewportRelativeOffset == -2048) 4020 error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", symbol->getName().c_str()); 4021 symbolQualifier.layoutViewportRelative = qualifier.layoutViewportRelative; 4022 symbolQualifier.layoutSecondaryViewportRelativeOffset = qualifier.layoutSecondaryViewportRelativeOffset; 4023 } 4024 #endif 4025 4026 // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above 4027 4028 return symbol; 4029 } 4030 4031 return nullptr; 4032 } 4033 4034 // 4035 // Either redeclare the requested block, or give an error message why it can't be done. 4036 // 4037 // TODO: functionality: explicitly sizing members of redeclared blocks is not giving them an explicit size 4038 void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName, 4039 const TString* instanceName, TArraySizes* arraySizes) 4040 { 4041 const char* feature = "built-in block redeclaration"; 4042 profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); 4043 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); 4044 4045 if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment" 4046 #ifdef NV_EXTENSIONS 4047 && blockName != "gl_MeshPerVertexNV" && blockName != "gl_MeshPerPrimitiveNV" 4048 #endif 4049 ) 4050 { 4051 error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str()); 4052 return; 4053 } 4054 4055 // Redeclaring a built-in block... 4056 4057 if (instanceName && ! builtInName(*instanceName)) { 4058 error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), ""); 4059 return; 4060 } 4061 4062 // Blocks with instance names are easy to find, lookup the instance name, 4063 // Anonymous blocks need to be found via a member. 4064 bool builtIn; 4065 TSymbol* block; 4066 if (instanceName) 4067 block = symbolTable.find(*instanceName, &builtIn); 4068 else 4069 block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn); 4070 4071 // If the block was not found, this must be a version/profile/stage 4072 // that doesn't have it, or the instance name is wrong. 4073 const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str(); 4074 if (! block) { 4075 error(loc, "no declaration found for redeclaration", errorName, ""); 4076 return; 4077 } 4078 // Built-in blocks cannot be redeclared more than once, which if happened, 4079 // we'd be finding the already redeclared one here, rather than the built in. 4080 if (! builtIn) { 4081 error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), ""); 4082 return; 4083 } 4084 4085 // Copy the block to make a writable version, to insert into the block table after editing. 4086 block = symbolTable.copyUpDeferredInsert(block); 4087 4088 if (block->getType().getBasicType() != EbtBlock) { 4089 error(loc, "cannot redeclare a non block as a block", errorName, ""); 4090 return; 4091 } 4092 4093 // Fix XFB stuff up, it applies to the order of the redeclaration, not 4094 // the order of the original members. 4095 if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) { 4096 if (!currentBlockQualifier.hasXfbBuffer()) 4097 currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; 4098 if (!currentBlockQualifier.hasStream()) 4099 currentBlockQualifier.layoutStream = globalOutputDefaults.layoutStream; 4100 fixXfbOffsets(currentBlockQualifier, newTypeList); 4101 } 4102 4103 // Edit and error check the container against the redeclaration 4104 // - remove unused members 4105 // - ensure remaining qualifiers/types match 4106 4107 TType& type = block->getWritableType(); 4108 4109 #ifdef NV_EXTENSIONS 4110 // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position" 4111 // for passthrough purpose, the redeclared block should have the same qualifers as 4112 // the current one 4113 if (currentBlockQualifier.layoutPassthrough) { 4114 type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough; 4115 type.getQualifier().storage = currentBlockQualifier.storage; 4116 type.getQualifier().layoutStream = currentBlockQualifier.layoutStream; 4117 type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; 4118 } 4119 #endif 4120 4121 TTypeList::iterator member = type.getWritableStruct()->begin(); 4122 size_t numOriginalMembersFound = 0; 4123 while (member != type.getStruct()->end()) { 4124 // look for match 4125 bool found = false; 4126 TTypeList::const_iterator newMember; 4127 TSourceLoc memberLoc; 4128 memberLoc.init(); 4129 for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) { 4130 if (member->type->getFieldName() == newMember->type->getFieldName()) { 4131 found = true; 4132 memberLoc = newMember->loc; 4133 break; 4134 } 4135 } 4136 4137 if (found) { 4138 ++numOriginalMembersFound; 4139 // - ensure match between redeclared members' types 4140 // - check for things that can't be changed 4141 // - update things that can be changed 4142 TType& oldType = *member->type; 4143 const TType& newType = *newMember->type; 4144 if (! newType.sameElementType(oldType)) 4145 error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), ""); 4146 if (oldType.isArray() != newType.isArray()) 4147 error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), ""); 4148 else if (! oldType.getQualifier().isPerView() && ! oldType.sameArrayness(newType) && oldType.isSizedArray()) 4149 error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), ""); 4150 else if (! oldType.getQualifier().isPerView() && newType.isArray()) 4151 arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize()); 4152 #ifdef NV_EXTENSIONS 4153 if (oldType.getQualifier().isPerView() && ! newType.getQualifier().isPerView()) 4154 error(memberLoc, "missing perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); 4155 else if (! oldType.getQualifier().isPerView() && newType.getQualifier().isPerView()) 4156 error(memberLoc, "cannot add perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); 4157 else if (newType.getQualifier().isPerView()) { 4158 if (oldType.getArraySizes()->getNumDims() != newType.getArraySizes()->getNumDims()) 4159 error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), ""); 4160 else if (! newType.isUnsizedArray() && newType.getOuterArraySize() != resources.maxMeshViewCountNV) 4161 error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", ""); 4162 else if (newType.getArraySizes()->getNumDims() == 2) { 4163 int innerDimSize = newType.getArraySizes()->getDimSize(1); 4164 arrayLimitCheck(memberLoc, member->type->getFieldName(), innerDimSize); 4165 oldType.getArraySizes()->setDimSize(1, innerDimSize); 4166 } 4167 } 4168 if (oldType.getQualifier().isPerPrimitive() && ! newType.getQualifier().isPerPrimitive()) 4169 error(memberLoc, "missing perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); 4170 else if (! oldType.getQualifier().isPerPrimitive() && newType.getQualifier().isPerPrimitive()) 4171 error(memberLoc, "cannot add perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); 4172 #endif 4173 if (newType.getQualifier().isMemory()) 4174 error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); 4175 if (newType.getQualifier().hasNonXfbLayout()) 4176 error(memberLoc, "cannot add non-XFB layout to redeclared block member", member->type->getFieldName().c_str(), ""); 4177 if (newType.getQualifier().patch) 4178 error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), ""); 4179 if (newType.getQualifier().hasXfbBuffer() && 4180 newType.getQualifier().layoutXfbBuffer != currentBlockQualifier.layoutXfbBuffer) 4181 error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); 4182 if (newType.getQualifier().hasStream() && 4183 newType.getQualifier().layoutStream != currentBlockQualifier.layoutStream) 4184 error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_stream", ""); 4185 oldType.getQualifier().centroid = newType.getQualifier().centroid; 4186 oldType.getQualifier().sample = newType.getQualifier().sample; 4187 oldType.getQualifier().invariant = newType.getQualifier().invariant; 4188 oldType.getQualifier().noContraction = newType.getQualifier().noContraction; 4189 oldType.getQualifier().smooth = newType.getQualifier().smooth; 4190 oldType.getQualifier().flat = newType.getQualifier().flat; 4191 oldType.getQualifier().nopersp = newType.getQualifier().nopersp; 4192 oldType.getQualifier().layoutXfbOffset = newType.getQualifier().layoutXfbOffset; 4193 oldType.getQualifier().layoutXfbBuffer = newType.getQualifier().layoutXfbBuffer; 4194 oldType.getQualifier().layoutXfbStride = newType.getQualifier().layoutXfbStride; 4195 if (oldType.getQualifier().layoutXfbOffset != TQualifier::layoutXfbBufferEnd) { 4196 // If any member has an xfb_offset, then the block's xfb_buffer inherents current xfb_buffer, 4197 // and for xfb processing, the member needs it as well, along with xfb_stride. 4198 type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; 4199 oldType.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; 4200 } 4201 if (oldType.isUnsizedArray() && newType.isSizedArray()) 4202 oldType.changeOuterArraySize(newType.getOuterArraySize()); 4203 4204 // check and process the member's type, which will include managing xfb information 4205 layoutTypeCheck(loc, oldType); 4206 4207 // go to next member 4208 ++member; 4209 } else { 4210 // For missing members of anonymous blocks that have been redeclared, 4211 // hide the original (shared) declaration. 4212 // Instance-named blocks can just have the member removed. 4213 if (instanceName) 4214 member = type.getWritableStruct()->erase(member); 4215 else { 4216 member->type->hideMember(); 4217 ++member; 4218 } 4219 } 4220 } 4221 4222 if (spvVersion.vulkan > 0) { 4223 // ...then streams apply to built-in blocks, instead of them being only on stream 0 4224 type.getQualifier().layoutStream = currentBlockQualifier.layoutStream; 4225 } 4226 4227 if (numOriginalMembersFound < newTypeList.size()) 4228 error(loc, "block redeclaration has extra members", blockName.c_str(), ""); 4229 if (type.isArray() != (arraySizes != nullptr) || 4230 (type.isArray() && arraySizes != nullptr && type.getArraySizes()->getNumDims() != arraySizes->getNumDims())) 4231 error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), ""); 4232 else if (type.isArray()) { 4233 // At this point, we know both are arrays and both have the same number of dimensions. 4234 4235 // It is okay for a built-in block redeclaration to be unsized, and keep the size of the 4236 // original block declaration. 4237 if (!arraySizes->isSized() && type.isSizedArray()) 4238 arraySizes->changeOuterSize(type.getOuterArraySize()); 4239 4240 // And, okay to be giving a size to the array, by the redeclaration 4241 if (!type.isSizedArray() && arraySizes->isSized()) 4242 type.changeOuterArraySize(arraySizes->getOuterSize()); 4243 4244 // Now, they must match in all dimensions. 4245 if (type.isSizedArray() && *type.getArraySizes() != *arraySizes) 4246 error(loc, "cannot change array size of redeclared block", blockName.c_str(), ""); 4247 } 4248 4249 symbolTable.insert(*block); 4250 4251 // Check for general layout qualifier errors 4252 layoutObjectCheck(loc, *block); 4253 4254 // Tracking for implicit sizing of array 4255 if (isIoResizeArray(block->getType())) { 4256 ioArraySymbolResizeList.push_back(block); 4257 checkIoArraysConsistency(loc, true, block->getType().getQualifier().isPerPrimitive()); 4258 } else if (block->getType().isArray()) 4259 fixIoArraySize(loc, block->getWritableType()); 4260 4261 // Save it in the AST for linker use. 4262 trackLinkage(*block); 4263 } 4264 4265 void TParseContext::paramCheckFixStorage(const TSourceLoc& loc, const TStorageQualifier& qualifier, TType& type) 4266 { 4267 switch (qualifier) { 4268 case EvqConst: 4269 case EvqConstReadOnly: 4270 type.getQualifier().storage = EvqConstReadOnly; 4271 break; 4272 case EvqIn: 4273 case EvqOut: 4274 case EvqInOut: 4275 type.getQualifier().storage = qualifier; 4276 break; 4277 case EvqGlobal: 4278 case EvqTemporary: 4279 type.getQualifier().storage = EvqIn; 4280 break; 4281 default: 4282 type.getQualifier().storage = EvqIn; 4283 error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), ""); 4284 break; 4285 } 4286 } 4287 4288 void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& qualifier, TType& type) 4289 { 4290 if (qualifier.isMemory()) { 4291 type.getQualifier().volatil = qualifier.volatil; 4292 type.getQualifier().coherent = qualifier.coherent; 4293 type.getQualifier().devicecoherent = qualifier.devicecoherent ; 4294 type.getQualifier().queuefamilycoherent = qualifier.queuefamilycoherent; 4295 type.getQualifier().workgroupcoherent = qualifier.workgroupcoherent; 4296 type.getQualifier().subgroupcoherent = qualifier.subgroupcoherent; 4297 type.getQualifier().nonprivate = qualifier.nonprivate; 4298 type.getQualifier().readonly = qualifier.readonly; 4299 type.getQualifier().writeonly = qualifier.writeonly; 4300 type.getQualifier().restrict = qualifier.restrict; 4301 } 4302 4303 if (qualifier.isAuxiliary() || 4304 qualifier.isInterpolation()) 4305 error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", ""); 4306 if (qualifier.hasLayout()) 4307 error(loc, "cannot use layout qualifiers on a function parameter", "", ""); 4308 if (qualifier.invariant) 4309 error(loc, "cannot use invariant qualifier on a function parameter", "", ""); 4310 if (qualifier.noContraction) { 4311 if (qualifier.isParamOutput()) 4312 type.getQualifier().noContraction = true; 4313 else 4314 warn(loc, "qualifier has no effect on non-output parameters", "precise", ""); 4315 } 4316 if (qualifier.isNonUniform()) 4317 type.getQualifier().nonUniform = qualifier.nonUniform; 4318 4319 paramCheckFixStorage(loc, qualifier.storage, type); 4320 } 4321 4322 void TParseContext::nestedBlockCheck(const TSourceLoc& loc) 4323 { 4324 if (structNestingLevel > 0) 4325 error(loc, "cannot nest a block definition inside a structure or block", "", ""); 4326 ++structNestingLevel; 4327 } 4328 4329 void TParseContext::nestedStructCheck(const TSourceLoc& loc) 4330 { 4331 if (structNestingLevel > 0) 4332 error(loc, "cannot nest a structure definition inside a structure or block", "", ""); 4333 ++structNestingLevel; 4334 } 4335 4336 void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, const char* op) 4337 { 4338 // Some versions don't allow comparing arrays or structures containing arrays 4339 if (type.containsArray()) { 4340 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, op); 4341 profileRequires(loc, EEsProfile, 300, nullptr, op); 4342 } 4343 } 4344 4345 void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op) 4346 { 4347 if (containsFieldWithBasicType(type, EbtSampler)) 4348 error(loc, "can't use with samplers or structs containing samplers", op, ""); 4349 } 4350 4351 void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op) 4352 { 4353 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16)) 4354 requireFloat16Arithmetic(loc, op, "can't use with structs containing float16"); 4355 4356 if (type.isArray() && type.getBasicType() == EbtFloat16) 4357 requireFloat16Arithmetic(loc, op, "can't use with arrays containing float16"); 4358 4359 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt16)) 4360 requireInt16Arithmetic(loc, op, "can't use with structs containing int16"); 4361 4362 if (type.isArray() && type.getBasicType() == EbtInt16) 4363 requireInt16Arithmetic(loc, op, "can't use with arrays containing int16"); 4364 4365 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint16)) 4366 requireInt16Arithmetic(loc, op, "can't use with structs containing uint16"); 4367 4368 if (type.isArray() && type.getBasicType() == EbtUint16) 4369 requireInt16Arithmetic(loc, op, "can't use with arrays containing uint16"); 4370 4371 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt8)) 4372 requireInt8Arithmetic(loc, op, "can't use with structs containing int8"); 4373 4374 if (type.isArray() && type.getBasicType() == EbtInt8) 4375 requireInt8Arithmetic(loc, op, "can't use with arrays containing int8"); 4376 4377 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint8)) 4378 requireInt8Arithmetic(loc, op, "can't use with structs containing uint8"); 4379 4380 if (type.isArray() && type.getBasicType() == EbtUint8) 4381 requireInt8Arithmetic(loc, op, "can't use with arrays containing uint8"); 4382 } 4383 4384 void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op) 4385 { 4386 if (type.containsSpecializationSize()) 4387 error(loc, "can't use with types containing arrays sized with a specialization constant", op, ""); 4388 } 4389 4390 void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publicType) 4391 { 4392 const TTypeList& typeList = *publicType.userDef->getStruct(); 4393 4394 // fix and check for member storage qualifiers and types that don't belong within a structure 4395 for (unsigned int member = 0; member < typeList.size(); ++member) { 4396 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 4397 const TSourceLoc& memberLoc = typeList[member].loc; 4398 if (memberQualifier.isAuxiliary() || 4399 memberQualifier.isInterpolation() || 4400 (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal)) 4401 error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); 4402 if (memberQualifier.isMemory()) 4403 error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); 4404 if (memberQualifier.hasLayout()) { 4405 error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); 4406 memberQualifier.clearLayout(); 4407 } 4408 if (memberQualifier.invariant) 4409 error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), ""); 4410 } 4411 } 4412 4413 // 4414 // See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A: 4415 // 4416 // "The loop index has type int or float. 4417 // 4418 // "The for statement has the form: 4419 // for ( init-declaration ; condition ; expression ) 4420 // init-declaration has the form: type-specifier identifier = constant-expression 4421 // condition has the form: loop-index relational_operator constant-expression 4422 // where relational_operator is one of: > >= < <= == or != 4423 // expression [sic] has one of the following forms: 4424 // loop-index++ 4425 // loop-index-- 4426 // loop-index += constant-expression 4427 // loop-index -= constant-expression 4428 // 4429 // The body is handled in an AST traversal. 4430 // 4431 void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop) 4432 { 4433 // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration 4434 bool badInit = false; 4435 if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1) 4436 badInit = true; 4437 TIntermBinary* binaryInit = 0; 4438 if (! badInit) { 4439 // get the declaration assignment 4440 binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode(); 4441 if (! binaryInit) 4442 badInit = true; 4443 } 4444 if (badInit) { 4445 error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); 4446 return; 4447 } 4448 4449 // loop index must be type int or float 4450 if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) { 4451 error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", ""); 4452 return; 4453 } 4454 4455 // init is the form "loop-index = constant" 4456 if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) { 4457 error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); 4458 return; 4459 } 4460 4461 // get the unique id of the loop index 4462 int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); 4463 inductiveLoopIds.insert(loopIndex); 4464 4465 // condition's form must be "loop-index relational-operator constant-expression" 4466 bool badCond = ! loop->getTest(); 4467 if (! badCond) { 4468 TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode(); 4469 badCond = ! binaryCond; 4470 if (! badCond) { 4471 switch (binaryCond->getOp()) { 4472 case EOpGreaterThan: 4473 case EOpGreaterThanEqual: 4474 case EOpLessThan: 4475 case EOpLessThanEqual: 4476 case EOpEqual: 4477 case EOpNotEqual: 4478 break; 4479 default: 4480 badCond = true; 4481 } 4482 } 4483 if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() || 4484 binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex || 4485 ! binaryCond->getRight()->getAsConstantUnion())) 4486 badCond = true; 4487 } 4488 if (badCond) { 4489 error(loc, "inductive-loop condition requires the form \"loop-index <comparison-op> constant-expression\"", "limitations", ""); 4490 return; 4491 } 4492 4493 // loop-index++ 4494 // loop-index-- 4495 // loop-index += constant-expression 4496 // loop-index -= constant-expression 4497 bool badTerminal = ! loop->getTerminal(); 4498 if (! badTerminal) { 4499 TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode(); 4500 TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode(); 4501 if (unaryTerminal || binaryTerminal) { 4502 switch(loop->getTerminal()->getAsOperator()->getOp()) { 4503 case EOpPostDecrement: 4504 case EOpPostIncrement: 4505 case EOpAddAssign: 4506 case EOpSubAssign: 4507 break; 4508 default: 4509 badTerminal = true; 4510 } 4511 } else 4512 badTerminal = true; 4513 if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() || 4514 binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex || 4515 ! binaryTerminal->getRight()->getAsConstantUnion())) 4516 badTerminal = true; 4517 if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() || 4518 unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex)) 4519 badTerminal = true; 4520 } 4521 if (badTerminal) { 4522 error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", ""); 4523 return; 4524 } 4525 4526 // the body 4527 inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable); 4528 } 4529 4530 // Do limit checks for built-in arrays. 4531 void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size) 4532 { 4533 if (identifier.compare("gl_TexCoord") == 0) 4534 limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size"); 4535 else if (identifier.compare("gl_ClipDistance") == 0) 4536 limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size"); 4537 else if (identifier.compare("gl_CullDistance") == 0) 4538 limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistance array size"); 4539 #ifdef NV_EXTENSIONS 4540 else if (identifier.compare("gl_ClipDistancePerViewNV") == 0) 4541 limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistancePerViewNV array size"); 4542 else if (identifier.compare("gl_CullDistancePerViewNV") == 0) 4543 limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistancePerViewNV array size"); 4544 #endif 4545 } 4546 4547 // See if the provided value is less than or equal to the symbol indicated by limit, 4548 // which should be a constant in the symbol table. 4549 void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature) 4550 { 4551 TSymbol* symbol = symbolTable.find(limit); 4552 assert(symbol->getAsVariable()); 4553 const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray(); 4554 assert(! constArray.empty()); 4555 if (value > constArray[0].getIConst()) 4556 error(loc, "must be less than or equal to", feature, "%s (%d)", limit, constArray[0].getIConst()); 4557 } 4558 4559 // 4560 // Do any additional error checking, etc., once we know the parsing is done. 4561 // 4562 void TParseContext::finish() 4563 { 4564 TParseContextBase::finish(); 4565 4566 if (parsingBuiltins) 4567 return; 4568 4569 // Check on array indexes for ES 2.0 (version 100) limitations. 4570 for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i) 4571 constantIndexExpressionCheck(needsIndexLimitationChecking[i]); 4572 4573 // Check for stages that are enabled by extension. 4574 // Can't do this at the beginning, it is chicken and egg to add a stage by 4575 // extension. 4576 // Stage-specific features were correctly tested for already, this is just 4577 // about the stage itself. 4578 switch (language) { 4579 case EShLangGeometry: 4580 if (profile == EEsProfile && version == 310) 4581 requireExtensions(getCurrentLoc(), Num_AEP_geometry_shader, AEP_geometry_shader, "geometry shaders"); 4582 break; 4583 case EShLangTessControl: 4584 case EShLangTessEvaluation: 4585 if (profile == EEsProfile && version == 310) 4586 requireExtensions(getCurrentLoc(), Num_AEP_tessellation_shader, AEP_tessellation_shader, "tessellation shaders"); 4587 else if (profile != EEsProfile && version < 400) 4588 requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_tessellation_shader, "tessellation shaders"); 4589 break; 4590 case EShLangCompute: 4591 if (profile != EEsProfile && version < 430) 4592 requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_compute_shader, "compute shaders"); 4593 break; 4594 #ifdef NV_EXTENSIONS 4595 case EShLangTaskNV: 4596 requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "task shaders"); 4597 break; 4598 case EShLangMeshNV: 4599 requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "mesh shaders"); 4600 break; 4601 #endif 4602 default: 4603 break; 4604 } 4605 4606 #ifdef NV_EXTENSIONS 4607 // Set default outputs for GL_NV_geometry_shader_passthrough 4608 if (language == EShLangGeometry && extensionTurnedOn(E_SPV_NV_geometry_shader_passthrough)) { 4609 if (intermediate.getOutputPrimitive() == ElgNone) { 4610 switch (intermediate.getInputPrimitive()) { 4611 case ElgPoints: intermediate.setOutputPrimitive(ElgPoints); break; 4612 case ElgLines: intermediate.setOutputPrimitive(ElgLineStrip); break; 4613 case ElgTriangles: intermediate.setOutputPrimitive(ElgTriangleStrip); break; 4614 default: break; 4615 } 4616 } 4617 if (intermediate.getVertices() == TQualifier::layoutNotSet) { 4618 switch (intermediate.getInputPrimitive()) { 4619 case ElgPoints: intermediate.setVertices(1); break; 4620 case ElgLines: intermediate.setVertices(2); break; 4621 case ElgTriangles: intermediate.setVertices(3); break; 4622 default: break; 4623 } 4624 } 4625 } 4626 #endif 4627 } 4628 4629 // 4630 // Layout qualifier stuff. 4631 // 4632 4633 // Put the id's layout qualification into the public type, for qualifiers not having a number set. 4634 // This is before we know any type information for error checking. 4635 void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id) 4636 { 4637 std::transform(id.begin(), id.end(), id.begin(), ::tolower); 4638 4639 if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) { 4640 publicType.qualifier.layoutMatrix = ElmColumnMajor; 4641 return; 4642 } 4643 if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) { 4644 publicType.qualifier.layoutMatrix = ElmRowMajor; 4645 return; 4646 } 4647 if (id == TQualifier::getLayoutPackingString(ElpPacked)) { 4648 if (spvVersion.spv != 0) 4649 spvRemoved(loc, "packed"); 4650 publicType.qualifier.layoutPacking = ElpPacked; 4651 return; 4652 } 4653 if (id == TQualifier::getLayoutPackingString(ElpShared)) { 4654 if (spvVersion.spv != 0) 4655 spvRemoved(loc, "shared"); 4656 publicType.qualifier.layoutPacking = ElpShared; 4657 return; 4658 } 4659 if (id == TQualifier::getLayoutPackingString(ElpStd140)) { 4660 publicType.qualifier.layoutPacking = ElpStd140; 4661 return; 4662 } 4663 if (id == TQualifier::getLayoutPackingString(ElpStd430)) { 4664 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430"); 4665 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430"); 4666 profileRequires(loc, EEsProfile, 310, nullptr, "std430"); 4667 publicType.qualifier.layoutPacking = ElpStd430; 4668 return; 4669 } 4670 if (id == TQualifier::getLayoutPackingString(ElpScalar)) { 4671 requireVulkan(loc, "scalar"); 4672 requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "scalar block layout"); 4673 publicType.qualifier.layoutPacking = ElpScalar; 4674 return; 4675 } 4676 // TODO: compile-time performance: may need to stop doing linear searches 4677 for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) { 4678 if (id == TQualifier::getLayoutFormatString(format)) { 4679 if ((format > ElfEsFloatGuard && format < ElfFloatGuard) || 4680 (format > ElfEsIntGuard && format < ElfIntGuard) || 4681 (format > ElfEsUintGuard && format < ElfCount)) 4682 requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format"); 4683 profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "image load store"); 4684 profileRequires(loc, EEsProfile, 310, E_GL_ARB_shader_image_load_store, "image load store"); 4685 publicType.qualifier.layoutFormat = format; 4686 return; 4687 } 4688 } 4689 if (id == "push_constant") { 4690 requireVulkan(loc, "push_constant"); 4691 publicType.qualifier.layoutPushConstant = true; 4692 return; 4693 } 4694 if (id == "buffer_reference") { 4695 requireVulkan(loc, "buffer_reference"); 4696 requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference"); 4697 publicType.qualifier.layoutBufferReference = true; 4698 intermediate.setUseStorageBuffer(); 4699 intermediate.setUsePhysicalStorageBuffer(); 4700 return; 4701 } 4702 if (language == EShLangGeometry || language == EShLangTessEvaluation 4703 #ifdef NV_EXTENSIONS 4704 || language == EShLangMeshNV 4705 #endif 4706 ) { 4707 if (id == TQualifier::getGeometryString(ElgTriangles)) { 4708 publicType.shaderQualifiers.geometry = ElgTriangles; 4709 return; 4710 } 4711 if (language == EShLangGeometry 4712 #ifdef NV_EXTENSIONS 4713 || language == EShLangMeshNV 4714 #endif 4715 ) { 4716 if (id == TQualifier::getGeometryString(ElgPoints)) { 4717 publicType.shaderQualifiers.geometry = ElgPoints; 4718 return; 4719 } 4720 if (id == TQualifier::getGeometryString(ElgLines)) { 4721 publicType.shaderQualifiers.geometry = ElgLines; 4722 return; 4723 } 4724 #ifdef NV_EXTENSIONS 4725 if (language == EShLangGeometry) 4726 #endif 4727 { 4728 if (id == TQualifier::getGeometryString(ElgLineStrip)) { 4729 publicType.shaderQualifiers.geometry = ElgLineStrip; 4730 return; 4731 } 4732 if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { 4733 publicType.shaderQualifiers.geometry = ElgLinesAdjacency; 4734 return; 4735 } 4736 if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { 4737 publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency; 4738 return; 4739 } 4740 if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { 4741 publicType.shaderQualifiers.geometry = ElgTriangleStrip; 4742 return; 4743 } 4744 #ifdef NV_EXTENSIONS 4745 if (id == "passthrough") { 4746 requireExtensions(loc, 1, &E_SPV_NV_geometry_shader_passthrough, "geometry shader passthrough"); 4747 publicType.qualifier.layoutPassthrough = true; 4748 intermediate.setGeoPassthroughEXT(); 4749 return; 4750 } 4751 #endif 4752 } 4753 } else { 4754 assert(language == EShLangTessEvaluation); 4755 4756 // input primitive 4757 if (id == TQualifier::getGeometryString(ElgTriangles)) { 4758 publicType.shaderQualifiers.geometry = ElgTriangles; 4759 return; 4760 } 4761 if (id == TQualifier::getGeometryString(ElgQuads)) { 4762 publicType.shaderQualifiers.geometry = ElgQuads; 4763 return; 4764 } 4765 if (id == TQualifier::getGeometryString(ElgIsolines)) { 4766 publicType.shaderQualifiers.geometry = ElgIsolines; 4767 return; 4768 } 4769 4770 // vertex spacing 4771 if (id == TQualifier::getVertexSpacingString(EvsEqual)) { 4772 publicType.shaderQualifiers.spacing = EvsEqual; 4773 return; 4774 } 4775 if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) { 4776 publicType.shaderQualifiers.spacing = EvsFractionalEven; 4777 return; 4778 } 4779 if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) { 4780 publicType.shaderQualifiers.spacing = EvsFractionalOdd; 4781 return; 4782 } 4783 4784 // triangle order 4785 if (id == TQualifier::getVertexOrderString(EvoCw)) { 4786 publicType.shaderQualifiers.order = EvoCw; 4787 return; 4788 } 4789 if (id == TQualifier::getVertexOrderString(EvoCcw)) { 4790 publicType.shaderQualifiers.order = EvoCcw; 4791 return; 4792 } 4793 4794 // point mode 4795 if (id == "point_mode") { 4796 publicType.shaderQualifiers.pointMode = true; 4797 return; 4798 } 4799 } 4800 } 4801 if (language == EShLangFragment) { 4802 if (id == "origin_upper_left") { 4803 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left"); 4804 publicType.shaderQualifiers.originUpperLeft = true; 4805 return; 4806 } 4807 if (id == "pixel_center_integer") { 4808 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer"); 4809 publicType.shaderQualifiers.pixelCenterInteger = true; 4810 return; 4811 } 4812 if (id == "early_fragment_tests") { 4813 profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "early_fragment_tests"); 4814 profileRequires(loc, EEsProfile, 310, nullptr, "early_fragment_tests"); 4815 publicType.shaderQualifiers.earlyFragmentTests = true; 4816 return; 4817 } 4818 if (id == "post_depth_coverage") { 4819 requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage"); 4820 if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) { 4821 publicType.shaderQualifiers.earlyFragmentTests = true; 4822 } 4823 publicType.shaderQualifiers.postDepthCoverage = true; 4824 return; 4825 } 4826 for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) { 4827 if (id == TQualifier::getLayoutDepthString(depth)) { 4828 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier"); 4829 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "depth layout qualifier"); 4830 publicType.shaderQualifiers.layoutDepth = depth; 4831 return; 4832 } 4833 } 4834 if (id.compare(0, 13, "blend_support") == 0) { 4835 bool found = false; 4836 for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { 4837 if (id == TQualifier::getBlendEquationString(be)) { 4838 profileRequires(loc, EEsProfile, 320, E_GL_KHR_blend_equation_advanced, "blend equation"); 4839 profileRequires(loc, ~EEsProfile, 0, E_GL_KHR_blend_equation_advanced, "blend equation"); 4840 intermediate.addBlendEquation(be); 4841 publicType.shaderQualifiers.blendEquation = true; 4842 found = true; 4843 break; 4844 } 4845 } 4846 if (! found) 4847 error(loc, "unknown blend equation", "blend_support", ""); 4848 return; 4849 } 4850 #ifdef NV_EXTENSIONS 4851 if (id == "override_coverage") { 4852 requireExtensions(loc, 1, &E_GL_NV_sample_mask_override_coverage, "sample mask override coverage"); 4853 publicType.shaderQualifiers.layoutOverrideCoverage = true; 4854 return; 4855 } 4856 } 4857 if (language == EShLangVertex || 4858 language == EShLangTessControl || 4859 language == EShLangTessEvaluation || 4860 language == EShLangGeometry ) { 4861 if (id == "viewport_relative") { 4862 requireExtensions(loc, 1, &E_GL_NV_viewport_array2, "view port array2"); 4863 publicType.qualifier.layoutViewportRelative = true; 4864 return; 4865 } 4866 } else { 4867 if (language == EShLangRayGenNV || language == EShLangIntersectNV || 4868 language == EShLangAnyHitNV || language == EShLangClosestHitNV || 4869 language == EShLangMissNV || language == EShLangCallableNV) { 4870 if (id == "shaderrecordnv") { 4871 publicType.qualifier.layoutShaderRecordNV = true; 4872 return; 4873 } 4874 } 4875 } 4876 if (language == EShLangCompute) { 4877 if (id.compare(0, 17, "derivative_group_") == 0) { 4878 requireExtensions(loc, 1, &E_GL_NV_compute_shader_derivatives, "compute shader derivatives"); 4879 if (id == "derivative_group_quadsnv") { 4880 publicType.shaderQualifiers.layoutDerivativeGroupQuads = true; 4881 return; 4882 } else if (id == "derivative_group_linearnv") { 4883 publicType.shaderQualifiers.layoutDerivativeGroupLinear = true; 4884 return; 4885 } 4886 } 4887 } 4888 #else 4889 } 4890 #endif 4891 error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); 4892 } 4893 4894 // Put the id's layout qualifier value into the public type, for qualifiers having a number set. 4895 // This is before we know any type information for error checking. 4896 void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id, const TIntermTyped* node) 4897 { 4898 const char* feature = "layout-id value"; 4899 const char* nonLiteralFeature = "non-literal layout-id value"; 4900 4901 integerCheck(node, feature); 4902 const TIntermConstantUnion* constUnion = node->getAsConstantUnion(); 4903 int value; 4904 if (constUnion) { 4905 value = constUnion->getConstArray()[0].getIConst(); 4906 if (! constUnion->isLiteral()) { 4907 requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature); 4908 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, nonLiteralFeature); 4909 } 4910 } else { 4911 // grammar should have give out the error message 4912 value = 0; 4913 } 4914 4915 if (value < 0) { 4916 error(loc, "cannot be negative", feature, ""); 4917 return; 4918 } 4919 4920 std::transform(id.begin(), id.end(), id.begin(), ::tolower); 4921 4922 if (id == "offset") { 4923 // "offset" can be for either 4924 // - uniform offsets 4925 // - atomic_uint offsets 4926 const char* feature = "offset"; 4927 if (spvVersion.spv == 0) { 4928 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); 4929 const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters }; 4930 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature); 4931 profileRequires(loc, EEsProfile, 310, nullptr, feature); 4932 } 4933 publicType.qualifier.layoutOffset = value; 4934 return; 4935 } else if (id == "align") { 4936 const char* feature = "uniform buffer-member align"; 4937 if (spvVersion.spv == 0) { 4938 requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); 4939 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); 4940 } 4941 // "The specified alignment must be a power of 2, or a compile-time error results." 4942 if (! IsPow2(value)) 4943 error(loc, "must be a power of 2", "align", ""); 4944 else 4945 publicType.qualifier.layoutAlign = value; 4946 return; 4947 } else if (id == "location") { 4948 profileRequires(loc, EEsProfile, 300, nullptr, "location"); 4949 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 4950 profileRequires(loc, ~EEsProfile, 330, 2, exts, "location"); 4951 if ((unsigned int)value >= TQualifier::layoutLocationEnd) 4952 error(loc, "location is too large", id.c_str(), ""); 4953 else 4954 publicType.qualifier.layoutLocation = value; 4955 return; 4956 } else if (id == "set") { 4957 if ((unsigned int)value >= TQualifier::layoutSetEnd) 4958 error(loc, "set is too large", id.c_str(), ""); 4959 else 4960 publicType.qualifier.layoutSet = value; 4961 if (value != 0) 4962 requireVulkan(loc, "descriptor set"); 4963 return; 4964 } else if (id == "binding") { 4965 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding"); 4966 profileRequires(loc, EEsProfile, 310, nullptr, "binding"); 4967 if ((unsigned int)value >= TQualifier::layoutBindingEnd) 4968 error(loc, "binding is too large", id.c_str(), ""); 4969 else 4970 publicType.qualifier.layoutBinding = value; 4971 return; 4972 } else if (id == "component") { 4973 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component"); 4974 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "component"); 4975 if ((unsigned)value >= TQualifier::layoutComponentEnd) 4976 error(loc, "component is too large", id.c_str(), ""); 4977 else 4978 publicType.qualifier.layoutComponent = value; 4979 return; 4980 } else if (id.compare(0, 4, "xfb_") == 0) { 4981 // "Any shader making any static use (after preprocessing) of any of these 4982 // *xfb_* qualifiers will cause the shader to be in a transform feedback 4983 // capturing mode and hence responsible for describing the transform feedback 4984 // setup." 4985 intermediate.setXfbMode(); 4986 const char* feature = "transform feedback qualifier"; 4987 requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature); 4988 requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); 4989 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); 4990 if (id == "xfb_buffer") { 4991 // "It is a compile-time error to specify an *xfb_buffer* that is greater than 4992 // the implementation-dependent constant gl_MaxTransformFeedbackBuffers." 4993 if (value >= resources.maxTransformFeedbackBuffers) 4994 error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", resources.maxTransformFeedbackBuffers); 4995 if (value >= (int)TQualifier::layoutXfbBufferEnd) 4996 error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd-1); 4997 else 4998 publicType.qualifier.layoutXfbBuffer = value; 4999 return; 5000 } else if (id == "xfb_offset") { 5001 if (value >= (int)TQualifier::layoutXfbOffsetEnd) 5002 error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd-1); 5003 else 5004 publicType.qualifier.layoutXfbOffset = value; 5005 return; 5006 } else if (id == "xfb_stride") { 5007 // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the 5008 // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." 5009 if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) { 5010 error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d", 5011 resources.maxTransformFeedbackInterleavedComponents); 5012 } 5013 if (value >= (int)TQualifier::layoutXfbStrideEnd) 5014 error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd-1); 5015 else 5016 publicType.qualifier.layoutXfbStride = value; 5017 return; 5018 } 5019 } 5020 5021 if (id == "input_attachment_index") { 5022 requireVulkan(loc, "input_attachment_index"); 5023 if (value >= (int)TQualifier::layoutAttachmentEnd) 5024 error(loc, "attachment index is too large", id.c_str(), ""); 5025 else 5026 publicType.qualifier.layoutAttachment = value; 5027 return; 5028 } 5029 if (id == "constant_id") { 5030 requireSpv(loc, "constant_id"); 5031 if (value >= (int)TQualifier::layoutSpecConstantIdEnd) { 5032 error(loc, "specialization-constant id is too large", id.c_str(), ""); 5033 } else { 5034 publicType.qualifier.layoutSpecConstantId = value; 5035 publicType.qualifier.specConstant = true; 5036 if (! intermediate.addUsedConstantId(value)) 5037 error(loc, "specialization-constant id already used", id.c_str(), ""); 5038 } 5039 return; 5040 } 5041 if (id == "num_views") { 5042 requireExtensions(loc, Num_OVR_multiview_EXTs, OVR_multiview_EXTs, "num_views"); 5043 publicType.shaderQualifiers.numViews = value; 5044 return; 5045 } 5046 5047 #if NV_EXTENSIONS 5048 if (language == EShLangVertex || 5049 language == EShLangTessControl || 5050 language == EShLangTessEvaluation || 5051 language == EShLangGeometry) { 5052 if (id == "secondary_view_offset") { 5053 requireExtensions(loc, 1, &E_GL_NV_stereo_view_rendering, "stereo view rendering"); 5054 publicType.qualifier.layoutSecondaryViewportRelativeOffset = value; 5055 return; 5056 } 5057 } 5058 #endif 5059 5060 if (id == "buffer_reference_align") { 5061 requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference_align"); 5062 if (! IsPow2(value)) 5063 error(loc, "must be a power of 2", "buffer_reference_align", ""); 5064 else 5065 publicType.qualifier.layoutBufferReferenceAlign = std::log2(value); 5066 return; 5067 } 5068 5069 switch (language) { 5070 case EShLangVertex: 5071 break; 5072 5073 case EShLangTessControl: 5074 if (id == "vertices") { 5075 if (value == 0) 5076 error(loc, "must be greater than 0", "vertices", ""); 5077 else 5078 publicType.shaderQualifiers.vertices = value; 5079 return; 5080 } 5081 break; 5082 5083 case EShLangTessEvaluation: 5084 break; 5085 5086 case EShLangGeometry: 5087 if (id == "invocations") { 5088 profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, nullptr, "invocations"); 5089 if (value == 0) 5090 error(loc, "must be at least 1", "invocations", ""); 5091 else 5092 publicType.shaderQualifiers.invocations = value; 5093 return; 5094 } 5095 if (id == "max_vertices") { 5096 publicType.shaderQualifiers.vertices = value; 5097 if (value > resources.maxGeometryOutputVertices) 5098 error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", ""); 5099 return; 5100 } 5101 if (id == "stream") { 5102 requireProfile(loc, ~EEsProfile, "selecting output stream"); 5103 publicType.qualifier.layoutStream = value; 5104 if (value > 0) 5105 intermediate.setMultiStream(); 5106 return; 5107 } 5108 break; 5109 5110 case EShLangFragment: 5111 if (id == "index") { 5112 requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output"); 5113 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 5114 profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output"); 5115 5116 // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1." 5117 if (value < 0 || value > 1) { 5118 value = 0; 5119 error(loc, "value must be 0 or 1", "index", ""); 5120 } 5121 5122 publicType.qualifier.layoutIndex = value; 5123 return; 5124 } 5125 break; 5126 5127 #ifdef NV_EXTENSIONS 5128 case EShLangMeshNV: 5129 if (id == "max_vertices") { 5130 requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "max_vertices"); 5131 publicType.shaderQualifiers.vertices = value; 5132 if (value > resources.maxMeshOutputVerticesNV) 5133 error(loc, "too large, must be less than gl_MaxMeshOutputVerticesNV", "max_vertices", ""); 5134 return; 5135 } 5136 if (id == "max_primitives") { 5137 requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "max_primitives"); 5138 publicType.shaderQualifiers.primitives = value; 5139 if (value > resources.maxMeshOutputPrimitivesNV) 5140 error(loc, "too large, must be less than gl_MaxMeshOutputPrimitivesNV", "max_primitives", ""); 5141 return; 5142 } 5143 // Fall through 5144 5145 case EShLangTaskNV: 5146 // Fall through 5147 #endif 5148 case EShLangCompute: 5149 if (id.compare(0, 11, "local_size_") == 0) { 5150 #ifdef NV_EXTENSIONS 5151 if (language == EShLangMeshNV || language == EShLangTaskNV) { 5152 requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "gl_WorkGroupSize"); 5153 } 5154 else 5155 #endif 5156 { 5157 profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize"); 5158 profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize"); 5159 } 5160 if (id.size() == 12 && value == 0) { 5161 error(loc, "must be at least 1", id.c_str(), ""); 5162 return; 5163 } 5164 if (id == "local_size_x") { 5165 publicType.shaderQualifiers.localSize[0] = value; 5166 return; 5167 } 5168 if (id == "local_size_y") { 5169 publicType.shaderQualifiers.localSize[1] = value; 5170 return; 5171 } 5172 if (id == "local_size_z") { 5173 publicType.shaderQualifiers.localSize[2] = value; 5174 return; 5175 } 5176 if (spvVersion.spv != 0) { 5177 if (id == "local_size_x_id") { 5178 publicType.shaderQualifiers.localSizeSpecId[0] = value; 5179 return; 5180 } 5181 if (id == "local_size_y_id") { 5182 publicType.shaderQualifiers.localSizeSpecId[1] = value; 5183 return; 5184 } 5185 if (id == "local_size_z_id") { 5186 publicType.shaderQualifiers.localSizeSpecId[2] = value; 5187 return; 5188 } 5189 } 5190 } 5191 break; 5192 5193 default: 5194 break; 5195 } 5196 5197 error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); 5198 } 5199 5200 // Merge any layout qualifier information from src into dst, leaving everything else in dst alone 5201 // 5202 // "More than one layout qualifier may appear in a single declaration. 5203 // Additionally, the same layout-qualifier-name can occur multiple times 5204 // within a layout qualifier or across multiple layout qualifiers in the 5205 // same declaration. When the same layout-qualifier-name occurs 5206 // multiple times, in a single declaration, the last occurrence overrides 5207 // the former occurrence(s). Further, if such a layout-qualifier-name 5208 // will effect subsequent declarations or other observable behavior, it 5209 // is only the last occurrence that will have any effect, behaving as if 5210 // the earlier occurrence(s) within the declaration are not present. 5211 // This is also true for overriding layout-qualifier-names, where one 5212 // overrides the other (e.g., row_major vs. column_major); only the last 5213 // occurrence has any effect." 5214 void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly) 5215 { 5216 if (src.hasMatrix()) 5217 dst.layoutMatrix = src.layoutMatrix; 5218 if (src.hasPacking()) 5219 dst.layoutPacking = src.layoutPacking; 5220 5221 if (src.hasStream()) 5222 dst.layoutStream = src.layoutStream; 5223 5224 if (src.hasFormat()) 5225 dst.layoutFormat = src.layoutFormat; 5226 5227 if (src.hasXfbBuffer()) 5228 dst.layoutXfbBuffer = src.layoutXfbBuffer; 5229 5230 if (src.hasAlign()) 5231 dst.layoutAlign = src.layoutAlign; 5232 5233 if (src.hasBufferReferenceAlign()) 5234 dst.layoutBufferReferenceAlign = src.layoutBufferReferenceAlign; 5235 5236 if (! inheritOnly) { 5237 if (src.hasLocation()) 5238 dst.layoutLocation = src.layoutLocation; 5239 if (src.hasComponent()) 5240 dst.layoutComponent = src.layoutComponent; 5241 if (src.hasIndex()) 5242 dst.layoutIndex = src.layoutIndex; 5243 5244 if (src.hasOffset()) 5245 dst.layoutOffset = src.layoutOffset; 5246 5247 if (src.hasSet()) 5248 dst.layoutSet = src.layoutSet; 5249 if (src.layoutBinding != TQualifier::layoutBindingEnd) 5250 dst.layoutBinding = src.layoutBinding; 5251 5252 if (src.hasXfbStride()) 5253 dst.layoutXfbStride = src.layoutXfbStride; 5254 if (src.hasXfbOffset()) 5255 dst.layoutXfbOffset = src.layoutXfbOffset; 5256 if (src.hasAttachment()) 5257 dst.layoutAttachment = src.layoutAttachment; 5258 if (src.hasSpecConstantId()) 5259 dst.layoutSpecConstantId = src.layoutSpecConstantId; 5260 5261 if (src.layoutPushConstant) 5262 dst.layoutPushConstant = true; 5263 5264 if (src.layoutBufferReference) 5265 dst.layoutBufferReference = true; 5266 5267 #ifdef NV_EXTENSIONS 5268 if (src.layoutPassthrough) 5269 dst.layoutPassthrough = true; 5270 if (src.layoutViewportRelative) 5271 dst.layoutViewportRelative = true; 5272 if (src.layoutSecondaryViewportRelativeOffset != -2048) 5273 dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; 5274 if (src.layoutShaderRecordNV) 5275 dst.layoutShaderRecordNV = true; 5276 if (src.pervertexNV) 5277 dst.pervertexNV = true; 5278 #endif 5279 } 5280 } 5281 5282 // Do error layout error checking given a full variable/block declaration. 5283 void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symbol) 5284 { 5285 const TType& type = symbol.getType(); 5286 const TQualifier& qualifier = type.getQualifier(); 5287 5288 // first, cross check WRT to just the type 5289 layoutTypeCheck(loc, type); 5290 5291 // now, any remaining error checking based on the object itself 5292 5293 if (qualifier.hasAnyLocation()) { 5294 switch (qualifier.storage) { 5295 case EvqUniform: 5296 case EvqBuffer: 5297 if (symbol.getAsVariable() == nullptr) 5298 error(loc, "can only be used on variable declaration", "location", ""); 5299 break; 5300 default: 5301 break; 5302 } 5303 } 5304 5305 // user-variable location check, which are required for SPIR-V in/out: 5306 // - variables have it directly, 5307 // - blocks have it on each member (already enforced), so check first one 5308 if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone && 5309 !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) { 5310 5311 switch (qualifier.storage) { 5312 case EvqVaryingIn: 5313 case EvqVaryingOut: 5314 if (!type.getQualifier().isTaskMemory() && 5315 (type.getBasicType() != EbtBlock || 5316 (!(*type.getStruct())[0].type->getQualifier().hasLocation() && 5317 (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))) 5318 error(loc, "SPIR-V requires location for user input/output", "location", ""); 5319 break; 5320 default: 5321 break; 5322 } 5323 } 5324 5325 // Check packing and matrix 5326 if (qualifier.hasUniformLayout()) { 5327 switch (qualifier.storage) { 5328 case EvqUniform: 5329 case EvqBuffer: 5330 if (type.getBasicType() != EbtBlock) { 5331 if (qualifier.hasMatrix()) 5332 error(loc, "cannot specify matrix layout on a variable declaration", "layout", ""); 5333 if (qualifier.hasPacking()) 5334 error(loc, "cannot specify packing on a variable declaration", "layout", ""); 5335 // "The offset qualifier can only be used on block members of blocks..." 5336 if (qualifier.hasOffset() && type.getBasicType() != EbtAtomicUint) 5337 error(loc, "cannot specify on a variable declaration", "offset", ""); 5338 // "The align qualifier can only be used on blocks or block members..." 5339 if (qualifier.hasAlign()) 5340 error(loc, "cannot specify on a variable declaration", "align", ""); 5341 if (qualifier.layoutPushConstant) 5342 error(loc, "can only specify on a uniform block", "push_constant", ""); 5343 #ifdef NV_EXTENSIONS 5344 if (qualifier.layoutShaderRecordNV) 5345 error(loc, "can only specify on a buffer block", "shaderRecordNV", ""); 5346 #endif 5347 } 5348 break; 5349 default: 5350 // these were already filtered by layoutTypeCheck() (or its callees) 5351 break; 5352 } 5353 } 5354 } 5355 5356 // "For some blocks declared as arrays, the location can only be applied at the block level: 5357 // When a block is declared as an array where additional locations are needed for each member 5358 // for each block array element, it is a compile-time error to specify locations on the block 5359 // members. That is, when locations would be under specified by applying them on block members, 5360 // they are not allowed on block members. For arrayed interfaces (those generally having an 5361 // extra level of arrayness due to interface expansion), the outer array is stripped before 5362 // applying this rule." 5363 void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation, 5364 TArraySizes* arraySizes) 5365 { 5366 if (memberWithLocation && arraySizes != nullptr) { 5367 if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0)) 5368 error(loc, "cannot use in a block array where new locations are needed for each block element", 5369 "location", ""); 5370 } 5371 } 5372 5373 // Do layout error checking with respect to a type. 5374 void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) 5375 { 5376 const TQualifier& qualifier = type.getQualifier(); 5377 5378 // first, intra-layout qualifier-only error checking 5379 layoutQualifierCheck(loc, qualifier); 5380 5381 // now, error checking combining type and qualifier 5382 5383 if (qualifier.hasAnyLocation()) { 5384 if (qualifier.hasLocation()) { 5385 if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) { 5386 if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers) 5387 error(loc, "too large for fragment output", "location", ""); 5388 } 5389 } 5390 if (qualifier.hasComponent()) { 5391 // "It is a compile-time error if this sequence of components gets larger than 3." 5392 if (qualifier.layoutComponent + type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1) > 4) 5393 error(loc, "type overflows the available 4 components", "component", ""); 5394 5395 // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these." 5396 if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct) 5397 error(loc, "cannot apply to a matrix, structure, or block", "component", ""); 5398 5399 // " It is a compile-time error to use component 1 or 3 as the beginning of a double or dvec2." 5400 if (type.getBasicType() == EbtDouble) 5401 if (qualifier.layoutComponent & 1) 5402 error(loc, "doubles cannot start on an odd-numbered component", "component", ""); 5403 } 5404 5405 switch (qualifier.storage) { 5406 case EvqVaryingIn: 5407 case EvqVaryingOut: 5408 if (type.getBasicType() == EbtBlock) 5409 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "location qualifier on in/out block"); 5410 #ifdef NV_EXTENSIONS 5411 if (type.getQualifier().isTaskMemory()) 5412 error(loc, "cannot apply to taskNV in/out blocks", "location", ""); 5413 #endif 5414 break; 5415 case EvqUniform: 5416 case EvqBuffer: 5417 if (type.getBasicType() == EbtBlock) 5418 error(loc, "cannot apply to uniform or buffer block", "location", ""); 5419 break; 5420 #ifdef NV_EXTENSIONS 5421 case EvqPayloadNV: 5422 case EvqPayloadInNV: 5423 case EvqHitAttrNV: 5424 case EvqCallableDataNV: 5425 case EvqCallableDataInNV: 5426 break; 5427 #endif 5428 default: 5429 error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", ""); 5430 break; 5431 } 5432 5433 bool typeCollision; 5434 int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision); 5435 if (repeated >= 0 && ! typeCollision) 5436 error(loc, "overlapping use of location", "location", "%d", repeated); 5437 // "fragment-shader outputs ... if two variables are placed within the same 5438 // location, they must have the same underlying type (floating-point or integer)" 5439 if (typeCollision && language == EShLangFragment && qualifier.isPipeOutput()) 5440 error(loc, "fragment outputs sharing the same location must be the same basic type", "location", "%d", repeated); 5441 } 5442 5443 if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) { 5444 int repeated = intermediate.addXfbBufferOffset(type); 5445 if (repeated >= 0) 5446 error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer); 5447 5448 // "The offset must be a multiple of the size of the first component of the first 5449 // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate 5450 // containing a double, the offset must also be a multiple of 8..." 5451 if (type.containsBasicType(EbtDouble) && ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 8)) 5452 error(loc, "type contains double; xfb_offset must be a multiple of 8", "xfb_offset", ""); 5453 // ..., if applied to an aggregate containing a float16_t, the offset must also be a multiple of 2..." 5454 else if (type.containsBasicType(EbtFloat16) && !IsMultipleOfPow2(qualifier.layoutXfbOffset, 2)) 5455 error(loc, "type contains half float; xfb_offset must be a multiple of 2", "xfb_offset", ""); 5456 else if (! IsMultipleOfPow2(qualifier.layoutXfbOffset, 4)) 5457 error(loc, "must be a multiple of size of first component", "xfb_offset", ""); 5458 } 5459 5460 if (qualifier.hasXfbStride() && qualifier.hasXfbBuffer()) { 5461 if (! intermediate.setXfbBufferStride(qualifier.layoutXfbBuffer, qualifier.layoutXfbStride)) 5462 error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); 5463 } 5464 5465 if (qualifier.hasBinding()) { 5466 // Binding checking, from the spec: 5467 // 5468 // "If the binding point for any uniform or shader storage block instance is less than zero, or greater than or 5469 // equal to the implementation-dependent maximum number of uniform buffer bindings, a compile-time 5470 // error will occur. When the binding identifier is used with a uniform or shader storage block instanced as 5471 // an array of size N, all elements of the array from binding through binding + N - 1 must be within this 5472 // range." 5473 // 5474 if (! type.isOpaque() && type.getBasicType() != EbtBlock) 5475 error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", ""); 5476 if (type.getBasicType() == EbtSampler) { 5477 int lastBinding = qualifier.layoutBinding; 5478 if (type.isArray()) { 5479 if (spvVersion.vulkan > 0) 5480 lastBinding += 1; 5481 else { 5482 if (type.isSizedArray()) 5483 lastBinding += type.getCumulativeArraySize(); 5484 else { 5485 lastBinding += 1; 5486 if (spvVersion.vulkan == 0) 5487 warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", ""); 5488 } 5489 } 5490 } 5491 if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits) 5492 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : ""); 5493 } 5494 if (type.getBasicType() == EbtAtomicUint) { 5495 if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { 5496 error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", ""); 5497 return; 5498 } 5499 } 5500 } else if (!intermediate.getAutoMapBindings()) { 5501 // some types require bindings 5502 5503 // atomic_uint 5504 if (type.getBasicType() == EbtAtomicUint) 5505 error(loc, "layout(binding=X) is required", "atomic_uint", ""); 5506 5507 // SPIR-V 5508 if (spvVersion.spv > 0) { 5509 if (qualifier.isUniformOrBuffer()) { 5510 if (type.getBasicType() == EbtBlock && !qualifier.layoutPushConstant && 5511 #ifdef NV_EXTENSIONS 5512 !qualifier.layoutShaderRecordNV && 5513 #endif 5514 !qualifier.layoutAttachment && 5515 !qualifier.layoutBufferReference) 5516 error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", ""); 5517 else if (spvVersion.vulkan > 0 && type.getBasicType() == EbtSampler) 5518 error(loc, "sampler/texture/image requires layout(binding=X)", "binding", ""); 5519 } 5520 } 5521 } 5522 5523 // some things can't have arrays of arrays 5524 if (type.isArrayOfArrays()) { 5525 if (spvVersion.vulkan > 0) { 5526 if (type.isOpaque() || (type.getQualifier().isUniformOrBuffer() && type.getBasicType() == EbtBlock)) 5527 warn(loc, "Generating SPIR-V array-of-arrays, but Vulkan only supports single array level for this resource", "[][]", ""); 5528 } 5529 } 5530 5531 // "The offset qualifier can only be used on block members of blocks..." 5532 if (qualifier.hasOffset()) { 5533 if (type.getBasicType() == EbtBlock) 5534 error(loc, "only applies to block members, not blocks", "offset", ""); 5535 } 5536 5537 // Image format 5538 if (qualifier.hasFormat()) { 5539 if (! type.isImage()) 5540 error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 5541 else { 5542 if (type.getSampler().type == EbtFloat && qualifier.layoutFormat > ElfFloatGuard) 5543 error(loc, "does not apply to floating point images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 5544 if (type.getSampler().type == EbtInt && (qualifier.layoutFormat < ElfFloatGuard || qualifier.layoutFormat > ElfIntGuard)) 5545 error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 5546 if (type.getSampler().type == EbtUint && qualifier.layoutFormat < ElfIntGuard) 5547 error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 5548 5549 if (profile == EEsProfile) { 5550 // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must 5551 // specify either memory qualifier readonly or the memory qualifier writeonly." 5552 if (! (qualifier.layoutFormat == ElfR32f || qualifier.layoutFormat == ElfR32i || qualifier.layoutFormat == ElfR32ui)) { 5553 if (! qualifier.readonly && ! qualifier.writeonly) 5554 error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 5555 } 5556 } 5557 } 5558 } else if (type.isImage() && ! qualifier.writeonly) { 5559 const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier"; 5560 requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation); 5561 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation); 5562 } 5563 5564 if (qualifier.layoutPushConstant && type.getBasicType() != EbtBlock) 5565 error(loc, "can only be used with a block", "push_constant", ""); 5566 5567 if (qualifier.layoutBufferReference && type.getBasicType() != EbtBlock) 5568 error(loc, "can only be used with a block", "buffer_reference", ""); 5569 5570 #ifdef NV_EXTENSIONS 5571 if (qualifier.layoutShaderRecordNV && type.getBasicType() != EbtBlock) 5572 error(loc, "can only be used with a block", "shaderRecordNV", ""); 5573 #endif 5574 5575 // input attachment 5576 if (type.isSubpass()) { 5577 if (! qualifier.hasAttachment()) 5578 error(loc, "requires an input_attachment_index layout qualifier", "subpass", ""); 5579 } else { 5580 if (qualifier.hasAttachment()) 5581 error(loc, "can only be used with a subpass", "input_attachment_index", ""); 5582 } 5583 5584 // specialization-constant id 5585 if (qualifier.hasSpecConstantId()) { 5586 if (type.getQualifier().storage != EvqConst) 5587 error(loc, "can only be applied to 'const'-qualified scalar", "constant_id", ""); 5588 if (! type.isScalar()) 5589 error(loc, "can only be applied to a scalar", "constant_id", ""); 5590 switch (type.getBasicType()) 5591 { 5592 case EbtInt8: 5593 case EbtUint8: 5594 case EbtInt16: 5595 case EbtUint16: 5596 case EbtInt: 5597 case EbtUint: 5598 case EbtInt64: 5599 case EbtUint64: 5600 case EbtBool: 5601 case EbtFloat: 5602 case EbtDouble: 5603 case EbtFloat16: 5604 break; 5605 default: 5606 error(loc, "cannot be applied to this type", "constant_id", ""); 5607 break; 5608 } 5609 } 5610 } 5611 5612 // Do layout error checking that can be done within a layout qualifier proper, not needing to know 5613 // if there are blocks, atomic counters, variables, etc. 5614 void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier) 5615 { 5616 if (qualifier.storage == EvqShared && qualifier.hasLayout()) 5617 error(loc, "cannot apply layout qualifiers to a shared variable", "shared", ""); 5618 5619 // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)." 5620 if (qualifier.hasComponent() && ! qualifier.hasLocation()) 5621 error(loc, "must specify 'location' to use 'component'", "component", ""); 5622 5623 if (qualifier.hasAnyLocation()) { 5624 5625 // "As with input layout qualifiers, all shaders except compute shaders 5626 // allow *location* layout qualifiers on output variable declarations, 5627 // output block declarations, and output block member declarations." 5628 5629 switch (qualifier.storage) { 5630 case EvqVaryingIn: 5631 { 5632 const char* feature = "location qualifier on input"; 5633 if (profile == EEsProfile && version < 310) 5634 requireStage(loc, EShLangVertex, feature); 5635 else 5636 requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); 5637 if (language == EShLangVertex) { 5638 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 5639 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); 5640 profileRequires(loc, EEsProfile, 300, nullptr, feature); 5641 } else { 5642 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); 5643 profileRequires(loc, EEsProfile, 310, nullptr, feature); 5644 } 5645 break; 5646 } 5647 case EvqVaryingOut: 5648 { 5649 const char* feature = "location qualifier on output"; 5650 if (profile == EEsProfile && version < 310) 5651 requireStage(loc, EShLangFragment, feature); 5652 else 5653 requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); 5654 if (language == EShLangFragment) { 5655 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 5656 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); 5657 profileRequires(loc, EEsProfile, 300, nullptr, feature); 5658 } else { 5659 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); 5660 profileRequires(loc, EEsProfile, 310, nullptr, feature); 5661 } 5662 break; 5663 } 5664 case EvqUniform: 5665 case EvqBuffer: 5666 { 5667 const char* feature = "location qualifier on uniform or buffer"; 5668 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); 5669 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); 5670 profileRequires(loc, EEsProfile, 310, nullptr, feature); 5671 break; 5672 } 5673 default: 5674 break; 5675 } 5676 if (qualifier.hasIndex()) { 5677 if (qualifier.storage != EvqVaryingOut) 5678 error(loc, "can only be used on an output", "index", ""); 5679 if (! qualifier.hasLocation()) 5680 error(loc, "can only be used with an explicit location", "index", ""); 5681 } 5682 } 5683 5684 if (qualifier.hasBinding()) { 5685 if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) 5686 error(loc, "requires uniform or buffer storage qualifier", "binding", ""); 5687 } 5688 if (qualifier.hasStream()) { 5689 if (!qualifier.isPipeOutput()) 5690 error(loc, "can only be used on an output", "stream", ""); 5691 } 5692 if (qualifier.hasXfb()) { 5693 if (!qualifier.isPipeOutput()) 5694 error(loc, "can only be used on an output", "xfb layout qualifier", ""); 5695 } 5696 if (qualifier.hasUniformLayout()) { 5697 if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) { 5698 if (qualifier.hasMatrix() || qualifier.hasPacking()) 5699 error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); 5700 if (qualifier.hasOffset() || qualifier.hasAlign()) 5701 error(loc, "offset/align can only be used on a uniform or buffer", "layout", ""); 5702 } 5703 } 5704 if (qualifier.layoutPushConstant) { 5705 if (qualifier.storage != EvqUniform) 5706 error(loc, "can only be used with a uniform", "push_constant", ""); 5707 if (qualifier.hasSet()) 5708 error(loc, "cannot be used with push_constant", "set", ""); 5709 } 5710 if (qualifier.layoutBufferReference) { 5711 if (qualifier.storage != EvqBuffer) 5712 error(loc, "can only be used with buffer", "buffer_reference", ""); 5713 } 5714 #ifdef NV_EXTENSIONS 5715 if (qualifier.layoutShaderRecordNV) { 5716 if (qualifier.storage != EvqBuffer) 5717 error(loc, "can only be used with a buffer", "shaderRecordNV", ""); 5718 if (qualifier.hasBinding()) 5719 error(loc, "cannot be used with shaderRecordNV", "binding", ""); 5720 if (qualifier.hasSet()) 5721 error(loc, "cannot be used with shaderRecordNV", "set", ""); 5722 5723 } 5724 if (qualifier.storage == EvqHitAttrNV && qualifier.hasLayout()) { 5725 error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", ""); 5726 } 5727 #endif 5728 } 5729 5730 // For places that can't have shader-level layout qualifiers 5731 void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQualifiers& shaderQualifiers) 5732 { 5733 const char* message = "can only apply to a standalone qualifier"; 5734 5735 if (shaderQualifiers.geometry != ElgNone) 5736 error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), ""); 5737 if (shaderQualifiers.spacing != EvsNone) 5738 error(loc, message, TQualifier::getVertexSpacingString(shaderQualifiers.spacing), ""); 5739 if (shaderQualifiers.order != EvoNone) 5740 error(loc, message, TQualifier::getVertexOrderString(shaderQualifiers.order), ""); 5741 if (shaderQualifiers.pointMode) 5742 error(loc, message, "point_mode", ""); 5743 if (shaderQualifiers.invocations != TQualifier::layoutNotSet) 5744 error(loc, message, "invocations", ""); 5745 if (shaderQualifiers.earlyFragmentTests) 5746 error(loc, message, "early_fragment_tests", ""); 5747 if (shaderQualifiers.postDepthCoverage) 5748 error(loc, message, "post_depth_coverage", ""); 5749 for (int i = 0; i < 3; ++i) { 5750 if (shaderQualifiers.localSize[i] > 1) 5751 error(loc, message, "local_size", ""); 5752 if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) 5753 error(loc, message, "local_size id", ""); 5754 } 5755 if (shaderQualifiers.vertices != TQualifier::layoutNotSet) { 5756 if (language == EShLangGeometry 5757 #ifdef NV_EXTENSIONS 5758 || language == EShLangMeshNV 5759 #endif 5760 ) 5761 error(loc, message, "max_vertices", ""); 5762 else if (language == EShLangTessControl) 5763 error(loc, message, "vertices", ""); 5764 else 5765 assert(0); 5766 } 5767 #ifdef NV_EXTENSIONS 5768 if (shaderQualifiers.primitives != TQualifier::layoutNotSet) { 5769 if (language == EShLangMeshNV) 5770 error(loc, message, "max_primitives", ""); 5771 else 5772 assert(0); 5773 } 5774 #endif 5775 if (shaderQualifiers.blendEquation) 5776 error(loc, message, "blend equation", ""); 5777 if (shaderQualifiers.numViews != TQualifier::layoutNotSet) 5778 error(loc, message, "num_views", ""); 5779 } 5780 5781 // Correct and/or advance an object's offset layout qualifier. 5782 void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol) 5783 { 5784 const TQualifier& qualifier = symbol.getType().getQualifier(); 5785 if (symbol.getType().getBasicType() == EbtAtomicUint) { 5786 if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) { 5787 5788 // Set the offset 5789 int offset; 5790 if (qualifier.hasOffset()) 5791 offset = qualifier.layoutOffset; 5792 else 5793 offset = atomicUintOffsets[qualifier.layoutBinding]; 5794 symbol.getWritableType().getQualifier().layoutOffset = offset; 5795 5796 // Check for overlap 5797 int numOffsets = 4; 5798 if (symbol.getType().isArray()) { 5799 if (symbol.getType().isSizedArray() && !symbol.getType().getArraySizes()->isInnerUnsized()) 5800 numOffsets *= symbol.getType().getCumulativeArraySize(); 5801 else { 5802 // "It is a compile-time error to declare an unsized array of atomic_uint." 5803 error(loc, "array must be explicitly sized", "atomic_uint", ""); 5804 } 5805 } 5806 int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets); 5807 if (repeated >= 0) 5808 error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated); 5809 5810 // Bump the default offset 5811 atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets; 5812 } 5813 } 5814 } 5815 5816 // 5817 // Look up a function name in the symbol table, and make sure it is a function. 5818 // 5819 // Return the function symbol if found, otherwise nullptr. 5820 // 5821 const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 5822 { 5823 const TFunction* function = nullptr; 5824 5825 if (symbolTable.isFunctionNameVariable(call.getName())) { 5826 error(loc, "can't use function syntax on variable", call.getName().c_str(), ""); 5827 return nullptr; 5828 } 5829 5830 bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || 5831 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) || 5832 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) || 5833 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32) || 5834 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64) || 5835 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16) || 5836 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32) || 5837 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64); 5838 5839 if (profile == EEsProfile || version < 120) 5840 function = findFunctionExact(loc, call, builtIn); 5841 else if (version < 400) 5842 function = findFunction120(loc, call, builtIn); 5843 else if (explicitTypesEnabled) 5844 function = findFunctionExplicitTypes(loc, call, builtIn); 5845 else 5846 function = findFunction400(loc, call, builtIn); 5847 5848 return function; 5849 } 5850 5851 // Function finding algorithm for ES and desktop 110. 5852 const TFunction* TParseContext::findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 5853 { 5854 TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); 5855 if (symbol == nullptr) { 5856 error(loc, "no matching overloaded function found", call.getName().c_str(), ""); 5857 5858 return nullptr; 5859 } 5860 5861 return symbol->getAsFunction(); 5862 } 5863 5864 // Function finding algorithm for desktop versions 120 through 330. 5865 const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 5866 { 5867 // first, look for an exact match 5868 TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); 5869 if (symbol) 5870 return symbol->getAsFunction(); 5871 5872 // exact match not found, look through a list of overloaded functions of the same name 5873 5874 // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types 5875 // on input parameters (in or inout or default) must have a conversion from the calling argument type to the 5876 // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion 5877 // from the formal parameter type to the calling argument type. When argument conversions are used to find 5878 // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match 5879 // more than one function." 5880 5881 const TFunction* candidate = nullptr; 5882 TVector<const TFunction*> candidateList; 5883 symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); 5884 5885 for (auto it = candidateList.begin(); it != candidateList.end(); ++it) { 5886 const TFunction& function = *(*it); 5887 5888 // to even be a potential match, number of arguments has to match 5889 if (call.getParamCount() != function.getParamCount()) 5890 continue; 5891 5892 bool possibleMatch = true; 5893 for (int i = 0; i < function.getParamCount(); ++i) { 5894 // same types is easy 5895 if (*function[i].type == *call[i].type) 5896 continue; 5897 5898 // We have a mismatch in type, see if it is implicitly convertible 5899 5900 if (function[i].type->isArray() || call[i].type->isArray() || 5901 ! function[i].type->sameElementShape(*call[i].type)) 5902 possibleMatch = false; 5903 else { 5904 // do direction-specific checks for conversion of basic type 5905 if (function[i].type->getQualifier().isParamInput()) { 5906 if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType())) 5907 possibleMatch = false; 5908 } 5909 if (function[i].type->getQualifier().isParamOutput()) { 5910 if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType())) 5911 possibleMatch = false; 5912 } 5913 } 5914 if (! possibleMatch) 5915 break; 5916 } 5917 if (possibleMatch) { 5918 if (candidate) { 5919 // our second match, meaning ambiguity 5920 error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), ""); 5921 } else 5922 candidate = &function; 5923 } 5924 } 5925 5926 if (candidate == nullptr) 5927 error(loc, "no matching overloaded function found", call.getName().c_str(), ""); 5928 5929 return candidate; 5930 } 5931 5932 // Function finding algorithm for desktop version 400 and above. 5933 // 5934 // "When function calls are resolved, an exact type match for all the arguments 5935 // is sought. If an exact match is found, all other functions are ignored, and 5936 // the exact match is used. If no exact match is found, then the implicit 5937 // conversions in section 4.1.10 Implicit Conversions will be applied to find 5938 // a match. Mismatched types on input parameters (in or inout or default) must 5939 // have a conversion from the calling argument type to the formal parameter type. 5940 // Mismatched types on output parameters (out or inout) must have a conversion 5941 // from the formal parameter type to the calling argument type. 5942 // 5943 // "If implicit conversions can be used to find more than one matching function, 5944 // a single best-matching function is sought. To determine a best match, the 5945 // conversions between calling argument and formal parameter types are compared 5946 // for each function argument and pair of matching functions. After these 5947 // comparisons are performed, each pair of matching functions are compared. 5948 // A function declaration A is considered a better match than function 5949 // declaration B if 5950 // 5951 // * for at least one function argument, the conversion for that argument in A 5952 // is better than the corresponding conversion in B; and 5953 // * there is no function argument for which the conversion in B is better than 5954 // the corresponding conversion in A. 5955 // 5956 // "If a single function declaration is considered a better match than every 5957 // other matching function declaration, it will be used. Otherwise, a 5958 // compile-time semantic error for an ambiguous overloaded function call occurs. 5959 // 5960 // "To determine whether the conversion for a single argument in one match is 5961 // better than that for another match, the following rules are applied, in order: 5962 // 5963 // 1. An exact match is better than a match involving any implicit conversion. 5964 // 2. A match involving an implicit conversion from float to double is better 5965 // than a match involving any other implicit conversion. 5966 // 3. A match involving an implicit conversion from either int or uint to float 5967 // is better than a match involving an implicit conversion from either int 5968 // or uint to double. 5969 // 5970 // "If none of the rules above apply to a particular pair of conversions, neither 5971 // conversion is considered better than the other." 5972 // 5973 const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 5974 { 5975 // first, look for an exact match 5976 TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); 5977 if (symbol) 5978 return symbol->getAsFunction(); 5979 5980 // no exact match, use the generic selector, parameterized by the GLSL rules 5981 5982 // create list of candidates to send 5983 TVector<const TFunction*> candidateList; 5984 symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); 5985 5986 // can 'from' convert to 'to'? 5987 const auto convertible = [this](const TType& from, const TType& to, TOperator, int) -> bool { 5988 if (from == to) 5989 return true; 5990 if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) 5991 return false; 5992 return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); 5993 }; 5994 5995 // Is 'to2' a better conversion than 'to1'? 5996 // Ties should not be considered as better. 5997 // Assumes 'convertible' already said true. 5998 const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool { 5999 // 1. exact match 6000 if (from == to2) 6001 return from != to1; 6002 if (from == to1) 6003 return false; 6004 6005 // 2. float -> double is better 6006 if (from.getBasicType() == EbtFloat) { 6007 if (to2.getBasicType() == EbtDouble && to1.getBasicType() != EbtDouble) 6008 return true; 6009 } 6010 6011 // 3. -> float is better than -> double 6012 return to2.getBasicType() == EbtFloat && to1.getBasicType() == EbtDouble; 6013 }; 6014 6015 // for ambiguity reporting 6016 bool tie = false; 6017 6018 // send to the generic selector 6019 const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); 6020 6021 if (bestMatch == nullptr) 6022 error(loc, "no matching overloaded function found", call.getName().c_str(), ""); 6023 else if (tie) 6024 error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); 6025 6026 return bestMatch; 6027 } 6028 6029 // "To determine whether the conversion for a single argument in one match 6030 // is better than that for another match, the conversion is assigned of the 6031 // three ranks ordered from best to worst: 6032 // 1. Exact match: no conversion. 6033 // 2. Promotion: integral or floating-point promotion. 6034 // 3. Conversion: integral conversion, floating-point conversion, 6035 // floating-integral conversion. 6036 // A conversion C1 is better than a conversion C2 if the rank of C1 is 6037 // better than the rank of C2." 6038 const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 6039 { 6040 // first, look for an exact match 6041 TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); 6042 if (symbol) 6043 return symbol->getAsFunction(); 6044 6045 // no exact match, use the generic selector, parameterized by the GLSL rules 6046 6047 // create list of candidates to send 6048 TVector<const TFunction*> candidateList; 6049 symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); 6050 6051 // can 'from' convert to 'to'? 6052 const auto convertible = [this](const TType& from, const TType& to, TOperator, int) -> bool { 6053 if (from == to) 6054 return true; 6055 if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) 6056 return false; 6057 return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); 6058 }; 6059 6060 // Is 'to2' a better conversion than 'to1'? 6061 // Ties should not be considered as better. 6062 // Assumes 'convertible' already said true. 6063 const auto better = [this](const TType& from, const TType& to1, const TType& to2) -> bool { 6064 // 1. exact match 6065 if (from == to2) 6066 return from != to1; 6067 if (from == to1) 6068 return false; 6069 6070 // 2. Promotion (integral, floating-point) is better 6071 TBasicType from_type = from.getBasicType(); 6072 TBasicType to1_type = to1.getBasicType(); 6073 TBasicType to2_type = to2.getBasicType(); 6074 bool isPromotion1 = (intermediate.isIntegralPromotion(from_type, to1_type) || 6075 intermediate.isFPPromotion(from_type, to1_type)); 6076 bool isPromotion2 = (intermediate.isIntegralPromotion(from_type, to2_type) || 6077 intermediate.isFPPromotion(from_type, to2_type)); 6078 if (isPromotion2) 6079 return !isPromotion1; 6080 if(isPromotion1) 6081 return false; 6082 6083 // 3. Conversion (integral, floating-point , floating-integral) 6084 bool isConversion1 = (intermediate.isIntegralConversion(from_type, to1_type) || 6085 intermediate.isFPConversion(from_type, to1_type) || 6086 intermediate.isFPIntegralConversion(from_type, to1_type)); 6087 bool isConversion2 = (intermediate.isIntegralConversion(from_type, to2_type) || 6088 intermediate.isFPConversion(from_type, to2_type) || 6089 intermediate.isFPIntegralConversion(from_type, to2_type)); 6090 6091 return isConversion2 && !isConversion1; 6092 }; 6093 6094 // for ambiguity reporting 6095 bool tie = false; 6096 6097 // send to the generic selector 6098 const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); 6099 6100 if (bestMatch == nullptr) 6101 error(loc, "no matching overloaded function found", call.getName().c_str(), ""); 6102 else if (tie) 6103 error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); 6104 6105 return bestMatch; 6106 } 6107 6108 // When a declaration includes a type, but not a variable name, it can be 6109 // to establish defaults. 6110 void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType) 6111 { 6112 if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding() && publicType.qualifier.hasOffset()) { 6113 if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { 6114 error(loc, "atomic_uint binding is too large", "binding", ""); 6115 return; 6116 } 6117 atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; 6118 return; 6119 } 6120 6121 if (publicType.qualifier.hasLayout() && !publicType.qualifier.layoutBufferReference) 6122 warn(loc, "useless application of layout qualifier", "layout", ""); 6123 } 6124 6125 // 6126 // Do everything necessary to handle a variable (non-block) declaration. 6127 // Either redeclaring a variable, or making a new one, updating the symbol 6128 // table, and all error checking. 6129 // 6130 // Returns a subtree node that computes an initializer, if needed. 6131 // Returns nullptr if there is no code to execute for initialization. 6132 // 6133 // 'publicType' is the type part of the declaration (to the left) 6134 // 'arraySizes' is the arrayness tagged on the identifier (to the right) 6135 // 6136 TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType, 6137 TArraySizes* arraySizes, TIntermTyped* initializer) 6138 { 6139 // Make a fresh type that combines the characteristics from the individual 6140 // identifier syntax and the declaration-type syntax. 6141 TType type(publicType); 6142 type.transferArraySizes(arraySizes); 6143 type.copyArrayInnerSizes(publicType.arraySizes); 6144 arrayOfArrayVersionCheck(loc, type.getArraySizes()); 6145 6146 if (voidErrorCheck(loc, identifier, type.getBasicType())) 6147 return nullptr; 6148 6149 if (initializer) 6150 rValueErrorCheck(loc, "initializer", initializer); 6151 else 6152 nonInitConstCheck(loc, identifier, type); 6153 6154 samplerCheck(loc, type, identifier, initializer); 6155 atomicUintCheck(loc, type, identifier); 6156 transparentOpaqueCheck(loc, type, identifier); 6157 #ifdef NV_EXTENSIONS 6158 accStructNVCheck(loc, type, identifier); 6159 #endif 6160 6161 if (type.getQualifier().storage != EvqUniform && type.getQualifier().storage != EvqBuffer) { 6162 if (type.containsBasicType(EbtFloat16)) 6163 requireFloat16Arithmetic(loc, "qualifier", "float16 types can only be in uniform block or buffer storage"); 6164 if (type.contains16BitInt()) 6165 requireInt16Arithmetic(loc, "qualifier", "(u)int16 types can only be in uniform block or buffer storage"); 6166 if (type.contains8BitInt()) 6167 requireInt8Arithmetic(loc, "qualifier", "(u)int8 types can only be in uniform block or buffer storage"); 6168 } 6169 6170 if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger)) 6171 error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", ""); 6172 if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.layoutDepth != EldNone) 6173 error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", ""); 6174 6175 // Check for redeclaration of built-ins and/or attempting to declare a reserved name 6176 TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers); 6177 if (symbol == nullptr) 6178 reservedErrorCheck(loc, identifier); 6179 6180 inheritGlobalDefaults(type.getQualifier()); 6181 6182 // Declare the variable 6183 if (type.isArray()) { 6184 // Check that implicit sizing is only where allowed. 6185 arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false); 6186 6187 if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type)) 6188 declareArray(loc, identifier, type, symbol); 6189 6190 if (initializer) { 6191 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "initializer"); 6192 profileRequires(loc, EEsProfile, 300, nullptr, "initializer"); 6193 } 6194 } else { 6195 // non-array case 6196 if (symbol == nullptr) 6197 symbol = declareNonArray(loc, identifier, type); 6198 else if (type != symbol->getType()) 6199 error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); 6200 } 6201 6202 if (symbol == nullptr) 6203 return nullptr; 6204 6205 // Deal with initializer 6206 TIntermNode* initNode = nullptr; 6207 if (symbol != nullptr && initializer) { 6208 TVariable* variable = symbol->getAsVariable(); 6209 if (! variable) { 6210 error(loc, "initializer requires a variable, not a member", identifier.c_str(), ""); 6211 return nullptr; 6212 } 6213 initNode = executeInitializer(loc, initializer, variable); 6214 } 6215 6216 // look for errors in layout qualifier use 6217 layoutObjectCheck(loc, *symbol); 6218 6219 // fix up 6220 fixOffset(loc, *symbol); 6221 6222 if (symbol->getType().getBasicType() == EbtStruct) { 6223 fixXfbOffsets(symbol->getWritableType().getQualifier(), 6224 *(symbol->getWritableType().getWritableStruct())); 6225 } 6226 6227 return initNode; 6228 } 6229 6230 // Pick up global defaults from the provide global defaults into dst. 6231 void TParseContext::inheritGlobalDefaults(TQualifier& dst) const 6232 { 6233 if (dst.storage == EvqVaryingOut) { 6234 if (! dst.hasStream() && language == EShLangGeometry) 6235 dst.layoutStream = globalOutputDefaults.layoutStream; 6236 if (! dst.hasXfbBuffer()) 6237 dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; 6238 } 6239 } 6240 6241 // 6242 // Make an internal-only variable whose name is for debug purposes only 6243 // and won't be searched for. Callers will only use the return value to use 6244 // the variable, not the name to look it up. It is okay if the name 6245 // is the same as other names; there won't be any conflict. 6246 // 6247 TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const 6248 { 6249 TString* nameString = NewPoolTString(name); 6250 TVariable* variable = new TVariable(nameString, type); 6251 symbolTable.makeInternalVariable(*variable); 6252 6253 return variable; 6254 } 6255 6256 // 6257 // Declare a non-array variable, the main point being there is no redeclaration 6258 // for resizing allowed. 6259 // 6260 // Return the successfully declared variable. 6261 // 6262 TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type) 6263 { 6264 // make a new variable 6265 TVariable* variable = new TVariable(&identifier, type); 6266 6267 ioArrayCheck(loc, type, identifier); 6268 6269 // add variable to symbol table 6270 if (symbolTable.insert(*variable)) { 6271 if (symbolTable.atGlobalLevel()) 6272 trackLinkage(*variable); 6273 return variable; 6274 } 6275 6276 error(loc, "redefinition", variable->getName().c_str(), ""); 6277 return nullptr; 6278 } 6279 6280 // 6281 // Handle all types of initializers from the grammar. 6282 // 6283 // Returning nullptr just means there is no code to execute to handle the 6284 // initializer, which will, for example, be the case for constant initializers. 6285 // 6286 TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable) 6287 { 6288 // 6289 // Identifier must be of type constant, a global, or a temporary, and 6290 // starting at version 120, desktop allows uniforms to have initializers. 6291 // 6292 TStorageQualifier qualifier = variable->getType().getQualifier().storage; 6293 if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst || 6294 (qualifier == EvqUniform && profile != EEsProfile && version >= 120))) { 6295 error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), ""); 6296 return nullptr; 6297 } 6298 arrayObjectCheck(loc, variable->getType(), "array initializer"); 6299 6300 // 6301 // If the initializer was from braces { ... }, we convert the whole subtree to a 6302 // constructor-style subtree, allowing the rest of the code to operate 6303 // identically for both kinds of initializers. 6304 // 6305 // Type can't be deduced from the initializer list, so a skeletal type to 6306 // follow has to be passed in. Constness and specialization-constness 6307 // should be deduced bottom up, not dictated by the skeletal type. 6308 // 6309 TType skeletalType; 6310 skeletalType.shallowCopy(variable->getType()); 6311 skeletalType.getQualifier().makeTemporary(); 6312 initializer = convertInitializerList(loc, skeletalType, initializer); 6313 if (! initializer) { 6314 // error recovery; don't leave const without constant values 6315 if (qualifier == EvqConst) 6316 variable->getWritableType().getQualifier().makeTemporary(); 6317 return nullptr; 6318 } 6319 6320 // Fix outer arrayness if variable is unsized, getting size from the initializer 6321 if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray()) 6322 variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize()); 6323 6324 // Inner arrayness can also get set by an initializer 6325 if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() && 6326 initializer->getType().getArraySizes()->getNumDims() == 6327 variable->getType().getArraySizes()->getNumDims()) { 6328 // adopt unsized sizes from the initializer's sizes 6329 for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) { 6330 if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) { 6331 variable->getWritableType().getArraySizes()->setDimSize(d, 6332 initializer->getType().getArraySizes()->getDimSize(d)); 6333 } 6334 } 6335 } 6336 6337 // Uniforms require a compile-time constant initializer 6338 if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { 6339 error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); 6340 variable->getWritableType().getQualifier().makeTemporary(); 6341 return nullptr; 6342 } 6343 // Global consts require a constant initializer (specialization constant is okay) 6344 if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { 6345 error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); 6346 variable->getWritableType().getQualifier().makeTemporary(); 6347 return nullptr; 6348 } 6349 6350 // Const variables require a constant initializer, depending on version 6351 if (qualifier == EvqConst) { 6352 if (! initializer->getType().getQualifier().isConstant()) { 6353 const char* initFeature = "non-constant initializer"; 6354 requireProfile(loc, ~EEsProfile, initFeature); 6355 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); 6356 variable->getWritableType().getQualifier().storage = EvqConstReadOnly; 6357 qualifier = EvqConstReadOnly; 6358 } 6359 } else { 6360 // Non-const global variables in ES need a const initializer. 6361 // 6362 // "In declarations of global variables with no storage qualifier or with a const 6363 // qualifier any initializer must be a constant expression." 6364 if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { 6365 const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)"; 6366 if (profile == EEsProfile) { 6367 if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers)) 6368 warn(loc, "not allowed in this version", initFeature, ""); 6369 else 6370 profileRequires(loc, EEsProfile, 0, E_GL_EXT_shader_non_constant_global_initializers, initFeature); 6371 } 6372 } 6373 } 6374 6375 if (qualifier == EvqConst || qualifier == EvqUniform) { 6376 // Compile-time tagging of the variable with its constant value... 6377 6378 initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); 6379 if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) { 6380 error(loc, "non-matching or non-convertible constant type for const initializer", 6381 variable->getType().getStorageQualifierString(), ""); 6382 variable->getWritableType().getQualifier().makeTemporary(); 6383 return nullptr; 6384 } 6385 6386 // We either have a folded constant in getAsConstantUnion, or we have to use 6387 // the initializer's subtree in the AST to represent the computation of a 6388 // specialization constant. 6389 assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant()); 6390 if (initializer->getAsConstantUnion()) 6391 variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); 6392 else { 6393 // It's a specialization constant. 6394 variable->getWritableType().getQualifier().makeSpecConstant(); 6395 6396 // Keep the subtree that computes the specialization constant with the variable. 6397 // Later, a symbol node will adopt the subtree from the variable. 6398 variable->setConstSubtree(initializer); 6399 } 6400 } else { 6401 // normal assigning of a value to a variable... 6402 specializationCheck(loc, initializer->getType(), "initializer"); 6403 TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); 6404 TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc); 6405 if (! initNode) 6406 assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); 6407 6408 return initNode; 6409 } 6410 6411 return nullptr; 6412 } 6413 6414 // 6415 // Reprocess any initializer-list (the "{ ... }" syntax) parts of the 6416 // initializer. 6417 // 6418 // Need to hierarchically assign correct types and implicit 6419 // conversions. Will do this mimicking the same process used for 6420 // creating a constructor-style initializer, ensuring we get the 6421 // same form. However, it has to in parallel walk the 'type' 6422 // passed in, as type cannot be deduced from an initializer list. 6423 // 6424 TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer) 6425 { 6426 // Will operate recursively. Once a subtree is found that is constructor style, 6427 // everything below it is already good: Only the "top part" of the initializer 6428 // can be an initializer list, where "top part" can extend for several (or all) levels. 6429 6430 // see if we have bottomed out in the tree within the initializer-list part 6431 TIntermAggregate* initList = initializer->getAsAggregate(); 6432 if (! initList || initList->getOp() != EOpNull) 6433 return initializer; 6434 6435 // Of the initializer-list set of nodes, need to process bottom up, 6436 // so recurse deep, then process on the way up. 6437 6438 // Go down the tree here... 6439 if (type.isArray()) { 6440 // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate. 6441 // Later on, initializer execution code will deal with array size logic. 6442 TType arrayType; 6443 arrayType.shallowCopy(type); // sharing struct stuff is fine 6444 arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below 6445 6446 // edit array sizes to fill in unsized dimensions 6447 arrayType.changeOuterArraySize((int)initList->getSequence().size()); 6448 TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped(); 6449 if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() && 6450 arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) { 6451 for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) { 6452 if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize) 6453 arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1)); 6454 } 6455 } 6456 6457 TType elementType(arrayType, 0); // dereferenced type 6458 for (size_t i = 0; i < initList->getSequence().size(); ++i) { 6459 initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped()); 6460 if (initList->getSequence()[i] == nullptr) 6461 return nullptr; 6462 } 6463 6464 return addConstructor(loc, initList, arrayType); 6465 } else if (type.isStruct()) { 6466 if (type.getStruct()->size() != initList->getSequence().size()) { 6467 error(loc, "wrong number of structure members", "initializer list", ""); 6468 return nullptr; 6469 } 6470 for (size_t i = 0; i < type.getStruct()->size(); ++i) { 6471 initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped()); 6472 if (initList->getSequence()[i] == nullptr) 6473 return nullptr; 6474 } 6475 } else if (type.isMatrix()) { 6476 if (type.getMatrixCols() != (int)initList->getSequence().size()) { 6477 error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str()); 6478 return nullptr; 6479 } 6480 TType vectorType(type, 0); // dereferenced type 6481 for (int i = 0; i < type.getMatrixCols(); ++i) { 6482 initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped()); 6483 if (initList->getSequence()[i] == nullptr) 6484 return nullptr; 6485 } 6486 } else if (type.isVector()) { 6487 if (type.getVectorSize() != (int)initList->getSequence().size()) { 6488 error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str()); 6489 return nullptr; 6490 } 6491 } else { 6492 error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str()); 6493 return nullptr; 6494 } 6495 6496 // Now that the subtree is processed, process this node as if the 6497 // initializer list is a set of arguments to a constructor. 6498 TIntermNode* emulatedConstructorArguments; 6499 if (initList->getSequence().size() == 1) 6500 emulatedConstructorArguments = initList->getSequence()[0]; 6501 else 6502 emulatedConstructorArguments = initList; 6503 return addConstructor(loc, emulatedConstructorArguments, type); 6504 } 6505 6506 // 6507 // Test for the correctness of the parameters passed to various constructor functions 6508 // and also convert them to the right data type, if allowed and required. 6509 // 6510 // 'node' is what to construct from. 6511 // 'type' is what type to construct. 6512 // 6513 // Returns nullptr for an error or the constructed node (aggregate or typed) for no error. 6514 // 6515 TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type) 6516 { 6517 if (node == nullptr || node->getAsTyped() == nullptr) 6518 return nullptr; 6519 rValueErrorCheck(loc, "constructor", node->getAsTyped()); 6520 6521 TIntermAggregate* aggrNode = node->getAsAggregate(); 6522 TOperator op = intermediate.mapTypeToConstructorOp(type); 6523 6524 // Combined texture-sampler constructors are completely semantic checked 6525 // in constructorTextureSamplerError() 6526 if (op == EOpConstructTextureSampler) { 6527 if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) { 6528 // Transfer depth into the texture (SPIR-V image) type, as a hint 6529 // for tools to know this texture/image is a depth image. 6530 aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true; 6531 } 6532 return intermediate.setAggregateOperator(aggrNode, op, type, loc); 6533 } 6534 6535 TTypeList::const_iterator memberTypes; 6536 if (op == EOpConstructStruct) 6537 memberTypes = type.getStruct()->begin(); 6538 6539 TType elementType; 6540 if (type.isArray()) { 6541 TType dereferenced(type, 0); 6542 elementType.shallowCopy(dereferenced); 6543 } else 6544 elementType.shallowCopy(type); 6545 6546 bool singleArg; 6547 if (aggrNode) { 6548 if (aggrNode->getOp() != EOpNull) 6549 singleArg = true; 6550 else 6551 singleArg = false; 6552 } else 6553 singleArg = true; 6554 6555 TIntermTyped *newNode; 6556 if (singleArg) { 6557 // If structure constructor or array constructor is being called 6558 // for only one parameter inside the structure, we need to call constructAggregate function once. 6559 if (type.isArray()) 6560 newNode = constructAggregate(node, elementType, 1, node->getLoc()); 6561 else if (op == EOpConstructStruct) 6562 newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); 6563 else 6564 newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false); 6565 6566 if (newNode && (type.isArray() || op == EOpConstructStruct)) 6567 newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); 6568 6569 return newNode; 6570 } 6571 6572 // 6573 // Handle list of arguments. 6574 // 6575 TIntermSequence &sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor 6576 // if the structure constructor contains more than one parameter, then construct 6577 // each parameter 6578 6579 int paramCount = 0; // keeps track of the constructor parameter number being checked 6580 6581 // for each parameter to the constructor call, check to see if the right type is passed or convert them 6582 // to the right type if possible (and allowed). 6583 // for structure constructors, just check if the right type is passed, no conversion is allowed. 6584 for (TIntermSequence::iterator p = sequenceVector.begin(); 6585 p != sequenceVector.end(); p++, paramCount++) { 6586 if (type.isArray()) 6587 newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc()); 6588 else if (op == EOpConstructStruct) 6589 newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc()); 6590 else 6591 newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); 6592 6593 if (newNode) 6594 *p = newNode; 6595 else 6596 return nullptr; 6597 } 6598 6599 return intermediate.setAggregateOperator(aggrNode, op, type, loc); 6600 } 6601 6602 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value 6603 // for the parameter to the constructor (passed to this function). Essentially, it converts 6604 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 6605 // float, then float is converted to int. 6606 // 6607 // Returns nullptr for an error or the constructed node. 6608 // 6609 TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, const TSourceLoc& loc, 6610 bool subset) 6611 { 6612 // If we are changing a matrix in both domain of basic type and to a non matrix, 6613 // do the shape change first (by default, below, basic type is changed before shape). 6614 // This avoids requesting a matrix of a new type that is going to be discarded anyway. 6615 // TODO: This could be generalized to more type combinations, but that would require 6616 // more extensive testing and full algorithm rework. For now, the need to do two changes makes 6617 // the recursive call work, and avoids the most aggregious case of creating integer matrices. 6618 if (node->getType().isMatrix() && (type.isScalar() || type.isVector()) && 6619 type.isFloatingDomain() != node->getType().isFloatingDomain()) { 6620 TType transitionType(node->getBasicType(), glslang::EvqTemporary, type.getVectorSize(), 0, 0, node->isVector()); 6621 TOperator transitionOp = intermediate.mapTypeToConstructorOp(transitionType); 6622 node = constructBuiltIn(transitionType, transitionOp, node, loc, false); 6623 } 6624 6625 TIntermTyped* newNode; 6626 TOperator basicOp; 6627 6628 // 6629 // First, convert types as needed. 6630 // 6631 switch (op) { 6632 case EOpConstructVec2: 6633 case EOpConstructVec3: 6634 case EOpConstructVec4: 6635 case EOpConstructMat2x2: 6636 case EOpConstructMat2x3: 6637 case EOpConstructMat2x4: 6638 case EOpConstructMat3x2: 6639 case EOpConstructMat3x3: 6640 case EOpConstructMat3x4: 6641 case EOpConstructMat4x2: 6642 case EOpConstructMat4x3: 6643 case EOpConstructMat4x4: 6644 case EOpConstructFloat: 6645 basicOp = EOpConstructFloat; 6646 break; 6647 6648 case EOpConstructDVec2: 6649 case EOpConstructDVec3: 6650 case EOpConstructDVec4: 6651 case EOpConstructDMat2x2: 6652 case EOpConstructDMat2x3: 6653 case EOpConstructDMat2x4: 6654 case EOpConstructDMat3x2: 6655 case EOpConstructDMat3x3: 6656 case EOpConstructDMat3x4: 6657 case EOpConstructDMat4x2: 6658 case EOpConstructDMat4x3: 6659 case EOpConstructDMat4x4: 6660 case EOpConstructDouble: 6661 basicOp = EOpConstructDouble; 6662 break; 6663 6664 case EOpConstructF16Vec2: 6665 case EOpConstructF16Vec3: 6666 case EOpConstructF16Vec4: 6667 case EOpConstructF16Mat2x2: 6668 case EOpConstructF16Mat2x3: 6669 case EOpConstructF16Mat2x4: 6670 case EOpConstructF16Mat3x2: 6671 case EOpConstructF16Mat3x3: 6672 case EOpConstructF16Mat3x4: 6673 case EOpConstructF16Mat4x2: 6674 case EOpConstructF16Mat4x3: 6675 case EOpConstructF16Mat4x4: 6676 case EOpConstructFloat16: 6677 basicOp = EOpConstructFloat16; 6678 break; 6679 6680 case EOpConstructI8Vec2: 6681 case EOpConstructI8Vec3: 6682 case EOpConstructI8Vec4: 6683 case EOpConstructInt8: 6684 basicOp = EOpConstructInt8; 6685 break; 6686 6687 case EOpConstructU8Vec2: 6688 case EOpConstructU8Vec3: 6689 case EOpConstructU8Vec4: 6690 case EOpConstructUint8: 6691 basicOp = EOpConstructUint8; 6692 break; 6693 6694 case EOpConstructI16Vec2: 6695 case EOpConstructI16Vec3: 6696 case EOpConstructI16Vec4: 6697 case EOpConstructInt16: 6698 basicOp = EOpConstructInt16; 6699 break; 6700 6701 case EOpConstructU16Vec2: 6702 case EOpConstructU16Vec3: 6703 case EOpConstructU16Vec4: 6704 case EOpConstructUint16: 6705 basicOp = EOpConstructUint16; 6706 break; 6707 6708 case EOpConstructIVec2: 6709 case EOpConstructIVec3: 6710 case EOpConstructIVec4: 6711 case EOpConstructInt: 6712 basicOp = EOpConstructInt; 6713 break; 6714 6715 case EOpConstructUVec2: 6716 case EOpConstructUVec3: 6717 case EOpConstructUVec4: 6718 case EOpConstructUint: 6719 basicOp = EOpConstructUint; 6720 break; 6721 6722 case EOpConstructI64Vec2: 6723 case EOpConstructI64Vec3: 6724 case EOpConstructI64Vec4: 6725 case EOpConstructInt64: 6726 basicOp = EOpConstructInt64; 6727 break; 6728 6729 case EOpConstructUint64: 6730 if (type.isScalar() && node->getType().getBasicType() == EbtReference) { 6731 TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvPtrToUint64, node, node->getLoc(), type); 6732 return newNode; 6733 } 6734 // fall through 6735 case EOpConstructU64Vec2: 6736 case EOpConstructU64Vec3: 6737 case EOpConstructU64Vec4: 6738 basicOp = EOpConstructUint64; 6739 break; 6740 6741 case EOpConstructBVec2: 6742 case EOpConstructBVec3: 6743 case EOpConstructBVec4: 6744 case EOpConstructBool: 6745 basicOp = EOpConstructBool; 6746 break; 6747 6748 case EOpConstructNonuniform: 6749 node->getWritableType().getQualifier().nonUniform = true; 6750 return node; 6751 break; 6752 6753 case EOpConstructReference: 6754 // construct reference from reference 6755 if (node->getType().getBasicType() == EbtReference) { 6756 newNode = intermediate.addUnaryNode(EOpConstructReference, node, node->getLoc(), type); 6757 return newNode; 6758 // construct reference from uint64 6759 } else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) { 6760 TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvUint64ToPtr, node, node->getLoc(), type); 6761 return newNode; 6762 } else { 6763 return nullptr; 6764 } 6765 6766 default: 6767 error(loc, "unsupported construction", "", ""); 6768 6769 return nullptr; 6770 } 6771 newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc()); 6772 if (newNode == nullptr) { 6773 error(loc, "can't convert", "constructor", ""); 6774 return nullptr; 6775 } 6776 6777 // 6778 // Now, if there still isn't an operation to do the construction, and we need one, add one. 6779 // 6780 6781 // Otherwise, skip out early. 6782 if (subset || (newNode != node && newNode->getType() == type)) 6783 return newNode; 6784 6785 // setAggregateOperator will insert a new node for the constructor, as needed. 6786 return intermediate.setAggregateOperator(newNode, op, type, loc); 6787 } 6788 6789 // This function tests for the type of the parameters to the structure or array constructor. Raises 6790 // an error message if the expected type does not match the parameter passed to the constructor. 6791 // 6792 // Returns nullptr for an error or the input node itself if the expected and the given parameter types match. 6793 // 6794 TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc) 6795 { 6796 TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); 6797 if (! converted || converted->getType() != type) { 6798 error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, 6799 node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str()); 6800 6801 return nullptr; 6802 } 6803 6804 return converted; 6805 } 6806 6807 // 6808 // Do everything needed to add an interface block. 6809 // 6810 void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName, 6811 TArraySizes* arraySizes) 6812 { 6813 blockStageIoCheck(loc, currentBlockQualifier); 6814 blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr); 6815 if (arraySizes != nullptr) { 6816 arraySizesCheck(loc, currentBlockQualifier, arraySizes, nullptr, false); 6817 arrayOfArrayVersionCheck(loc, arraySizes); 6818 if (arraySizes->getNumDims() > 1) 6819 requireProfile(loc, ~EEsProfile, "array-of-array of block"); 6820 } 6821 6822 // fix and check for member storage qualifiers and types that don't belong within a block 6823 for (unsigned int member = 0; member < typeList.size(); ++member) { 6824 TType& memberType = *typeList[member].type; 6825 TQualifier& memberQualifier = memberType.getQualifier(); 6826 const TSourceLoc& memberLoc = typeList[member].loc; 6827 globalQualifierFixCheck(memberLoc, memberQualifier); 6828 if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage) 6829 error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), ""); 6830 memberQualifier.storage = currentBlockQualifier.storage; 6831 #ifdef NV_EXTENSIONS 6832 if (currentBlockQualifier.perPrimitiveNV) 6833 memberQualifier.perPrimitiveNV = currentBlockQualifier.perPrimitiveNV; 6834 if (currentBlockQualifier.perViewNV) 6835 memberQualifier.perViewNV = currentBlockQualifier.perViewNV; 6836 if (currentBlockQualifier.perTaskNV) 6837 memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV; 6838 #endif 6839 if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())) 6840 error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), ""); 6841 if (memberType.isArray()) 6842 arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1); 6843 if (memberQualifier.hasOffset()) { 6844 if (spvVersion.spv == 0) { 6845 requireProfile(memberLoc, ~EEsProfile, "offset on block member"); 6846 profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member"); 6847 } 6848 } 6849 6850 if (memberType.containsOpaque()) 6851 error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), ""); 6852 } 6853 6854 // This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will 6855 // do all the rest. 6856 if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) { 6857 redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes); 6858 return; 6859 } 6860 6861 // Not a redeclaration of a built-in; check that all names are user names. 6862 reservedErrorCheck(loc, *blockName); 6863 if (instanceName) 6864 reservedErrorCheck(loc, *instanceName); 6865 for (unsigned int member = 0; member < typeList.size(); ++member) 6866 reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName()); 6867 6868 // Make default block qualification, and adjust the member qualifications 6869 6870 TQualifier defaultQualification; 6871 switch (currentBlockQualifier.storage) { 6872 case EvqUniform: defaultQualification = globalUniformDefaults; break; 6873 case EvqBuffer: defaultQualification = globalBufferDefaults; break; 6874 case EvqVaryingIn: defaultQualification = globalInputDefaults; break; 6875 case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; 6876 default: defaultQualification.clear(); break; 6877 } 6878 6879 // Special case for "push_constant uniform", which has a default of std430, 6880 // contrary to normal uniform defaults, and can't have a default tracked for it. 6881 if ((currentBlockQualifier.layoutPushConstant && !currentBlockQualifier.hasPacking()) 6882 #ifdef NV_EXTENSIONS 6883 || (currentBlockQualifier.layoutShaderRecordNV && !currentBlockQualifier.hasPacking()) 6884 #endif 6885 ) 6886 currentBlockQualifier.layoutPacking = ElpStd430; 6887 6888 #ifdef NV_EXTENSIONS 6889 // Special case for "taskNV in/out", which has a default of std430, 6890 if (currentBlockQualifier.perTaskNV && !currentBlockQualifier.hasPacking()) 6891 currentBlockQualifier.layoutPacking = ElpStd430; 6892 #endif 6893 6894 // fix and check for member layout qualifiers 6895 6896 mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true); 6897 6898 // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." 6899 if (currentBlockQualifier.hasAlign()) { 6900 if (defaultQualification.layoutPacking != ElpStd140 && 6901 defaultQualification.layoutPacking != ElpStd430 && 6902 defaultQualification.layoutPacking != ElpScalar) { 6903 error(loc, "can only be used with std140, std430, or scalar layout packing", "align", ""); 6904 defaultQualification.layoutAlign = -1; 6905 } 6906 } 6907 6908 bool memberWithLocation = false; 6909 bool memberWithoutLocation = false; 6910 #ifdef NV_EXTENSIONS 6911 bool memberWithPerViewQualifier = false; 6912 #endif 6913 for (unsigned int member = 0; member < typeList.size(); ++member) { 6914 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 6915 const TSourceLoc& memberLoc = typeList[member].loc; 6916 if (memberQualifier.hasStream()) { 6917 if (defaultQualification.layoutStream != memberQualifier.layoutStream) 6918 error(memberLoc, "member cannot contradict block", "stream", ""); 6919 } 6920 6921 // "This includes a block's inheritance of the 6922 // current global default buffer, a block member's inheritance of the block's 6923 // buffer, and the requirement that any *xfb_buffer* declared on a block 6924 // member must match the buffer inherited from the block." 6925 if (memberQualifier.hasXfbBuffer()) { 6926 if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer) 6927 error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); 6928 } 6929 6930 if (memberQualifier.hasPacking()) 6931 error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), ""); 6932 if (memberQualifier.hasLocation()) { 6933 const char* feature = "location on block member"; 6934 switch (currentBlockQualifier.storage) { 6935 case EvqVaryingIn: 6936 case EvqVaryingOut: 6937 requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature); 6938 profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); 6939 profileRequires(memberLoc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); 6940 memberWithLocation = true; 6941 break; 6942 default: 6943 error(memberLoc, "can only use in an in/out block", feature, ""); 6944 break; 6945 } 6946 } else 6947 memberWithoutLocation = true; 6948 6949 // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts." 6950 // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." 6951 if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) { 6952 if (defaultQualification.layoutPacking != ElpStd140 && 6953 defaultQualification.layoutPacking != ElpStd430 && 6954 defaultQualification.layoutPacking != ElpScalar) 6955 error(memberLoc, "can only be used with std140, std430, or scalar layout packing", "offset/align", ""); 6956 } 6957 6958 #ifdef NV_EXTENSIONS 6959 if (memberQualifier.isPerView()) { 6960 memberWithPerViewQualifier = true; 6961 } 6962 #endif 6963 6964 TQualifier newMemberQualification = defaultQualification; 6965 mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false); 6966 memberQualifier = newMemberQualification; 6967 } 6968 6969 layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes); 6970 6971 // Ensure that the block has an XfbBuffer assigned. This is needed 6972 // because if the block has a XfbOffset assigned, then it is 6973 // assumed that it has implicitly assigned the current global 6974 // XfbBuffer, and because it's members need to be assigned a 6975 // XfbOffset if they lack it. 6976 if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) { 6977 if (!currentBlockQualifier.hasXfbBuffer() && currentBlockQualifier.hasXfbOffset()) 6978 currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; 6979 } 6980 6981 // Process the members 6982 fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); 6983 fixXfbOffsets(currentBlockQualifier, typeList); 6984 fixBlockUniformOffsets(currentBlockQualifier, typeList); 6985 for (unsigned int member = 0; member < typeList.size(); ++member) 6986 layoutTypeCheck(typeList[member].loc, *typeList[member].type); 6987 6988 #ifdef NV_EXTENSIONS 6989 if (memberWithPerViewQualifier) { 6990 for (unsigned int member = 0; member < typeList.size(); ++member) { 6991 resizeMeshViewDimension(typeList[member].loc, *typeList[member].type); 6992 } 6993 } 6994 #endif 6995 6996 // reverse merge, so that currentBlockQualifier now has all layout information 6997 // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) 6998 mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true); 6999 7000 // 7001 // Build and add the interface block as a new type named 'blockName' 7002 // 7003 7004 TType blockType(&typeList, *blockName, currentBlockQualifier); 7005 if (arraySizes != nullptr) 7006 blockType.transferArraySizes(arraySizes); 7007 else 7008 ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName); 7009 7010 if (currentBlockQualifier.layoutBufferReference) { 7011 7012 if (currentBlockQualifier.storage != EvqBuffer) 7013 error(loc, "can only be used with buffer", "buffer_reference", ""); 7014 7015 // Create the block reference type. If it was forward-declared, detect that 7016 // as a referent struct type with no members. Replace the referent type with 7017 // blockType. 7018 TType blockNameType(EbtReference, blockType, *blockName); 7019 TVariable* blockNameVar = new TVariable(blockName, blockNameType, true); 7020 if (! symbolTable.insert(*blockNameVar)) { 7021 TSymbol* existingName = symbolTable.find(*blockName); 7022 if (existingName->getType().getBasicType() == EbtReference && 7023 existingName->getType().getReferentType()->getStruct() && 7024 existingName->getType().getReferentType()->getStruct()->size() == 0 && 7025 existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { 7026 existingName->getType().getReferentType()->deepCopy(blockType); 7027 } else { 7028 error(loc, "block name cannot be redefined", blockName->c_str(), ""); 7029 } 7030 } 7031 if (!instanceName) { 7032 return; 7033 } 7034 } else { 7035 // 7036 // Don't make a user-defined type out of block name; that will cause an error 7037 // if the same block name gets reused in a different interface. 7038 // 7039 // "Block names have no other use within a shader 7040 // beyond interface matching; it is a compile-time error to use a block name at global scope for anything 7041 // other than as a block name (e.g., use of a block name for a global variable name or function name is 7042 // currently reserved)." 7043 // 7044 // Use the symbol table to prevent normal reuse of the block's name, as a variable entry, 7045 // whose type is EbtBlock, but without all the structure; that will come from the type 7046 // the instances point to. 7047 // 7048 TType blockNameType(EbtBlock, blockType.getQualifier().storage); 7049 TVariable* blockNameVar = new TVariable(blockName, blockNameType); 7050 if (! symbolTable.insert(*blockNameVar)) { 7051 TSymbol* existingName = symbolTable.find(*blockName); 7052 if (existingName->getType().getBasicType() == EbtBlock) { 7053 if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { 7054 error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString()); 7055 return; 7056 } 7057 } else { 7058 error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); 7059 return; 7060 } 7061 } 7062 } 7063 7064 // Add the variable, as anonymous or named instanceName. 7065 // Make an anonymous variable if no name was provided. 7066 if (! instanceName) 7067 instanceName = NewPoolTString(""); 7068 7069 TVariable& variable = *new TVariable(instanceName, blockType); 7070 if (! symbolTable.insert(variable)) { 7071 if (*instanceName == "") 7072 error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), ""); 7073 else 7074 error(loc, "block instance name redefinition", variable.getName().c_str(), ""); 7075 7076 return; 7077 } 7078 7079 // Check for general layout qualifier errors 7080 layoutObjectCheck(loc, variable); 7081 7082 // fix up 7083 if (isIoResizeArray(blockType)) { 7084 ioArraySymbolResizeList.push_back(&variable); 7085 checkIoArraysConsistency(loc, true, blockType.getQualifier().isPerPrimitive()); 7086 } else 7087 fixIoArraySize(loc, variable.getWritableType()); 7088 7089 // Save it in the AST for linker use. 7090 trackLinkage(variable); 7091 } 7092 7093 // Do all block-declaration checking regarding the combination of in/out/uniform/buffer 7094 // with a particular stage. 7095 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier) 7096 { 7097 switch (qualifier.storage) { 7098 case EvqUniform: 7099 profileRequires(loc, EEsProfile, 300, nullptr, "uniform block"); 7100 profileRequires(loc, ENoProfile, 140, nullptr, "uniform block"); 7101 if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.layoutPushConstant) 7102 requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "std430 requires the buffer storage qualifier"); 7103 break; 7104 case EvqBuffer: 7105 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block"); 7106 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block"); 7107 profileRequires(loc, EEsProfile, 310, nullptr, "buffer block"); 7108 break; 7109 case EvqVaryingIn: 7110 profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "input block"); 7111 // It is a compile-time error to have an input block in a vertex shader or an output block in a fragment shader 7112 // "Compute shaders do not permit user-defined input variables..." 7113 requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|EShLangFragmentMask 7114 #ifdef NV_EXTENSIONS 7115 |EShLangMeshNVMask 7116 #endif 7117 ), "input block"); 7118 if (language == EShLangFragment) { 7119 profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block"); 7120 } 7121 #ifdef NV_EXTENSIONS 7122 else if (language == EShLangMeshNV && ! qualifier.isTaskMemory()) { 7123 error(loc, "input blocks cannot be used in a mesh shader", "out", ""); 7124 } 7125 #endif 7126 break; 7127 case EvqVaryingOut: 7128 profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block"); 7129 requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask 7130 #ifdef NV_EXTENSIONS 7131 |EShLangMeshNVMask|EShLangTaskNVMask 7132 #endif 7133 ), "output block"); 7134 // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins 7135 if (language == EShLangVertex && ! parsingBuiltins) { 7136 profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block"); 7137 } 7138 #ifdef NV_EXTENSIONS 7139 else if (language == EShLangMeshNV && qualifier.isTaskMemory()) { 7140 error(loc, "can only use on input blocks in mesh shader", "taskNV", ""); 7141 } 7142 else if (language == EShLangTaskNV && ! qualifier.isTaskMemory()) { 7143 error(loc, "output blocks cannot be used in a task shader", "out", ""); 7144 } 7145 #endif 7146 break; 7147 #ifdef NV_EXTENSIONS 7148 case EvqPayloadNV: 7149 profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block"); 7150 requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask), 7151 "rayPayloadNV block"); 7152 break; 7153 case EvqPayloadInNV: 7154 profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV block"); 7155 requireStage(loc, (EShLanguageMask)(EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask), 7156 "rayPayloadInNV block"); 7157 break; 7158 case EvqHitAttrNV: 7159 profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV block"); 7160 requireStage(loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask), "hitAttributeNV block"); 7161 break; 7162 case EvqCallableDataNV: 7163 profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataNV block"); 7164 requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), 7165 "callableDataNV block"); 7166 break; 7167 case EvqCallableDataInNV: 7168 profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV block"); 7169 requireStage(loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV block"); 7170 break; 7171 #endif 7172 default: 7173 error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), ""); 7174 break; 7175 } 7176 } 7177 7178 // Do all block-declaration checking regarding its qualifiers. 7179 void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/) 7180 { 7181 // The 4.5 specification says: 7182 // 7183 // interface-block : 7184 // layout-qualifieropt interface-qualifier block-name { member-list } instance-nameopt ; 7185 // 7186 // interface-qualifier : 7187 // in 7188 // out 7189 // patch in 7190 // patch out 7191 // uniform 7192 // buffer 7193 // 7194 // Note however memory qualifiers aren't included, yet the specification also says 7195 // 7196 // "...memory qualifiers may also be used in the declaration of shader storage blocks..." 7197 7198 if (qualifier.isInterpolation()) 7199 error(loc, "cannot use interpolation qualifiers on an interface block", "flat/smooth/noperspective", ""); 7200 if (qualifier.centroid) 7201 error(loc, "cannot use centroid qualifier on an interface block", "centroid", ""); 7202 if (qualifier.sample) 7203 error(loc, "cannot use sample qualifier on an interface block", "sample", ""); 7204 if (qualifier.invariant) 7205 error(loc, "cannot use invariant qualifier on an interface block", "invariant", ""); 7206 if (qualifier.layoutPushConstant) 7207 intermediate.addPushConstantCount(); 7208 #ifdef NV_EXTENSIONS 7209 if (qualifier.layoutShaderRecordNV) 7210 intermediate.addShaderRecordNVCount(); 7211 if (qualifier.perTaskNV) 7212 intermediate.addTaskNVCount(); 7213 #endif 7214 } 7215 7216 // 7217 // "For a block, this process applies to the entire block, or until the first member 7218 // is reached that has a location layout qualifier. When a block member is declared with a location 7219 // qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level 7220 // declaration. Subsequent members are again assigned consecutive locations, based on the newest location, 7221 // until the next member declared with a location qualifier. The values used for locations do not have to be 7222 // declared in increasing order." 7223 void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation) 7224 { 7225 // "If a block has no block-level location layout qualifier, it is required that either all or none of its members 7226 // have a location layout qualifier, or a compile-time error results." 7227 if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation) 7228 error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", ""); 7229 else { 7230 if (memberWithLocation) { 7231 // remove any block-level location and make it per *every* member 7232 int nextLocation = 0; // by the rule above, initial value is not relevant 7233 if (qualifier.hasAnyLocation()) { 7234 nextLocation = qualifier.layoutLocation; 7235 qualifier.layoutLocation = TQualifier::layoutLocationEnd; 7236 if (qualifier.hasComponent()) { 7237 // "It is a compile-time error to apply the *component* qualifier to a ... block" 7238 error(loc, "cannot apply to a block", "component", ""); 7239 } 7240 if (qualifier.hasIndex()) { 7241 error(loc, "cannot apply to a block", "index", ""); 7242 } 7243 } 7244 for (unsigned int member = 0; member < typeList.size(); ++member) { 7245 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 7246 const TSourceLoc& memberLoc = typeList[member].loc; 7247 if (! memberQualifier.hasLocation()) { 7248 if (nextLocation >= (int)TQualifier::layoutLocationEnd) 7249 error(memberLoc, "location is too large", "location", ""); 7250 memberQualifier.layoutLocation = nextLocation; 7251 memberQualifier.layoutComponent = TQualifier::layoutComponentEnd; 7252 } 7253 nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize( 7254 *typeList[member].type, language); 7255 } 7256 } 7257 } 7258 } 7259 7260 void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList) 7261 { 7262 // "If a block is qualified with xfb_offset, all its 7263 // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any 7264 // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer 7265 // offsets." 7266 7267 if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset()) 7268 return; 7269 7270 int nextOffset = qualifier.layoutXfbOffset; 7271 for (unsigned int member = 0; member < typeList.size(); ++member) { 7272 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 7273 bool containsDouble = false; 7274 int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, containsDouble); 7275 // see if we need to auto-assign an offset to this member 7276 if (! memberQualifier.hasXfbOffset()) { 7277 // "if applied to an aggregate containing a double, the offset must also be a multiple of 8" 7278 if (containsDouble) 7279 RoundToPow2(nextOffset, 8); 7280 memberQualifier.layoutXfbOffset = nextOffset; 7281 } else 7282 nextOffset = memberQualifier.layoutXfbOffset; 7283 nextOffset += memberSize; 7284 } 7285 7286 // The above gave all block members an offset, so we can take it off the block now, 7287 // which will avoid double counting the offset usage. 7288 qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd; 7289 } 7290 7291 // Calculate and save the offset of each block member, using the recursively 7292 // defined block offset rules and the user-provided offset and align. 7293 // 7294 // Also, compute and save the total size of the block. For the block's size, arrayness 7295 // is not taken into account, as each element is backed by a separate buffer. 7296 // 7297 void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList) 7298 { 7299 if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) 7300 return; 7301 if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar) 7302 return; 7303 7304 int offset = 0; 7305 int memberSize; 7306 for (unsigned int member = 0; member < typeList.size(); ++member) { 7307 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 7308 const TSourceLoc& memberLoc = typeList[member].loc; 7309 7310 // "When align is applied to an array, it effects only the start of the array, not the array's internal stride." 7311 7312 // modify just the children's view of matrix layout, if there is one for this member 7313 TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix; 7314 int dummyStride; 7315 int memberAlignment = intermediate.getMemberAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking, 7316 subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor); 7317 if (memberQualifier.hasOffset()) { 7318 // "The specified offset must be a multiple 7319 // of the base alignment of the type of the block member it qualifies, or a compile-time error results." 7320 if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) 7321 error(memberLoc, "must be a multiple of the member's alignment", "offset", ""); 7322 7323 // GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous 7324 // member in the block or that lies within the previous member of the block" 7325 if (spvVersion.spv == 0) { 7326 if (memberQualifier.layoutOffset < offset) 7327 error(memberLoc, "cannot lie in previous members", "offset", ""); 7328 7329 // "The offset qualifier forces the qualified member to start at or after the specified 7330 // integral-constant expression, which will be its byte offset from the beginning of the buffer. 7331 // "The actual offset of a member is computed as 7332 // follows: If offset was declared, start with that offset, otherwise start with the next available offset." 7333 offset = std::max(offset, memberQualifier.layoutOffset); 7334 } else { 7335 // TODO: Vulkan: "It is a compile-time error to have any offset, explicit or assigned, 7336 // that lies within another member of the block." 7337 7338 offset = memberQualifier.layoutOffset; 7339 } 7340 } 7341 7342 // "The actual alignment of a member will be the greater of the specified align alignment and the standard 7343 // (e.g., std140) base alignment for the member's type." 7344 if (memberQualifier.hasAlign()) 7345 memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign); 7346 7347 // "If the resulting offset is not a multiple of the actual alignment, 7348 // increase it to the first offset that is a multiple of 7349 // the actual alignment." 7350 RoundToPow2(offset, memberAlignment); 7351 typeList[member].type->getQualifier().layoutOffset = offset; 7352 offset += memberSize; 7353 } 7354 } 7355 7356 // For an identifier that is already declared, add more qualification to it. 7357 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier) 7358 { 7359 TSymbol* symbol = symbolTable.find(identifier); 7360 7361 // A forward declaration of a block reference looks to the grammar like adding 7362 // a qualifier to an existing symbol. Detect this and create the block reference 7363 // type with an empty type list, which will be filled in later in 7364 // TParseContext::declareBlock. 7365 if (!symbol && qualifier.layoutBufferReference) { 7366 TTypeList typeList; 7367 TType blockType(&typeList, identifier, qualifier);; 7368 TType blockNameType(EbtReference, blockType, identifier); 7369 TVariable* blockNameVar = new TVariable(&identifier, blockNameType, true); 7370 if (! symbolTable.insert(*blockNameVar)) { 7371 error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); 7372 } 7373 return; 7374 } 7375 7376 if (! symbol) { 7377 error(loc, "identifier not previously declared", identifier.c_str(), ""); 7378 return; 7379 } 7380 if (symbol->getAsFunction()) { 7381 error(loc, "cannot re-qualify a function name", identifier.c_str(), ""); 7382 return; 7383 } 7384 7385 if (qualifier.isAuxiliary() || 7386 qualifier.isMemory() || 7387 qualifier.isInterpolation() || 7388 qualifier.hasLayout() || 7389 qualifier.storage != EvqTemporary || 7390 qualifier.precision != EpqNone) { 7391 error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), ""); 7392 return; 7393 } 7394 7395 // For read-only built-ins, add a new symbol for holding the modified qualifier. 7396 // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block) 7397 if (symbol->isReadOnly()) 7398 symbol = symbolTable.copyUp(symbol); 7399 7400 if (qualifier.invariant) { 7401 if (intermediate.inIoAccessed(identifier)) 7402 error(loc, "cannot change qualification after use", "invariant", ""); 7403 symbol->getWritableType().getQualifier().invariant = true; 7404 invariantCheck(loc, symbol->getType().getQualifier()); 7405 } else if (qualifier.noContraction) { 7406 if (intermediate.inIoAccessed(identifier)) 7407 error(loc, "cannot change qualification after use", "precise", ""); 7408 symbol->getWritableType().getQualifier().noContraction = true; 7409 } else if (qualifier.specConstant) { 7410 symbol->getWritableType().getQualifier().makeSpecConstant(); 7411 if (qualifier.hasSpecConstantId()) 7412 symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId; 7413 } else 7414 warn(loc, "unknown requalification", "", ""); 7415 } 7416 7417 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers) 7418 { 7419 for (unsigned int i = 0; i < identifiers.size(); ++i) 7420 addQualifierToExisting(loc, qualifier, *identifiers[i]); 7421 } 7422 7423 // Make sure 'invariant' isn't being applied to a non-allowed object. 7424 void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qualifier) 7425 { 7426 if (! qualifier.invariant) 7427 return; 7428 7429 bool pipeOut = qualifier.isPipeOutput(); 7430 bool pipeIn = qualifier.isPipeInput(); 7431 if (version >= 300 || (profile != EEsProfile && version >= 420)) { 7432 if (! pipeOut) 7433 error(loc, "can only apply to an output", "invariant", ""); 7434 } else { 7435 if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn)) 7436 error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", ""); 7437 } 7438 } 7439 7440 // 7441 // Updating default qualifier for the case of a declaration with just a qualifier, 7442 // no type, block, or identifier. 7443 // 7444 void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType) 7445 { 7446 if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) { 7447 #ifdef NV_EXTENSIONS 7448 assert(language == EShLangTessControl || language == EShLangGeometry || language == EShLangMeshNV); 7449 #else 7450 assert(language == EShLangTessControl || language == EShLangGeometry); 7451 #endif 7452 const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; 7453 7454 if (publicType.qualifier.storage != EvqVaryingOut) 7455 error(loc, "can only apply to 'out'", id, ""); 7456 if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) 7457 error(loc, "cannot change previously set layout value", id, ""); 7458 7459 if (language == EShLangTessControl) 7460 checkIoArraysConsistency(loc); 7461 } 7462 #ifdef NV_EXTENSIONS 7463 if (publicType.shaderQualifiers.primitives != TQualifier::layoutNotSet) { 7464 assert(language == EShLangMeshNV); 7465 const char* id = "max_primitives"; 7466 7467 if (publicType.qualifier.storage != EvqVaryingOut) 7468 error(loc, "can only apply to 'out'", id, ""); 7469 if (! intermediate.setPrimitives(publicType.shaderQualifiers.primitives)) 7470 error(loc, "cannot change previously set layout value", id, ""); 7471 } 7472 #endif 7473 if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) { 7474 if (publicType.qualifier.storage != EvqVaryingIn) 7475 error(loc, "can only apply to 'in'", "invocations", ""); 7476 if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) 7477 error(loc, "cannot change previously set layout value", "invocations", ""); 7478 } 7479 if (publicType.shaderQualifiers.geometry != ElgNone) { 7480 if (publicType.qualifier.storage == EvqVaryingIn) { 7481 switch (publicType.shaderQualifiers.geometry) { 7482 case ElgPoints: 7483 case ElgLines: 7484 case ElgLinesAdjacency: 7485 case ElgTriangles: 7486 case ElgTrianglesAdjacency: 7487 case ElgQuads: 7488 case ElgIsolines: 7489 #ifdef NV_EXTENSIONS 7490 if (language == EShLangMeshNV) { 7491 error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 7492 break; 7493 } 7494 #endif 7495 if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) { 7496 if (language == EShLangGeometry) 7497 checkIoArraysConsistency(loc); 7498 } else 7499 error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 7500 break; 7501 default: 7502 error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 7503 } 7504 } else if (publicType.qualifier.storage == EvqVaryingOut) { 7505 switch (publicType.shaderQualifiers.geometry) { 7506 #ifdef NV_EXTENSIONS 7507 case ElgLines: 7508 case ElgTriangles: 7509 if (language != EShLangMeshNV) { 7510 error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 7511 break; 7512 } 7513 #endif 7514 // Fall through 7515 case ElgPoints: 7516 case ElgLineStrip: 7517 case ElgTriangleStrip: 7518 if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry)) 7519 error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 7520 break; 7521 default: 7522 error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 7523 } 7524 } else 7525 error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage)); 7526 } 7527 if (publicType.shaderQualifiers.spacing != EvsNone) { 7528 if (publicType.qualifier.storage == EvqVaryingIn) { 7529 if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing)) 7530 error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); 7531 } else 7532 error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); 7533 } 7534 if (publicType.shaderQualifiers.order != EvoNone) { 7535 if (publicType.qualifier.storage == EvqVaryingIn) { 7536 if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order)) 7537 error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); 7538 } else 7539 error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); 7540 } 7541 if (publicType.shaderQualifiers.pointMode) { 7542 if (publicType.qualifier.storage == EvqVaryingIn) 7543 intermediate.setPointMode(); 7544 else 7545 error(loc, "can only apply to 'in'", "point_mode", ""); 7546 } 7547 for (int i = 0; i < 3; ++i) { 7548 if (publicType.shaderQualifiers.localSize[i] > 1) { 7549 if (publicType.qualifier.storage == EvqVaryingIn) { 7550 if (! intermediate.setLocalSize(i, publicType.shaderQualifiers.localSize[i])) 7551 error(loc, "cannot change previously set size", "local_size", ""); 7552 else { 7553 int max = 0; 7554 if (language == EShLangCompute) { 7555 switch (i) { 7556 case 0: max = resources.maxComputeWorkGroupSizeX; break; 7557 case 1: max = resources.maxComputeWorkGroupSizeY; break; 7558 case 2: max = resources.maxComputeWorkGroupSizeZ; break; 7559 default: break; 7560 } 7561 if (intermediate.getLocalSize(i) > (unsigned int)max) 7562 error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", ""); 7563 } 7564 #ifdef NV_EXTENSIONS 7565 else if (language == EShLangMeshNV) { 7566 switch (i) { 7567 case 0: max = resources.maxMeshWorkGroupSizeX_NV; break; 7568 case 1: max = resources.maxMeshWorkGroupSizeY_NV; break; 7569 case 2: max = resources.maxMeshWorkGroupSizeZ_NV; break; 7570 default: break; 7571 } 7572 if (intermediate.getLocalSize(i) > (unsigned int)max) 7573 error(loc, "too large; see gl_MaxMeshWorkGroupSizeNV", "local_size", ""); 7574 } 7575 else if (language == EShLangTaskNV) { 7576 switch (i) { 7577 case 0: max = resources.maxTaskWorkGroupSizeX_NV; break; 7578 case 1: max = resources.maxTaskWorkGroupSizeY_NV; break; 7579 case 2: max = resources.maxTaskWorkGroupSizeZ_NV; break; 7580 default: break; 7581 } 7582 if (intermediate.getLocalSize(i) > (unsigned int)max) 7583 error(loc, "too large; see gl_MaxTaskWorkGroupSizeNV", "local_size", ""); 7584 } 7585 #endif 7586 else { 7587 assert(0); 7588 } 7589 7590 // Fix the existing constant gl_WorkGroupSize with this new information. 7591 TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); 7592 if (workGroupSize != nullptr) 7593 workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i)); 7594 } 7595 } else 7596 error(loc, "can only apply to 'in'", "local_size", ""); 7597 } 7598 if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) { 7599 if (publicType.qualifier.storage == EvqVaryingIn) { 7600 if (! intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i])) 7601 error(loc, "cannot change previously set size", "local_size", ""); 7602 } else 7603 error(loc, "can only apply to 'in'", "local_size id", ""); 7604 // Set the workgroup built-in variable as a specialization constant 7605 TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); 7606 if (workGroupSize != nullptr) 7607 workGroupSize->getWritableType().getQualifier().specConstant = true; 7608 } 7609 } 7610 if (publicType.shaderQualifiers.earlyFragmentTests) { 7611 if (publicType.qualifier.storage == EvqVaryingIn) 7612 intermediate.setEarlyFragmentTests(); 7613 else 7614 error(loc, "can only apply to 'in'", "early_fragment_tests", ""); 7615 } 7616 if (publicType.shaderQualifiers.postDepthCoverage) { 7617 if (publicType.qualifier.storage == EvqVaryingIn) 7618 intermediate.setPostDepthCoverage(); 7619 else 7620 error(loc, "can only apply to 'in'", "post_coverage_coverage", ""); 7621 } 7622 if (publicType.shaderQualifiers.blendEquation) { 7623 if (publicType.qualifier.storage != EvqVaryingOut) 7624 error(loc, "can only apply to 'out'", "blend equation", ""); 7625 } 7626 7627 #ifdef NV_EXTENSIONS 7628 if (publicType.shaderQualifiers.layoutDerivativeGroupQuads && 7629 publicType.shaderQualifiers.layoutDerivativeGroupLinear) { 7630 error(loc, "cannot be both specified", "derivative_group_quadsNV and derivative_group_linearNV", ""); 7631 } 7632 7633 if (publicType.shaderQualifiers.layoutDerivativeGroupQuads) { 7634 if (publicType.qualifier.storage == EvqVaryingIn) { 7635 if ((intermediate.getLocalSize(0) & 1) || 7636 (intermediate.getLocalSize(1) & 1)) 7637 error(loc, "requires local_size_x and local_size_y to be multiple of two", "derivative_group_quadsNV", ""); 7638 else 7639 intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupQuads); 7640 } 7641 else 7642 error(loc, "can only apply to 'in'", "derivative_group_quadsNV", ""); 7643 } 7644 if (publicType.shaderQualifiers.layoutDerivativeGroupLinear) { 7645 if (publicType.qualifier.storage == EvqVaryingIn) { 7646 if((intermediate.getLocalSize(0) * 7647 intermediate.getLocalSize(1) * 7648 intermediate.getLocalSize(2)) % 4 != 0) 7649 error(loc, "requires total group size to be multiple of four", "derivative_group_linearNV", ""); 7650 else 7651 intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupLinear); 7652 } 7653 else 7654 error(loc, "can only apply to 'in'", "derivative_group_linearNV", ""); 7655 } 7656 #endif 7657 const TQualifier& qualifier = publicType.qualifier; 7658 7659 if (qualifier.isAuxiliary() || 7660 qualifier.isMemory() || 7661 qualifier.isInterpolation() || 7662 qualifier.precision != EpqNone) 7663 error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", ""); 7664 // "The offset qualifier can only be used on block members of blocks..." 7665 // "The align qualifier can only be used on blocks or block members..." 7666 if (qualifier.hasOffset() || 7667 qualifier.hasAlign()) 7668 error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", ""); 7669 7670 layoutQualifierCheck(loc, qualifier); 7671 7672 switch (qualifier.storage) { 7673 case EvqUniform: 7674 if (qualifier.hasMatrix()) 7675 globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; 7676 if (qualifier.hasPacking()) 7677 globalUniformDefaults.layoutPacking = qualifier.layoutPacking; 7678 break; 7679 case EvqBuffer: 7680 if (qualifier.hasMatrix()) 7681 globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; 7682 if (qualifier.hasPacking()) 7683 globalBufferDefaults.layoutPacking = qualifier.layoutPacking; 7684 break; 7685 case EvqVaryingIn: 7686 break; 7687 case EvqVaryingOut: 7688 if (qualifier.hasStream()) 7689 globalOutputDefaults.layoutStream = qualifier.layoutStream; 7690 if (qualifier.hasXfbBuffer()) 7691 globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer; 7692 if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) { 7693 if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride)) 7694 error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); 7695 } 7696 break; 7697 default: 7698 error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); 7699 return; 7700 } 7701 7702 if (qualifier.hasBinding()) 7703 error(loc, "cannot declare a default, include a type or full declaration", "binding", ""); 7704 if (qualifier.hasAnyLocation()) 7705 error(loc, "cannot declare a default, use a full declaration", "location/component/index", ""); 7706 if (qualifier.hasXfbOffset()) 7707 error(loc, "cannot declare a default, use a full declaration", "xfb_offset", ""); 7708 if (qualifier.layoutPushConstant) 7709 error(loc, "cannot declare a default, can only be used on a block", "push_constant", ""); 7710 if (qualifier.layoutBufferReference) 7711 error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", ""); 7712 if (qualifier.hasSpecConstantId()) 7713 error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", ""); 7714 #ifdef NV_EXTENSIONS 7715 if (qualifier.layoutShaderRecordNV) 7716 error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", ""); 7717 #endif 7718 } 7719 7720 // 7721 // Take the sequence of statements that has been built up since the last case/default, 7722 // put it on the list of top-level nodes for the current (inner-most) switch statement, 7723 // and follow that by the case/default we are on now. (See switch topology comment on 7724 // TIntermSwitch.) 7725 // 7726 void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode) 7727 { 7728 TIntermSequence* switchSequence = switchSequenceStack.back(); 7729 7730 if (statements) { 7731 if (switchSequence->size() == 0) 7732 error(statements->getLoc(), "cannot have statements before first case/default label", "switch", ""); 7733 statements->setOperator(EOpSequence); 7734 switchSequence->push_back(statements); 7735 } 7736 if (branchNode) { 7737 // check all previous cases for the same label (or both are 'default') 7738 for (unsigned int s = 0; s < switchSequence->size(); ++s) { 7739 TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode(); 7740 if (prevBranch) { 7741 TIntermTyped* prevExpression = prevBranch->getExpression(); 7742 TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression(); 7743 if (prevExpression == nullptr && newExpression == nullptr) 7744 error(branchNode->getLoc(), "duplicate label", "default", ""); 7745 else if (prevExpression != nullptr && 7746 newExpression != nullptr && 7747 prevExpression->getAsConstantUnion() && 7748 newExpression->getAsConstantUnion() && 7749 prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() == 7750 newExpression->getAsConstantUnion()->getConstArray()[0].getIConst()) 7751 error(branchNode->getLoc(), "duplicated value", "case", ""); 7752 } 7753 } 7754 switchSequence->push_back(branchNode); 7755 } 7756 } 7757 7758 // 7759 // Turn the top-level node sequence built up of wrapupSwitchSubsequence9) 7760 // into a switch node. 7761 // 7762 TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, TIntermAggregate* lastStatements) 7763 { 7764 profileRequires(loc, EEsProfile, 300, nullptr, "switch statements"); 7765 profileRequires(loc, ENoProfile, 130, nullptr, "switch statements"); 7766 7767 wrapupSwitchSubsequence(lastStatements, nullptr); 7768 7769 if (expression == nullptr || 7770 (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) || 7771 expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) 7772 error(loc, "condition must be a scalar integer expression", "switch", ""); 7773 7774 // If there is nothing to do, drop the switch but still execute the expression 7775 TIntermSequence* switchSequence = switchSequenceStack.back(); 7776 if (switchSequence->size() == 0) 7777 return expression; 7778 7779 if (lastStatements == nullptr) { 7780 // This was originally an ERRROR, because early versions of the specification said 7781 // "it is an error to have no statement between a label and the end of the switch statement." 7782 // The specifications were updated to remove this (being ill-defined what a "statement" was), 7783 // so, this became a warning. However, 3.0 tests still check for the error. 7784 if (profile == EEsProfile && version <= 300 && ! relaxedErrors()) 7785 error(loc, "last case/default label not followed by statements", "switch", ""); 7786 else 7787 warn(loc, "last case/default label not followed by statements", "switch", ""); 7788 7789 // emulate a break for error recovery 7790 lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc)); 7791 lastStatements->setOperator(EOpSequence); 7792 switchSequence->push_back(lastStatements); 7793 } 7794 7795 TIntermAggregate* body = new TIntermAggregate(EOpSequence); 7796 body->getSequence() = *switchSequenceStack.back(); 7797 body->setLoc(loc); 7798 7799 TIntermSwitch* switchNode = new TIntermSwitch(expression, body); 7800 switchNode->setLoc(loc); 7801 7802 return switchNode; 7803 } 7804 7805 } // end namespace glslang 7806