Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 // Copyright (C) 2013-2016 LunarG, Inc.
      4 // Copyright (C) 2015-2018 Google, Inc.
      5 //
      6 // All rights reserved.
      7 //
      8 // Redistribution and use in source and binary forms, with or without
      9 // modification, are permitted provided that the following conditions
     10 // are met:
     11 //
     12 //    Redistributions of source code must retain the above copyright
     13 //    notice, this list of conditions and the following disclaimer.
     14 //
     15 //    Redistributions in binary form must reproduce the above
     16 //    copyright notice, this list of conditions and the following
     17 //    disclaimer in the documentation and/or other materials provided
     18 //    with the distribution.
     19 //
     20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
     21 //    contributors may be used to endorse or promote products derived
     22 //    from this software without specific prior written permission.
     23 //
     24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35 // POSSIBILITY OF SUCH DAMAGE.
     36 //
     37 
     38 //
     39 // Implement the top-level of interface to the compiler/linker,
     40 // as defined in ShaderLang.h
     41 // This is the platform independent interface between an OGL driver
     42 // and the shading language compiler/linker.
     43 //
     44 #include <cstring>
     45 #include <iostream>
     46 #include <sstream>
     47 #include <memory>
     48 #include "SymbolTable.h"
     49 #include "ParseHelper.h"
     50 #include "Scan.h"
     51 #include "ScanContext.h"
     52 
     53 #ifdef ENABLE_HLSL
     54 #include "../../hlsl/hlslParseHelper.h"
     55 #include "../../hlsl/hlslParseables.h"
     56 #include "../../hlsl/hlslScanContext.h"
     57 #endif
     58 
     59 #include "../Include/ShHandle.h"
     60 #include "../../OGLCompilersDLL/InitializeDll.h"
     61 
     62 #include "preprocessor/PpContext.h"
     63 
     64 #define SH_EXPORTING
     65 #include "../Public/ShaderLang.h"
     66 #include "reflection.h"
     67 #include "iomapper.h"
     68 #include "Initialize.h"
     69 
     70 // TODO: this really shouldn't be here, it is only because of the trial addition
     71 // of printing pre-processed tokens, which requires knowing the string literal
     72 // token to print ", but none of that seems appropriate for this file.
     73 #include "preprocessor/PpTokens.h"
     74 
     75 namespace { // anonymous namespace for file-local functions and symbols
     76 
     77 // Total number of successful initializers of glslang: a refcount
     78 // Shared global; access should be protected by a global mutex/critical section.
     79 int NumberOfClients = 0;
     80 
     81 using namespace glslang;
     82 
     83 // Create a language specific version of parseables.
     84 TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source)
     85 {
     86     switch (source) {
     87     case EShSourceGlsl: return new TBuiltIns();              // GLSL builtIns
     88 #ifdef ENABLE_HLSL
     89     case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics
     90 #endif
     91 
     92     default:
     93         infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
     94         return nullptr;
     95     }
     96 }
     97 
     98 // Create a language specific version of a parse context.
     99 TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate,
    100                                       int version, EProfile profile, EShSource source,
    101                                       EShLanguage language, TInfoSink& infoSink,
    102                                       SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
    103                                       bool parsingBuiltIns, std::string sourceEntryPointName = "")
    104 {
    105     switch (source) {
    106     case EShSourceGlsl: {
    107         if (sourceEntryPointName.size() == 0)
    108             intermediate.setEntryPointName("main");
    109         TString entryPoint = sourceEntryPointName.c_str();
    110         return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
    111                                  language, infoSink, forwardCompatible, messages, &entryPoint);
    112     }
    113 #ifdef ENABLE_HLSL
    114     case EShSourceHlsl:
    115         return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
    116                                     language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages);
    117 #endif
    118     default:
    119         infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
    120         return nullptr;
    121     }
    122 }
    123 
    124 // Local mapping functions for making arrays of symbol tables....
    125 
    126 const int VersionCount = 17;  // index range in MapVersionToIndex
    127 
    128 int MapVersionToIndex(int version)
    129 {
    130     int index = 0;
    131 
    132     switch (version) {
    133     case 100: index =  0; break;
    134     case 110: index =  1; break;
    135     case 120: index =  2; break;
    136     case 130: index =  3; break;
    137     case 140: index =  4; break;
    138     case 150: index =  5; break;
    139     case 300: index =  6; break;
    140     case 330: index =  7; break;
    141     case 400: index =  8; break;
    142     case 410: index =  9; break;
    143     case 420: index = 10; break;
    144     case 430: index = 11; break;
    145     case 440: index = 12; break;
    146     case 310: index = 13; break;
    147     case 450: index = 14; break;
    148     case 500: index =  0; break; // HLSL
    149     case 320: index = 15; break;
    150     case 460: index = 16; break;
    151     default:  assert(0);  break;
    152     }
    153 
    154     assert(index < VersionCount);
    155 
    156     return index;
    157 }
    158 
    159 const int SpvVersionCount = 3;  // index range in MapSpvVersionToIndex
    160 
    161 int MapSpvVersionToIndex(const SpvVersion& spvVersion)
    162 {
    163     int index = 0;
    164 
    165     if (spvVersion.openGl > 0)
    166         index = 1;
    167     else if (spvVersion.vulkan > 0)
    168         index = 2;
    169 
    170     assert(index < SpvVersionCount);
    171 
    172     return index;
    173 }
    174 
    175 const int ProfileCount = 4;   // index range in MapProfileToIndex
    176 
    177 int MapProfileToIndex(EProfile profile)
    178 {
    179     int index = 0;
    180 
    181     switch (profile) {
    182     case ENoProfile:            index = 0; break;
    183     case ECoreProfile:          index = 1; break;
    184     case ECompatibilityProfile: index = 2; break;
    185     case EEsProfile:            index = 3; break;
    186     default:                               break;
    187     }
    188 
    189     assert(index < ProfileCount);
    190 
    191     return index;
    192 }
    193 
    194 const int SourceCount = 2;
    195 
    196 int MapSourceToIndex(EShSource source)
    197 {
    198     int index = 0;
    199 
    200     switch (source) {
    201     case EShSourceGlsl: index = 0; break;
    202     case EShSourceHlsl: index = 1; break;
    203     default:                       break;
    204     }
    205 
    206     assert(index < SourceCount);
    207 
    208     return index;
    209 }
    210 
    211 // only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins
    212 enum EPrecisionClass {
    213     EPcGeneral,
    214     EPcFragment,
    215     EPcCount
    216 };
    217 
    218 // A process-global symbol table per version per profile for built-ins common
    219 // to multiple stages (languages), and a process-global symbol table per version
    220 // per profile per stage for built-ins unique to each stage.  They will be sparsely
    221 // populated, so they will only be generated as needed.
    222 //
    223 // Each has a different set of built-ins, and we want to preserve that from
    224 // compile to compile.
    225 //
    226 TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EPcCount] = {};
    227 TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EShLangCount] = {};
    228 
    229 TPoolAllocator* PerProcessGPA = nullptr;
    230 
    231 //
    232 // Parse and add to the given symbol table the content of the given shader string.
    233 //
    234 bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
    235                            EShSource source, TInfoSink& infoSink, TSymbolTable& symbolTable)
    236 {
    237     TIntermediate intermediate(language, version, profile);
    238 
    239     intermediate.setSource(source);
    240 
    241     std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(symbolTable, intermediate, version, profile, source,
    242                                                                        language, infoSink, spvVersion, true, EShMsgDefault,
    243                                                                        true));
    244 
    245     TShader::ForbidIncluder includer;
    246     TPpContext ppContext(*parseContext, "", includer);
    247     TScanContext scanContext(*parseContext);
    248     parseContext->setScanContext(&scanContext);
    249     parseContext->setPpContext(&ppContext);
    250 
    251     //
    252     // Push the symbol table to give it an initial scope.  This
    253     // push should not have a corresponding pop, so that built-ins
    254     // are preserved, and the test for an empty table fails.
    255     //
    256 
    257     symbolTable.push();
    258 
    259     const char* builtInShaders[2];
    260     size_t builtInLengths[2];
    261     builtInShaders[0] = builtIns.c_str();
    262     builtInLengths[0] = builtIns.size();
    263 
    264     if (builtInLengths[0] == 0)
    265         return true;
    266 
    267     TInputScanner input(1, builtInShaders, builtInLengths);
    268     if (! parseContext->parseShaderStrings(ppContext, input) != 0) {
    269         infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
    270         printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str());
    271         printf("%s\n", builtInShaders[0]);
    272 
    273         return false;
    274     }
    275 
    276     return true;
    277 }
    278 
    279 int CommonIndex(EProfile profile, EShLanguage language)
    280 {
    281     return (profile == EEsProfile && language == EShLangFragment) ? EPcFragment : EPcGeneral;
    282 }
    283 
    284 //
    285 // To initialize per-stage shared tables, with the common table already complete.
    286 //
    287 void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, const SpvVersion& spvVersion,
    288                                 EShLanguage language, EShSource source, TInfoSink& infoSink, TSymbolTable** commonTable,
    289                                 TSymbolTable** symbolTables)
    290 {
    291     (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
    292     InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spvVersion, language, source,
    293                           infoSink, *symbolTables[language]);
    294     builtInParseables.identifyBuiltIns(version, profile, spvVersion, language, *symbolTables[language]);
    295     if (profile == EEsProfile && version >= 300)
    296         (*symbolTables[language]).setNoBuiltInRedeclarations();
    297     if (version == 110)
    298         (*symbolTables[language]).setSeparateNameSpaces();
    299 }
    300 
    301 //
    302 // Initialize the full set of shareable symbol tables;
    303 // The common (cross-stage) and those shareable per-stage.
    304 //
    305 bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TSymbolTable** symbolTables, int version, EProfile profile, const SpvVersion& spvVersion, EShSource source)
    306 {
    307     std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
    308 
    309     if (builtInParseables == nullptr)
    310         return false;
    311 
    312     builtInParseables->initialize(version, profile, spvVersion);
    313 
    314     // do the common tables
    315     InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, source,
    316                           infoSink, *commonTable[EPcGeneral]);
    317     if (profile == EEsProfile)
    318         InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, source,
    319                               infoSink, *commonTable[EPcFragment]);
    320 
    321     // do the per-stage tables
    322 
    323     // always have vertex and fragment
    324     InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, source,
    325                                infoSink, commonTable, symbolTables);
    326     InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, source,
    327                                infoSink, commonTable, symbolTables);
    328 
    329     // check for tessellation
    330     if ((profile != EEsProfile && version >= 150) ||
    331         (profile == EEsProfile && version >= 310)) {
    332         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, source,
    333                                    infoSink, commonTable, symbolTables);
    334         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, source,
    335                                    infoSink, commonTable, symbolTables);
    336     }
    337 
    338     // check for geometry
    339     if ((profile != EEsProfile && version >= 150) ||
    340         (profile == EEsProfile && version >= 310))
    341         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source,
    342                                    infoSink, commonTable, symbolTables);
    343 
    344     // check for compute
    345     if ((profile != EEsProfile && version >= 420) ||
    346         (profile == EEsProfile && version >= 310))
    347         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
    348                                    infoSink, commonTable, symbolTables);
    349 
    350 #ifdef NV_EXTENSIONS
    351     // check for ray tracing stages
    352     if (profile != EEsProfile && version >= 450) {
    353         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
    354             infoSink, commonTable, symbolTables);
    355         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
    356             infoSink, commonTable, symbolTables);
    357         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
    358             infoSink, commonTable, symbolTables);
    359         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
    360             infoSink, commonTable, symbolTables);
    361         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
    362             infoSink, commonTable, symbolTables);
    363         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
    364             infoSink, commonTable, symbolTables);
    365     }
    366 
    367     // check for mesh
    368     if ((profile != EEsProfile && version >= 450) ||
    369         (profile == EEsProfile && version >= 320))
    370         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMeshNV, source,
    371                                    infoSink, commonTable, symbolTables);
    372 
    373     // check for task
    374     if ((profile != EEsProfile && version >= 450) ||
    375         (profile == EEsProfile && version >= 320))
    376         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
    377                                    infoSink, commonTable, symbolTables);
    378 #endif
    379 
    380     return true;
    381 }
    382 
    383 bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, int version,
    384                                EProfile profile, const SpvVersion& spvVersion, EShLanguage language, EShSource source)
    385 {
    386     std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
    387 
    388     if (builtInParseables == nullptr)
    389         return false;
    390 
    391     builtInParseables->initialize(*resources, version, profile, spvVersion, language);
    392     InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, source, infoSink, symbolTable);
    393     builtInParseables->identifyBuiltIns(version, profile, spvVersion, language, symbolTable, *resources);
    394 
    395     return true;
    396 }
    397 
    398 //
    399 // To do this on the fly, we want to leave the current state of our thread's
    400 // pool allocator intact, so:
    401 //  - Switch to a new pool for parsing the built-ins
    402 //  - Do the parsing, which builds the symbol table, using the new pool
    403 //  - Switch to the process-global pool to save a copy of the resulting symbol table
    404 //  - Free up the new pool used to parse the built-ins
    405 //  - Switch back to the original thread's pool
    406 //
    407 // This only gets done the first time any thread needs a particular symbol table
    408 // (lazy evaluation).
    409 //
    410 void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& spvVersion, EShSource source)
    411 {
    412     TInfoSink infoSink;
    413 
    414     // Make sure only one thread tries to do this at a time
    415     glslang::GetGlobalLock();
    416 
    417     // See if it's already been done for this version/profile combination
    418     int versionIndex = MapVersionToIndex(version);
    419     int spvVersionIndex = MapSpvVersionToIndex(spvVersion);
    420     int profileIndex = MapProfileToIndex(profile);
    421     int sourceIndex = MapSourceToIndex(source);
    422     if (CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][EPcGeneral]) {
    423         glslang::ReleaseGlobalLock();
    424 
    425         return;
    426     }
    427 
    428     // Switch to a new pool
    429     TPoolAllocator& previousAllocator = GetThreadPoolAllocator();
    430     TPoolAllocator* builtInPoolAllocator = new TPoolAllocator;
    431     SetThreadPoolAllocator(builtInPoolAllocator);
    432 
    433     // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped.
    434     TSymbolTable* commonTable[EPcCount];
    435     TSymbolTable* stageTables[EShLangCount];
    436     for (int precClass = 0; precClass < EPcCount; ++precClass)
    437         commonTable[precClass] = new TSymbolTable;
    438     for (int stage = 0; stage < EShLangCount; ++stage)
    439         stageTables[stage] = new TSymbolTable;
    440 
    441     // Generate the local symbol tables using the new pool
    442     InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spvVersion, source);
    443 
    444     // Switch to the process-global pool
    445     SetThreadPoolAllocator(PerProcessGPA);
    446 
    447     // Copy the local symbol tables from the new pool to the global tables using the process-global pool
    448     for (int precClass = 0; precClass < EPcCount; ++precClass) {
    449         if (! commonTable[precClass]->isEmpty()) {
    450             CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass] = new TSymbolTable;
    451             CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->copyTable(*commonTable[precClass]);
    452             CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->readOnly();
    453         }
    454     }
    455     for (int stage = 0; stage < EShLangCount; ++stage) {
    456         if (! stageTables[stage]->isEmpty()) {
    457             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage] = new TSymbolTable;
    458             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->adoptLevels(*CommonSymbolTable
    459                               [versionIndex][spvVersionIndex][profileIndex][sourceIndex][CommonIndex(profile, (EShLanguage)stage)]);
    460             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->copyTable(*stageTables[stage]);
    461             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->readOnly();
    462         }
    463     }
    464 
    465     // Clean up the local tables before deleting the pool they used.
    466     for (int precClass = 0; precClass < EPcCount; ++precClass)
    467         delete commonTable[precClass];
    468     for (int stage = 0; stage < EShLangCount; ++stage)
    469         delete stageTables[stage];
    470 
    471     delete builtInPoolAllocator;
    472     SetThreadPoolAllocator(&previousAllocator);
    473 
    474     glslang::ReleaseGlobalLock();
    475 }
    476 
    477 // Return true if the shader was correctly specified for version/profile/stage.
    478 bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion,
    479                           EShSource source, int& version, EProfile& profile, const SpvVersion& spvVersion)
    480 {
    481     const int FirstProfileVersion = 150;
    482     bool correct = true;
    483 
    484     if (source == EShSourceHlsl) {
    485         version = 500;          // shader model; currently a characteristic of glslang, not the input
    486         profile = ECoreProfile; // allow doubles in prototype parsing
    487         return correct;
    488     }
    489 
    490     // Get a version...
    491     if (version == 0) {
    492         version = defaultVersion;
    493         // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader");
    494     }
    495 
    496     // Get a good profile...
    497     if (profile == ENoProfile) {
    498         if (version == 300 || version == 310 || version == 320) {
    499             correct = false;
    500             infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 require specifying the 'es' profile");
    501             profile = EEsProfile;
    502         } else if (version == 100)
    503             profile = EEsProfile;
    504         else if (version >= FirstProfileVersion)
    505             profile = ECoreProfile;
    506         else
    507             profile = ENoProfile;
    508     } else {
    509         // a profile was provided...
    510         if (version < 150) {
    511             correct = false;
    512             infoSink.info.message(EPrefixError, "#version: versions before 150 do not allow a profile token");
    513             if (version == 100)
    514                 profile = EEsProfile;
    515             else
    516                 profile = ENoProfile;
    517         } else if (version == 300 || version == 310 || version == 320) {
    518             if (profile != EEsProfile) {
    519                 correct = false;
    520                 infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 support only the es profile");
    521             }
    522             profile = EEsProfile;
    523         } else {
    524             if (profile == EEsProfile) {
    525                 correct = false;
    526                 infoSink.info.message(EPrefixError, "#version: only version 300, 310, and 320 support the es profile");
    527                 if (version >= FirstProfileVersion)
    528                     profile = ECoreProfile;
    529                 else
    530                     profile = ENoProfile;
    531             }
    532             // else: typical desktop case... e.g., "#version 410 core"
    533         }
    534     }
    535 
    536     // Fix version...
    537     switch (version) {
    538     // ES versions
    539     case 100: break;
    540     case 300: break;
    541     case 310: break;
    542     case 320: break;
    543 
    544     // desktop versions
    545     case 110: break;
    546     case 120: break;
    547     case 130: break;
    548     case 140: break;
    549     case 150: break;
    550     case 330: break;
    551     case 400: break;
    552     case 410: break;
    553     case 420: break;
    554     case 430: break;
    555     case 440: break;
    556     case 450: break;
    557     case 460: break;
    558 
    559     // unknown version
    560     default:
    561         correct = false;
    562         infoSink.info.message(EPrefixError, "version not supported");
    563         if (profile == EEsProfile)
    564             version = 310;
    565         else {
    566             version = 450;
    567             profile = ECoreProfile;
    568         }
    569         break;
    570     }
    571 
    572     // Correct for stage type...
    573     switch (stage) {
    574     case EShLangGeometry:
    575         if ((profile == EEsProfile && version < 310) ||
    576             (profile != EEsProfile && version < 150)) {
    577             correct = false;
    578             infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above");
    579             version = (profile == EEsProfile) ? 310 : 150;
    580             if (profile == EEsProfile || profile == ENoProfile)
    581                 profile = ECoreProfile;
    582         }
    583         break;
    584     case EShLangTessControl:
    585     case EShLangTessEvaluation:
    586         if ((profile == EEsProfile && version < 310) ||
    587             (profile != EEsProfile && version < 150)) {
    588             correct = false;
    589             infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or non-es profile with version 150 or above");
    590             version = (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not
    591             if (profile == EEsProfile || profile == ENoProfile)
    592                 profile = ECoreProfile;
    593         }
    594         break;
    595     case EShLangCompute:
    596         if ((profile == EEsProfile && version < 310) ||
    597             (profile != EEsProfile && version < 420)) {
    598             correct = false;
    599             infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 420 or above");
    600             version = profile == EEsProfile ? 310 : 420;
    601         }
    602         break;
    603 #ifdef NV_EXTENSIONS
    604     case EShLangRayGenNV:
    605     case EShLangIntersectNV:
    606     case EShLangAnyHitNV:
    607     case EShLangClosestHitNV:
    608     case EShLangMissNV:
    609     case EShLangCallableNV:
    610         if (profile == EEsProfile || version < 460) {
    611             correct = false;
    612             infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
    613             version = 460;
    614         }
    615         break;
    616     case EShLangMeshNV:
    617     case EShLangTaskNV:
    618         if ((profile == EEsProfile && version < 320) ||
    619             (profile != EEsProfile && version < 450)) {
    620             correct = false;
    621             infoSink.info.message(EPrefixError, "#version: mesh/task shaders require es profile with version 320 or above, or non-es profile with version 450 or above");
    622             version = profile == EEsProfile ? 320 : 450;
    623         }
    624 #endif
    625     default:
    626         break;
    627     }
    628 
    629     if (profile == EEsProfile && version >= 300 && versionNotFirst) {
    630         correct = false;
    631         infoSink.info.message(EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines");
    632     }
    633 
    634     // Check for SPIR-V compatibility
    635     if (spvVersion.spv != 0) {
    636         switch (profile) {
    637         case  EEsProfile:
    638             if (spvVersion.vulkan > 0 && version < 310) {
    639                 correct = false;
    640                 infoSink.info.message(EPrefixError, "#version: ES shaders for Vulkan SPIR-V require version 310 or higher");
    641                 version = 310;
    642             }
    643             if (spvVersion.openGl >= 100) {
    644                 correct = false;
    645                 infoSink.info.message(EPrefixError, "#version: ES shaders for OpenGL SPIR-V are not supported");
    646                 version = 310;
    647             }
    648             break;
    649         case ECompatibilityProfile:
    650             infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile");
    651             break;
    652         default:
    653             if (spvVersion.vulkan > 0 && version < 140) {
    654                 correct = false;
    655                 infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher");
    656                 version = 140;
    657             }
    658             if (spvVersion.openGl >= 100 && version < 330) {
    659                 correct = false;
    660                 infoSink.info.message(EPrefixError, "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher");
    661                 version = 330;
    662             }
    663             break;
    664         }
    665     }
    666 
    667     return correct;
    668 }
    669 
    670 // There are multiple paths in for setting environment stuff.
    671 // TEnvironment takes precedence, for what it sets, so sort all this out.
    672 // Ideally, the internal code could be made to use TEnvironment, but for
    673 // now, translate it to the historically used parameters.
    674 void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages, EShSource& source,
    675                           EShLanguage& stage, SpvVersion& spvVersion)
    676 {
    677     // Set up environmental defaults, first ignoring 'environment'.
    678     if (messages & EShMsgSpvRules)
    679         spvVersion.spv = EShTargetSpv_1_0;
    680     if (messages & EShMsgVulkanRules) {
    681         spvVersion.vulkan = EShTargetVulkan_1_0;
    682         spvVersion.vulkanGlsl = 100;
    683     } else if (spvVersion.spv != 0)
    684         spvVersion.openGl = 100;
    685 
    686     // Now, override, based on any content set in 'environment'.
    687     // 'environment' must be cleared to ESh*None settings when items
    688     // are not being set.
    689     if (environment != nullptr) {
    690         // input language
    691         if (environment->input.languageFamily != EShSourceNone) {
    692             stage = environment->input.stage;
    693             switch (environment->input.dialect) {
    694             case EShClientNone:
    695                 break;
    696             case EShClientVulkan:
    697                 spvVersion.vulkanGlsl = environment->input.dialectVersion;
    698                 break;
    699             case EShClientOpenGL:
    700                 spvVersion.openGl = environment->input.dialectVersion;
    701                 break;
    702             }
    703             switch (environment->input.languageFamily) {
    704             case EShSourceNone:
    705                 break;
    706             case EShSourceGlsl:
    707                 source = EShSourceGlsl;
    708                 messages = static_cast<EShMessages>(messages & ~EShMsgReadHlsl);
    709                 break;
    710             case EShSourceHlsl:
    711                 source = EShSourceHlsl;
    712                 messages = static_cast<EShMessages>(messages | EShMsgReadHlsl);
    713                 break;
    714             }
    715         }
    716 
    717         // client
    718         switch (environment->client.client) {
    719         case EShClientVulkan:
    720             spvVersion.vulkan = environment->client.version;
    721             break;
    722         default:
    723             break;
    724         }
    725 
    726         // generated code
    727         switch (environment->target.language) {
    728         case EshTargetSpv:
    729             spvVersion.spv = environment->target.version;
    730             break;
    731         default:
    732             break;
    733         }
    734     }
    735 }
    736 
    737 // Most processes are recorded when set in the intermediate representation,
    738 // These are the few that are not.
    739 void RecordProcesses(TIntermediate& intermediate, EShMessages messages, const std::string& sourceEntryPointName)
    740 {
    741     if ((messages & EShMsgRelaxedErrors) != 0)
    742         intermediate.addProcess("relaxed-errors");
    743     if ((messages & EShMsgSuppressWarnings) != 0)
    744         intermediate.addProcess("suppress-warnings");
    745     if ((messages & EShMsgKeepUncalled) != 0)
    746         intermediate.addProcess("keep-uncalled");
    747     if (sourceEntryPointName.size() > 0) {
    748         intermediate.addProcess("source-entrypoint");
    749         intermediate.addProcessArgument(sourceEntryPointName);
    750     }
    751 }
    752 
    753 // This is the common setup and cleanup code for PreprocessDeferred and
    754 // CompileDeferred.
    755 // It takes any callable with a signature of
    756 //  bool (TParseContextBase& parseContext, TPpContext& ppContext,
    757 //                  TInputScanner& input, bool versionWillBeError,
    758 //                  TSymbolTable& , TIntermediate& ,
    759 //                  EShOptimizationLevel , EShMessages );
    760 // Which returns false if a failure was detected and true otherwise.
    761 //
    762 template<typename ProcessingContext>
    763 bool ProcessDeferred(
    764     TCompiler* compiler,
    765     const char* const shaderStrings[],
    766     const int numStrings,
    767     const int* inputLengths,
    768     const char* const stringNames[],
    769     const char* customPreamble,
    770     const EShOptimizationLevel optLevel,
    771     const TBuiltInResource* resources,
    772     int defaultVersion,  // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan
    773     EProfile defaultProfile,
    774     // set version/profile to defaultVersion/defaultProfile regardless of the #version
    775     // directive in the source code
    776     bool forceDefaultVersionAndProfile,
    777     bool forwardCompatible,     // give errors for use of deprecated features
    778     EShMessages messages,       // warnings/errors/AST; things to print out
    779     TIntermediate& intermediate, // returned tree, etc.
    780     ProcessingContext& processingContext,
    781     bool requireNonempty,
    782     TShader::Includer& includer,
    783     const std::string sourceEntryPointName = "",
    784     const TEnvironment* environment = nullptr)  // optional way of fully setting all versions, overriding the above
    785 {
    786     // This must be undone (.pop()) by the caller, after it finishes consuming the created tree.
    787     GetThreadPoolAllocator().push();
    788 
    789     if (numStrings == 0)
    790         return true;
    791 
    792     // Move to length-based strings, rather than null-terminated strings.
    793     // Also, add strings to include the preamble and to ensure the shader is not null,
    794     // which lets the grammar accept what was a null (post preprocessing) shader.
    795     //
    796     // Shader will look like
    797     //   string 0:                system preamble
    798     //   string 1:                custom preamble
    799     //   string 2...numStrings+1: user's shader
    800     //   string numStrings+2:     "int;"
    801     const int numPre = 2;
    802     const int numPost = requireNonempty? 1 : 0;
    803     const int numTotal = numPre + numStrings + numPost;
    804     std::unique_ptr<size_t[]> lengths(new size_t[numTotal]);
    805     std::unique_ptr<const char*[]> strings(new const char*[numTotal]);
    806     std::unique_ptr<const char*[]> names(new const char*[numTotal]);
    807     for (int s = 0; s < numStrings; ++s) {
    808         strings[s + numPre] = shaderStrings[s];
    809         if (inputLengths == nullptr || inputLengths[s] < 0)
    810             lengths[s + numPre] = strlen(shaderStrings[s]);
    811         else
    812             lengths[s + numPre] = inputLengths[s];
    813     }
    814     if (stringNames != nullptr) {
    815         for (int s = 0; s < numStrings; ++s)
    816             names[s + numPre] = stringNames[s];
    817     } else {
    818         for (int s = 0; s < numStrings; ++s)
    819             names[s + numPre] = nullptr;
    820     }
    821 
    822     // Get all the stages, languages, clients, and other environment
    823     // stuff sorted out.
    824     EShSource source = (messages & EShMsgReadHlsl) != 0 ? EShSourceHlsl : EShSourceGlsl;
    825     SpvVersion spvVersion;
    826     EShLanguage stage = compiler->getLanguage();
    827     TranslateEnvironment(environment, messages, source, stage, spvVersion);
    828     if (environment != nullptr && environment->target.hlslFunctionality1)
    829         intermediate.setHlslFunctionality1();
    830 
    831     // First, without using the preprocessor or parser, find the #version, so we know what
    832     // symbol tables, processing rules, etc. to set up.  This does not need the extra strings
    833     // outlined above, just the user shader, after the system and user preambles.
    834     glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]);
    835     int version = 0;
    836     EProfile profile = ENoProfile;
    837     bool versionNotFirstToken = false;
    838     bool versionNotFirst = (source == EShSourceHlsl)
    839                                 ? true
    840                                 : userInput.scanVersion(version, profile, versionNotFirstToken);
    841     bool versionNotFound = version == 0;
    842     if (forceDefaultVersionAndProfile && source == EShSourceGlsl) {
    843         if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
    844             (version != defaultVersion || profile != defaultProfile)) {
    845             compiler->infoSink.info << "Warning, (version, profile) forced to be ("
    846                                     << defaultVersion << ", " << ProfileName(defaultProfile)
    847                                     << "), while in source code it is ("
    848                                     << version << ", " << ProfileName(profile) << ")\n";
    849         }
    850 
    851         if (versionNotFound) {
    852             versionNotFirstToken = false;
    853             versionNotFirst = false;
    854             versionNotFound = false;
    855         }
    856         version = defaultVersion;
    857         profile = defaultProfile;
    858     }
    859 
    860     bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage,
    861                                             versionNotFirst, defaultVersion, source, version, profile, spvVersion);
    862     bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
    863     bool warnVersionNotFirst = false;
    864     if (! versionWillBeError && versionNotFirstToken) {
    865         if (messages & EShMsgRelaxedErrors)
    866             warnVersionNotFirst = true;
    867         else
    868             versionWillBeError = true;
    869     }
    870 
    871     intermediate.setSource(source);
    872     intermediate.setVersion(version);
    873     intermediate.setProfile(profile);
    874     intermediate.setSpv(spvVersion);
    875     RecordProcesses(intermediate, messages, sourceEntryPointName);
    876     if (spvVersion.vulkan > 0)
    877         intermediate.setOriginUpperLeft();
    878     if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl)
    879         intermediate.setHlslOffsets();
    880     if (messages & EShMsgDebugInfo) {
    881         intermediate.setSourceFile(names[numPre]);
    882         for (int s = 0; s < numStrings; ++s) {
    883             // The string may not be null-terminated, so make sure we provide
    884             // the length along with the string.
    885             intermediate.addSourceText(strings[numPre + s], lengths[numPre + s]);
    886         }
    887     }
    888     SetupBuiltinSymbolTable(version, profile, spvVersion, source);
    889 
    890     TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
    891                                                   [MapSpvVersionToIndex(spvVersion)]
    892                                                   [MapProfileToIndex(profile)]
    893                                                   [MapSourceToIndex(source)]
    894                                                   [stage];
    895 
    896     // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
    897     std::unique_ptr<TSymbolTable> symbolTable(new TSymbolTable);
    898     if (cachedTable)
    899         symbolTable->adoptLevels(*cachedTable);
    900 
    901     // Add built-in symbols that are potentially context dependent;
    902     // they get popped again further down.
    903     if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
    904                                     stage, source)) {
    905         return false;
    906     }
    907 
    908     //
    909     // Now we can process the full shader under proper symbols and rules.
    910     //
    911 
    912     std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source,
    913                                                     stage, compiler->infoSink,
    914                                                     spvVersion, forwardCompatible, messages, false, sourceEntryPointName));
    915     TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer);
    916 
    917     // only GLSL (bison triggered, really) needs an externally set scan context
    918     glslang::TScanContext scanContext(*parseContext);
    919     if (source == EShSourceGlsl)
    920         parseContext->setScanContext(&scanContext);
    921 
    922     parseContext->setPpContext(&ppContext);
    923     parseContext->setLimits(*resources);
    924     if (! goodVersion)
    925         parseContext->addError();
    926     if (warnVersionNotFirst) {
    927         TSourceLoc loc;
    928         loc.init();
    929         parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", "");
    930     }
    931 
    932     parseContext->initializeExtensionBehavior();
    933 
    934     // Fill in the strings as outlined above.
    935     std::string preamble;
    936     parseContext->getPreamble(preamble);
    937     strings[0] = preamble.c_str();
    938     lengths[0] = strlen(strings[0]);
    939     names[0] = nullptr;
    940     strings[1] = customPreamble;
    941     lengths[1] = strlen(strings[1]);
    942     names[1] = nullptr;
    943     assert(2 == numPre);
    944     if (requireNonempty) {
    945         const int postIndex = numStrings + numPre;
    946         strings[postIndex] = "\n int;";
    947         lengths[postIndex] = strlen(strings[numStrings + numPre]);
    948         names[postIndex] = nullptr;
    949     }
    950     TInputScanner fullInput(numStrings + numPre + numPost, strings.get(), lengths.get(), names.get(), numPre, numPost);
    951 
    952     // Push a new symbol allocation scope that will get used for the shader's globals.
    953     symbolTable->push();
    954 
    955     bool success = processingContext(*parseContext, ppContext, fullInput,
    956                                      versionWillBeError, *symbolTable,
    957                                      intermediate, optLevel, messages);
    958     return success;
    959 }
    960 
    961 // Responsible for keeping track of the most recent source string and line in
    962 // the preprocessor and outputting newlines appropriately if the source string
    963 // or line changes.
    964 class SourceLineSynchronizer {
    965 public:
    966     SourceLineSynchronizer(const std::function<int()>& lastSourceIndex,
    967                            std::string* output)
    968       : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {}
    969 //    SourceLineSynchronizer(const SourceLineSynchronizer&) = delete;
    970 //    SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete;
    971 
    972     // Sets the internally tracked source string index to that of the most
    973     // recently read token. If we switched to a new source string, returns
    974     // true and inserts a newline. Otherwise, returns false and outputs nothing.
    975     bool syncToMostRecentString() {
    976         if (getLastSourceIndex() != lastSource) {
    977             // After switching to a new source string, we need to reset lastLine
    978             // because line number resets every time a new source string is
    979             // used. We also need to output a newline to separate the output
    980             // from the previous source string (if there is one).
    981             if (lastSource != -1 || lastLine != 0)
    982                 *output += '\n';
    983             lastSource = getLastSourceIndex();
    984             lastLine = -1;
    985             return true;
    986         }
    987         return false;
    988     }
    989 
    990     // Calls syncToMostRecentString() and then sets the internally tracked line
    991     // number to tokenLine. If we switched to a new line, returns true and inserts
    992     // newlines appropriately. Otherwise, returns false and outputs nothing.
    993     bool syncToLine(int tokenLine) {
    994         syncToMostRecentString();
    995         const bool newLineStarted = lastLine < tokenLine;
    996         for (; lastLine < tokenLine; ++lastLine) {
    997             if (lastLine > 0) *output += '\n';
    998         }
    999         return newLineStarted;
   1000     }
   1001 
   1002     // Sets the internally tracked line number to newLineNum.
   1003     void setLineNum(int newLineNum) { lastLine = newLineNum; }
   1004 
   1005 private:
   1006     SourceLineSynchronizer& operator=(const SourceLineSynchronizer&);
   1007 
   1008     // A function for getting the index of the last valid source string we've
   1009     // read tokens from.
   1010     const std::function<int()> getLastSourceIndex;
   1011     // output string for newlines.
   1012     std::string* output;
   1013     // lastSource is the source string index (starting from 0) of the last token
   1014     // processed. It is tracked in order for newlines to be inserted when a new
   1015     // source string starts. -1 means we haven't started processing any source
   1016     // string.
   1017     int lastSource;
   1018     // lastLine is the line number (starting from 1) of the last token processed.
   1019     // It is tracked in order for newlines to be inserted when a token appears
   1020     // on a new line. 0 means we haven't started processing any line in the
   1021     // current source string.
   1022     int lastLine;
   1023 };
   1024 
   1025 // DoPreprocessing is a valid ProcessingContext template argument,
   1026 // which only performs the preprocessing step of compilation.
   1027 // It places the result in the "string" argument to its constructor.
   1028 //
   1029 // This is not an officially supported or fully working path.
   1030 struct DoPreprocessing {
   1031     explicit DoPreprocessing(std::string* string): outputString(string) {}
   1032     bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
   1033                     TInputScanner& input, bool versionWillBeError,
   1034                     TSymbolTable&, TIntermediate&,
   1035                     EShOptimizationLevel, EShMessages)
   1036     {
   1037         // This is a list of tokens that do not require a space before or after.
   1038         static const std::string unNeededSpaceTokens = ";()[]";
   1039         static const std::string noSpaceBeforeTokens = ",";
   1040         glslang::TPpToken ppToken;
   1041 
   1042         parseContext.setScanner(&input);
   1043         ppContext.setInput(input, versionWillBeError);
   1044 
   1045         std::string outputBuffer;
   1046         SourceLineSynchronizer lineSync(
   1047             std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputBuffer);
   1048 
   1049         parseContext.setExtensionCallback([&lineSync, &outputBuffer](
   1050             int line, const char* extension, const char* behavior) {
   1051                 lineSync.syncToLine(line);
   1052                 outputBuffer += "#extension ";
   1053                 outputBuffer += extension;
   1054                 outputBuffer += " : ";
   1055                 outputBuffer += behavior;
   1056         });
   1057 
   1058         parseContext.setLineCallback([&lineSync, &outputBuffer, &parseContext](
   1059             int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) {
   1060             // SourceNum is the number of the source-string that is being parsed.
   1061             lineSync.syncToLine(curLineNum);
   1062             outputBuffer += "#line ";
   1063             outputBuffer += std::to_string(newLineNum);
   1064             if (hasSource) {
   1065                 outputBuffer += ' ';
   1066                 if (sourceName != nullptr) {
   1067                     outputBuffer += '\"';
   1068                     outputBuffer += sourceName;
   1069                     outputBuffer += '\"';
   1070                 } else {
   1071                     outputBuffer += std::to_string(sourceNum);
   1072                 }
   1073             }
   1074             if (parseContext.lineDirectiveShouldSetNextLine()) {
   1075                 // newLineNum is the new line number for the line following the #line
   1076                 // directive. So the new line number for the current line is
   1077                 newLineNum -= 1;
   1078             }
   1079             outputBuffer += '\n';
   1080             // And we are at the next line of the #line directive now.
   1081             lineSync.setLineNum(newLineNum + 1);
   1082         });
   1083 
   1084         parseContext.setVersionCallback(
   1085             [&lineSync, &outputBuffer](int line, int version, const char* str) {
   1086                 lineSync.syncToLine(line);
   1087                 outputBuffer += "#version ";
   1088                 outputBuffer += std::to_string(version);
   1089                 if (str) {
   1090                     outputBuffer += ' ';
   1091                     outputBuffer += str;
   1092                 }
   1093             });
   1094 
   1095         parseContext.setPragmaCallback([&lineSync, &outputBuffer](
   1096             int line, const glslang::TVector<glslang::TString>& ops) {
   1097                 lineSync.syncToLine(line);
   1098                 outputBuffer += "#pragma ";
   1099                 for(size_t i = 0; i < ops.size(); ++i) {
   1100                     outputBuffer += ops[i].c_str();
   1101                 }
   1102         });
   1103 
   1104         parseContext.setErrorCallback([&lineSync, &outputBuffer](
   1105             int line, const char* errorMessage) {
   1106                 lineSync.syncToLine(line);
   1107                 outputBuffer += "#error ";
   1108                 outputBuffer += errorMessage;
   1109         });
   1110 
   1111         int lastToken = EndOfInput; // lastToken records the last token processed.
   1112         do {
   1113             int token = ppContext.tokenize(ppToken);
   1114             if (token == EndOfInput)
   1115                 break;
   1116 
   1117             bool isNewString = lineSync.syncToMostRecentString();
   1118             bool isNewLine = lineSync.syncToLine(ppToken.loc.line);
   1119 
   1120             if (isNewLine) {
   1121                 // Don't emit whitespace onto empty lines.
   1122                 // Copy any whitespace characters at the start of a line
   1123                 // from the input to the output.
   1124                 outputBuffer += std::string(ppToken.loc.column - 1, ' ');
   1125             }
   1126 
   1127             // Output a space in between tokens, but not at the start of a line,
   1128             // and also not around special tokens. This helps with readability
   1129             // and consistency.
   1130             if (!isNewString && !isNewLine && lastToken != EndOfInput &&
   1131                 (unNeededSpaceTokens.find((char)token) == std::string::npos) &&
   1132                 (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
   1133                 (noSpaceBeforeTokens.find((char)token) == std::string::npos)) {
   1134                 outputBuffer += ' ';
   1135             }
   1136             lastToken = token;
   1137             if (token == PpAtomConstString)
   1138                 outputBuffer += "\"";
   1139             outputBuffer += ppToken.name;
   1140             if (token == PpAtomConstString)
   1141                 outputBuffer += "\"";
   1142         } while (true);
   1143         outputBuffer += '\n';
   1144         *outputString = std::move(outputBuffer);
   1145 
   1146         bool success = true;
   1147         if (parseContext.getNumErrors() > 0) {
   1148             success = false;
   1149             parseContext.infoSink.info.prefix(EPrefixError);
   1150             parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors.  No code generated.\n\n";
   1151         }
   1152         return success;
   1153     }
   1154     std::string* outputString;
   1155 };
   1156 
   1157 // DoFullParse is a valid ProcessingConext template argument for fully
   1158 // parsing the shader.  It populates the "intermediate" with the AST.
   1159 struct DoFullParse{
   1160   bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
   1161                   TInputScanner& fullInput, bool versionWillBeError,
   1162                   TSymbolTable&, TIntermediate& intermediate,
   1163                   EShOptimizationLevel optLevel, EShMessages messages)
   1164     {
   1165         bool success = true;
   1166         // Parse the full shader.
   1167         if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError))
   1168             success = false;
   1169 
   1170         if (success && intermediate.getTreeRoot()) {
   1171             if (optLevel == EShOptNoGeneration)
   1172                 parseContext.infoSink.info.message(EPrefixNone, "No errors.  No code generation or linking was requested.");
   1173             else
   1174                 success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage());
   1175         } else if (! success) {
   1176             parseContext.infoSink.info.prefix(EPrefixError);
   1177             parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors.  No code generated.\n\n";
   1178         }
   1179 
   1180         if (messages & EShMsgAST)
   1181             intermediate.output(parseContext.infoSink, true);
   1182 
   1183         return success;
   1184     }
   1185 };
   1186 
   1187 // Take a single compilation unit, and run the preprocessor on it.
   1188 // Return: True if there were no issues found in preprocessing,
   1189 //         False if during preprocessing any unknown version, pragmas or
   1190 //         extensions were found.
   1191 //
   1192 // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
   1193 // is not an officially supported or fully working path.
   1194 bool PreprocessDeferred(
   1195     TCompiler* compiler,
   1196     const char* const shaderStrings[],
   1197     const int numStrings,
   1198     const int* inputLengths,
   1199     const char* const stringNames[],
   1200     const char* preamble,
   1201     const EShOptimizationLevel optLevel,
   1202     const TBuiltInResource* resources,
   1203     int defaultVersion,         // use 100 for ES environment, 110 for desktop
   1204     EProfile defaultProfile,
   1205     bool forceDefaultVersionAndProfile,
   1206     bool forwardCompatible,     // give errors for use of deprecated features
   1207     EShMessages messages,       // warnings/errors/AST; things to print out
   1208     TShader::Includer& includer,
   1209     TIntermediate& intermediate, // returned tree, etc.
   1210     std::string* outputString)
   1211 {
   1212     DoPreprocessing parser(outputString);
   1213     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
   1214                            preamble, optLevel, resources, defaultVersion,
   1215                            defaultProfile, forceDefaultVersionAndProfile,
   1216                            forwardCompatible, messages, intermediate, parser,
   1217                            false, includer);
   1218 }
   1219 
   1220 //
   1221 // do a partial compile on the given strings for a single compilation unit
   1222 // for a potential deferred link into a single stage (and deferred full compile of that
   1223 // stage through machine-dependent compilation).
   1224 //
   1225 // all preprocessing, parsing, semantic checks, etc. for a single compilation unit
   1226 // are done here.
   1227 //
   1228 // return:  the tree and other information is filled into the intermediate argument,
   1229 //          and true is returned by the function for success.
   1230 //
   1231 bool CompileDeferred(
   1232     TCompiler* compiler,
   1233     const char* const shaderStrings[],
   1234     const int numStrings,
   1235     const int* inputLengths,
   1236     const char* const stringNames[],
   1237     const char* preamble,
   1238     const EShOptimizationLevel optLevel,
   1239     const TBuiltInResource* resources,
   1240     int defaultVersion,         // use 100 for ES environment, 110 for desktop
   1241     EProfile defaultProfile,
   1242     bool forceDefaultVersionAndProfile,
   1243     bool forwardCompatible,     // give errors for use of deprecated features
   1244     EShMessages messages,       // warnings/errors/AST; things to print out
   1245     TIntermediate& intermediate,// returned tree, etc.
   1246     TShader::Includer& includer,
   1247     const std::string sourceEntryPointName = "",
   1248     TEnvironment* environment = nullptr)
   1249 {
   1250     DoFullParse parser;
   1251     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
   1252                            preamble, optLevel, resources, defaultVersion,
   1253                            defaultProfile, forceDefaultVersionAndProfile,
   1254                            forwardCompatible, messages, intermediate, parser,
   1255                            true, includer, sourceEntryPointName, environment);
   1256 }
   1257 
   1258 } // end anonymous namespace for local functions
   1259 
   1260 //
   1261 // ShInitialize() should be called exactly once per process, not per thread.
   1262 //
   1263 int ShInitialize()
   1264 {
   1265     glslang::InitGlobalLock();
   1266 
   1267     if (! InitProcess())
   1268         return 0;
   1269 
   1270     glslang::GetGlobalLock();
   1271     ++NumberOfClients;
   1272     glslang::ReleaseGlobalLock();
   1273 
   1274     if (PerProcessGPA == nullptr)
   1275         PerProcessGPA = new TPoolAllocator();
   1276 
   1277     glslang::TScanContext::fillInKeywordMap();
   1278 #ifdef ENABLE_HLSL
   1279     glslang::HlslScanContext::fillInKeywordMap();
   1280 #endif
   1281 
   1282     return 1;
   1283 }
   1284 
   1285 //
   1286 // Driver calls these to create and destroy compiler/linker
   1287 // objects.
   1288 //
   1289 
   1290 ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions)
   1291 {
   1292     if (!InitThread())
   1293         return 0;
   1294 
   1295     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, debugOptions));
   1296 
   1297     return reinterpret_cast<void*>(base);
   1298 }
   1299 
   1300 ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions)
   1301 {
   1302     if (!InitThread())
   1303         return 0;
   1304 
   1305     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructLinker(executable, debugOptions));
   1306 
   1307     return reinterpret_cast<void*>(base);
   1308 }
   1309 
   1310 ShHandle ShConstructUniformMap()
   1311 {
   1312     if (!InitThread())
   1313         return 0;
   1314 
   1315     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructUniformMap());
   1316 
   1317     return reinterpret_cast<void*>(base);
   1318 }
   1319 
   1320 void ShDestruct(ShHandle handle)
   1321 {
   1322     if (handle == 0)
   1323         return;
   1324 
   1325     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
   1326 
   1327     if (base->getAsCompiler())
   1328         DeleteCompiler(base->getAsCompiler());
   1329     else if (base->getAsLinker())
   1330         DeleteLinker(base->getAsLinker());
   1331     else if (base->getAsUniformMap())
   1332         DeleteUniformMap(base->getAsUniformMap());
   1333 }
   1334 
   1335 //
   1336 // Cleanup symbol tables
   1337 //
   1338 int __fastcall ShFinalize()
   1339 {
   1340     glslang::GetGlobalLock();
   1341     --NumberOfClients;
   1342     assert(NumberOfClients >= 0);
   1343     bool finalize = NumberOfClients == 0;
   1344     glslang::ReleaseGlobalLock();
   1345     if (! finalize)
   1346         return 1;
   1347 
   1348     for (int version = 0; version < VersionCount; ++version) {
   1349         for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
   1350             for (int p = 0; p < ProfileCount; ++p) {
   1351                 for (int source = 0; source < SourceCount; ++source) {
   1352                     for (int stage = 0; stage < EShLangCount; ++stage) {
   1353                         delete SharedSymbolTables[version][spvVersion][p][source][stage];
   1354                         SharedSymbolTables[version][spvVersion][p][source][stage] = 0;
   1355                     }
   1356                 }
   1357             }
   1358         }
   1359     }
   1360 
   1361     for (int version = 0; version < VersionCount; ++version) {
   1362         for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
   1363             for (int p = 0; p < ProfileCount; ++p) {
   1364                 for (int source = 0; source < SourceCount; ++source) {
   1365                     for (int pc = 0; pc < EPcCount; ++pc) {
   1366                         delete CommonSymbolTable[version][spvVersion][p][source][pc];
   1367                         CommonSymbolTable[version][spvVersion][p][source][pc] = 0;
   1368                     }
   1369                 }
   1370             }
   1371         }
   1372     }
   1373 
   1374     if (PerProcessGPA != nullptr) {
   1375         delete PerProcessGPA;
   1376         PerProcessGPA = nullptr;
   1377     }
   1378 
   1379     glslang::TScanContext::deleteKeywordMap();
   1380 #ifdef ENABLE_HLSL
   1381     glslang::HlslScanContext::deleteKeywordMap();
   1382 #endif
   1383 
   1384     return 1;
   1385 }
   1386 
   1387 //
   1388 // Do a full compile on the given strings for a single compilation unit
   1389 // forming a complete stage.  The result of the machine dependent compilation
   1390 // is left in the provided compile object.
   1391 //
   1392 // Return:  The return value is really boolean, indicating
   1393 // success (1) or failure (0).
   1394 //
   1395 int ShCompile(
   1396     const ShHandle handle,
   1397     const char* const shaderStrings[],
   1398     const int numStrings,
   1399     const int* inputLengths,
   1400     const EShOptimizationLevel optLevel,
   1401     const TBuiltInResource* resources,
   1402     int /*debugOptions*/,
   1403     int defaultVersion,        // use 100 for ES environment, 110 for desktop
   1404     bool forwardCompatible,    // give errors for use of deprecated features
   1405     EShMessages messages       // warnings/errors/AST; things to print out
   1406     )
   1407 {
   1408     // Map the generic handle to the C++ object
   1409     if (handle == 0)
   1410         return 0;
   1411 
   1412     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1413     TCompiler* compiler = base->getAsCompiler();
   1414     if (compiler == 0)
   1415         return 0;
   1416 
   1417     SetThreadPoolAllocator(compiler->getPool());
   1418 
   1419     compiler->infoSink.info.erase();
   1420     compiler->infoSink.debug.erase();
   1421 
   1422     TIntermediate intermediate(compiler->getLanguage());
   1423     TShader::ForbidIncluder includer;
   1424     bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr,
   1425                                    "", optLevel, resources, defaultVersion, ENoProfile, false,
   1426                                    forwardCompatible, messages, intermediate, includer);
   1427 
   1428     //
   1429     // Call the machine dependent compiler
   1430     //
   1431     if (success && intermediate.getTreeRoot() && optLevel != EShOptNoGeneration)
   1432         success = compiler->compile(intermediate.getTreeRoot(), intermediate.getVersion(), intermediate.getProfile());
   1433 
   1434     intermediate.removeTree();
   1435 
   1436     // Throw away all the temporary memory used by the compilation process.
   1437     // The push was done in the CompileDeferred() call above.
   1438     GetThreadPoolAllocator().pop();
   1439 
   1440     return success ? 1 : 0;
   1441 }
   1442 
   1443 //
   1444 // Link the given compile objects.
   1445 //
   1446 // Return:  The return value of is really boolean, indicating
   1447 // success or failure.
   1448 //
   1449 int ShLinkExt(
   1450     const ShHandle linkHandle,
   1451     const ShHandle compHandles[],
   1452     const int numHandles)
   1453 {
   1454     if (linkHandle == 0 || numHandles == 0)
   1455         return 0;
   1456 
   1457     THandleList cObjects;
   1458 
   1459     for (int i = 0; i < numHandles; ++i) {
   1460         if (compHandles[i] == 0)
   1461             return 0;
   1462         TShHandleBase* base = reinterpret_cast<TShHandleBase*>(compHandles[i]);
   1463         if (base->getAsLinker()) {
   1464             cObjects.push_back(base->getAsLinker());
   1465         }
   1466         if (base->getAsCompiler())
   1467             cObjects.push_back(base->getAsCompiler());
   1468 
   1469         if (cObjects[i] == 0)
   1470             return 0;
   1471     }
   1472 
   1473     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
   1474     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1475 
   1476     SetThreadPoolAllocator(linker->getPool());
   1477 
   1478     if (linker == 0)
   1479         return 0;
   1480 
   1481     linker->infoSink.info.erase();
   1482 
   1483     for (int i = 0; i < numHandles; ++i) {
   1484         if (cObjects[i]->getAsCompiler()) {
   1485             if (! cObjects[i]->getAsCompiler()->linkable()) {
   1486                 linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code.");
   1487                 return 0;
   1488             }
   1489         }
   1490     }
   1491 
   1492     bool ret = linker->link(cObjects);
   1493 
   1494     return ret ? 1 : 0;
   1495 }
   1496 
   1497 //
   1498 // ShSetEncrpytionMethod is a place-holder for specifying
   1499 // how source code is encrypted.
   1500 //
   1501 void ShSetEncryptionMethod(ShHandle handle)
   1502 {
   1503     if (handle == 0)
   1504         return;
   1505 }
   1506 
   1507 //
   1508 // Return any compiler/linker/uniformmap log of messages for the application.
   1509 //
   1510 const char* ShGetInfoLog(const ShHandle handle)
   1511 {
   1512     if (handle == 0)
   1513         return 0;
   1514 
   1515     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
   1516     TInfoSink* infoSink;
   1517 
   1518     if (base->getAsCompiler())
   1519         infoSink = &(base->getAsCompiler()->getInfoSink());
   1520     else if (base->getAsLinker())
   1521         infoSink = &(base->getAsLinker()->getInfoSink());
   1522     else
   1523         return 0;
   1524 
   1525     infoSink->info << infoSink->debug.c_str();
   1526     return infoSink->info.c_str();
   1527 }
   1528 
   1529 //
   1530 // Return the resulting binary code from the link process.  Structure
   1531 // is machine dependent.
   1532 //
   1533 const void* ShGetExecutable(const ShHandle handle)
   1534 {
   1535     if (handle == 0)
   1536         return 0;
   1537 
   1538     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1539 
   1540     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1541     if (linker == 0)
   1542         return 0;
   1543 
   1544     return linker->getObjectCode();
   1545 }
   1546 
   1547 //
   1548 // Let the linker know where the application said it's attributes are bound.
   1549 // The linker does not use these values, they are remapped by the ICD or
   1550 // hardware.  It just needs them to know what's aliased.
   1551 //
   1552 // Return:  The return value of is really boolean, indicating
   1553 // success or failure.
   1554 //
   1555 int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
   1556 {
   1557     if (handle == 0)
   1558         return 0;
   1559 
   1560     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1561     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1562 
   1563     if (linker == 0)
   1564         return 0;
   1565 
   1566     linker->setAppAttributeBindings(table);
   1567 
   1568     return 1;
   1569 }
   1570 
   1571 //
   1572 // Let the linker know where the predefined attributes have to live.
   1573 //
   1574 int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
   1575 {
   1576     if (handle == 0)
   1577         return 0;
   1578 
   1579     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1580     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1581 
   1582     if (linker == 0)
   1583         return 0;
   1584 
   1585     linker->setFixedAttributeBindings(table);
   1586     return 1;
   1587 }
   1588 
   1589 //
   1590 // Some attribute locations are off-limits to the linker...
   1591 //
   1592 int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
   1593 {
   1594     if (handle == 0)
   1595         return 0;
   1596 
   1597     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1598     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1599     if (linker == 0)
   1600         return 0;
   1601 
   1602     linker->setExcludedAttributes(attributes, count);
   1603 
   1604     return 1;
   1605 }
   1606 
   1607 //
   1608 // Return the index for OpenGL to use for knowing where a uniform lives.
   1609 //
   1610 // Return:  The return value of is really boolean, indicating
   1611 // success or failure.
   1612 //
   1613 int ShGetUniformLocation(const ShHandle handle, const char* name)
   1614 {
   1615     if (handle == 0)
   1616         return -1;
   1617 
   1618     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1619     TUniformMap* uniformMap= base->getAsUniformMap();
   1620     if (uniformMap == 0)
   1621         return -1;
   1622 
   1623     return uniformMap->getLocation(name);
   1624 }
   1625 
   1626 ////////////////////////////////////////////////////////////////////////////////////////////
   1627 //
   1628 // Deferred-Lowering C++ Interface
   1629 // -----------------------------------
   1630 //
   1631 // Below is a new alternate C++ interface that might potentially replace the above
   1632 // opaque handle-based interface.
   1633 //
   1634 // See more detailed comment in ShaderLang.h
   1635 //
   1636 
   1637 namespace glslang {
   1638 
   1639 #include "../Include/revision.h"
   1640 
   1641 #define QUOTE(s) #s
   1642 #define STR(n) QUOTE(n)
   1643 
   1644 const char* GetEsslVersionString()
   1645 {
   1646     return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
   1647 }
   1648 
   1649 const char* GetGlslVersionString()
   1650 {
   1651     return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
   1652 }
   1653 
   1654 int GetKhronosToolId()
   1655 {
   1656     return 8;
   1657 }
   1658 
   1659 bool InitializeProcess()
   1660 {
   1661     return ShInitialize() != 0;
   1662 }
   1663 
   1664 void FinalizeProcess()
   1665 {
   1666     ShFinalize();
   1667 }
   1668 
   1669 class TDeferredCompiler : public TCompiler {
   1670 public:
   1671     TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) { }
   1672     virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; }
   1673 };
   1674 
   1675 TShader::TShader(EShLanguage s)
   1676     : stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
   1677 {
   1678     pool = new TPoolAllocator;
   1679     infoSink = new TInfoSink;
   1680     compiler = new TDeferredCompiler(stage, *infoSink);
   1681     intermediate = new TIntermediate(s);
   1682 
   1683     // clear environment (avoid constructors in them for use in a C interface)
   1684     environment.input.languageFamily = EShSourceNone;
   1685     environment.input.dialect = EShClientNone;
   1686     environment.client.client = EShClientNone;
   1687     environment.target.language = EShTargetNone;
   1688     environment.target.hlslFunctionality1 = false;
   1689 }
   1690 
   1691 TShader::~TShader()
   1692 {
   1693     delete infoSink;
   1694     delete compiler;
   1695     delete intermediate;
   1696     delete pool;
   1697 }
   1698 
   1699 void TShader::setStrings(const char* const* s, int n)
   1700 {
   1701     strings = s;
   1702     numStrings = n;
   1703     lengths = nullptr;
   1704 }
   1705 
   1706 void TShader::setStringsWithLengths(const char* const* s, const int* l, int n)
   1707 {
   1708     strings = s;
   1709     numStrings = n;
   1710     lengths = l;
   1711 }
   1712 
   1713 void TShader::setStringsWithLengthsAndNames(
   1714     const char* const* s, const int* l, const char* const* names, int n)
   1715 {
   1716     strings = s;
   1717     numStrings = n;
   1718     lengths = l;
   1719     stringNames = names;
   1720 }
   1721 
   1722 void TShader::setEntryPoint(const char* entryPoint)
   1723 {
   1724     intermediate->setEntryPointName(entryPoint);
   1725 }
   1726 
   1727 void TShader::setSourceEntryPoint(const char* name)
   1728 {
   1729     sourceEntryPointName = name;
   1730 }
   1731 
   1732 void TShader::addProcesses(const std::vector<std::string>& p)
   1733 {
   1734     intermediate->addProcesses(p);
   1735 }
   1736 
   1737 // Set binding base for given resource type
   1738 void TShader::setShiftBinding(TResourceType res, unsigned int base) {
   1739     intermediate->setShiftBinding(res, base);
   1740 }
   1741 
   1742 // Set binding base for given resource type for a given binding set.
   1743 void TShader::setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set) {
   1744     intermediate->setShiftBindingForSet(res, base, set);
   1745 }
   1746 
   1747 // Set binding base for sampler types
   1748 void TShader::setShiftSamplerBinding(unsigned int base) { setShiftBinding(EResSampler, base); }
   1749 // Set binding base for texture types (SRV)
   1750 void TShader::setShiftTextureBinding(unsigned int base) { setShiftBinding(EResTexture, base); }
   1751 // Set binding base for image types
   1752 void TShader::setShiftImageBinding(unsigned int base)   { setShiftBinding(EResImage, base); }
   1753 // Set binding base for uniform buffer objects (CBV)
   1754 void TShader::setShiftUboBinding(unsigned int base)     { setShiftBinding(EResUbo, base); }
   1755 // Synonym for setShiftUboBinding, to match HLSL language.
   1756 void TShader::setShiftCbufferBinding(unsigned int base) { setShiftBinding(EResUbo, base); }
   1757 // Set binding base for UAV (unordered access view)
   1758 void TShader::setShiftUavBinding(unsigned int base)     { setShiftBinding(EResUav, base); }
   1759 // Set binding base for SSBOs
   1760 void TShader::setShiftSsboBinding(unsigned int base)    { setShiftBinding(EResSsbo, base); }
   1761 // Enables binding automapping using TIoMapper
   1762 void TShader::setAutoMapBindings(bool map)              { intermediate->setAutoMapBindings(map); }
   1763 // Enables position.Y output negation in vertex shader
   1764 void TShader::setInvertY(bool invert)                   { intermediate->setInvertY(invert); }
   1765 // Fragile: currently within one stage: simple auto-assignment of location
   1766 void TShader::setAutoMapLocations(bool map)             { intermediate->setAutoMapLocations(map); }
   1767 void TShader::addUniformLocationOverride(const char* name, int loc)
   1768 {
   1769     intermediate->addUniformLocationOverride(name, loc);
   1770 }
   1771 void TShader::setUniformLocationBase(int base)
   1772 {
   1773     intermediate->setUniformLocationBase(base);
   1774 }
   1775 // See comment above TDefaultHlslIoMapper in iomapper.cpp:
   1776 void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
   1777 void TShader::setFlattenUniformArrays(bool flatten)     { intermediate->setFlattenUniformArrays(flatten); }
   1778 void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
   1779 void TShader::setResourceSetBinding(const std::vector<std::string>& base)   { intermediate->setResourceSetBinding(base); }
   1780 void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
   1781 
   1782 //
   1783 // Turn the shader strings into a parse tree in the TIntermediate.
   1784 //
   1785 // Returns true for success.
   1786 //
   1787 bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
   1788                     bool forwardCompatible, EShMessages messages, Includer& includer)
   1789 {
   1790     if (! InitThread())
   1791         return false;
   1792     SetThreadPoolAllocator(pool);
   1793 
   1794     if (! preamble)
   1795         preamble = "";
   1796 
   1797     return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
   1798                            preamble, EShOptNone, builtInResources, defaultVersion,
   1799                            defaultProfile, forceDefaultVersionAndProfile,
   1800                            forwardCompatible, messages, *intermediate, includer, sourceEntryPointName,
   1801                            &environment);
   1802 }
   1803 
   1804 // Fill in a string with the result of preprocessing ShaderStrings
   1805 // Returns true if all extensions, pragmas and version strings were valid.
   1806 //
   1807 // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
   1808 // is not an officially supported or fully working path.
   1809 bool TShader::preprocess(const TBuiltInResource* builtInResources,
   1810                          int defaultVersion, EProfile defaultProfile,
   1811                          bool forceDefaultVersionAndProfile,
   1812                          bool forwardCompatible, EShMessages message,
   1813                          std::string* output_string,
   1814                          Includer& includer)
   1815 {
   1816     if (! InitThread())
   1817         return false;
   1818     SetThreadPoolAllocator(pool);
   1819 
   1820     if (! preamble)
   1821         preamble = "";
   1822 
   1823     return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
   1824                               EShOptNone, builtInResources, defaultVersion,
   1825                               defaultProfile, forceDefaultVersionAndProfile,
   1826                               forwardCompatible, message, includer, *intermediate, output_string);
   1827 }
   1828 
   1829 const char* TShader::getInfoLog()
   1830 {
   1831     return infoSink->info.c_str();
   1832 }
   1833 
   1834 const char* TShader::getInfoDebugLog()
   1835 {
   1836     return infoSink->debug.c_str();
   1837 }
   1838 
   1839 TProgram::TProgram() : reflection(0), ioMapper(nullptr), linked(false)
   1840 {
   1841     pool = new TPoolAllocator;
   1842     infoSink = new TInfoSink;
   1843     for (int s = 0; s < EShLangCount; ++s) {
   1844         intermediate[s] = 0;
   1845         newedIntermediate[s] = false;
   1846     }
   1847 }
   1848 
   1849 TProgram::~TProgram()
   1850 {
   1851     delete ioMapper;
   1852     delete infoSink;
   1853     delete reflection;
   1854 
   1855     for (int s = 0; s < EShLangCount; ++s)
   1856         if (newedIntermediate[s])
   1857             delete intermediate[s];
   1858 
   1859     delete pool;
   1860 }
   1861 
   1862 //
   1863 // Merge the compilation units within each stage into a single TIntermediate.
   1864 // All starting compilation units need to be the result of calling TShader::parse().
   1865 //
   1866 // Return true for success.
   1867 //
   1868 bool TProgram::link(EShMessages messages)
   1869 {
   1870     if (linked)
   1871         return false;
   1872     linked = true;
   1873 
   1874     bool error = false;
   1875 
   1876     SetThreadPoolAllocator(pool);
   1877 
   1878     for (int s = 0; s < EShLangCount; ++s) {
   1879         if (! linkStage((EShLanguage)s, messages))
   1880             error = true;
   1881     }
   1882 
   1883     // TODO: Link: cross-stage error checking
   1884 
   1885     return ! error;
   1886 }
   1887 
   1888 //
   1889 // Merge the compilation units within the given stage into a single TIntermediate.
   1890 //
   1891 // Return true for success.
   1892 //
   1893 bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
   1894 {
   1895     if (stages[stage].size() == 0)
   1896         return true;
   1897 
   1898     int numEsShaders = 0, numNonEsShaders = 0;
   1899     for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
   1900         if ((*it)->intermediate->getProfile() == EEsProfile) {
   1901             numEsShaders++;
   1902         } else {
   1903             numNonEsShaders++;
   1904         }
   1905     }
   1906 
   1907     if (numEsShaders > 0 && numNonEsShaders > 0) {
   1908         infoSink->info.message(EPrefixError, "Cannot mix ES profile with non-ES profile shaders");
   1909         return false;
   1910     } else if (numEsShaders > 1) {
   1911         infoSink->info.message(EPrefixError, "Cannot attach multiple ES shaders of the same type to a single program");
   1912         return false;
   1913     }
   1914 
   1915     //
   1916     // Be efficient for the common single compilation unit per stage case,
   1917     // reusing it's TIntermediate instead of merging into a new one.
   1918     //
   1919     TIntermediate *firstIntermediate = stages[stage].front()->intermediate;
   1920     if (stages[stage].size() == 1)
   1921         intermediate[stage] = firstIntermediate;
   1922     else {
   1923         intermediate[stage] = new TIntermediate(stage,
   1924                                                 firstIntermediate->getVersion(),
   1925                                                 firstIntermediate->getProfile());
   1926 
   1927 
   1928         // The new TIntermediate must use the same origin as the original TIntermediates.
   1929         // Otherwise linking will fail due to different coordinate systems.
   1930         if (firstIntermediate->getOriginUpperLeft()) {
   1931             intermediate[stage]->setOriginUpperLeft();
   1932         }
   1933         intermediate[stage]->setSpv(firstIntermediate->getSpv());
   1934 
   1935         newedIntermediate[stage] = true;
   1936     }
   1937 
   1938     if (messages & EShMsgAST)
   1939         infoSink->info << "\nLinked " << StageName(stage) << " stage:\n\n";
   1940 
   1941     if (stages[stage].size() > 1) {
   1942         std::list<TShader*>::const_iterator it;
   1943         for (it = stages[stage].begin(); it != stages[stage].end(); ++it)
   1944             intermediate[stage]->merge(*infoSink, *(*it)->intermediate);
   1945     }
   1946 
   1947     intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0);
   1948 
   1949     if (messages & EShMsgAST)
   1950         intermediate[stage]->output(*infoSink, true);
   1951 
   1952     return intermediate[stage]->getNumErrors() == 0;
   1953 }
   1954 
   1955 const char* TProgram::getInfoLog()
   1956 {
   1957     return infoSink->info.c_str();
   1958 }
   1959 
   1960 const char* TProgram::getInfoDebugLog()
   1961 {
   1962     return infoSink->debug.c_str();
   1963 }
   1964 
   1965 //
   1966 // Reflection implementation.
   1967 //
   1968 
   1969 bool TProgram::buildReflection()
   1970 {
   1971     if (! linked || reflection)
   1972         return false;
   1973 
   1974     reflection = new TReflection;
   1975 
   1976     for (int s = 0; s < EShLangCount; ++s) {
   1977         if (intermediate[s]) {
   1978             if (! reflection->addStage((EShLanguage)s, *intermediate[s]))
   1979                 return false;
   1980         }
   1981     }
   1982 
   1983     return true;
   1984 }
   1985 
   1986 int TProgram::getNumLiveUniformVariables() const             { return reflection->getNumUniforms(); }
   1987 int TProgram::getNumLiveUniformBlocks() const                { return reflection->getNumUniformBlocks(); }
   1988 const char* TProgram::getUniformName(int index) const        { return reflection->getUniform(index).name.c_str(); }
   1989 const char* TProgram::getUniformBlockName(int index) const   { return reflection->getUniformBlock(index).name.c_str(); }
   1990 int TProgram::getUniformBlockSize(int index) const           { return reflection->getUniformBlock(index).size; }
   1991 int TProgram::getUniformIndex(const char* name) const        { return reflection->getIndex(name); }
   1992 int TProgram::getUniformBinding(int index) const             { return reflection->getUniform(index).getBinding(); }
   1993 EShLanguageMask TProgram::getUniformStages(int index) const  { return reflection->getUniform(index).stages; }
   1994 int TProgram::getUniformBlockBinding(int index) const        { return reflection->getUniformBlock(index).getBinding(); }
   1995 int TProgram::getUniformBlockIndex(int index) const          { return reflection->getUniform(index).index; }
   1996 int TProgram::getUniformBlockCounterIndex(int index) const   { return reflection->getUniformBlock(index).counterIndex; }
   1997 int TProgram::getUniformType(int index) const                { return reflection->getUniform(index).glDefineType; }
   1998 int TProgram::getUniformBufferOffset(int index) const        { return reflection->getUniform(index).offset; }
   1999 int TProgram::getUniformArraySize(int index) const           { return reflection->getUniform(index).size; }
   2000 int TProgram::getNumLiveAttributes() const                   { return reflection->getNumAttributes(); }
   2001 const char* TProgram::getAttributeName(int index) const      { return reflection->getAttribute(index).name.c_str(); }
   2002 int TProgram::getAttributeType(int index) const              { return reflection->getAttribute(index).glDefineType; }
   2003 const TType* TProgram::getAttributeTType(int index) const    { return reflection->getAttribute(index).getType(); }
   2004 const TType* TProgram::getUniformTType(int index) const      { return reflection->getUniform(index).getType(); }
   2005 const TType* TProgram::getUniformBlockTType(int index) const { return reflection->getUniformBlock(index).getType(); }
   2006 unsigned TProgram::getLocalSize(int dim) const               { return reflection->getLocalSize(dim); }
   2007 
   2008 void TProgram::dumpReflection()                      { reflection->dump(); }
   2009 
   2010 //
   2011 // I/O mapping implementation.
   2012 //
   2013 bool TProgram::mapIO(TIoMapResolver* resolver)
   2014 {
   2015     if (! linked || ioMapper)
   2016         return false;
   2017 
   2018     ioMapper = new TIoMapper;
   2019 
   2020     for (int s = 0; s < EShLangCount; ++s) {
   2021         if (intermediate[s]) {
   2022             if (! ioMapper->addStage((EShLanguage)s, *intermediate[s], *infoSink, resolver))
   2023                 return false;
   2024         }
   2025     }
   2026 
   2027     return true;
   2028 }
   2029 
   2030 } // end namespace glslang
   2031