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