1 // 2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 // Copyright (C) 2013-2016 LunarG, Inc. 4 // Copyright (C) 2015-2018 Google, Inc. 5 // 6 // All rights reserved. 7 // 8 // Redistribution and use in source and binary forms, with or without 9 // modification, are permitted provided that the following conditions 10 // are met: 11 // 12 // Redistributions of source code must retain the above copyright 13 // notice, this list of conditions and the following disclaimer. 14 // 15 // Redistributions in binary form must reproduce the above 16 // copyright notice, this list of conditions and the following 17 // disclaimer in the documentation and/or other materials provided 18 // with the distribution. 19 // 20 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 21 // contributors may be used to endorse or promote products derived 22 // from this software without specific prior written permission. 23 // 24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 // POSSIBILITY OF SUCH DAMAGE. 36 // 37 #ifndef _COMPILER_INTERFACE_INCLUDED_ 38 #define _COMPILER_INTERFACE_INCLUDED_ 39 40 #include "../Include/ResourceLimits.h" 41 #include "../MachineIndependent/Versions.h" 42 43 #include <cstring> 44 #include <vector> 45 46 #ifdef _WIN32 47 #define C_DECL __cdecl 48 //#ifdef SH_EXPORTING 49 // #define SH_IMPORT_EXPORT __declspec(dllexport) 50 //#else 51 // #define SH_IMPORT_EXPORT __declspec(dllimport) 52 //#endif 53 #define SH_IMPORT_EXPORT 54 #else 55 #define SH_IMPORT_EXPORT 56 #ifndef __fastcall 57 #define __fastcall 58 #endif 59 #define C_DECL 60 #endif 61 62 // 63 // This is the platform independent interface between an OGL driver 64 // and the shading language compiler/linker. 65 // 66 67 #ifdef __cplusplus 68 extern "C" { 69 #endif 70 71 // This should always increase, as some paths to do not consume 72 // a more major number. 73 // It should increment by one when new functionality is added. 74 #define GLSLANG_MINOR_VERSION 11 75 76 // 77 // Call before doing any other compiler/linker operations. 78 // 79 // (Call once per process, not once per thread.) 80 // 81 SH_IMPORT_EXPORT int ShInitialize(); 82 83 // 84 // Call this at process shutdown to clean up memory. 85 // 86 SH_IMPORT_EXPORT int __fastcall ShFinalize(); 87 88 // 89 // Types of languages the compiler can consume. 90 // 91 typedef enum { 92 EShLangVertex, 93 EShLangTessControl, 94 EShLangTessEvaluation, 95 EShLangGeometry, 96 EShLangFragment, 97 EShLangCompute, 98 EShLangRayGenNV, 99 EShLangIntersectNV, 100 EShLangAnyHitNV, 101 EShLangClosestHitNV, 102 EShLangMissNV, 103 EShLangCallableNV, 104 EShLangTaskNV, 105 EShLangMeshNV, 106 EShLangCount, 107 } EShLanguage; // would be better as stage, but this is ancient now 108 109 typedef enum { 110 EShLangVertexMask = (1 << EShLangVertex), 111 EShLangTessControlMask = (1 << EShLangTessControl), 112 EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), 113 EShLangGeometryMask = (1 << EShLangGeometry), 114 EShLangFragmentMask = (1 << EShLangFragment), 115 EShLangComputeMask = (1 << EShLangCompute), 116 EShLangRayGenNVMask = (1 << EShLangRayGenNV), 117 EShLangIntersectNVMask = (1 << EShLangIntersectNV), 118 EShLangAnyHitNVMask = (1 << EShLangAnyHitNV), 119 EShLangClosestHitNVMask = (1 << EShLangClosestHitNV), 120 EShLangMissNVMask = (1 << EShLangMissNV), 121 EShLangCallableNVMask = (1 << EShLangCallableNV), 122 EShLangTaskNVMask = (1 << EShLangTaskNV), 123 EShLangMeshNVMask = (1 << EShLangMeshNV), 124 } EShLanguageMask; 125 126 namespace glslang { 127 128 class TType; 129 130 typedef enum { 131 EShSourceNone, 132 EShSourceGlsl, 133 EShSourceHlsl, 134 } EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead 135 136 typedef enum { 137 EShClientNone, 138 EShClientVulkan, 139 EShClientOpenGL, 140 } EShClient; 141 142 typedef enum { 143 EShTargetNone, 144 EShTargetSpv, // preferred spelling 145 EshTargetSpv = EShTargetSpv, // legacy spelling 146 } EShTargetLanguage; 147 148 typedef enum { 149 EShTargetVulkan_1_0 = (1 << 22), 150 EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), 151 EShTargetOpenGL_450 = 450, 152 } EShTargetClientVersion; 153 154 typedef EShTargetClientVersion EshTargetClientVersion; 155 156 typedef enum { 157 EShTargetSpv_1_0 = (1 << 16), 158 EShTargetSpv_1_1 = (1 << 16) | (1 << 8), 159 EShTargetSpv_1_2 = (1 << 16) | (2 << 8), 160 EShTargetSpv_1_3 = (1 << 16) | (3 << 8), 161 EShTargetSpv_1_4 = (1 << 16) | (4 << 8), 162 } EShTargetLanguageVersion; 163 164 struct TInputLanguage { 165 EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone 166 EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone 167 EShClient dialect; 168 int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) 169 }; 170 171 struct TClient { 172 EShClient client; 173 EShTargetClientVersion version; // version of client itself (not the client's input dialect) 174 }; 175 176 struct TTarget { 177 EShTargetLanguage language; 178 EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header 179 bool hlslFunctionality1; // can target hlsl_functionality1 extension(s) 180 }; 181 182 // All source/client/target versions and settings. 183 // Can override previous methods of setting, when items are set here. 184 // Expected to grow, as more are added, rather than growing parameter lists. 185 struct TEnvironment { 186 TInputLanguage input; // definition of the input language 187 TClient client; // what client is the overall compilation being done for? 188 TTarget target; // what to generate 189 }; 190 191 const char* StageName(EShLanguage); 192 193 } // end namespace glslang 194 195 // 196 // Types of output the linker will create. 197 // 198 typedef enum { 199 EShExVertexFragment, 200 EShExFragment 201 } EShExecutable; 202 203 // 204 // Optimization level for the compiler. 205 // 206 typedef enum { 207 EShOptNoGeneration, 208 EShOptNone, 209 EShOptSimple, // Optimizations that can be done quickly 210 EShOptFull, // Optimizations that will take more time 211 } EShOptimizationLevel; 212 213 // 214 // Texture and Sampler transformation mode. 215 // 216 typedef enum { 217 EShTexSampTransKeep, // keep textures and samplers as is (default) 218 EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers 219 } EShTextureSamplerTransformMode; 220 221 // 222 // Message choices for what errors and warnings are given. 223 // 224 enum EShMessages { 225 EShMsgDefault = 0, // default is to give all required errors and extra warnings 226 EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input 227 EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification 228 EShMsgAST = (1 << 2), // print the AST intermediate representation 229 EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation 230 EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V 231 EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor 232 EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics 233 EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit 234 EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions 235 EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules 236 EShMsgDebugInfo = (1 << 10), // save debug information 237 EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL 238 EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages 239 EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) 240 }; 241 242 // 243 // Build a table for bindings. This can be used for locating 244 // attributes, uniforms, globals, etc., as needed. 245 // 246 typedef struct { 247 const char* name; 248 int binding; 249 } ShBinding; 250 251 typedef struct { 252 int numBindings; 253 ShBinding* bindings; // array of bindings 254 } ShBindingTable; 255 256 // 257 // ShHandle held by but opaque to the driver. It is allocated, 258 // managed, and de-allocated by the compiler/linker. It's contents 259 // are defined by and used by the compiler and linker. For example, 260 // symbol table information and object code passed from the compiler 261 // to the linker can be stored where ShHandle points. 262 // 263 // If handle creation fails, 0 will be returned. 264 // 265 typedef void* ShHandle; 266 267 // 268 // Driver calls these to create and destroy compiler/linker 269 // objects. 270 // 271 SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader 272 SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair 273 SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) 274 SH_IMPORT_EXPORT void ShDestruct(ShHandle); 275 276 // 277 // The return value of ShCompile is boolean, non-zero indicating 278 // success. 279 // 280 // The info-log should be written by ShCompile into 281 // ShHandle, so it can answer future queries. 282 // 283 SH_IMPORT_EXPORT int ShCompile( 284 const ShHandle, 285 const char* const shaderStrings[], 286 const int numStrings, 287 const int* lengths, 288 const EShOptimizationLevel, 289 const TBuiltInResource *resources, 290 int debugOptions, 291 int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader 292 bool forwardCompatible = false, // give errors for use of deprecated features 293 EShMessages messages = EShMsgDefault // warnings and errors 294 ); 295 296 SH_IMPORT_EXPORT int ShLinkExt( 297 const ShHandle, // linker object 298 const ShHandle h[], // compiler objects to link together 299 const int numHandles); 300 301 // 302 // ShSetEncrpytionMethod is a place-holder for specifying 303 // how source code is encrypted. 304 // 305 SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); 306 307 // 308 // All the following return 0 if the information is not 309 // available in the object passed down, or the object is bad. 310 // 311 SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); 312 SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); 313 SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing 314 SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings 315 // 316 // Tell the linker to never assign a vertex attribute to this list of physical attributes 317 // 318 SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); 319 320 // 321 // Returns the location ID of the named uniform. 322 // Returns -1 if error. 323 // 324 SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); 325 326 #ifdef __cplusplus 327 } // end extern "C" 328 #endif 329 330 //////////////////////////////////////////////////////////////////////////////////////////// 331 // 332 // Deferred-Lowering C++ Interface 333 // ----------------------------------- 334 // 335 // Below is a new alternate C++ interface, which deprecates the above 336 // opaque handle-based interface. 337 // 338 // The below is further designed to handle multiple compilation units per stage, where 339 // the intermediate results, including the parse tree, are preserved until link time, 340 // rather than the above interface which is designed to have each compilation unit 341 // lowered at compile time. In the above model, linking occurs on the lowered results, 342 // whereas in this model intra-stage linking can occur at the parse tree 343 // (treeRoot in TIntermediate) level, and then a full stage can be lowered. 344 // 345 346 #include <list> 347 #include <string> 348 #include <utility> 349 350 class TCompiler; 351 class TInfoSink; 352 353 namespace glslang { 354 355 const char* GetEsslVersionString(); 356 const char* GetGlslVersionString(); 357 int GetKhronosToolId(); 358 359 class TIntermediate; 360 class TProgram; 361 class TPoolAllocator; 362 363 // Call this exactly once per process before using anything else 364 bool InitializeProcess(); 365 366 // Call once per process to tear down everything 367 void FinalizeProcess(); 368 369 // Resource type for IO resolver 370 enum TResourceType { 371 EResSampler, 372 EResTexture, 373 EResImage, 374 EResUbo, 375 EResSsbo, 376 EResUav, 377 EResCount 378 }; 379 380 // Make one TShader per shader that you will link into a program. Then 381 // - provide the shader through setStrings() or setStringsWithLengths() 382 // - optionally call setEnv*(), see below for more detail 383 // - optionally use setPreamble() to set a special shader string that will be 384 // processed before all others but won't affect the validity of #version 385 // - call parse(): source language and target environment must be selected 386 // either by correct setting of EShMessages sent to parse(), or by 387 // explicitly calling setEnv*() 388 // - query the info logs 389 // 390 // N.B.: Does not yet support having the same TShader instance being linked into 391 // multiple programs. 392 // 393 // N.B.: Destruct a linked program *before* destructing the shaders linked into it. 394 // 395 class TShader { 396 public: 397 explicit TShader(EShLanguage); 398 virtual ~TShader(); 399 void setStrings(const char* const* s, int n); 400 void setStringsWithLengths(const char* const* s, const int* l, int n); 401 void setStringsWithLengthsAndNames( 402 const char* const* s, const int* l, const char* const* names, int n); setPreamble(const char * s)403 void setPreamble(const char* s) { preamble = s; } 404 void setEntryPoint(const char* entryPoint); 405 void setSourceEntryPoint(const char* sourceEntryPointName); 406 void addProcesses(const std::vector<std::string>&); 407 408 // IO resolver binding data: see comments in ShaderLang.cpp 409 void setShiftBinding(TResourceType res, unsigned int base); 410 void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding 411 void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding 412 void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding 413 void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding 414 void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding 415 void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding 416 void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding 417 void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); 418 void setResourceSetBinding(const std::vector<std::string>& base); 419 void setAutoMapBindings(bool map); 420 void setAutoMapLocations(bool map); 421 void addUniformLocationOverride(const char* name, int loc); 422 void setUniformLocationBase(int base); 423 void setInvertY(bool invert); 424 void setHlslIoMapping(bool hlslIoMap); 425 void setFlattenUniformArrays(bool flatten); 426 void setNoStorageFormat(bool useUnknownFormat); 427 void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); 428 429 // For setting up the environment (cleared to nothingness in the constructor). 430 // These must be called so that parsing is done for the right source language and 431 // target environment, either indirectly through TranslateEnvironment() based on 432 // EShMessages et. al., or directly by the user. setEnvInput(EShSource lang,EShLanguage envStage,EShClient client,int version)433 void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version) 434 { 435 environment.input.languageFamily = lang; 436 environment.input.stage = envStage; 437 environment.input.dialect = client; 438 environment.input.dialectVersion = version; 439 } setEnvClient(EShClient client,EShTargetClientVersion version)440 void setEnvClient(EShClient client, EShTargetClientVersion version) 441 { 442 environment.client.client = client; 443 environment.client.version = version; 444 } setEnvTarget(EShTargetLanguage lang,EShTargetLanguageVersion version)445 void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version) 446 { 447 environment.target.language = lang; 448 environment.target.version = version; 449 } setEnvTargetHlslFunctionality1()450 void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } getEnvTargetHlslFunctionality1()451 bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } 452 453 // Interface to #include handlers. 454 // 455 // To support #include, a client of Glslang does the following: 456 // 1. Call setStringsWithNames to set the source strings and associated 457 // names. For example, the names could be the names of the files 458 // containing the shader sources. 459 // 2. Call parse with an Includer. 460 // 461 // When the Glslang parser encounters an #include directive, it calls 462 // the Includer's include method with the requested include name 463 // together with the current string name. The returned IncludeResult 464 // contains the fully resolved name of the included source, together 465 // with the source text that should replace the #include directive 466 // in the source stream. After parsing that source, Glslang will 467 // release the IncludeResult object. 468 class Includer { 469 public: 470 // An IncludeResult contains the resolved name and content of a source 471 // inclusion. 472 struct IncludeResult { IncludeResultIncludeResult473 IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : 474 headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } 475 // For a successful inclusion, the fully resolved name of the requested 476 // include. For example, in a file system-based includer, full resolution 477 // should convert a relative path name into an absolute path name. 478 // For a failed inclusion, this is an empty string. 479 const std::string headerName; 480 // The content and byte length of the requested inclusion. The 481 // Includer producing this IncludeResult retains ownership of the 482 // storage. 483 // For a failed inclusion, the header 484 // field points to a string containing error details. 485 const char* const headerData; 486 const size_t headerLength; 487 // Include resolver's context. 488 void* userData; 489 protected: 490 IncludeResult& operator=(const IncludeResult&); 491 IncludeResult(); 492 }; 493 494 // For both include methods below: 495 // 496 // Resolves an inclusion request by name, current source name, 497 // and include depth. 498 // On success, returns an IncludeResult containing the resolved name 499 // and content of the include. 500 // On failure, returns a nullptr, or an IncludeResult 501 // with an empty string for the headerName and error details in the 502 // header field. 503 // The Includer retains ownership of the contents 504 // of the returned IncludeResult value, and those contents must 505 // remain valid until the releaseInclude method is called on that 506 // IncludeResult object. 507 // 508 // Note "local" vs. "system" is not an "either/or": "local" is an 509 // extra thing to do over "system". Both might get called, as per 510 // the C++ specification. 511 512 // For the "system" or <>-style includes; search the "system" paths. includeSystem(const char *,const char *,size_t)513 virtual IncludeResult* includeSystem(const char* /*headerName*/, 514 const char* /*includerName*/, 515 size_t /*inclusionDepth*/) { return nullptr; } 516 517 // For the "local"-only aspect of a "" include. Should not search in the 518 // "system" paths, because on returning a failure, the parser will 519 // call includeSystem() to look in the "system" locations. includeLocal(const char *,const char *,size_t)520 virtual IncludeResult* includeLocal(const char* /*headerName*/, 521 const char* /*includerName*/, 522 size_t /*inclusionDepth*/) { return nullptr; } 523 524 // Signals that the parser will no longer use the contents of the 525 // specified IncludeResult. 526 virtual void releaseInclude(IncludeResult*) = 0; ~Includer()527 virtual ~Includer() {} 528 }; 529 530 // Fail all Includer searches 531 class ForbidIncluder : public Includer { 532 public: releaseInclude(IncludeResult *)533 virtual void releaseInclude(IncludeResult*) override { } 534 }; 535 536 bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, 537 bool forwardCompatible, EShMessages, Includer&); 538 parse(const TBuiltInResource * res,int defaultVersion,EProfile defaultProfile,bool forceDefaultVersionAndProfile,bool forwardCompatible,EShMessages messages)539 bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, 540 bool forwardCompatible, EShMessages messages) 541 { 542 TShader::ForbidIncluder includer; 543 return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); 544 } 545 546 // Equivalent to parse() without a default profile and without forcing defaults. parse(const TBuiltInResource * builtInResources,int defaultVersion,bool forwardCompatible,EShMessages messages)547 bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) 548 { 549 return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); 550 } 551 parse(const TBuiltInResource * builtInResources,int defaultVersion,bool forwardCompatible,EShMessages messages,Includer & includer)552 bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, 553 Includer& includer) 554 { 555 return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); 556 } 557 558 // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string 559 // is not an officially supported or fully working path. 560 bool preprocess(const TBuiltInResource* builtInResources, 561 int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, 562 bool forwardCompatible, EShMessages message, std::string* outputString, 563 Includer& includer); 564 565 const char* getInfoLog(); 566 const char* getInfoDebugLog(); getStage()567 EShLanguage getStage() const { return stage; } getIntermediate()568 TIntermediate* getIntermediate() const { return intermediate; } 569 570 protected: 571 TPoolAllocator* pool; 572 EShLanguage stage; 573 TCompiler* compiler; 574 TIntermediate* intermediate; 575 TInfoSink* infoSink; 576 // strings and lengths follow the standard for glShaderSource: 577 // strings is an array of numStrings pointers to string data. 578 // lengths can be null, but if not it is an array of numStrings 579 // integers containing the length of the associated strings. 580 // if lengths is null or lengths[n] < 0 the associated strings[n] is 581 // assumed to be null-terminated. 582 // stringNames is the optional names for all the strings. If stringNames 583 // is null, then none of the strings has name. If a certain element in 584 // stringNames is null, then the corresponding string does not have name. 585 const char* const* strings; 586 const int* lengths; 587 const char* const* stringNames; 588 const char* preamble; 589 int numStrings; 590 591 // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. 592 std::string sourceEntryPointName; 593 594 TEnvironment environment; 595 596 friend class TProgram; 597 598 private: 599 TShader& operator=(TShader&); 600 }; 601 602 class TReflection; 603 class TIoMapper; 604 605 // Allows to customize the binding layout after linking. 606 // All used uniform variables will invoke at least validateBinding. 607 // If validateBinding returned true then the other resolveBinding, 608 // resolveSet, and resolveLocation are invoked to resolve the binding 609 // and descriptor set index respectively. 610 // 611 // Invocations happen in a particular order: 612 // 1) all shader inputs 613 // 2) all shader outputs 614 // 3) all uniforms with binding and set already defined 615 // 4) all uniforms with binding but no set defined 616 // 5) all uniforms with set but no binding defined 617 // 6) all uniforms with no binding and no set defined 618 // 619 // mapIO will use this resolver in two phases. The first 620 // phase is a notification phase, calling the corresponging 621 // notifiy callbacks, this phase ends with a call to endNotifications. 622 // Phase two starts directly after the call to endNotifications 623 // and calls all other callbacks to validate and to get the 624 // bindings, sets, locations, component and color indices. 625 // 626 // NOTE: that still limit checks are applied to bindings and sets 627 // and may result in an error. 628 class TIoMapResolver 629 { 630 public: ~TIoMapResolver()631 virtual ~TIoMapResolver() {} 632 633 // Should return true if the resulting/current binding would be okay. 634 // Basic idea is to do aliasing binding checks with this. 635 virtual bool validateBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 636 // Should return a value >= 0 if the current binding should be overridden. 637 // Return -1 if the current binding (including no binding) should be kept. 638 virtual int resolveBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 639 // Should return a value >= 0 if the current set should be overridden. 640 // Return -1 if the current set (including no set) should be kept. 641 virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 642 // Should return a value >= 0 if the current location should be overridden. 643 // Return -1 if the current location (including no location) should be kept. 644 virtual int resolveUniformLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 645 // Should return true if the resulting/current setup would be okay. 646 // Basic idea is to do aliasing checks and reject invalid semantic names. 647 virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 648 // Should return a value >= 0 if the current location should be overridden. 649 // Return -1 if the current location (including no location) should be kept. 650 virtual int resolveInOutLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 651 // Should return a value >= 0 if the current component index should be overridden. 652 // Return -1 if the current component index (including no index) should be kept. 653 virtual int resolveInOutComponent(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 654 // Should return a value >= 0 if the current color index should be overridden. 655 // Return -1 if the current color index (including no index) should be kept. 656 virtual int resolveInOutIndex(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 657 // Notification of a uniform variable 658 virtual void notifyBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 659 // Notification of a in or out variable 660 virtual void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; 661 // Called by mapIO when it has finished the notify pass 662 virtual void endNotifications(EShLanguage stage) = 0; 663 // Called by mapIO when it starts its notify pass for the given stage 664 virtual void beginNotifications(EShLanguage stage) = 0; 665 // Called by mipIO when it starts its resolve pass for the given stage 666 virtual void beginResolve(EShLanguage stage) = 0; 667 // Called by mapIO when it has finished the resolve pass 668 virtual void endResolve(EShLanguage stage) = 0; 669 }; 670 671 // Make one TProgram per set of shaders that will get linked together. Add all 672 // the shaders that are to be linked together. After calling shader.parse() 673 // for all shaders, call link(). 674 // 675 // N.B.: Destruct a linked program *before* destructing the shaders linked into it. 676 // 677 class TProgram { 678 public: 679 TProgram(); 680 virtual ~TProgram(); addShader(TShader * shader)681 void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } 682 683 // Link Validation interface 684 bool link(EShMessages); 685 const char* getInfoLog(); 686 const char* getInfoDebugLog(); 687 getIntermediate(EShLanguage stage)688 TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } 689 690 // Reflection Interface 691 bool buildReflection(); // call first, to do liveness analysis, index mapping, etc.; returns false on failure 692 int getNumLiveUniformVariables() const; // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) 693 int getNumLiveUniformBlocks() const; // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) 694 const char* getUniformName(int index) const; // can be used for "name" part of glGetActiveUniform() 695 const char* getUniformBlockName(int blockIndex) const; // can be used for glGetActiveUniformBlockName() 696 int getUniformBlockSize(int blockIndex) const; // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) 697 int getUniformIndex(const char* name) const; // can be used for glGetUniformIndices() 698 int getUniformBinding(int index) const; // returns the binding number 699 EShLanguageMask getUniformStages(int index) const; // returns Shaders Stages where a Uniform is present 700 int getUniformBlockBinding(int index) const; // returns the block binding number 701 int getUniformBlockIndex(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) 702 int getUniformBlockCounterIndex(int index) const; // returns block index of associated counter. 703 int getUniformType(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) 704 int getUniformBufferOffset(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) 705 int getUniformArraySize(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) 706 int getNumLiveAttributes() const; // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) 707 unsigned getLocalSize(int dim) const; // return dim'th local size 708 const char *getAttributeName(int index) const; // can be used for glGetActiveAttrib() 709 int getAttributeType(int index) const; // can be used for glGetActiveAttrib() 710 const TType* getUniformTType(int index) const; // returns a TType* 711 const TType* getUniformBlockTType(int index) const; // returns a TType* 712 const TType* getAttributeTType(int index) const; // returns a TType* 713 714 void dumpReflection(); 715 716 // I/O mapping: apply base offsets and map live unbound variables 717 // If resolver is not provided it uses the previous approach 718 // and respects auto assignment and offsets. 719 bool mapIO(TIoMapResolver* resolver = NULL); 720 721 protected: 722 bool linkStage(EShLanguage, EShMessages); 723 724 TPoolAllocator* pool; 725 std::list<TShader*> stages[EShLangCount]; 726 TIntermediate* intermediate[EShLangCount]; 727 bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage 728 TInfoSink* infoSink; 729 TReflection* reflection; 730 TIoMapper* ioMapper; 731 bool linked; 732 733 private: 734 TProgram(TProgram&); 735 TProgram& operator=(TProgram&); 736 }; 737 738 } // end namespace glslang 739 740 #endif // _COMPILER_INTERFACE_INCLUDED_ 741