Home | History | Annotate | Download | only in Public
      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