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