1 // 2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 //All rights reserved. 4 // 5 //Redistribution and use in source and binary forms, with or without 6 //modification, are permitted provided that the following conditions 7 //are met: 8 // 9 // Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // 12 // Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following 14 // disclaimer in the documentation and/or other materials provided 15 // with the distribution. 16 // 17 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 18 // contributors may be used to endorse or promote products derived 19 // from this software without specific prior written permission. 20 // 21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 //POSSIBILITY OF SUCH DAMAGE. 33 // 34 #ifndef _COMPILER_INTERFACE_INCLUDED_ 35 #define _COMPILER_INTERFACE_INCLUDED_ 36 37 #include "../Include/ResourceLimits.h" 38 #include "../MachineIndependent/Versions.h" 39 40 #include <string.h> 41 42 #ifdef _WIN32 43 #define C_DECL __cdecl 44 //#ifdef SH_EXPORTING 45 // #define SH_IMPORT_EXPORT __declspec(dllexport) 46 //#else 47 // #define SH_IMPORT_EXPORT __declspec(dllimport) 48 //#endif 49 #define SH_IMPORT_EXPORT 50 #else 51 #define SH_IMPORT_EXPORT 52 #ifndef __fastcall 53 #define __fastcall 54 #endif 55 #define C_DECL 56 #endif 57 58 // 59 // This is the platform independent interface between an OGL driver 60 // and the shading language compiler/linker. 61 // 62 63 #ifdef __cplusplus 64 extern "C" { 65 #endif 66 67 // 68 // Driver must call this first, once, before doing any other 69 // compiler/linker operations. 70 // 71 // (Call once per process, not once per thread.) 72 // 73 SH_IMPORT_EXPORT int ShInitialize(); 74 75 // 76 // Driver should call this at process shutdown. 77 // 78 SH_IMPORT_EXPORT int __fastcall ShFinalize(); 79 80 // 81 // Types of languages the compiler can consume. 82 // 83 typedef enum { 84 EShLangVertex, 85 EShLangTessControl, 86 EShLangTessEvaluation, 87 EShLangGeometry, 88 EShLangFragment, 89 EShLangCompute, 90 EShLangCount, 91 } EShLanguage; // would be better as stage, but this is ancient now 92 93 typedef enum { 94 EShLangVertexMask = (1 << EShLangVertex), 95 EShLangTessControlMask = (1 << EShLangTessControl), 96 EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), 97 EShLangGeometryMask = (1 << EShLangGeometry), 98 EShLangFragmentMask = (1 << EShLangFragment), 99 EShLangComputeMask = (1 << EShLangCompute), 100 } EShLanguageMask; 101 102 namespace glslang { 103 104 typedef enum { 105 EShSourceNone, 106 EShSourceGlsl, 107 EShSourceHlsl, 108 } EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead 109 110 const char* StageName(EShLanguage); 111 112 } // end namespace glslang 113 114 // 115 // Types of output the linker will create. 116 // 117 typedef enum { 118 EShExVertexFragment, 119 EShExFragment 120 } EShExecutable; 121 122 // 123 // Optimization level for the compiler. 124 // 125 typedef enum { 126 EShOptNoGeneration, 127 EShOptNone, 128 EShOptSimple, // Optimizations that can be done quickly 129 EShOptFull, // Optimizations that will take more time 130 } EShOptimizationLevel; 131 132 // 133 // Message choices for what errors and warnings are given. 134 // 135 enum EShMessages { 136 EShMsgDefault = 0, // default is to give all required errors and extra warnings 137 EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input 138 EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification 139 EShMsgAST = (1 << 2), // print the AST intermediate representation 140 EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation 141 EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V 142 EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor 143 EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics 144 EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit 145 }; 146 147 // 148 // Build a table for bindings. This can be used for locating 149 // attributes, uniforms, globals, etc., as needed. 150 // 151 typedef struct { 152 const char* name; 153 int binding; 154 } ShBinding; 155 156 typedef struct { 157 int numBindings; 158 ShBinding* bindings; // array of bindings 159 } ShBindingTable; 160 161 // 162 // ShHandle held by but opaque to the driver. It is allocated, 163 // managed, and de-allocated by the compiler/linker. It's contents 164 // are defined by and used by the compiler and linker. For example, 165 // symbol table information and object code passed from the compiler 166 // to the linker can be stored where ShHandle points. 167 // 168 // If handle creation fails, 0 will be returned. 169 // 170 typedef void* ShHandle; 171 172 // 173 // Driver calls these to create and destroy compiler/linker 174 // objects. 175 // 176 SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader 177 SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair 178 SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) 179 SH_IMPORT_EXPORT void ShDestruct(ShHandle); 180 181 // 182 // The return value of ShCompile is boolean, non-zero indicating 183 // success. 184 // 185 // The info-log should be written by ShCompile into 186 // ShHandle, so it can answer future queries. 187 // 188 SH_IMPORT_EXPORT int ShCompile( 189 const ShHandle, 190 const char* const shaderStrings[], 191 const int numStrings, 192 const int* lengths, 193 const EShOptimizationLevel, 194 const TBuiltInResource *resources, 195 int debugOptions, 196 int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader 197 bool forwardCompatible = false, // give errors for use of deprecated features 198 EShMessages messages = EShMsgDefault // warnings and errors 199 ); 200 201 SH_IMPORT_EXPORT int ShLink( 202 const ShHandle, // linker object 203 const ShHandle h[], // compiler objects to link together 204 const int numHandles, 205 ShHandle uniformMap, // updated with new uniforms 206 short int** uniformsAccessed, // returned with indexes of uniforms accessed 207 int* numUniformsAccessed); 208 209 SH_IMPORT_EXPORT int ShLinkExt( 210 const ShHandle, // linker object 211 const ShHandle h[], // compiler objects to link together 212 const int numHandles); 213 214 // 215 // ShSetEncrpytionMethod is a place-holder for specifying 216 // how source code is encrypted. 217 // 218 SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); 219 220 // 221 // All the following return 0 if the information is not 222 // available in the object passed down, or the object is bad. 223 // 224 SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); 225 SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); 226 SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing 227 SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings 228 // 229 // Tell the linker to never assign a vertex attribute to this list of physical attributes 230 // 231 SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); 232 233 // 234 // Returns the location ID of the named uniform. 235 // Returns -1 if error. 236 // 237 SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); 238 239 #ifdef __cplusplus 240 } // end extern "C" 241 #endif 242 243 //////////////////////////////////////////////////////////////////////////////////////////// 244 // 245 // Deferred-Lowering C++ Interface 246 // ----------------------------------- 247 // 248 // Below is a new alternate C++ interface that might potentially replace the above 249 // opaque handle-based interface. 250 // 251 // The below is further designed to handle multiple compilation units per stage, where 252 // the intermediate results, including the parse tree, are preserved until link time, 253 // rather than the above interface which is designed to have each compilation unit 254 // lowered at compile time. In the above model, linking occurs on the lowered results, 255 // whereas in this model intra-stage linking can occur at the parse tree 256 // (treeRoot in TIntermediate) level, and then a full stage can be lowered. 257 // 258 259 #include <list> 260 #include <string> 261 #include <utility> 262 263 class TCompiler; 264 class TInfoSink; 265 266 namespace glslang { 267 268 const char* GetEsslVersionString(); 269 const char* GetGlslVersionString(); 270 int GetKhronosToolId(); 271 272 class TIntermediate; 273 class TProgram; 274 class TPoolAllocator; 275 276 // Call this exactly once per process before using anything else 277 bool InitializeProcess(); 278 279 // Call once per process to tear down everything 280 void FinalizeProcess(); 281 282 // Make one TShader per shader that you will link into a program. Then provide 283 // the shader through setStrings() or setStringsWithLengths(), then call parse(), 284 // then query the info logs. 285 // Optionally use setPreamble() to set a special shader string that will be 286 // processed before all others but won't affect the validity of #version. 287 // 288 // N.B.: Does not yet support having the same TShader instance being linked into 289 // multiple programs. 290 // 291 // N.B.: Destruct a linked program *before* destructing the shaders linked into it. 292 // 293 class TShader { 294 public: 295 explicit TShader(EShLanguage); 296 virtual ~TShader(); 297 void setStrings(const char* const* s, int n); 298 void setStringsWithLengths(const char* const* s, const int* l, int n); 299 void setStringsWithLengthsAndNames( 300 const char* const* s, const int* l, const char* const* names, int n); 301 void setPreamble(const char* s) { preamble = s; } 302 void setEntryPoint(const char* entryPoint); 303 304 // Interface to #include handlers. 305 // 306 // To support #include, a client of Glslang does the following: 307 // 1. Call setStringsWithNames to set the source strings and associated 308 // names. For example, the names could be the names of the files 309 // containing the shader sources. 310 // 2. Call parse with an Includer. 311 // 312 // When the Glslang parser encounters an #include directive, it calls 313 // the Includer's include method with the requested include name 314 // together with the current string name. The returned IncludeResult 315 // contains the fully resolved name of the included source, together 316 // with the source text that should replace the #include directive 317 // in the source stream. After parsing that source, Glslang will 318 // release the IncludeResult object. 319 class Includer { 320 public: 321 typedef enum { 322 EIncludeRelative, // For #include "something" 323 EIncludeStandard // Reserved. For #include <something> 324 } IncludeType; 325 326 // An IncludeResult contains the resolved name and content of a source 327 // inclusion. 328 struct IncludeResult { 329 IncludeResult(const std::string& file_name, const char* const file_data, const size_t file_length, void* user_data) : 330 file_name(file_name), file_data(file_data), file_length(file_length), user_data(user_data) { } 331 // For a successful inclusion, the fully resolved name of the requested 332 // include. For example, in a file system-based includer, full resolution 333 // should convert a relative path name into an absolute path name. 334 // For a failed inclusion, this is an empty string. 335 const std::string file_name; 336 // The content and byte length of the requested inclusion. The 337 // Includer producing this IncludeResult retains ownership of the 338 // storage. 339 // For a failed inclusion, the file_data 340 // field points to a string containing error details. 341 const char* const file_data; 342 const size_t file_length; 343 // Include resolver's context. 344 void* user_data; 345 protected: 346 IncludeResult& operator=(const IncludeResult&); 347 IncludeResult(); 348 }; 349 350 // Resolves an inclusion request by name, type, current source name, 351 // and include depth. 352 // On success, returns an IncludeResult containing the resolved name 353 // and content of the include. On failure, returns an IncludeResult 354 // with an empty string for the file_name and error details in the 355 // file_data field. The Includer retains ownership of the contents 356 // of the returned IncludeResult value, and those contents must 357 // remain valid until the releaseInclude method is called on that 358 // IncludeResult object. 359 virtual IncludeResult* include(const char* requested_source, 360 IncludeType type, 361 const char* requesting_source, 362 size_t inclusion_depth) = 0; 363 // Signals that the parser will no longer use the contents of the 364 // specified IncludeResult. 365 virtual void releaseInclude(IncludeResult* result) = 0; 366 #ifdef __ANDROID__ 367 virtual ~Includer() {} // Pacify -Werror=non-virtual-dtor 368 #endif 369 }; 370 371 // Returns an error message for any #include directive. 372 class ForbidInclude : public Includer { 373 public: 374 IncludeResult* include(const char*, IncludeType, const char*, size_t) override 375 { 376 const char* unexpected_include = "unexpected include directive"; 377 return new IncludeResult(std::string(""), unexpected_include, strlen(unexpected_include), nullptr); 378 } 379 virtual void releaseInclude(IncludeResult* result) override 380 { 381 delete result; 382 } 383 }; 384 385 bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, 386 bool forwardCompatible, EShMessages messages) 387 { 388 TShader::ForbidInclude includer; 389 return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); 390 } 391 392 bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, 393 bool forwardCompatible, EShMessages, Includer&); 394 395 // Equivalent to parse() without a default profile and without forcing defaults. 396 // Provided for backwards compatibility. 397 bool parse(const TBuiltInResource*, int defaultVersion, bool forwardCompatible, EShMessages); 398 bool preprocess(const TBuiltInResource* builtInResources, 399 int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, 400 bool forwardCompatible, EShMessages message, std::string* outputString, 401 Includer& includer); 402 403 const char* getInfoLog(); 404 const char* getInfoDebugLog(); 405 406 EShLanguage getStage() const { return stage; } 407 408 protected: 409 TPoolAllocator* pool; 410 EShLanguage stage; 411 TCompiler* compiler; 412 TIntermediate* intermediate; 413 TInfoSink* infoSink; 414 // strings and lengths follow the standard for glShaderSource: 415 // strings is an array of numStrings pointers to string data. 416 // lengths can be null, but if not it is an array of numStrings 417 // integers containing the length of the associated strings. 418 // if lengths is null or lengths[n] < 0 the associated strings[n] is 419 // assumed to be null-terminated. 420 // stringNames is the optional names for all the strings. If stringNames 421 // is null, then none of the strings has name. If a certain element in 422 // stringNames is null, then the corresponding string does not have name. 423 const char* const* strings; 424 const int* lengths; 425 const char* const* stringNames; 426 const char* preamble; 427 int numStrings; 428 429 friend class TProgram; 430 431 private: 432 TShader& operator=(TShader&); 433 }; 434 435 class TReflection; 436 437 // Make one TProgram per set of shaders that will get linked together. Add all 438 // the shaders that are to be linked together. After calling shader.parse() 439 // for all shaders, call link(). 440 // 441 // N.B.: Destruct a linked program *before* destructing the shaders linked into it. 442 // 443 class TProgram { 444 public: 445 TProgram(); 446 virtual ~TProgram(); 447 void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } 448 449 // Link Validation interface 450 bool link(EShMessages); 451 const char* getInfoLog(); 452 const char* getInfoDebugLog(); 453 454 TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } 455 456 // Reflection Interface 457 bool buildReflection(); // call first, to do liveness analysis, index mapping, etc.; returns false on failure 458 int getNumLiveUniformVariables(); // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) 459 int getNumLiveUniformBlocks(); // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) 460 const char* getUniformName(int index); // can be used for "name" part of glGetActiveUniform() 461 const char* getUniformBlockName(int blockIndex); // can be used for glGetActiveUniformBlockName() 462 int getUniformBlockSize(int blockIndex); // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) 463 int getUniformIndex(const char* name); // can be used for glGetUniformIndices() 464 int getUniformBlockIndex(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) 465 int getUniformType(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) 466 int getUniformBufferOffset(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) 467 int getUniformArraySize(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) 468 int getNumLiveAttributes(); // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) 469 const char *getAttributeName(int index); // can be used for glGetActiveAttrib() 470 int getAttributeType(int index); // can be used for glGetActiveAttrib() 471 void dumpReflection(); 472 473 protected: 474 bool linkStage(EShLanguage, EShMessages); 475 476 TPoolAllocator* pool; 477 std::list<TShader*> stages[EShLangCount]; 478 TIntermediate* intermediate[EShLangCount]; 479 bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage 480 TInfoSink* infoSink; 481 TReflection* reflection; 482 bool linked; 483 484 private: 485 TProgram& operator=(TProgram&); 486 }; 487 488 } // end namespace glslang 489 490 #endif // _COMPILER_INTERFACE_INCLUDED_ 491