yum-mirror/glslang
git clone https://git.yummers.dev/yum-mirror/glslang
e0735231
main
1// 2// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3// Copyright (C) 2013-2016 LunarG, Inc. 4// Copyright (C) 2016-2020 Google, Inc. 5// Modifications Copyright(C) 2021 Advanced Micro Devices, Inc.All rights reserved. 6// 7// All rights reserved. 8// 9// Redistribution and use in source and binary forms, with or without 10// modification, are permitted provided that the following conditions 11// are met: 12// 13// Redistributions of source code must retain the above copyright 14// notice, this list of conditions and the following disclaimer. 15// 16// Redistributions in binary form must reproduce the above 17// copyright notice, this list of conditions and the following 18// disclaimer in the documentation and/or other materials provided 19// with the distribution. 20// 21// Neither the name of 3Dlabs Inc. Ltd. nor the names of its 22// contributors may be used to endorse or promote products derived 23// from this software without specific prior written permission. 24// 25// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 35// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36// POSSIBILITY OF SUCH DAMAGE. 37// 38 39// this only applies to the standalone wrapper, not the front end in general 40#ifndef _CRT_SECURE_NO_WARNINGS 41#define _CRT_SECURE_NO_WARNINGS 42#endif 43 44#include "glslang/Public/ResourceLimits.h" 45#include "Worklist.h" 46#include "DirStackFileIncluder.h" 47#include "./../glslang/Public/ShaderLang.h" 48#include "../glslang/MachineIndependent/localintermediate.h" 49#include "../SPIRV/GlslangToSpv.h" 50#include "../SPIRV/GLSL.std.450.h" 51#include "../SPIRV/disassemble.h" 52 53#include <array> 54#include <atomic> 55#include <cctype> 56#include <cmath> 57#include <cstdlib> 58#include <cstring> 59#include <filesystem> 60#include <iterator> 61#include <map> 62#include <memory> 63#include <set> 64#include <thread> 65#include <type_traits> 66 67#include "../glslang/OSDependent/osinclude.h" 68 69// Build-time generated includes 70#include "glslang/build_info.h" 71 72#include "glslang/glsl_intrinsic_header.h" 73 74extern "C" { 75GLSLANG_EXPORT void ShOutputHtml (); 76} 77 78// Command-line options 79enum TOptions :uint64_t { 80EOptionNone = 0 , 81EOptionIntermediate = (1ull <<0 ), 82EOptionSuppressInfolog = (1ull <<1 ), 83EOptionMemoryLeakMode = (1ull <<2 ), 84EOptionRelaxedErrors = (1ull <<3 ), 85EOptionGiveWarnings = (1ull <<4 ), 86EOptionLinkProgram = (1ull <<5 ), 87EOptionMultiThreaded = (1ull <<6 ), 88EOptionDumpConfig = (1ull <<7 ), 89EOptionDumpReflection = (1ull <<8 ), 90EOptionSuppressWarnings = (1ull <<9 ), 91EOptionDumpVersions = (1ull <<10 ), 92EOptionSpv = (1ull <<11 ), 93EOptionHumanReadableSpv = (1ull <<12 ), 94EOptionVulkanRules = (1ull <<13 ), 95EOptionDefaultDesktop = (1ull <<14 ), 96EOptionOutputPreprocessed = (1ull <<15 ), 97EOptionOutputHexadecimal = (1ull <<16 ), 98EOptionReadHlsl = (1ull <<17 ), 99EOptionCascadingErrors = (1ull <<18 ), 100EOptionAutoMapBindings = (1ull <<19 ), 101EOptionFlattenUniformArrays = (1ull <<20 ), 102EOptionNoStorageFormat = (1ull <<21 ), 103EOptionKeepUncalled = (1ull <<22 ), 104EOptionHlslOffsets = (1ull <<23 ), 105EOptionHlslIoMapping = (1ull <<24 ), 106EOptionAutoMapLocations = (1ull <<25 ), 107EOptionDebug = (1ull <<26 ), 108EOptionStdin = (1ull <<27 ), 109EOptionOptimizeDisable = (1ull <<28 ), 110EOptionOptimizeSize = (1ull <<29 ), 111EOptionInvertY = (1ull <<30 ), 112EOptionDumpBareVersion = (1ull <<31 ), 113EOptionCompileOnly = (1ull <<32 ), 114EOptionDisplayErrorColumn = (1ull <<33 ), 115EOptionLinkTimeOptimization = (1ull <<34 ), 116EOptionValidateCrossStageIO = (1ull <<35 ), 117EOptionBindingsPerResourceType = (1ull <<36 ), 118EOptionRelaxSetBindingLimits = (1ull <<37 ), 119EOptionDiscardIsTerminate = (1ull <<38 ), 120EOptionOptimizePerformance = (1ull <<39 ), 121}; 122bool targetHlslFunctionality1 = false; 123bool SpvToolsDisassembler = false; 124bool SpvToolsValidate = false; 125bool NaNClamp = false; 126bool stripDebugInfo = false; 127bool emitNonSemanticShaderDebugInfo = false; 128bool emitNonSemanticShaderDebugSource = false; 129bool emitSourceFileName = false; 130bool beQuiet = false; 131bool VulkanRulesRelaxed = false; 132bool autoSampledTextures = false; 133 134// 135// Return codes from main/exit(). 136// 137enum TFailCode { 138ESuccess = 0 , 139EFailUsage , 140EFailCompile , 141EFailLink , 142EFailCompilerCreate , 143EFailThreadCreate , 144EFailLinkerCreate 145}; 146 147// 148// Forward declarations. 149// 150EShLanguage FindLanguage (const std::string & name ,bool parseSuffix = true); 151void CompileFile (const char * fileName ,ShHandle ); 152void usage (); 153char * ReadFileData (const char * fileName ); 154void FreeFileData (char * data ); 155void InfoLogMsg (const char * msg ,const char * name ,const int num ); 156 157// Globally track if any compile or link failure. 158std::atomic < int8_t > CompileFailed {0 }; 159std::atomic < int8_t > LinkFailed {0 }; 160std::atomic < int8_t > CompileOrLinkFailed {0 }; 161 162// array of unique places to leave the shader names and infologs for the asynchronous compiles 163std::vector < std::unique_ptr < glslang::TWorkItem >> WorkItems ; 164 165std::string ConfigFile ; 166 167// 168// Parse either a .conf file provided by the user or the default from glslang::DefaultTBuiltInResource 169// 170void ProcessConfigFile () 171{ 172if (ConfigFile .size ()== 0 ) 173* GetResources ()= * GetDefaultResources (); 174else { 175char * configString = ReadFileData (ConfigFile .c_str ()); 176DecodeResourceLimits (GetResources (),configString ); 177FreeFileData (configString ); 178 } 179} 180 181int ReflectOptions = EShReflectionDefault ; 182std::underlying_type_t < TOptions > Options = EOptionNone ; 183const char * ExecutableName = nullptr ; 184const char * binaryFileName = nullptr ; 185const char * depencyFileName = nullptr ; 186const char * entryPointName = nullptr ; 187const char * sourceEntryPointName = nullptr ; 188const char * shaderStageName = nullptr ; 189const char * variableName = nullptr ; 190bool HlslEnable16BitTypes = false; 191bool HlslDX9compatible = false; 192bool HlslDxPositionW = false; 193bool EnhancedMsgs = false; 194bool AbsolutePath = false; 195bool DumpBuiltinSymbols = false; 196std::vector < std::string > IncludeDirectoryList ; 197 198// Source environment 199// (source 'Client' is currently the same as target 'Client') 200int ClientInputSemanticsVersion = 100 ; 201 202// Target environment 203glslang::EShClient Client = glslang::EShClientNone ;// will stay EShClientNone if only validating 204glslang::EShTargetClientVersion ClientVersion ;// not valid until Client is set 205glslang::EShTargetLanguage TargetLanguage = glslang::EShTargetNone ; 206glslang::EShTargetLanguageVersion TargetVersion ;// not valid until TargetLanguage is set 207 208// GLSL version 209int GlslVersion = 0 ;// GLSL version specified on CLI, overrides #version in shader source 210 211std::vector < std::string > Processes ;// what should be recorded by OpModuleProcessed, or equivalent 212std::string CommandLineArguments ;// original arguments passed to the standalone compiler 213 214// Per descriptor-set binding base data 215typedef std::map < unsigned int ,unsigned int > TPerSetBaseBinding ; 216 217std::vector < std::pair < std::string ,int >> uniformLocationOverrides ; 218int uniformBase = 0 ; 219 220std::array < std::array < unsigned int ,EShLangCount > , glslang::EResCount > baseBinding ; 221std::array < std::array < TPerSetBaseBinding ,EShLangCount > , glslang::EResCount > baseBindingForSet ; 222std::array < std::vector < std::string > ,EShLangCount > baseResourceSetBinding ; 223 224std::vector < std::pair < std::string , glslang::TBlockStorageClass >> blockStorageOverrides ; 225 226bool setGlobalUniformBlock = false; 227std::string globalUniformName ; 228unsigned int globalUniformBinding ; 229unsigned int globalUniformSet ; 230 231bool setGlobalBufferBlock = false; 232std::string atomicCounterBlockName ; 233unsigned int atomicCounterBlockSet ; 234 235// Add things like "#define ..." to a preamble to use in the beginning of the shader. 236class TPreamble { 237public : 238TPreamble () { } 239 240bool isSet ()const {return text .size ()> 0 ; } 241const char * get ()const {return text .c_str (); } 242 243// #define... 244void addDef (std::string def ) 245 { 246text .append ("#define " ); 247fixLine (def ); 248 249Processes .push_back ("define-macro " ); 250Processes .back ().append (def ); 251 252// The first "=" needs to turn into a space 253const size_t equal = def .find_first_of ("=" ); 254if (equal != def .npos ) 255def [equal ]= ' ' ; 256 257text .append (def ); 258text .append ("\n" ); 259 } 260 261// #undef... 262void addUndef (std::string undef ) 263 { 264text .append ("#undef " ); 265fixLine (undef ); 266 267Processes .push_back ("undef-macro " ); 268Processes .back ().append (undef ); 269 270text .append (undef ); 271text .append ("\n" ); 272 } 273 274void addText (std::string preambleText ) 275 { 276fixLine (preambleText ); 277 278Processes .push_back ("preamble-text" ); 279Processes .back ().append (preambleText ); 280 281text .append (preambleText ); 282text .append ("\n" ); 283 } 284 285protected : 286void fixLine (std::string & line ) 287 { 288// Can't go past a newline in the line 289const size_t end = line .find_first_of ("\n" ); 290if (end != line .npos ) 291line = line .substr (0 ,end ); 292 } 293 294 std::string text ;// contents of preamble 295}; 296 297// Track the user's #define and #undef from the command line. 298TPreamble UserPreamble ; 299std::string PreambleString ; 300 301// 302// Create the default name for saving a binary if -o is not provided. 303// 304const char * GetBinaryName (EShLanguage stage ) 305{ 306const char * name ; 307if (binaryFileName == nullptr ) { 308switch (stage ) { 309case EShLangVertex :name = "vert.spv" ;break ; 310case EShLangTessControl :name = "tesc.spv" ;break ; 311case EShLangTessEvaluation :name = "tese.spv" ;break ; 312case EShLangGeometry :name = "geom.spv" ;break ; 313case EShLangFragment :name = "frag.spv" ;break ; 314case EShLangCompute :name = "comp.spv" ;break ; 315case EShLangRayGen :name = "rgen.spv" ;break ; 316case EShLangIntersect :name = "rint.spv" ;break ; 317case EShLangAnyHit :name = "rahit.spv" ;break ; 318case EShLangClosestHit :name = "rchit.spv" ;break ; 319case EShLangMiss :name = "rmiss.spv" ;break ; 320case EShLangCallable :name = "rcall.spv" ;break ; 321case EShLangMesh :name = "mesh.spv" ;break ; 322case EShLangTask :name = "task.spv" ;break ; 323default :name = "unknown" ;break ; 324 } 325 }else 326name = binaryFileName ; 327 328return name ; 329} 330 331// 332// *.conf => this is a config file that can set limits/resources 333// 334bool SetConfigFile (const std::string & name ) 335{ 336if (name .size ()< 5 ) 337return false; 338 339if (name .compare (name .size ()- 5 ,5 ,".conf" )== 0 ) { 340ConfigFile = name ; 341return true; 342 } 343 344return false; 345} 346 347// 348// Give error and exit with failure code. 349// 350void Error (const char * message ,const char * detail = nullptr ) 351{ 352fprintf (stderr ,"%s: Error: " ,ExecutableName ); 353if (detail != nullptr ) 354fprintf (stderr ,"%s: " ,detail ); 355fprintf (stderr ,"%s (use -h for usage)\n" ,message ); 356exit (EFailUsage ); 357} 358 359// 360// Process an optional binding base of one the forms: 361// --argname [stage] base // base for stage (if given) or all stages (if not) 362// --argname [stage] [base set]... // set/base pairs: set the base for given binding set. 363 364// Where stage is one of the forms accepted by FindLanguage, and base is an integer 365// 366void ProcessBindingBase (int & argc ,char **& argv , glslang::TResourceType res ) 367{ 368if (argc < 2 ) 369usage (); 370 371EShLanguage lang = EShLangCount ; 372int singleBase = 0 ; 373TPerSetBaseBinding perSetBase ; 374int arg = 1 ; 375 376// Parse stage, if given 377if (!isdigit (argv [arg ][0 ])) { 378if (argc < 3 )// this form needs one more argument 379usage (); 380 381lang = FindLanguage (argv [arg ++ ], false); 382 } 383 384if ((argc - arg ) >=2 && isdigit (argv [arg + 0 ][0 ])&& isdigit (argv [arg + 1 ][0 ])) { 385// Parse a per-set binding base 386do { 387const int baseNum = atoi (argv [arg ++ ]); 388const int setNum = atoi (argv [arg ++ ]); 389perSetBase [setNum ]= baseNum ; 390 }while ((argc - arg ) >=2 && isdigit (argv [arg + 0 ][0 ])&& isdigit (argv [arg + 1 ][0 ])); 391 }else { 392// Parse single binding base 393singleBase = atoi (argv [arg ++ ]); 394 } 395 396argc -= (arg - 1 ); 397argv += (arg - 1 ); 398 399// Set one or all languages 400const int langMin = (lang < EShLangCount ) ?lang + 0 :0 ; 401const int langMax = (lang < EShLangCount ) ?lang + 1 :EShLangCount ; 402 403for (int lang = langMin ;lang < langMax ;++ lang ) { 404if (!perSetBase .empty ()) 405baseBindingForSet [res ][lang ].insert (perSetBase .begin (),perSetBase .end ()); 406else 407baseBinding [res ][lang ]= singleBase ; 408 } 409} 410 411void ProcessResourceSetBindingBase (int & argc ,char **& argv , std::array < std::vector < std::string > ,EShLangCount >& base ) 412{ 413if (argc < 2 ) 414usage (); 415 416if (!isdigit (argv [1 ][0 ])) { 417if (argc < 3 )// this form needs one more argument 418usage (); 419 420// Parse form: --argname stage [regname set base...], or: 421// --argname stage set 422const EShLanguage lang = FindLanguage (argv [1 ], false); 423 424argc -- ; 425argv ++ ; 426 427while (argc > 1 && argv [1 ]!= nullptr && argv [1 ][0 ]!= '-' ) { 428base [lang ].push_back (argv [1 ]); 429 430argc -- ; 431argv ++ ; 432 } 433 434// Must have one arg, or a multiple of three (for [regname set binding] triples) 435if (base [lang ].size ()!= 1 && (base [lang ].size () %3 )!= 0 ) 436usage (); 437 438 }else { 439// Parse form: --argname set 440for (int lang = 0 ;lang < EShLangCount ;++ lang ) 441base [lang ].push_back (argv [1 ]); 442 443argc -- ; 444argv ++ ; 445 } 446} 447 448// 449// Process an optional binding base of one the forms: 450// --argname name {uniform|buffer|push_constant} 451void ProcessBlockStorage (int & argc ,char **& argv , std::vector < std::pair < std::string , glslang::TBlockStorageClass >>& storage ) 452{ 453if (argc < 3 ) 454usage (); 455 456 glslang::TBlockStorageClass blockStorage = glslang::EbsNone ; 457 458 std::string strBacking (argv [2 ]); 459if (strBacking == "uniform" ) 460blockStorage = glslang::EbsUniform ; 461else if (strBacking == "buffer" ) 462blockStorage = glslang::EbsStorageBuffer ; 463else if (strBacking == "push_constant" ) 464blockStorage = glslang::EbsPushConstant ; 465else { 466printf ("%s: invalid block storage\n" ,strBacking .c_str ()); 467usage (); 468 } 469 470storage .push_back (std::make_pair (std::string (argv [1 ]),blockStorage )); 471 472argc -= 2 ; 473argv += 2 ; 474} 475 476inline bool isNonDigit (char c ) { 477// a non-digit character valid in a glsl identifier 478return (c == '_' )|| (c >='a' && c <='z' )|| (c >='A' && c <='Z' ); 479} 480 481// whether string isa valid identifier to be used in glsl 482bool isValidIdentifier (const char * str ) { 483 std::string idn (str ); 484 485if (idn .length ()== 0 ) { 486return false; 487 } 488 489if (idn .length () >=3 && idn .substr (0 ,3 )== "gl_" ) { 490// identifiers startin with "gl_" are reserved 491return false; 492 } 493 494if (!isNonDigit (idn [0 ])) { 495return false; 496 } 497 498for (unsigned int i = 1 ;i < idn .length ();++ i ) { 499if (!(isdigit (idn [i ])|| isNonDigit (idn [i ]))) { 500return false; 501 } 502 } 503 504return true; 505} 506 507// Process settings for either the global buffer block or global unfirom block 508// of the form: 509// --argname name set binding 510void ProcessGlobalBlockSettings (int & argc ,char **& argv , std::string * name ,unsigned int * set ,unsigned int * binding ) 511{ 512if (argc < 4 ) 513usage (); 514 515unsigned int curArg = 1 ; 516 517assert (name || set || binding ); 518 519if (name ) { 520if (!isValidIdentifier (argv [curArg ])) { 521printf ("%s: invalid identifier\n" ,argv [curArg ]); 522usage (); 523 } 524* name = argv [curArg ]; 525 526curArg ++ ; 527 } 528 529if (set ) { 530errno = 0 ; 531int setVal = static_cast < int > (::strtol (argv [curArg ],nullptr ,10 )); 532if (errno || setVal < 0 ) { 533printf ("%s: invalid set\n" ,argv [curArg ]); 534usage (); 535 } 536* set = setVal ; 537 538curArg ++ ; 539 } 540 541if (binding ) { 542errno = 0 ; 543int bindingVal = static_cast < int > (::strtol (argv [curArg ],nullptr ,10 )); 544if (errno || bindingVal < 0 ) { 545printf ("%s: invalid binding\n" ,argv [curArg ]); 546usage (); 547 } 548* binding = bindingVal ; 549 550curArg ++ ; 551 } 552 553argc -= (curArg - 1 ); 554argv += (curArg - 1 ); 555} 556 557// 558// Do all command-line argument parsing. This includes building up the work-items 559// to be processed later, and saving all the command-line options. 560// 561// Does not return (it exits) if command-line is fatally flawed. 562// 563void ProcessArguments (std::vector < std::unique_ptr < glslang::TWorkItem >>& workItems ,int argc ,char * argv []) 564{ 565for (int res = 0 ;res < glslang::EResCount ;++ res ) 566baseBinding [res ].fill (0 ); 567 568ExecutableName = argv [0 ]; 569workItems .reserve (argc ); 570 571CommandLineArguments .clear (); 572for (int arg = 1 ;arg < argc ;++ arg ) { 573if (arg > 1 ) 574CommandLineArguments += ' ' ; 575CommandLineArguments += argv [arg ]; 576 } 577 578const auto bumpArg = [& ]() { 579if (argc > 0 ) { 580argc -- ; 581argv ++ ; 582 } 583 }; 584 585// read a string directly attached to a single-letter option 586const auto getStringOperand = [& ](const char * desc ) { 587if (argv [0 ][2 ]== 0 ) { 588printf ("%s must immediately follow option (no spaces)\n" ,desc ); 589exit (EFailUsage ); 590 } 591return argv [0 ]+ 2 ; 592 }; 593 594// read a number attached to a single-letter option 595const auto getAttachedNumber = [& ](const char * desc ) { 596int num = atoi (argv [0 ]+ 2 ); 597if (num == 0 ) { 598printf ("%s: expected attached non-0 number\n" ,desc ); 599exit (EFailUsage ); 600 } 601return num ; 602 }; 603 604// minimum needed (without overriding something else) to target Vulkan SPIR-V 605const auto setVulkanSpv = []() { 606if (Client == glslang::EShClientNone ) 607ClientVersion = glslang::EShTargetVulkan_1_0 ; 608Client = glslang::EShClientVulkan ; 609Options |=EOptionSpv ; 610Options |=EOptionVulkanRules ; 611Options |=EOptionLinkProgram ; 612 }; 613 614// minimum needed (without overriding something else) to target OpenGL SPIR-V 615const auto setOpenGlSpv = []() { 616if (Client == glslang::EShClientNone ) 617ClientVersion = glslang::EShTargetOpenGL_450 ; 618Client = glslang::EShClientOpenGL ; 619Options |=EOptionSpv ; 620Options |=EOptionLinkProgram ; 621// undo a -H default to Vulkan 622Options &= ~EOptionVulkanRules ; 623 }; 624 625const auto getUniformOverride = [getStringOperand ]() { 626const char * arg = getStringOperand ("-u<name>:<location>" ); 627const char * split = strchr (arg ,':' ); 628if (split == nullptr ) { 629printf ("%s: missing location\n" ,arg ); 630exit (EFailUsage ); 631 } 632errno = 0 ; 633int location = static_cast < int > (::strtol (split + 1 ,nullptr ,10 )); 634if (errno ) { 635printf ("%s: invalid location\n" ,arg ); 636exit (EFailUsage ); 637 } 638return std::make_pair (std::string (arg ,split - arg ),location ); 639 }; 640 641for (bumpArg ();argc >=1 ;bumpArg ()) { 642if (argv [0 ][0 ]== '-' ) { 643switch (argv [0 ][1 ]) { 644case '-' : 645 { 646 std::string lowerword (argv [0 ]+ 2 ); 647 std::transform (lowerword .begin (),lowerword .end (),lowerword .begin (), ::tolower ); 648 649// handle --word style options 650if (lowerword == "auto-map-bindings" || // synonyms 651lowerword == "auto-map-binding" || 652lowerword == "amb" ) { 653Options |=EOptionAutoMapBindings ; 654 }else if (lowerword == "relax-set-binding-limits" ) { 655Options |=EOptionRelaxSetBindingLimits ; 656 }else if (lowerword == "auto-map-locations" || // synonyms 657lowerword == "aml" ) { 658Options |=EOptionAutoMapLocations ; 659 }else if (lowerword == "uniform-base" ) { 660if (argc <=1 ) 661Error ("no <base> provided" ,lowerword .c_str ()); 662uniformBase = static_cast < int > (::strtol (argv [1 ],nullptr ,10 )); 663bumpArg (); 664break ; 665 }else if (lowerword == "client" ) { 666if (argc > 1 ) { 667if (strcmp (argv [1 ],"vulkan100" )== 0 ) 668setVulkanSpv (); 669else if (strcmp (argv [1 ],"opengl100" )== 0 ) 670setOpenGlSpv (); 671else 672Error ("expects vulkan100 or opengl100" ,lowerword .c_str ()); 673 }else 674Error ("expects vulkan100 or opengl100" ,lowerword .c_str ()); 675bumpArg (); 676 }else if (lowerword == "define-macro" || 677lowerword == "d" ) { 678if (argc > 1 ) 679UserPreamble .addDef (argv [1 ]); 680else 681Error ("expects <name[=def]>" ,argv [0 ]); 682bumpArg (); 683 }else if (lowerword == "dump-builtin-symbols" ) { 684DumpBuiltinSymbols = true; 685 }else if (lowerword == "entry-point" ) { 686entryPointName = argv [1 ]; 687if (argc <=1 ) 688Error ("no <name> provided" ,lowerword .c_str ()); 689bumpArg (); 690 }else if (lowerword == "flatten-uniform-arrays" || // synonyms 691lowerword == "flatten-uniform-array" || 692lowerword == "fua" ) { 693Options |=EOptionFlattenUniformArrays ; 694 }else if (lowerword == "glsl-version" ) { 695if (argc > 1 ) { 696if (strcmp (argv [1 ],"100" )== 0 ) { 697GlslVersion = 100 ; 698 }else if (strcmp (argv [1 ],"110" )== 0 ) { 699GlslVersion = 110 ; 700 }else if (strcmp (argv [1 ],"120" )== 0 ) { 701GlslVersion = 120 ; 702 }else if (strcmp (argv [1 ],"130" )== 0 ) { 703GlslVersion = 130 ; 704 }else if (strcmp (argv [1 ],"140" )== 0 ) { 705GlslVersion = 140 ; 706 }else if (strcmp (argv [1 ],"150" )== 0 ) { 707GlslVersion = 150 ; 708 }else if (strcmp (argv [1 ],"300es" )== 0 ) { 709GlslVersion = 300 ; 710 }else if (strcmp (argv [1 ],"310es" )== 0 ) { 711GlslVersion = 310 ; 712 }else if (strcmp (argv [1 ],"320es" )== 0 ) { 713GlslVersion = 320 ; 714 }else if (strcmp (argv [1 ],"330" )== 0 ) { 715GlslVersion = 330 ; 716 }else if (strcmp (argv [1 ],"400" )== 0 ) { 717GlslVersion = 400 ; 718 }else if (strcmp (argv [1 ],"410" )== 0 ) { 719GlslVersion = 410 ; 720 }else if (strcmp (argv [1 ],"420" )== 0 ) { 721GlslVersion = 420 ; 722 }else if (strcmp (argv [1 ],"430" )== 0 ) { 723GlslVersion = 430 ; 724 }else if (strcmp (argv [1 ],"440" )== 0 ) { 725GlslVersion = 440 ; 726 }else if (strcmp (argv [1 ],"450" )== 0 ) { 727GlslVersion = 450 ; 728 }else if (strcmp (argv [1 ],"460" )== 0 ) { 729GlslVersion = 460 ; 730 }else 731Error ("--glsl-version expected one of: 100, 110, 120, 130, 140, 150,\n" 732"300es, 310es, 320es, 330\n" 733"400, 410, 420, 430, 440, 450, 460" ); 734 } 735bumpArg (); 736 }else if (lowerword == "hlsl-offsets" ) { 737Options |=EOptionHlslOffsets ; 738 }else if (lowerword == "hlsl-iomap" || 739lowerword == "hlsl-iomapper" || 740lowerword == "hlsl-iomapping" ) { 741Options |=EOptionHlslIoMapping ; 742 }else if (lowerword == "hlsl-enable-16bit-types" ) { 743HlslEnable16BitTypes = true; 744 }else if (lowerword == "hlsl-dx9-compatible" ) { 745HlslDX9compatible = true; 746 }else if (lowerword == "hlsl-dx-position-w" ) { 747HlslDxPositionW = true; 748 }else if (lowerword == "enhanced-msgs" ) { 749EnhancedMsgs = true; 750 }else if (lowerword == "absolute-path" ) { 751AbsolutePath = true; 752 }else if (lowerword == "auto-sampled-textures" ) { 753autoSampledTextures = true; 754 }else if (lowerword == "discard-is-terminate" ) { 755Options |=EOptionDiscardIsTerminate ; 756 }else if (lowerword == "invert-y" || // synonyms 757lowerword == "iy" ) { 758Options |=EOptionInvertY ; 759 }else if (lowerword == "keep-uncalled" || // synonyms 760lowerword == "ku" ) { 761Options |=EOptionKeepUncalled ; 762 }else if (lowerword == "nan-clamp" ) { 763NaNClamp = true; 764 }else if (lowerword == "no-storage-format" || // synonyms 765lowerword == "nsf" ) { 766Options |=EOptionNoStorageFormat ; 767 }else if (lowerword == "preamble-text" || 768lowerword == "p" ) { 769if (argc > 1 ) 770UserPreamble .addText (argv [1 ]); 771else 772Error ("expects <text>" ,argv [0 ]); 773bumpArg (); 774 }else if (lowerword == "relaxed-errors" ) { 775Options |=EOptionRelaxedErrors ; 776 }else if (lowerword == "reflect-strict-array-suffix" ) { 777ReflectOptions |=EShReflectionStrictArraySuffix ; 778 }else if (lowerword == "reflect-basic-array-suffix" ) { 779ReflectOptions |=EShReflectionBasicArraySuffix ; 780 }else if (lowerword == "reflect-intermediate-io" ) { 781ReflectOptions |=EShReflectionIntermediateIO ; 782 }else if (lowerword == "reflect-separate-buffers" ) { 783ReflectOptions |=EShReflectionSeparateBuffers ; 784 }else if (lowerword == "reflect-all-block-variables" ) { 785ReflectOptions |=EShReflectionAllBlockVariables ; 786 }else if (lowerword == "reflect-unwrap-io-blocks" ) { 787ReflectOptions |=EShReflectionUnwrapIOBlocks ; 788 }else if (lowerword == "reflect-all-io-variables" ) { 789ReflectOptions |=EShReflectionAllIOVariables ; 790 }else if (lowerword == "reflect-shared-std140-ubo" ) { 791ReflectOptions |=EShReflectionSharedStd140UBO ; 792 }else if (lowerword == "reflect-shared-std140-ssbo" ) { 793ReflectOptions |=EShReflectionSharedStd140SSBO ; 794 }else if (lowerword == "resource-set-bindings" || // synonyms 795lowerword == "resource-set-binding" || 796lowerword == "rsb" ) { 797ProcessResourceSetBindingBase (argc ,argv ,baseResourceSetBinding ); 798 }else if (lowerword == "set-block-storage" || 799lowerword == "sbs" ) { 800ProcessBlockStorage (argc ,argv ,blockStorageOverrides ); 801 }else if (lowerword == "set-atomic-counter-block" || 802lowerword == "sacb" ) { 803ProcessGlobalBlockSettings (argc ,argv ,& atomicCounterBlockName ,& atomicCounterBlockSet ,nullptr ); 804setGlobalBufferBlock = true; 805 }else if (lowerword == "set-default-uniform-block" || 806lowerword == "sdub" ) { 807ProcessGlobalBlockSettings (argc ,argv ,& globalUniformName ,& globalUniformSet ,& globalUniformBinding ); 808setGlobalUniformBlock = true; 809 }else if (lowerword == "shift-image-bindings" || // synonyms 810lowerword == "shift-image-binding" || 811lowerword == "sib" ) { 812ProcessBindingBase (argc ,argv , glslang::EResImage ); 813 }else if (lowerword == "shift-sampler-bindings" || // synonyms 814lowerword == "shift-sampler-binding" || 815lowerword == "ssb" ) { 816ProcessBindingBase (argc ,argv , glslang::EResSampler ); 817 }else if (lowerword == "shift-uav-bindings" || // synonyms 818lowerword == "shift-uav-binding" || 819lowerword == "suavb" ) { 820ProcessBindingBase (argc ,argv , glslang::EResUav ); 821 }else if (lowerword == "shift-texture-bindings" || // synonyms 822lowerword == "shift-texture-binding" || 823lowerword == "stb" ) { 824ProcessBindingBase (argc ,argv , glslang::EResTexture ); 825 }else if (lowerword == "shift-ubo-bindings" || // synonyms 826lowerword == "shift-ubo-binding" || 827lowerword == "shift-cbuffer-bindings" || 828lowerword == "shift-cbuffer-binding" || 829lowerword == "sub" || 830lowerword == "scb" ) { 831ProcessBindingBase (argc ,argv , glslang::EResUbo ); 832 }else if (lowerword == "shift-ssbo-bindings" || // synonyms 833lowerword == "shift-ssbo-binding" || 834lowerword == "sbb" ) { 835ProcessBindingBase (argc ,argv , glslang::EResSsbo ); 836 }else if (lowerword == "shift-combined-sampler-bindings" || 837lowerword == "shift-combined-sampler-binding" || 838lowerword == "scsb" ) { 839ProcessBindingBase (argc ,argv , glslang::EResCombinedSampler ); 840 }else if (lowerword == "shift-as-bindings" || 841lowerword == "shift-as-binding" || 842lowerword == "sab" ) { 843ProcessBindingBase (argc ,argv , glslang::EResAs ); 844 }else if (lowerword == "source-entrypoint" || // synonyms 845lowerword == "sep" ) { 846if (argc <=1 ) 847Error ("no <entry-point> provided" ,lowerword .c_str ()); 848sourceEntryPointName = argv [1 ]; 849bumpArg (); 850break ; 851 }else if (lowerword == "spirv-dis" ) { 852SpvToolsDisassembler = true; 853 }else if (lowerword == "spirv-val" ) { 854SpvToolsValidate = true; 855 }else if (lowerword == "stdin" ) { 856Options |=EOptionStdin ; 857shaderStageName = argv [1 ]; 858 }else if (lowerword == "suppress-warnings" ) { 859Options |=EOptionSuppressWarnings ; 860 }else if (lowerword == "target-env" ) { 861if (argc > 1 ) { 862if (strcmp (argv [1 ],"vulkan1.0" )== 0 ) { 863setVulkanSpv (); 864ClientVersion = glslang::EShTargetVulkan_1_0 ; 865 }else if (strcmp (argv [1 ],"vulkan1.1" )== 0 ) { 866setVulkanSpv (); 867ClientVersion = glslang::EShTargetVulkan_1_1 ; 868 }else if (strcmp (argv [1 ],"vulkan1.2" )== 0 ) { 869setVulkanSpv (); 870ClientVersion = glslang::EShTargetVulkan_1_2 ; 871 }else if (strcmp (argv [1 ],"vulkan1.3" )== 0 ) { 872setVulkanSpv (); 873ClientVersion = glslang::EShTargetVulkan_1_3 ; 874 }else if (strcmp (argv [1 ],"vulkan1.4" )== 0 ) { 875setVulkanSpv (); 876ClientVersion = glslang::EShTargetVulkan_1_4 ; 877 }else if (strcmp (argv [1 ],"opengl" )== 0 ) { 878setOpenGlSpv (); 879ClientVersion = glslang::EShTargetOpenGL_450 ; 880 }else if (strcmp (argv [1 ],"spirv1.0" )== 0 ) { 881TargetLanguage = glslang::EShTargetSpv ; 882TargetVersion = glslang::EShTargetSpv_1_0 ; 883 }else if (strcmp (argv [1 ],"spirv1.1" )== 0 ) { 884TargetLanguage = glslang::EShTargetSpv ; 885TargetVersion = glslang::EShTargetSpv_1_1 ; 886 }else if (strcmp (argv [1 ],"spirv1.2" )== 0 ) { 887TargetLanguage = glslang::EShTargetSpv ; 888TargetVersion = glslang::EShTargetSpv_1_2 ; 889 }else if (strcmp (argv [1 ],"spirv1.3" )== 0 ) { 890TargetLanguage = glslang::EShTargetSpv ; 891TargetVersion = glslang::EShTargetSpv_1_3 ; 892 }else if (strcmp (argv [1 ],"spirv1.4" )== 0 ) { 893TargetLanguage = glslang::EShTargetSpv ; 894TargetVersion = glslang::EShTargetSpv_1_4 ; 895 }else if (strcmp (argv [1 ],"spirv1.5" )== 0 ) { 896TargetLanguage = glslang::EShTargetSpv ; 897TargetVersion = glslang::EShTargetSpv_1_5 ; 898 }else if (strcmp (argv [1 ],"spirv1.6" )== 0 ) { 899TargetLanguage = glslang::EShTargetSpv ; 900TargetVersion = glslang::EShTargetSpv_1_6 ; 901 }else 902Error ("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2,\n" 903"vulkan1.3, vulkan1.4, opengl, spirv1.0, spirv1.1, spirv1.2, spirv1.3,\n" 904"spirv1.4, spirv1.5 or spirv1.6" ); 905 } 906bumpArg (); 907 }else if (lowerword == "undef-macro" || 908lowerword == "u" ) { 909if (argc > 1 ) 910UserPreamble .addUndef (argv [1 ]); 911else 912Error ("expects <name>" ,argv [0 ]); 913bumpArg (); 914 }else if (lowerword == "variable-name" || // synonyms 915lowerword == "vn" ) { 916Options |=EOptionOutputHexadecimal ; 917if (argc <=1 ) 918Error ("no <C-variable-name> provided" ,lowerword .c_str ()); 919variableName = argv [1 ]; 920bumpArg (); 921break ; 922 }else if (lowerword == "quiet" ) { 923beQuiet = true; 924 }else if (lowerword == "depfile" ) { 925if (argc <=1 ) 926Error ("no <depfile-name> provided" ,lowerword .c_str ()); 927depencyFileName = argv [1 ]; 928bumpArg (); 929 }else if (lowerword == "version" ) { 930Options |=EOptionDumpVersions ; 931 }else if (lowerword == "no-link" ) { 932Options |=EOptionCompileOnly ; 933 }else if (lowerword == "error-column" ) { 934Options |=EOptionDisplayErrorColumn ; 935 }else if (lowerword == "lto" ) { 936Options |=EOptionLinkTimeOptimization ; 937 }else if (lowerword == "validate-io" ) { 938Options |=EOptionValidateCrossStageIO ; 939 }else if (lowerword == "bindings-per-resource-type" ) { 940Options |=EOptionBindingsPerResourceType ; 941 }else if (lowerword == "help" ) { 942usage (); 943break ; 944 }else { 945Error ("unrecognized command-line option" ,argv [0 ]); 946 } 947 } 948break ; 949case 'C' : 950Options |=EOptionCascadingErrors ; 951break ; 952case 'D' : 953if (argv [0 ][2 ]== 0 ) 954Options |=EOptionReadHlsl ; 955else 956UserPreamble .addDef (getStringOperand ("-D<name[=def]>" )); 957break ; 958case 'u' : 959uniformLocationOverrides .push_back (getUniformOverride ()); 960break ; 961case 'E' : 962Options |=EOptionOutputPreprocessed ; 963break ; 964case 'G' : 965// OpenGL client 966setOpenGlSpv (); 967if (argv [0 ][2 ]!= 0 ) 968ClientInputSemanticsVersion = getAttachedNumber ("-G<num> client input semantics" ); 969if (ClientInputSemanticsVersion != 100 ) 970Error ("unknown client version for -G, should be 100" ); 971break ; 972case 'H' : 973Options |=EOptionHumanReadableSpv ; 974if ((Options & EOptionSpv )== 0 ) { 975// default to Vulkan 976setVulkanSpv (); 977 } 978break ; 979case 'I' : 980IncludeDirectoryList .push_back (getStringOperand ("-I<dir> include path" )); 981break ; 982case 'O' : 983if (argv [0 ][2 ]== 'd' ) 984Options |=EOptionOptimizeDisable ; 985else if (argv [0 ][2 ]== 's' ) 986#if ENABLE_OPT 987Options |=EOptionOptimizeSize ; 988#else 989Error ("-Os not available; optimizer not linked" ); 990#endif 991else if (argv [0 ][2 ]== '\0' ) 992#if ENABLE_OPT 993Options |=EOptionOptimizePerformance ; 994#else 995Error ("-O not available; optimizer not linked" ); 996#endif 997else 998Error ("unknown -O option" ); 999break ; 1000case 'P' : 1001UserPreamble .addText (getStringOperand ("-P<text>" )); 1002break ; 1003case 'R' : 1004VulkanRulesRelaxed = true; 1005break ; 1006case 'S' : 1007if (argc <=1 ) 1008Error ("no <stage> specified for -S" ); 1009shaderStageName = argv [1 ]; 1010bumpArg (); 1011break ; 1012case 'U' : 1013UserPreamble .addUndef (getStringOperand ("-U<name>" )); 1014break ; 1015case 'V' : 1016setVulkanSpv (); 1017if (argv [0 ][2 ]!= 0 ) 1018ClientInputSemanticsVersion = getAttachedNumber ("-V<num> client input semantics" ); 1019if (ClientInputSemanticsVersion != 100 ) 1020Error ("unknown client version for -V, should be 100" ); 1021break ; 1022case 'c' : 1023Options |=EOptionDumpConfig ; 1024break ; 1025case 'd' : 1026if (strncmp (& argv [0 ][1 ],"dumpversion" ,strlen (& argv [0 ][1 ])+ 1 )== 0 || 1027strncmp (& argv [0 ][1 ],"dumpfullversion" ,strlen (& argv [0 ][1 ])+ 1 )== 0 ) 1028Options |=EOptionDumpBareVersion ; 1029else 1030Options |=EOptionDefaultDesktop ; 1031break ; 1032case 'e' : 1033entryPointName = argv [1 ]; 1034if (argc <=1 ) 1035Error ("no <name> provided for -e" ); 1036bumpArg (); 1037break ; 1038case 'f' : 1039if (strcmp (& argv [0 ][2 ],"hlsl_functionality1" )== 0 ) 1040targetHlslFunctionality1 = true; 1041else 1042Error ("-f: expected hlsl_functionality1" ); 1043break ; 1044case 'g' : 1045// Override previous -g or -g0 argument 1046stripDebugInfo = false; 1047emitNonSemanticShaderDebugInfo = false; 1048emitSourceFileName = false; 1049Options &= ~EOptionDebug ; 1050if (argv [0 ][2 ]== '0' ) 1051stripDebugInfo = true; 1052else if (argv [0 ][2 ]== 'N' ) 1053emitSourceFileName = true; 1054else { 1055Options |=EOptionDebug ; 1056if (argv [0 ][2 ]== 'V' ) { 1057emitNonSemanticShaderDebugInfo = true; 1058if (argv [0 ][3 ]== 'S' ) { 1059emitNonSemanticShaderDebugSource = true; 1060 }else { 1061emitNonSemanticShaderDebugSource = false; 1062 } 1063 } 1064 } 1065break ; 1066case 'h' : 1067usage (); 1068break ; 1069case 'i' : 1070Options |=EOptionIntermediate ; 1071break ; 1072case 'l' : 1073Options |=EOptionLinkProgram ; 1074break ; 1075case 'm' : 1076Options |=EOptionMemoryLeakMode ; 1077break ; 1078case 'o' : 1079if (argc <=1 ) 1080Error ("no <file> provided for -o" ); 1081binaryFileName = argv [1 ]; 1082bumpArg (); 1083break ; 1084case 'q' : 1085Options |=EOptionDumpReflection ; 1086break ; 1087case 'r' : 1088Options |=EOptionRelaxedErrors ; 1089break ; 1090case 's' : 1091Options |=EOptionSuppressInfolog ; 1092break ; 1093case 't' : 1094Options |=EOptionMultiThreaded ; 1095break ; 1096case 'v' : 1097Options |=EOptionDumpVersions ; 1098break ; 1099case 'w' : 1100Options |=EOptionSuppressWarnings ; 1101break ; 1102case 'x' : 1103Options |=EOptionOutputHexadecimal ; 1104break ; 1105default : 1106Error ("unrecognized command-line option" ,argv [0 ]); 1107break ; 1108 } 1109 }else { 1110 std::string name (argv [0 ]); 1111if (!SetConfigFile (name )) { 1112workItems .push_back (std::unique_ptr < glslang::TWorkItem > (new glslang::TWorkItem (name ))); 1113 } 1114 } 1115 } 1116 1117// Make sure that -S is always specified if --stdin is specified 1118if ((Options & EOptionStdin )&& shaderStageName == nullptr ) 1119Error ("must provide -S when --stdin is given" ); 1120 1121// Make sure that -E is not specified alongside linking (which includes SPV generation) 1122// Or things that require linking 1123if (Options & EOptionOutputPreprocessed ) { 1124if (Options & EOptionLinkProgram ) 1125Error ("can't use -E when linking is selected" ); 1126if (Options & EOptionDumpReflection ) 1127Error ("reflection requires linking, which can't be used when -E when is selected" ); 1128 } 1129 1130// reflection requires linking 1131if ((Options & EOptionDumpReflection )&& !(Options & EOptionLinkProgram )) 1132Error ("reflection requires -l for linking" ); 1133 1134// link time optimization makes no sense unless linking 1135if ((Options & EOptionLinkTimeOptimization )&& !(Options & EOptionLinkProgram )) 1136Error ("link time optimization requires -l for linking" ); 1137 1138// cross stage IO validation makes no sense unless linking 1139if ((Options & EOptionValidateCrossStageIO )&& !(Options & EOptionLinkProgram )) 1140Error ("cross stage IO validation requires -l for linking" ); 1141 1142// -o or -x makes no sense if there is no target binary 1143if (binaryFileName && (Options & EOptionSpv )== 0 ) 1144Error ("no binary generation requested (e.g., -V)" ); 1145 1146if ((Options & EOptionFlattenUniformArrays )!= 0 && 1147 (Options & EOptionReadHlsl )== 0 ) 1148Error ("uniform array flattening only valid when compiling HLSL source." ); 1149 1150if ((Options & EOptionReadHlsl )&& (Client == glslang::EShClientOpenGL )) { 1151Error ("Using HLSL input under OpenGL semantics is not currently supported." ); 1152 } 1153 1154// rationalize client and target language 1155if (TargetLanguage == glslang::EShTargetNone ) { 1156switch (ClientVersion ) { 1157case glslang::EShTargetVulkan_1_0 : 1158TargetLanguage = glslang::EShTargetSpv ; 1159TargetVersion = glslang::EShTargetSpv_1_0 ; 1160break ; 1161case glslang::EShTargetVulkan_1_1 : 1162TargetLanguage = glslang::EShTargetSpv ; 1163TargetVersion = glslang::EShTargetSpv_1_3 ; 1164break ; 1165case glslang::EShTargetVulkan_1_2 : 1166TargetLanguage = glslang::EShTargetSpv ; 1167TargetVersion = glslang::EShTargetSpv_1_5 ; 1168break ; 1169case glslang::EShTargetVulkan_1_3 : 1170TargetLanguage = glslang::EShTargetSpv ; 1171TargetVersion = glslang::EShTargetSpv_1_6 ; 1172break ; 1173case glslang::EShTargetVulkan_1_4 : 1174TargetLanguage = glslang::EShTargetSpv ; 1175TargetVersion = glslang::EShTargetSpv_1_6 ; 1176break ; 1177case glslang::EShTargetOpenGL_450 : 1178TargetLanguage = glslang::EShTargetSpv ; 1179TargetVersion = glslang::EShTargetSpv_1_0 ; 1180break ; 1181default : 1182break ; 1183 } 1184 } 1185if (TargetLanguage != glslang::EShTargetNone && Client == glslang::EShClientNone ) 1186Error ("To generate SPIR-V, also specify client semantics. See -G and -V." ); 1187} 1188 1189// 1190// Translate the meaningful subset of command-line options to parser-behavior options. 1191// 1192void SetMessageOptions (EShMessages & messages ) 1193{ 1194if (Options & EOptionRelaxedErrors ) 1195messages = (EShMessages )(messages |EShMsgRelaxedErrors ); 1196if (Options & EOptionIntermediate ) 1197messages = (EShMessages )(messages |EShMsgAST ); 1198if (Options & EOptionSuppressWarnings ) 1199messages = (EShMessages )(messages |EShMsgSuppressWarnings ); 1200if (Options & EOptionSpv ) 1201messages = (EShMessages )(messages |EShMsgSpvRules ); 1202if (Options & EOptionVulkanRules ) 1203messages = (EShMessages )(messages |EShMsgVulkanRules ); 1204if (Options & EOptionOutputPreprocessed ) 1205messages = (EShMessages )(messages |EShMsgOnlyPreprocessor ); 1206if (Options & EOptionReadHlsl ) 1207messages = (EShMessages )(messages |EShMsgReadHlsl ); 1208if (Options & EOptionCascadingErrors ) 1209messages = (EShMessages )(messages |EShMsgCascadingErrors ); 1210if (Options & EOptionKeepUncalled ) 1211messages = (EShMessages )(messages |EShMsgKeepUncalled ); 1212if (Options & EOptionHlslOffsets ) 1213messages = (EShMessages )(messages |EShMsgHlslOffsets ); 1214if (Options & EOptionDebug ) 1215messages = (EShMessages )(messages |EShMsgDebugInfo ); 1216if (HlslEnable16BitTypes ) 1217messages = (EShMessages )(messages |EShMsgHlslEnable16BitTypes ); 1218if ((Options & EOptionOptimizeDisable )|| !ENABLE_OPT ) 1219messages = (EShMessages )(messages |EShMsgHlslLegalization ); 1220if (HlslDX9compatible ) 1221messages = (EShMessages )(messages |EShMsgHlslDX9Compatible ); 1222if (DumpBuiltinSymbols ) 1223messages = (EShMessages )(messages |EShMsgBuiltinSymbolTable ); 1224if (EnhancedMsgs ) 1225messages = (EShMessages )(messages |EShMsgEnhanced ); 1226if (AbsolutePath ) 1227messages = (EShMessages )(messages |EShMsgAbsolutePath ); 1228if (Options & EOptionDisplayErrorColumn ) 1229messages = (EShMessages )(messages |EShMsgDisplayErrorColumn ); 1230if (Options & EOptionLinkTimeOptimization ) 1231messages = (EShMessages )(messages |EShMsgLinkTimeOptimization ); 1232if (Options & EOptionValidateCrossStageIO ) 1233messages = (EShMessages )(messages |EShMsgValidateCrossStageIO ); 1234if (Options & EOptionRelaxSetBindingLimits ) 1235messages = (EShMessages )(messages |EShMsgRelaxSetBindingLimits ); 1236} 1237 1238// 1239// Thread entry point, for non-linking asynchronous mode. 1240// 1241void CompileShaders (glslang::TWorklist & worklist ) 1242{ 1243if (Options & EOptionDebug ) 1244Error ("cannot generate debug information unless linking to generate code" ); 1245 1246// NOTE: TWorkList::remove is thread-safe 1247 glslang::TWorkItem * workItem ; 1248if (Options & EOptionStdin ) { 1249if (worklist .remove (workItem )) { 1250ShHandle compiler = ShConstructCompiler (FindLanguage ("stdin" ),0 ); 1251if (compiler == nullptr ) 1252return ; 1253 1254CompileFile ("stdin" ,compiler ); 1255 1256if (! (Options & EOptionSuppressInfolog )) 1257workItem -> results = ShGetInfoLog (compiler ); 1258 1259ShDestruct (compiler ); 1260 } 1261 }else { 1262while (worklist .remove (workItem )) { 1263ShHandle compiler = ShConstructCompiler (FindLanguage (workItem -> name ),0 ); 1264if (compiler == nullptr ) 1265return ; 1266 1267 1268CompileFile (workItem -> name .c_str (),compiler ); 1269 1270if (! (Options & EOptionSuppressInfolog )) 1271workItem -> results = ShGetInfoLog (compiler ); 1272 1273ShDestruct (compiler ); 1274 } 1275 } 1276} 1277 1278// Outputs the given string, but only if it is non-null and non-empty. 1279// This prevents erroneous newlines from appearing. 1280void PutsIfNonEmpty (const char * str ) 1281{ 1282if (str && str [0 ]) { 1283puts (str ); 1284 } 1285} 1286 1287// Outputs the given string to stderr, but only if it is non-null and non-empty. 1288// This prevents erroneous newlines from appearing. 1289void StderrIfNonEmpty (const char * str ) 1290{ 1291if (str && str [0 ]) 1292fprintf (stderr ,"%s\n" ,str ); 1293} 1294 1295// Simple bundling of what makes a compilation unit for ease in passing around, 1296// and separation of handling file IO versus API (programmatic) compilation. 1297struct ShaderCompUnit { 1298EShLanguage stage ; 1299static const int maxCount = 1 ; 1300int count ;// live number of strings/names 1301const char * text [maxCount ];// memory owned/managed externally 1302 std::string fileName [maxCount ];// hold's the memory, but... 1303const char * fileNameList [maxCount ];// downstream interface wants pointers 1304 1305ShaderCompUnit (EShLanguage stage ) :stage (stage ),count (0 ) { } 1306 1307ShaderCompUnit (const ShaderCompUnit & rhs ) 1308 { 1309stage = rhs .stage ; 1310count = rhs .count ; 1311for (int i = 0 ;i < count ;++ i ) { 1312fileName [i ]= rhs .fileName [i ]; 1313text [i ]= rhs .text [i ]; 1314fileNameList [i ]= rhs .fileName [i ].c_str (); 1315 } 1316 } 1317 1318void addString (std::string & ifileName ,const char * itext ) 1319 { 1320assert (count < maxCount ); 1321fileName [count ]= ifileName ; 1322text [count ]= itext ; 1323fileNameList [count ]= fileName [count ].c_str (); 1324++ count ; 1325 } 1326}; 1327 1328// Writes a string into a depfile, escaping some special characters following the Makefile rules. 1329static void writeEscapedDepString (std::ofstream & file ,const std::string & str ) 1330{ 1331for (char c :str ) { 1332switch (c ) { 1333case ' ' : 1334case ':' : 1335case '#' : 1336case '[' : 1337case ']' : 1338case '\\' : 1339file <<'\\' ; 1340break ; 1341case '$' : 1342file <<'$' ; 1343break ; 1344 } 1345file <<c ; 1346 } 1347} 1348 1349// Writes a depfile similar to gcc -MMD foo.c 1350bool writeDepFile (std::string depfile , std::vector < std::string >& binaryFiles ,const std::vector < std::string >& sources ) 1351{ 1352 std::ofstream file (depfile ); 1353if (file .fail ()) 1354return false; 1355 1356for (auto binaryFile = binaryFiles .begin ();binaryFile != binaryFiles .end ();binaryFile ++ ) { 1357writeEscapedDepString (file ,* binaryFile ); 1358file <<":" ; 1359for (auto sourceFile = sources .begin ();sourceFile != sources .end ();sourceFile ++ ) { 1360file <<" " ; 1361writeEscapedDepString (file ,* sourceFile ); 1362 } 1363file << std::endl ; 1364 } 1365return true; 1366} 1367 1368// 1369// For linking mode: Will independently parse each compilation unit, but then put them 1370// in the same program and link them together, making at most one linked module per 1371// pipeline stage. 1372// 1373// Uses the new C++ interface instead of the old handle-based interface. 1374// 1375 1376void CompileAndLinkShaderUnits (std::vector < ShaderCompUnit > compUnits ) 1377{ 1378// keep track of what to free 1379 std::list < glslang::TShader *> shaders ; 1380 1381EShMessages messages = EShMsgDefault ; 1382SetMessageOptions (messages ); 1383 1384DirStackFileIncluder includer ; 1385 std::for_each (IncludeDirectoryList .begin (),IncludeDirectoryList .end (), [& includer ](const std::string & dir ) { 1386includer .pushExternalDirectory (dir ); }); 1387 1388 std::vector < std::string > sources ; 1389 1390// 1391// Per-shader processing... 1392// 1393 1394 glslang::TProgram & program = * new glslang::TProgram ; 1395const bool compileOnly = (Options & EOptionCompileOnly )!= 0 ; 1396for (auto it = compUnits .cbegin ();it != compUnits .cend ();++ it ) { 1397const auto & compUnit = * it ; 1398for (int i = 0 ;i < compUnit .count ;i ++ ) { 1399sources .push_back (compUnit .fileNameList [i ]); 1400 } 1401 glslang::TShader * shader = new glslang::TShader (compUnit .stage ); 1402shader -> setStringsWithLengthsAndNames (compUnit .text ,nullptr ,compUnit .fileNameList ,compUnit .count ); 1403if (entryPointName ) 1404shader -> setEntryPoint (entryPointName ); 1405if (sourceEntryPointName ) { 1406if (entryPointName == nullptr ) 1407printf ("Warning: Changing source entry point name without setting an entry-point name.\n" 1408"Use '-e <name>'.\n" ); 1409shader -> setSourceEntryPoint (sourceEntryPointName ); 1410 } 1411 1412if (compileOnly ) 1413shader -> setCompileOnly (); 1414 1415shader -> setOverrideVersion (GlslVersion ); 1416 1417 std::string intrinsicString = getIntrinsic (compUnit .text ,compUnit .count ); 1418 1419PreambleString = "" ; 1420if (UserPreamble .isSet ()) 1421PreambleString .append (UserPreamble .get ()); 1422 1423if (!intrinsicString .empty ()) 1424PreambleString .append (intrinsicString ); 1425 1426shader -> setPreamble (PreambleString .c_str ()); 1427shader -> addProcesses (Processes ); 1428 1429// Set IO mapper binding shift values 1430for (int r = 0 ;r < glslang::EResCount ;++ r ) { 1431const glslang::TResourceType res = glslang::TResourceType (r ); 1432 1433// Set base bindings 1434shader -> setShiftBinding (res ,baseBinding [res ][compUnit .stage ]); 1435 1436// Set bindings for particular resource sets 1437// TODO: use a range based for loop here, when available in all environments. 1438for (auto i = baseBindingForSet [res ][compUnit .stage ].begin (); 1439i != baseBindingForSet [res ][compUnit .stage ].end ();++ i ) 1440shader -> setShiftBindingForSet (res ,i -> second ,i -> first ); 1441 } 1442shader -> setNoStorageFormat ((Options & EOptionNoStorageFormat )!= 0 ); 1443shader -> setResourceSetBinding (baseResourceSetBinding [compUnit .stage ]); 1444 1445if (autoSampledTextures ) 1446shader -> setTextureSamplerTransformMode (EShTexSampTransUpgradeTextureRemoveSampler ); 1447 1448if (Options & EOptionAutoMapBindings ) 1449shader -> setAutoMapBindings (true); 1450 1451if (Options & EOptionAutoMapLocations ) 1452shader -> setAutoMapLocations (true); 1453 1454for (auto & uniOverride :uniformLocationOverrides ) { 1455shader -> addUniformLocationOverride (uniOverride .first .c_str (), 1456uniOverride .second ); 1457 } 1458 1459shader -> setUniformLocationBase (uniformBase ); 1460 1461if (VulkanRulesRelaxed ) { 1462for (auto & storageOverride :blockStorageOverrides ) { 1463shader -> addBlockStorageOverride (storageOverride .first .c_str (), 1464storageOverride .second ); 1465 } 1466 1467if (setGlobalBufferBlock ) { 1468shader -> setAtomicCounterBlockName (atomicCounterBlockName .c_str ()); 1469shader -> setAtomicCounterBlockSet (atomicCounterBlockSet ); 1470 } 1471 1472if (setGlobalUniformBlock ) { 1473shader -> setGlobalUniformBlockName (globalUniformName .c_str ()); 1474shader -> setGlobalUniformSet (globalUniformSet ); 1475shader -> setGlobalUniformBinding (globalUniformBinding ); 1476 } 1477 } 1478 1479shader -> setNanMinMaxClamp (NaNClamp ); 1480 1481#ifdef ENABLE_HLSL 1482shader -> setFlattenUniformArrays ((Options & EOptionFlattenUniformArrays )!= 0 ); 1483if (Options & EOptionHlslIoMapping ) 1484shader -> setHlslIoMapping (true); 1485#endif 1486 1487if (Options & EOptionInvertY ) 1488shader -> setInvertY (true); 1489 1490if (HlslDxPositionW ) 1491shader -> setDxPositionW (true); 1492 1493if (EnhancedMsgs ) 1494shader -> setEnhancedMsgs (); 1495 1496if (emitNonSemanticShaderDebugInfo ) 1497shader -> setDebugInfo (true); 1498 1499if (emitSourceFileName && compUnit .count > 0 ) 1500shader -> setSourceFile (compUnit .fileNameList [0 ]); 1501 1502if (Options & EOptionBindingsPerResourceType ) 1503shader -> setBindingsPerResourceType (); 1504 1505if (Options & EOptionDiscardIsTerminate ) 1506shader -> setDiscardIsTerminate (true); 1507 1508// Set up the environment, some subsettings take precedence over earlier 1509// ways of setting things. 1510if (Options & EOptionSpv ) { 1511shader -> setEnvInput ((Options & EOptionReadHlsl ) ? glslang::EShSourceHlsl 1512 : glslang::EShSourceGlsl , 1513compUnit .stage ,Client ,ClientInputSemanticsVersion ); 1514shader -> setEnvClient (Client ,ClientVersion ); 1515shader -> setEnvTarget (TargetLanguage ,TargetVersion ); 1516#ifdef ENABLE_HLSL 1517if (targetHlslFunctionality1 ) 1518shader -> setEnvTargetHlslFunctionality1 (); 1519#endif 1520if (VulkanRulesRelaxed ) 1521shader -> setEnvInputVulkanRulesRelaxed (); 1522 } 1523 1524shaders .push_back (shader ); 1525 1526const int defaultVersion = Options & EOptionDefaultDesktop ?110 :100 ; 1527 1528if (Options & EOptionOutputPreprocessed ) { 1529 std::string str ; 1530if (shader -> preprocess (GetResources (),defaultVersion ,ENoProfile , false, false,messages ,& str ,includer )) { 1531PutsIfNonEmpty (str .c_str ()); 1532 }else { 1533CompileFailed = 1 ; 1534 } 1535StderrIfNonEmpty (shader -> getInfoLog ()); 1536StderrIfNonEmpty (shader -> getInfoDebugLog ()); 1537continue ; 1538 } 1539 1540if (!shader -> parse (GetResources (),defaultVersion , false,messages ,includer )) 1541CompileFailed = 1 ; 1542 1543if (!compileOnly ) 1544program .addShader (shader ); 1545 1546if (! (Options & EOptionSuppressInfolog )&& 1547 ! (Options & EOptionMemoryLeakMode )) { 1548if (!beQuiet ) 1549StderrIfNonEmpty (compUnit .fileName [0 ].c_str ()); 1550StderrIfNonEmpty (shader -> getInfoLog ()); 1551StderrIfNonEmpty (shader -> getInfoDebugLog ()); 1552 } 1553 } 1554 1555// 1556// Program-level processing... 1557// 1558 1559if (!compileOnly ) { 1560// Link 1561if (!(Options & EOptionOutputPreprocessed )&& !program .link (messages )) 1562LinkFailed = true; 1563 1564// Map IO 1565if (Options & EOptionSpv ) { 1566if (!program .mapIO ()) 1567LinkFailed = true; 1568 } 1569 1570// Report 1571if (!(Options & EOptionSuppressInfolog )&& !(Options & EOptionMemoryLeakMode )) { 1572StderrIfNonEmpty (program .getInfoLog ()); 1573StderrIfNonEmpty (program .getInfoDebugLog ()); 1574 } 1575 1576// Reflect 1577if (Options & EOptionDumpReflection ) { 1578program .buildReflection (ReflectOptions ); 1579program .dumpReflection (); 1580 } 1581 } 1582 1583 std::vector < std::string > outputFiles ; 1584 1585// Dump SPIR-V 1586if (Options & EOptionSpv ) { 1587#ifdef ENABLE_SPIRV 1588CompileOrLinkFailed .fetch_or (CompileFailed ); 1589CompileOrLinkFailed .fetch_or (LinkFailed ); 1590if (static_cast < bool > (CompileOrLinkFailed .load ())) 1591printf ("SPIR-V is not generated for failed compile or link\n" ); 1592else { 1593 std::vector < glslang::TIntermediate *> intermediates ; 1594if (!compileOnly ) { 1595for (int stage = 0 ;stage < EShLangCount ;++ stage ) { 1596if (auto * i = program .getIntermediate ((EShLanguage )stage )) { 1597intermediates .emplace_back (i ); 1598 } 1599 } 1600 }else { 1601for (const auto * shader :shaders ) { 1602if (auto * i = shader -> getIntermediate ()) { 1603intermediates .emplace_back (i ); 1604 } 1605 } 1606 } 1607for (auto * intermediate :intermediates ) { 1608 std::vector < unsigned int > spirv ; 1609 spv::SpvBuildLogger logger ; 1610 glslang::SpvOptions spvOptions ; 1611if (Options & EOptionDebug ) { 1612spvOptions .generateDebugInfo = true; 1613if (emitNonSemanticShaderDebugInfo ) { 1614spvOptions .emitNonSemanticShaderDebugInfo = true; 1615if (emitNonSemanticShaderDebugSource ) { 1616spvOptions .emitNonSemanticShaderDebugSource = true; 1617 } 1618 } 1619 }else if (stripDebugInfo ) 1620spvOptions .stripDebugInfo = true; 1621else if (emitSourceFileName ) 1622spvOptions .emitSourceFileName = true; 1623spvOptions .disableOptimizer = (Options & EOptionOptimizeDisable )!= 0 ; 1624spvOptions .optimizeSize = (Options & EOptionOptimizeSize )!= 0 ; 1625spvOptions .optimizePerformance = (Options & EOptionOptimizePerformance )!= 0 ; 1626spvOptions .disassemble = SpvToolsDisassembler ; 1627spvOptions .validate = SpvToolsValidate ; 1628spvOptions .compileOnly = compileOnly ; 1629spvOptions .compilerSignature = "glslang" ; 1630spvOptions .commandLineArguments = CommandLineArguments .c_str (); 1631 std::error_code currentPathError ; 1632const std::string currentWorkingDirectory = std::filesystem::current_path (currentPathError ).string (); 1633if (!currentPathError ) 1634spvOptions .currentWorkingDirectory = currentWorkingDirectory .c_str (); 1635 glslang::GlslangToSpv (* intermediate ,spirv ,& logger ,& spvOptions ); 1636 1637// Dump the spv to a file or stdout, etc., but only if not doing 1638// memory/perf testing, as it's not internal to programmatic use. 1639if (!(Options & EOptionMemoryLeakMode )) { 1640printf ("%s" ,logger .getAllMessages ().c_str ()); 1641const auto filename = GetBinaryName (intermediate -> getStage ()); 1642if (Options & EOptionOutputHexadecimal ) { 1643if (!glslang::OutputSpvHex (spirv ,filename ,variableName )) 1644exit (EFailUsage ); 1645 }else { 1646if (!glslang::OutputSpvBin (spirv ,filename )) 1647exit (EFailUsage ); 1648 } 1649 1650outputFiles .push_back (filename ); 1651if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv )) 1652 spv::Disassemble (std::cout ,spirv ); 1653 } 1654 } 1655 } 1656#else 1657Error ("This configuration of glslang does not have SPIR-V support" ); 1658#endif 1659 } 1660 1661CompileOrLinkFailed .fetch_or (CompileFailed ); 1662CompileOrLinkFailed .fetch_or (LinkFailed ); 1663if (depencyFileName && !static_cast < bool > (CompileOrLinkFailed .load ())) { 1664 std::set < std::string > includedFiles = includer .getIncludedFiles (); 1665sources .insert (sources .end (),includedFiles .begin (),includedFiles .end ()); 1666 1667writeDepFile (depencyFileName ,outputFiles ,sources ); 1668 } 1669 1670// Free everything up, program has to go before the shaders 1671// because it might have merged stuff from the shaders, and 1672// the stuff from the shaders has to have its destructors called 1673// before the pools holding the memory in the shaders is freed. 1674delete & program ; 1675while (shaders .size ()> 0 ) { 1676delete shaders .back (); 1677shaders .pop_back (); 1678 } 1679} 1680 1681// 1682// Do file IO part of compile and link, handing off the pure 1683// API/programmatic mode to CompileAndLinkShaderUnits(), which can 1684// be put in a loop for testing memory footprint and performance. 1685// 1686// This is just for linking mode: meaning all the shaders will be put into the 1687// the same program linked together. 1688// 1689// This means there are a limited number of work items (not multi-threading mode) 1690// and that the point is testing at the linking level. Hence, to enable 1691// performance and memory testing, the actual compile/link can be put in 1692// a loop, independent of processing the work items and file IO. 1693// 1694void CompileAndLinkShaderFiles (glslang::TWorklist & Worklist ) 1695{ 1696 std::vector < ShaderCompUnit > compUnits ; 1697 1698// If this is using stdin, we can't really detect multiple different file 1699// units by input type. We need to assume that we're just being given one 1700// file of a certain type. 1701if ((Options & EOptionStdin )!= 0 ) { 1702ShaderCompUnit compUnit (FindLanguage ("stdin" )); 1703 std::istreambuf_iterator < char > begin (std::cin ),end ; 1704 std::string tempString (begin ,end ); 1705char * fileText = strdup (tempString .c_str ()); 1706 std::string fileName = "stdin" ; 1707compUnit .addString (fileName ,fileText ); 1708compUnits .push_back (compUnit ); 1709 }else { 1710// Transfer all the work items from to a simple list of 1711// of compilation units. (We don't care about the thread 1712// work-item distribution properties in this path, which 1713// is okay due to the limited number of shaders, know since 1714// they are all getting linked together.) 1715 glslang::TWorkItem * workItem ; 1716while (Worklist .remove (workItem )) { 1717ShaderCompUnit compUnit (FindLanguage (workItem -> name )); 1718char * fileText = ReadFileData (workItem -> name .c_str ()); 1719if (fileText == nullptr ) 1720usage (); 1721compUnit .addString (workItem -> name ,fileText ); 1722compUnits .push_back (compUnit ); 1723 } 1724 } 1725 1726// Actual call to programmatic processing of compile and link, 1727// in a loop for testing memory and performance. This part contains 1728// all the perf/memory that a programmatic consumer will care about. 1729for (int i = 0 ;i < ((Options & EOptionMemoryLeakMode ) ?100 :1 );++ i ) { 1730for (int j = 0 ;j < ((Options & EOptionMemoryLeakMode ) ?100 :1 );++ j ) 1731CompileAndLinkShaderUnits (compUnits ); 1732 1733if (Options & EOptionMemoryLeakMode ) 1734 glslang::OS_DumpMemoryCounters (); 1735 } 1736 1737// free memory from ReadFileData, which got stored in a const char* 1738// as the first string above 1739for (auto it = compUnits .begin ();it != compUnits .end ();++ it ) 1740FreeFileData (const_cast < char *> (it -> text [0 ])); 1741} 1742 1743int singleMain () 1744{ 1745 glslang::TWorklist workList ; 1746 std::for_each (WorkItems .begin (),WorkItems .end (), [& workList ](std::unique_ptr < glslang::TWorkItem >& item ) { 1747assert (item ); 1748workList .add (item .get ()); 1749 }); 1750 1751if (Options & EOptionDumpConfig ) { 1752printf ("%s" ,GetDefaultTBuiltInResourceString ().c_str ()); 1753if (workList .empty ()) 1754return ESuccess ; 1755 } 1756 1757if (Options & EOptionDumpBareVersion ) { 1758int spirvGeneratorVersion = 0 ; 1759#ifdef ENABLE_SPIRV 1760spirvGeneratorVersion = glslang::GetSpirvGeneratorVersion (); 1761#endif 1762printf ("%d:%d.%d.%d%s\n" ,spirvGeneratorVersion ,GLSLANG_VERSION_MAJOR ,GLSLANG_VERSION_MINOR , 1763GLSLANG_VERSION_PATCH ,GLSLANG_VERSION_FLAVOR ); 1764if (workList .empty ()) 1765return ESuccess ; 1766 }else if (Options & EOptionDumpVersions ) { 1767int spirvGeneratorVersion = 0 ; 1768#ifdef ENABLE_SPIRV 1769spirvGeneratorVersion = glslang::GetSpirvGeneratorVersion (); 1770#endif 1771printf ("Glslang Version: %d:%d.%d.%d%s\n" ,spirvGeneratorVersion ,GLSLANG_VERSION_MAJOR , 1772GLSLANG_VERSION_MINOR ,GLSLANG_VERSION_PATCH ,GLSLANG_VERSION_FLAVOR ); 1773printf ("ESSL Version: %s\n" , glslang::GetEsslVersionString ()); 1774printf ("GLSL Version: %s\n" , glslang::GetGlslVersionString ()); 1775 std::string spirvVersion ; 1776#if ENABLE_SPIRV 1777 glslang::GetSpirvVersion (spirvVersion ); 1778#endif 1779printf ("SPIR-V Version %s\n" ,spirvVersion .c_str ()); 1780printf ("GLSL.std.450 Version %d, Revision %d\n" ,GLSLstd450Version ,GLSLstd450Revision ); 1781printf ("Khronos Tool ID %d\n" , glslang::GetKhronosToolId ()); 1782printf ("SPIR-V Generator Version %d\n" ,spirvGeneratorVersion ); 1783printf ("GL_KHR_vulkan_glsl version %d\n" ,100 ); 1784printf ("ARB_GL_gl_spirv version %d\n" ,100 ); 1785if (workList .empty ()) 1786return ESuccess ; 1787 } 1788 1789if (workList .empty ()&& ((Options & EOptionStdin )== 0 )) { 1790usage (); 1791 } 1792 1793if (Options & EOptionStdin ) { 1794WorkItems .push_back (std::unique_ptr < glslang::TWorkItem > {new glslang::TWorkItem ("stdin" )}); 1795workList .add (WorkItems .back ().get ()); 1796 } 1797 1798ProcessConfigFile (); 1799 1800if ((Options & EOptionReadHlsl )&& !((Options & EOptionOutputPreprocessed )|| (Options & EOptionSpv ))) 1801Error ("HLSL requires SPIR-V code generation (or preprocessing only)" ); 1802 1803// 1804// Two modes: 1805// 1) linking all arguments together, single-threaded, new C++ interface 1806// 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface 1807// 1808if (Options & (EOptionLinkProgram |EOptionOutputPreprocessed )) { 1809 glslang::InitializeProcess (); 1810 glslang::InitializeProcess ();// also test reference counting of users 1811 glslang::InitializeProcess ();// also test reference counting of users 1812 glslang::FinalizeProcess ();// also test reference counting of users 1813 glslang::FinalizeProcess ();// also test reference counting of users 1814CompileAndLinkShaderFiles (workList ); 1815 glslang::FinalizeProcess (); 1816 }else { 1817ShInitialize (); 1818ShInitialize ();// also test reference counting of users 1819ShFinalize ();// also test reference counting of users 1820 1821bool printShaderNames = workList .size ()> 1 ; 1822 1823if (Options & EOptionMultiThreaded ) { 1824 std::array < std::thread ,16 > threads ; 1825for (unsigned int t = 0 ;t < threads .size ();++ t ) { 1826threads [t ]= std::thread (CompileShaders , std::ref (workList )); 1827if (threads [t ].get_id ()== std::thread::id ()) { 1828fprintf (stderr ,"Failed to create thread\n" ); 1829return EFailThreadCreate ; 1830 } 1831 } 1832 1833 std::for_each (threads .begin (),threads .end (), [](std::thread & t ) {t .join (); }); 1834 }else 1835CompileShaders (workList ); 1836 1837// Print out all the resulting infologs 1838for (size_t w = 0 ;w < WorkItems .size ();++ w ) { 1839if (WorkItems [w ]) { 1840if (printShaderNames || WorkItems [w ]-> results .size ()> 0 ) 1841PutsIfNonEmpty (WorkItems [w ]-> name .c_str ()); 1842PutsIfNonEmpty (WorkItems [w ]-> results .c_str ()); 1843 } 1844 } 1845 1846ShFinalize (); 1847 } 1848 1849if (CompileFailed .load ()) 1850return EFailCompile ; 1851if (LinkFailed .load ()) 1852return EFailLink ; 1853 1854return 0 ; 1855} 1856 1857int C_DECL main (int argc ,char * argv []) 1858{ 1859ProcessArguments (WorkItems ,argc ,argv ); 1860 1861int ret = 0 ; 1862 1863// Loop over the entire init/finalize cycle to watch memory changes 1864const int iterations = 1 ; 1865if (iterations > 1 ) 1866 glslang::OS_DumpMemoryCounters (); 1867for (int i = 0 ;i < iterations ;++ i ) { 1868ret = singleMain (); 1869if (iterations > 1 ) 1870 glslang::OS_DumpMemoryCounters (); 1871 } 1872 1873return ret ; 1874} 1875 1876// 1877// Deduce the language from the filename. Files must end in one of the 1878// following extensions: 1879// 1880// .vert = vertex 1881// .tesc = tessellation control 1882// .tese = tessellation evaluation 1883// .geom = geometry 1884// .frag = fragment 1885// .comp = compute 1886// .rgen = ray generation 1887// .rint = ray intersection 1888// .rahit = ray any hit 1889// .rchit = ray closest hit 1890// .rmiss = ray miss 1891// .rcall = ray callable 1892// .mesh = mesh 1893// .task = task 1894// Additionally, the file names may end in .<stage>.glsl and .<stage>.hlsl 1895// where <stage> is one of the stages listed above. 1896// 1897EShLanguage FindLanguage (const std::string & name ,bool parseStageName ) 1898{ 1899 std::string stageName ; 1900if (shaderStageName ) 1901stageName = shaderStageName ; 1902else if (parseStageName ) { 1903// Note: "first" extension means "first from the end", i.e. 1904// if the file is named foo.vert.glsl, then "glsl" is first, 1905// "vert" is second. 1906size_t firstExtStart = name .find_last_of ("." ); 1907bool hasFirstExt = firstExtStart != std::string::npos ; 1908size_t secondExtStart = hasFirstExt ?name .find_last_of ("." ,firstExtStart - 1 ) : std::string::npos ; 1909bool hasSecondExt = secondExtStart != std::string::npos ; 1910 std::string firstExt = name .substr (firstExtStart + 1 , std::string::npos ); 1911bool usesUnifiedExt = hasFirstExt && (firstExt == "glsl" || firstExt == "hlsl" ); 1912if (usesUnifiedExt && firstExt == "hlsl" ) 1913Options |=EOptionReadHlsl ; 1914if (hasFirstExt && !usesUnifiedExt ) 1915stageName = firstExt ; 1916else if (usesUnifiedExt && hasSecondExt ) 1917stageName = name .substr (secondExtStart + 1 ,firstExtStart - secondExtStart - 1 ); 1918else { 1919usage (); 1920return EShLangVertex ; 1921 } 1922 }else 1923stageName = name ; 1924 1925if (stageName == "vert" ) 1926return EShLangVertex ; 1927else if (stageName == "tesc" ) 1928return EShLangTessControl ; 1929else if (stageName == "tese" ) 1930return EShLangTessEvaluation ; 1931else if (stageName == "geom" ) 1932return EShLangGeometry ; 1933else if (stageName == "frag" ) 1934return EShLangFragment ; 1935else if (stageName == "comp" ) 1936return EShLangCompute ; 1937else if (stageName == "rgen" ) 1938return EShLangRayGen ; 1939else if (stageName == "rint" ) 1940return EShLangIntersect ; 1941else if (stageName == "rahit" ) 1942return EShLangAnyHit ; 1943else if (stageName == "rchit" ) 1944return EShLangClosestHit ; 1945else if (stageName == "rmiss" ) 1946return EShLangMiss ; 1947else if (stageName == "rcall" ) 1948return EShLangCallable ; 1949else if (stageName == "mesh" ) 1950return EShLangMesh ; 1951else if (stageName == "task" ) 1952return EShLangTask ; 1953 1954usage (); 1955return EShLangVertex ; 1956} 1957 1958// 1959// Read a file's data into a string, and compile it using the old interface ShCompile, 1960// for non-linkable results. 1961// 1962void CompileFile (const char * fileName ,ShHandle compiler ) 1963{ 1964int ret = 0 ; 1965char * shaderString ; 1966if ((Options & EOptionStdin )!= 0 ) { 1967 std::istreambuf_iterator < char > begin (std::cin ),end ; 1968 std::string tempString (begin ,end ); 1969shaderString = strdup (tempString .c_str ()); 1970 }else { 1971shaderString = ReadFileData (fileName ); 1972 } 1973 1974// move to length-based strings, rather than null-terminated strings 1975int * lengths = new int [1 ]; 1976lengths [0 ]= (int )strlen (shaderString ); 1977 1978EShMessages messages = EShMsgDefault ; 1979SetMessageOptions (messages ); 1980 1981if (UserPreamble .isSet ()) 1982Error ("-D, -U and -P options require -l (linking)\n" ); 1983 1984for (int i = 0 ;i < ((Options & EOptionMemoryLeakMode ) ?100 :1 );++ i ) { 1985for (int j = 0 ;j < ((Options & EOptionMemoryLeakMode ) ?100 :1 );++ j ) { 1986// ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); 1987ret = ShCompile (compiler ,& shaderString ,1 ,nullptr ,EShOptNone ,GetResources (),0 , 1988 (Options & EOptionDefaultDesktop ) ?110 :100 , false,messages ,fileName ); 1989// const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err", 1990// "or should be l", "ine 1", "string 5\n", "float glo", "bal", 1991// ";\n#error should be line 2\n void main() {", "global = 2.3;}" }; 1992// const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" }; 1993// ret = ShCompile(compiler, multi, 7, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); 1994 } 1995 1996if (Options & EOptionMemoryLeakMode ) 1997 glslang::OS_DumpMemoryCounters (); 1998 } 1999 2000delete []lengths ; 2001FreeFileData (shaderString ); 2002 2003if (ret == 0 ) 2004CompileFailed = true; 2005} 2006 2007// 2008// print usage to stdout 2009// 2010void usage () 2011{ 2012printf ("Usage: glslang [option]... [file]...\n" 2013"\n" 2014"'file' with one of the following three endings can be auto-classified:\n" 2015"1) .<stage>, where <stage> is one of:\n" 2016" vert for a vertex shader\n" 2017" tesc for a tessellation control shader\n" 2018" tese for a tessellation evaluation shader\n" 2019" geom for a geometry shader\n" 2020" frag for a fragment shader\n" 2021" comp for a compute shader\n" 2022" mesh for a mesh shader\n" 2023" task for a task shader\n" 2024" rgen for a ray generation shader\n" 2025" rint for a ray intersection shader\n" 2026" rahit for a ray any hit shader\n" 2027" rchit for a ray closest hit shader\n" 2028" rmiss for a ray miss shader\n" 2029" rcall for a ray callable shader\n" 2030"2) .<stage>.glsl or .<stage>.hlsl compound suffix, where stage options are\n" 2031" described above\n" 2032"3) .conf, to provide a config file that replaces the default configuration (see\n" 2033" -c option below for generating a template)\n" 2034"\n" 2035"Options:\n" 2036" -C cascading errors; risk crash from accumulation of error recoveries\n" 2037" -D input is HLSL (this is the default when any suffix is .hlsl)\n" 2038" -D<name[=def]> | --D <name[=def]> | --define-macro <name[=def]>\n" 2039" define a pre-processor macro\n" 2040" -E print pre-processed GLSL; cannot be used with -l; errors will\n" 2041" appear on stderr\n" 2042" -G[ver] create SPIR-V binary under OpenGL semantics; turns on -l; default\n" 2043" file name is <stage>.spv (-o overrides this); ver, when present,\n" 2044" is the version of the input semantics which will appear in\n" 2045" '#define GL_SPIRV ver'; --client opengl100 is the same as -G100; a\n" 2046" --target-env for OpenGL will also imply -G; currently only\n" 2047" supports GLSL\n" 2048" -H print human readable form of SPIR-V; turns on -V\n" 2049" -I<dir> add <dir> to the include search path; includer's directory is\n" 2050" searched first, followed by left-to-right order of -I\n" 2051" -O optimizes SPIR-V for performance\n" 2052" -Os optimizes SPIR-V to minimize size\n" 2053" -Od disables optimization; may cause illegal SPIR-V for HLSL\n" 2054" -P<text> | --P <text> | --preamble-text <text>\n" 2055" inject custom preamble text which is treated as if it appeared\n" 2056" immediately after the version declaration (if any)\n" 2057" -R use relaxed verification rules for generating Vulkan SPIR-V,\n" 2058" allowing the use of default uniforms, atomic_uints, and the\n" 2059" gl_VertexID and gl_InstanceID keywords\n" 2060" -S <stage> uses the specified <stage> rather than parsing the file extension;\n" 2061" choices for <stage> include vert, tesc, tese, geom, frag, and\n" 2062" comp; a full list of options is given above\n" 2063" -U<name> | --undef-macro <name> | --U <name>\n" 2064" undefine a pre-processor macro\n" 2065" -V[ver] create SPIR-V binary under Vulkan semantics; turns on -l; default\n" 2066" file name is <stage>.spv (-o overrides this); ver, when present,\n" 2067" is the version of the input semantics which will appear in\n" 2068" '#define VULKAN ver'; --client vulkan100 is the same as -V100; a\n" 2069" '--target-env' for Vulkan will also imply '-V'\n" 2070" -c configuration dump; creates the default configuration file\n" 2071" (redirect to a .conf file)\n" 2072" -d default to desktop (#version 110) when there is no shader #version\n" 2073" (default is ES version 100)\n" 2074" -e <name> | --entry-point <name>\n" 2075" specify <name> as the entry-point function name\n" 2076" -f{hlsl_functionality1}\n" 2077" 'hlsl_functionality1' enables use of the\n" 2078" SPV_GOOGLE_hlsl_functionality1 extension\n" 2079" -g generate debug information\n" 2080" -g0 strip debug information\n" 2081" -gV generate nonsemantic shader debug information\n" 2082" -gVS generate nonsemantic shader debug information with source\n" 2083" -gN generate debug information for the source file name only\n" 2084" -h | --help print this usage message\n" 2085" -i intermediate tree (glslang AST) is printed out\n" 2086" -l link all input files together to form a single module\n" 2087" -m memory leak mode\n" 2088" -o <file> save binary to <file>; requires a binary option (e.g., -V)\n" 2089" -q dump reflection query database; requires -l for linking\n" 2090" -r | --relaxed-errors\n" 2091" relaxed GLSL semantic error-checking mode\n" 2092" -s silence syntax and semantic error reporting\n" 2093" -t multi-threaded mode\n" 2094" -u<name>:<loc>\n" 2095" specify a uniform location override for --aml\n" 2096" -v | --version\n" 2097" print version strings\n" 2098" -w | --suppress-warnings\n" 2099" suppress GLSL warnings, except as required by '#extension : warn'\n" 2100" -x save binary output as text-based 32-bit hexadecimal numbers\n" 2101" --absolute-path prints absolute path for messages\n" 2102" --relax-set-binding-limits allow larger layout(set) and\n" 2103" layout(binding) values\n" 2104" --auto-map-binding | --auto-map-bindings | --amb\n" 2105" automatically bind uniform variables without\n" 2106" explicit bindings\n" 2107" --auto-map-locations | --aml automatically locate input/output lacking\n" 2108" 'location' (fragile, not cross stage)\n" 2109" --auto-sampled-textures removes sampler variables and converts\n" 2110" existing textures to sampled textures\n" 2111" --client {vulkan<ver> | opengl<ver>}\n" 2112" see -V and -G\n" 2113" --depfile <file> writes depfile for build systems\n" 2114" --discard-is-terminate map GLSL discard to OpTerminateInvocation\n" 2115" instead of OpDemoteToHelperInvocation\n" 2116" --dump-builtin-symbols prints builtin symbol table prior each\n" 2117" compile\n" 2118" -dumpfullversion | -dumpversion print bare major.minor.patchlevel\n" 2119" --enhanced-msgs print more readable error messages (GLSL\n" 2120" only)\n" 2121" --error-column display the column of the error along the\n" 2122" line\n" 2123" --flatten-uniform-array | --flatten-uniform-arrays | --fua\n" 2124" flatten uniform texture/sampler arrays to\n" 2125" scalars\n" 2126" --glsl-version {100 | 110 | 120 | 130 | 140 | 150 |\n" 2127" 300es | 310es | 320es | 330 |\n" 2128" 400 | 410 | 420 | 430 | 440 | 450 | 460}\n" 2129" set GLSL version; overrides #version in\n" 2130" shader source\n" 2131" --hlsl-dx-position-w W component of SV_Position in HLSL fragment\n" 2132" shaders compatible with DirectX\n" 2133" --hlsl-dx9-compatible interprets sampler declarations as a\n" 2134" texture/sampler combo like DirectX9 would,\n" 2135" and recognizes DirectX9-specific semantics\n" 2136" --hlsl-enable-16bit-types allow 16-bit types in SPIR-V for HLSL\n" 2137" --hlsl-iomap | --hlsl-iomapper | --hlsl-iomapping\n" 2138" perform IO mapping in HLSL register space\n" 2139" --hlsl-offsets allow block offsets to follow HLSL rules;\n" 2140" works independently of source language\n" 2141" --invert-y | --iy invert position.Y output in vertex shader\n" 2142" --keep-uncalled | --ku don't eliminate uncalled functions\n" 2143" --lto perform link time optimization\n" 2144" --nan-clamp favor non-NaN operand in min, max, and clamp\n" 2145" --no-link only compile shader; do not link (GLSL only)\n" 2146" NOTE: this option will set the export\n" 2147" linkage attribute on all functions\n" 2148" --no-storage-format | --nsf use Unknown image format\n" 2149" --quiet do not print anything to stdout unless\n" 2150" requested by another option\n" 2151" --reflect-all-block-variables reflect all variables in blocks, whether\n" 2152" inactive or active\n" 2153" --reflect-basic-array-suffix arrays of basic types will have trailing [0]\n" 2154" --reflect-intermediate-io reflection includes inputs/outputs of linked\n" 2155" shaders rather than just vertex/fragment\n" 2156" --reflect-separate-buffers reflect buffer variables and blocks\n" 2157" separately to uniforms\n" 2158" --reflect-strict-array-suffix use strict array suffix rules when\n" 2159" reflecting\n" 2160" --reflect-unwrap-io-blocks unwrap input/output blocks the same as\n" 2161" uniform blocks\n" 2162" --resource-set-binding <stage> [name] <set> [binding]...\n" 2163" set descriptor set and binding for\n" 2164" individual resources\n" 2165" --resource-set-binding [stage] <set>\n" 2166" set descriptor set for all resources\n" 2167" --resource-set-bindings | --rsb synonyms for --resource-set-binding\n" 2168" --set-atomic-counter-block <name> <set>\n" 2169" set name and descriptor set for atomic\n" 2170" counter blocks with -R opt\n" 2171" --sacb synonym for set-atomic-counter-block\n" 2172" --set-block-backing name {uniform | buffer | push_constant}\n" 2173" changes the backing type of a uniform,\n" 2174" buffer, or push_constant block declared in\n" 2175" the program when using the -R option; this\n" 2176" can be used to change the backing for\n" 2177" existing blocks as well as implicit ones\n" 2178" such as 'gl_DefaultUniformBlock'\n" 2179" --set-default-uniform-block <name> <set> <binding>\n" 2180" set name, descriptor set, and binding for\n" 2181" global default-uniform-block with -R opt\n" 2182" --sdub synonym for set-default-uniform-block\n" 2183" --shift-image-binding [stage] <num>\n" 2184" base binding number for images (UAV)\n" 2185" --shift-image-binding [stage] <num> <set>...\n" 2186" per-descriptor-set shift values\n" 2187" --shift-image-bindings | --sib synonyms for --shift-image-binding\n" 2188" --shift-sampler-binding [stage] <num>\n" 2189" base binding number for samplers\n" 2190" --shift-sampler-binding [stage] <num> <set>...\n" 2191" per-descriptor-set shift values\n" 2192" --shift-sampler-bindings | --ssb synonyms for --shift-sampler-binding\n" 2193" --shift-ssbo-binding [stage] <num>\n" 2194" base binding number for SSBOs\n" 2195" --shift-ssbo-binding [stage] <num> <set>...\n" 2196" per-descriptor-set shift values\n" 2197" --shift-ssbo-bindings | --sbb synonyms for --shift-ssbo-binding\n" 2198" --shift-texture-binding [stage] <num>\n" 2199" base binding number for textures\n" 2200" --shift-texture-binding [stage] <num> <set>...\n" 2201" per-descriptor-set shift values\n" 2202" --shift-texture-bindings | --stb synonyms for --shift-texture-binding\n" 2203" --shift-uav-binding [stage] <num> base binding number for UAVs\n" 2204" --shift-uav-binding [stage] <num> <set>...\n" 2205" per-descriptor-set shift values\n" 2206" --shift-uav-bindings | --suavb synonyms for --shift-uav-binding\n" 2207" --shift-ubo-binding [stage] <num> base binding number for UBOs\n" 2208" --shift-ubo-binding [stage] <num> <set>...\n" 2209" per-descriptor-set shift values\n" 2210" --shift-ubo-bindings | --sub |\n" 2211" --shift-cbuffer-binding | --shift-cbuffer-bindings | --scb\n" 2212" synonyms for --shift-ubo-binding\n" 2213" --shift-combined-sampler-binding [stage] <num>\n" 2214" base binding number for combined samplers\n" 2215" --shift-combined-sampler-binding [stage] <num> <set>...\n" 2216" per-descriptor-set shift values\n" 2217" --shift-combined-sampler-bindings | --scsb\n" 2218" synonyms for --shift-combined-sampler-binding\n" 2219" --shift-as-binding [stage] <num>\n" 2220" base binding number for acceleration structures\n" 2221" --shift-as-binding [stage] <num> <set>...\n" 2222" per-descriptor-set shift values\n" 2223" --shift-as-bindings | --sab\n" 2224" synonyms for --shift-as-binding\n" 2225" --spirv-dis output standard-form disassembly; works only\n" 2226" when a SPIR-V generation option is also used\n" 2227" --spirv-val execute the SPIRV-Tools validator\n" 2228" --source-entrypoint <name> | --sep <name>\n" 2229" the given shader source function is renamed\n" 2230" to be the <name> given in -e\n" 2231" --stdin read from stdin instead of from a file;\n" 2232" requires providing the shader stage using -S\n" 2233" --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | vulkan1.3 | vulkan1.4 |\n" 2234" opengl | spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 |\n" 2235" spirv1.4 | spirv1.5 | spirv1.6}\n" 2236" set the execution environment the generated\n" 2237" code will be executed in; defaults to:\n" 2238" * vulkan1.0 under --client vulkan<ver>\n" 2239" * opengl under --client opengl<ver>\n" 2240" * spirv1.0 under --target-env vulkan1.0\n" 2241" * spirv1.3 under --target-env vulkan1.1\n" 2242" * spirv1.5 under --target-env vulkan1.2\n" 2243" * spirv1.6 under --target-env vulkan1.3\n" 2244" * spirv1.6 under --target-env vulkan1.4\n" 2245" multiple --target-env can be specified\n" 2246" --uniform-base <base> set a base to use for generated uniform\n" 2247" locations\n" 2248" --variable-name <name> | --vn <name>\n" 2249" creates a C header file that contains a\n" 2250" uint32_t array named <name> initialized with\n" 2251" the shader binary code\n" 2252" --validate-io validate cross stage IO\n" 2253" --bindings-per-resource-type\n" ); 2254 2255exit (EFailUsage ); 2256} 2257 2258#if !defined_MSC_VER && !definedMINGW_HAS_SECURE_API 2259 2260#include <errno.h> 2261 2262int fopen_s ( 2263FILE ** pFile , 2264const char * filename , 2265const char * mode 2266) 2267{ 2268if (!pFile || !filename || !mode ) { 2269return EINVAL ; 2270 } 2271 2272FILE * f = fopen (filename ,mode ); 2273if (!f ) { 2274if (errno != 0 ) { 2275return errno ; 2276 }else { 2277return ENOENT ; 2278 } 2279 } 2280* pFile = f ; 2281 2282return 0 ; 2283} 2284 2285#endif 2286 2287// 2288// Malloc a string of sufficient size and read a string into it. 2289// 2290char * ReadFileData (const char * fileName ) 2291{ 2292FILE * in = nullptr ; 2293int errorCode = fopen_s (& in ,fileName ,"r" ); 2294if (errorCode || in == nullptr ) 2295Error ("unable to open input file" ); 2296 2297int count = 0 ; 2298while (fgetc (in )!= EOF ) 2299count ++ ; 2300 2301fseek (in ,0 ,SEEK_SET ); 2302 2303if (count > 3 ) { 2304unsigned char head [3 ]; 2305if (fread (head ,1 ,3 ,in )== 3 ) { 2306if (head [0 ]== 0xef && head [1 ]== 0xbb && head [2 ]== 0xbf ) { 2307// skip BOM 2308count -= 3 ; 2309 }else { 2310fseek (in ,0 ,SEEK_SET ); 2311 } 2312 }else { 2313Error ("can't read input file" ); 2314 } 2315 } 2316 2317char * return_data = (char * )malloc (count + 1 );// freed in FreeFileData() 2318if ((int )fread (return_data ,1 ,count ,in )!= count ) { 2319free (return_data ); 2320Error ("can't read input file" ); 2321 } 2322 2323return_data [count ]= '\0' ; 2324fclose (in ); 2325 2326return return_data ; 2327} 2328 2329void FreeFileData (char * data ) 2330{ 2331free (data ); 2332} 2333 2334void InfoLogMsg (const char * msg ,const char * name ,const int num ) 2335{ 2336if (num >=0 ) 2337printf ("#### %s %s %d INFO LOG ####\n" ,msg ,name ,num ); 2338else 2339printf ("#### %s %s INFO LOG ####\n" ,msg ,name ); 2340}