Home | History | Annotate | Download | only in compiler
      1 //
      2 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 //
      8 // Implement the top-level of interface to the compiler,
      9 // as defined in ShaderLang.h
     10 //
     11 
     12 #include "GLSLANG/ShaderLang.h"
     13 
     14 #include "compiler/InitializeDll.h"
     15 #include "compiler/preprocessor/length_limits.h"
     16 #include "compiler/ShHandle.h"
     17 #include "compiler/TranslatorHLSL.h"
     18 #include "compiler/VariablePacker.h"
     19 
     20 //
     21 // This is the platform independent interface between an OGL driver
     22 // and the shading language compiler.
     23 //
     24 
     25 static bool checkVariableMaxLengths(const ShHandle handle,
     26                                     size_t expectedValue)
     27 {
     28     size_t activeUniformLimit = 0;
     29     ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
     30     size_t activeAttribLimit = 0;
     31     ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
     32     size_t varyingLimit = 0;
     33     ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
     34     return (expectedValue == activeUniformLimit &&
     35             expectedValue == activeAttribLimit &&
     36             expectedValue == varyingLimit);
     37 }
     38 
     39 static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
     40 {
     41     size_t mappedNameMaxLength = 0;
     42     ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
     43     return (expectedValue == mappedNameMaxLength);
     44 }
     45 
     46 //
     47 // Driver must call this first, once, before doing any other compiler operations.
     48 // Subsequent calls to this function are no-op.
     49 //
     50 int ShInitialize()
     51 {
     52     static const bool kInitialized = InitProcess();
     53     return kInitialized ? 1 : 0;
     54 }
     55 
     56 //
     57 // Cleanup symbol tables
     58 //
     59 int ShFinalize()
     60 {
     61     DetachProcess();
     62     return 1;
     63 }
     64 
     65 //
     66 // Initialize built-in resources with minimum expected values.
     67 //
     68 void ShInitBuiltInResources(ShBuiltInResources* resources)
     69 {
     70     // Constants.
     71     resources->MaxVertexAttribs = 8;
     72     resources->MaxVertexUniformVectors = 128;
     73     resources->MaxVaryingVectors = 8;
     74     resources->MaxVertexTextureImageUnits = 0;
     75     resources->MaxCombinedTextureImageUnits = 8;
     76     resources->MaxTextureImageUnits = 8;
     77     resources->MaxFragmentUniformVectors = 16;
     78     resources->MaxDrawBuffers = 1;
     79 
     80     // Extensions.
     81     resources->OES_standard_derivatives = 0;
     82     resources->OES_EGL_image_external = 0;
     83     resources->ARB_texture_rectangle = 0;
     84     resources->EXT_draw_buffers = 0;
     85     resources->EXT_frag_depth = 0;
     86 
     87     // Disable highp precision in fragment shader by default.
     88     resources->FragmentPrecisionHigh = 0;
     89 
     90     // Disable name hashing by default.
     91     resources->HashFunction = NULL;
     92 
     93     resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
     94 }
     95 
     96 //
     97 // Driver calls these to create and destroy compiler objects.
     98 //
     99 ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
    100                              ShShaderOutput output,
    101                              const ShBuiltInResources* resources)
    102 {
    103     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
    104     TCompiler* compiler = base->getAsCompiler();
    105     if (compiler == 0)
    106         return 0;
    107 
    108     // Generate built-in symbol table.
    109     if (!compiler->Init(*resources)) {
    110         ShDestruct(base);
    111         return 0;
    112     }
    113 
    114     return reinterpret_cast<void*>(base);
    115 }
    116 
    117 void ShDestruct(ShHandle handle)
    118 {
    119     if (handle == 0)
    120         return;
    121 
    122     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
    123 
    124     if (base->getAsCompiler())
    125         DeleteCompiler(base->getAsCompiler());
    126 }
    127 
    128 //
    129 // Do an actual compile on the given strings.  The result is left
    130 // in the given compile object.
    131 //
    132 // Return:  The return value of ShCompile is really boolean, indicating
    133 // success or failure.
    134 //
    135 int ShCompile(
    136     const ShHandle handle,
    137     const char* const shaderStrings[],
    138     size_t numStrings,
    139     int compileOptions)
    140 {
    141     if (handle == 0)
    142         return 0;
    143 
    144     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
    145     TCompiler* compiler = base->getAsCompiler();
    146     if (compiler == 0)
    147         return 0;
    148 
    149     bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
    150     return success ? 1 : 0;
    151 }
    152 
    153 void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
    154 {
    155     if (!handle || !params)
    156         return;
    157 
    158     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
    159     TCompiler* compiler = base->getAsCompiler();
    160     if (!compiler) return;
    161 
    162     switch(pname)
    163     {
    164     case SH_INFO_LOG_LENGTH:
    165         *params = compiler->getInfoSink().info.size() + 1;
    166         break;
    167     case SH_OBJECT_CODE_LENGTH:
    168         *params = compiler->getInfoSink().obj.size() + 1;
    169         break;
    170     case SH_ACTIVE_UNIFORMS:
    171         *params = compiler->getUniforms().size();
    172         break;
    173     case SH_ACTIVE_UNIFORM_MAX_LENGTH:
    174         *params = 1 +  MAX_SYMBOL_NAME_LEN;
    175         break;
    176     case SH_ACTIVE_ATTRIBUTES:
    177         *params = compiler->getAttribs().size();
    178         break;
    179     case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
    180         *params = 1 + MAX_SYMBOL_NAME_LEN;
    181         break;
    182     case SH_VARYINGS:
    183         *params = compiler->getVaryings().size();
    184         break;
    185     case SH_VARYING_MAX_LENGTH:
    186         *params = 1 + MAX_SYMBOL_NAME_LEN;
    187         break;
    188     case SH_MAPPED_NAME_MAX_LENGTH:
    189         // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
    190         // handle array and struct dereferences.
    191         *params = 1 + MAX_SYMBOL_NAME_LEN;
    192         break;
    193     case SH_NAME_MAX_LENGTH:
    194         *params = 1 + MAX_SYMBOL_NAME_LEN;
    195         break;
    196     case SH_HASHED_NAME_MAX_LENGTH:
    197         if (compiler->getHashFunction() == NULL) {
    198             *params = 0;
    199         } else {
    200             // 64 bits hashing output requires 16 bytes for hex
    201             // representation.
    202             const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
    203             *params = 16 + sizeof(HashedNamePrefix);
    204         }
    205         break;
    206     case SH_HASHED_NAMES_COUNT:
    207         *params = compiler->getNameMap().size();
    208         break;
    209     default: UNREACHABLE();
    210     }
    211 }
    212 
    213 //
    214 // Return any compiler log of messages for the application.
    215 //
    216 void ShGetInfoLog(const ShHandle handle, char* infoLog)
    217 {
    218     if (!handle || !infoLog)
    219         return;
    220 
    221     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
    222     TCompiler* compiler = base->getAsCompiler();
    223     if (!compiler) return;
    224 
    225     TInfoSink& infoSink = compiler->getInfoSink();
    226     strcpy(infoLog, infoSink.info.c_str());
    227 }
    228 
    229 //
    230 // Return any object code.
    231 //
    232 void ShGetObjectCode(const ShHandle handle, char* objCode)
    233 {
    234     if (!handle || !objCode)
    235         return;
    236 
    237     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
    238     TCompiler* compiler = base->getAsCompiler();
    239     if (!compiler) return;
    240 
    241     TInfoSink& infoSink = compiler->getInfoSink();
    242     strcpy(objCode, infoSink.obj.c_str());
    243 }
    244 
    245 void ShGetVariableInfo(const ShHandle handle,
    246                        ShShaderInfo varType,
    247                        int index,
    248                        size_t* length,
    249                        int* size,
    250                        ShDataType* type,
    251                        ShPrecisionType* precision,
    252                        int* staticUse,
    253                        char* name,
    254                        char* mappedName)
    255 {
    256     if (!handle || !size || !type || !precision || !staticUse || !name)
    257         return;
    258     ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
    259            (varType == SH_ACTIVE_UNIFORMS) ||
    260            (varType == SH_VARYINGS));
    261 
    262     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
    263     TCompiler* compiler = base->getAsCompiler();
    264     if (compiler == 0)
    265         return;
    266 
    267     const TVariableInfoList& varList =
    268         varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() :
    269             (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() :
    270                 compiler->getVaryings());
    271     if (index < 0 || index >= static_cast<int>(varList.size()))
    272         return;
    273 
    274     const TVariableInfo& varInfo = varList[index];
    275     if (length) *length = varInfo.name.size();
    276     *size = varInfo.size;
    277     *type = varInfo.type;
    278     switch (varInfo.precision) {
    279     case EbpLow:
    280         *precision = SH_PRECISION_LOWP;
    281         break;
    282     case EbpMedium:
    283         *precision = SH_PRECISION_MEDIUMP;
    284         break;
    285     case EbpHigh:
    286         *precision = SH_PRECISION_HIGHP;
    287         break;
    288     default:
    289         // Some types does not support precision, for example, boolean.
    290         *precision = SH_PRECISION_UNDEFINED;
    291         break;
    292     }
    293     *staticUse = varInfo.staticUse ? 1 : 0;
    294 
    295     // This size must match that queried by
    296     // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
    297     // in ShGetInfo, below.
    298     size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN;
    299     ASSERT(checkVariableMaxLengths(handle, variableLength));
    300     strncpy(name, varInfo.name.c_str(), variableLength);
    301     name[variableLength - 1] = 0;
    302     if (mappedName) {
    303         // This size must match that queried by
    304         // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
    305         size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
    306         ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
    307         strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
    308         mappedName[maxMappedNameLength - 1] = 0;
    309     }
    310 }
    311 
    312 void ShGetNameHashingEntry(const ShHandle handle,
    313                            int index,
    314                            char* name,
    315                            char* hashedName)
    316 {
    317     if (!handle || !name || !hashedName || index < 0)
    318         return;
    319 
    320     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
    321     TCompiler* compiler = base->getAsCompiler();
    322     if (!compiler) return;
    323 
    324     const NameMap& nameMap = compiler->getNameMap();
    325     if (index >= static_cast<int>(nameMap.size()))
    326         return;
    327 
    328     NameMap::const_iterator it = nameMap.begin();
    329     for (int i = 0; i < index; ++i)
    330         ++it;
    331 
    332     size_t len = it->first.length() + 1;
    333     size_t max_len = 0;
    334     ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
    335     if (len > max_len) {
    336         ASSERT(false);
    337         len = max_len;
    338     }
    339     strncpy(name, it->first.c_str(), len);
    340     // To be on the safe side in case the source is longer than expected.
    341     name[len - 1] = '\0';
    342 
    343     len = it->second.length() + 1;
    344     max_len = 0;
    345     ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
    346     if (len > max_len) {
    347         ASSERT(false);
    348         len = max_len;
    349     }
    350     strncpy(hashedName, it->second.c_str(), len);
    351     // To be on the safe side in case the source is longer than expected.
    352     hashedName[len - 1] = '\0';
    353 }
    354 
    355 void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
    356 {
    357     if (!handle || !params)
    358         return;
    359 
    360     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
    361     TranslatorHLSL* translator = base->getAsTranslatorHLSL();
    362     if (!translator) return;
    363 
    364     switch(pname)
    365     {
    366     case SH_ACTIVE_UNIFORMS_ARRAY:
    367         *params = (void*)&translator->getUniforms();
    368         break;
    369     default: UNREACHABLE();
    370     }
    371 }
    372 
    373 int ShCheckVariablesWithinPackingLimits(
    374     int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
    375 {
    376     if (varInfoArraySize == 0)
    377         return 1;
    378     ASSERT(varInfoArray);
    379     TVariableInfoList variables;
    380     for (size_t ii = 0; ii < varInfoArraySize; ++ii)
    381     {
    382         TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size);
    383         variables.push_back(var);
    384     }
    385     VariablePacker packer;
    386     return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
    387 }
    388