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