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 #include "compiler/translator/VariableInfo.h"
      8 
      9 namespace {
     10 
     11 TString arrayBrackets(int index)
     12 {
     13     TStringStream stream;
     14     stream << "[" << index << "]";
     15     return stream.str();
     16 }
     17 
     18 // Returns the data type for an attribute, uniform, or varying.
     19 ShDataType getVariableDataType(const TType& type)
     20 {
     21     switch (type.getBasicType()) {
     22       case EbtFloat:
     23           if (type.isMatrix()) {
     24               switch (type.getCols())
     25               {
     26                 case 2:
     27                   switch (type.getRows())
     28                   {
     29                     case 2: return SH_FLOAT_MAT2;
     30                     case 3: return SH_FLOAT_MAT2x3;
     31                     case 4: return SH_FLOAT_MAT2x4;
     32                     default: UNREACHABLE();
     33                   }
     34                 case 3:
     35                   switch (type.getRows())
     36                   {
     37                     case 2: return SH_FLOAT_MAT3x2;
     38                     case 3: return SH_FLOAT_MAT3;
     39                     case 4: return SH_FLOAT_MAT3x4;
     40                     default: UNREACHABLE();
     41                   }
     42                 case 4:
     43                   switch (type.getRows())
     44                   {
     45                     case 2: return SH_FLOAT_MAT4x2;
     46                     case 3: return SH_FLOAT_MAT4x3;
     47                     case 4: return SH_FLOAT_MAT4;
     48                     default: UNREACHABLE();
     49                   }
     50               }
     51           } else if (type.isVector()) {
     52               switch (type.getNominalSize()) {
     53                 case 2: return SH_FLOAT_VEC2;
     54                 case 3: return SH_FLOAT_VEC3;
     55                 case 4: return SH_FLOAT_VEC4;
     56                 default: UNREACHABLE();
     57               }
     58           } else {
     59               return SH_FLOAT;
     60           }
     61       case EbtInt:
     62           if (type.isMatrix()) {
     63               UNREACHABLE();
     64           } else if (type.isVector()) {
     65               switch (type.getNominalSize()) {
     66                 case 2: return SH_INT_VEC2;
     67                 case 3: return SH_INT_VEC3;
     68                 case 4: return SH_INT_VEC4;
     69                 default: UNREACHABLE();
     70               }
     71           } else {
     72               return SH_INT;
     73           }
     74       case EbtUInt:
     75           if (type.isMatrix()) {
     76               UNREACHABLE();
     77           } else if (type.isVector()) {
     78               switch (type.getNominalSize()) {
     79                 case 2: return SH_UNSIGNED_INT_VEC2;
     80                 case 3: return SH_UNSIGNED_INT_VEC3;
     81                 case 4: return SH_UNSIGNED_INT_VEC4;
     82                 default: UNREACHABLE();
     83               }
     84           } else {
     85               return SH_UNSIGNED_INT;
     86           }
     87       case EbtBool:
     88           if (type.isMatrix()) {
     89               UNREACHABLE();
     90           } else if (type.isVector()) {
     91               switch (type.getNominalSize()) {
     92                 case 2: return SH_BOOL_VEC2;
     93                 case 3: return SH_BOOL_VEC3;
     94                 case 4: return SH_BOOL_VEC4;
     95                 default: UNREACHABLE();
     96               }
     97           } else {
     98               return SH_BOOL;
     99           }
    100       case EbtSampler2D: return SH_SAMPLER_2D;
    101       case EbtSampler3D: return SH_SAMPLER_3D;
    102       case EbtSamplerCube: return SH_SAMPLER_CUBE;
    103       case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
    104       case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
    105       case EbtSampler2DArray: return SH_SAMPLER_2D_ARRAY;
    106       case EbtISampler2D: return SH_INT_SAMPLER_2D;
    107       case EbtISampler3D: return SH_INT_SAMPLER_3D;
    108       case EbtISamplerCube: return SH_INT_SAMPLER_CUBE;
    109       case EbtISampler2DArray: return SH_INT_SAMPLER_2D_ARRAY;
    110       case EbtUSampler2D: return SH_UNSIGNED_INT_SAMPLER_2D;
    111       case EbtUSampler3D: return SH_UNSIGNED_INT_SAMPLER_3D;
    112       case EbtUSamplerCube: return SH_UNSIGNED_INT_SAMPLER_CUBE;
    113       case EbtUSampler2DArray: return SH_UNSIGNED_INT_SAMPLER_2D_ARRAY;
    114       case EbtSampler2DShadow: return SH_SAMPLER_2D_SHADOW;
    115       case EbtSamplerCubeShadow: return SH_SAMPLER_CUBE_SHADOW;
    116       case EbtSampler2DArrayShadow: return SH_SAMPLER_2D_ARRAY_SHADOW;
    117       default: UNREACHABLE();
    118     }
    119     return SH_NONE;
    120 }
    121 
    122 void getBuiltInVariableInfo(const TType& type,
    123                             const TString& name,
    124                             const TString& mappedName,
    125                             TVariableInfoList& infoList);
    126 void getUserDefinedVariableInfo(const TType& type,
    127                                 const TString& name,
    128                                 const TString& mappedName,
    129                                 TVariableInfoList& infoList,
    130                                 ShHashFunction64 hashFunction);
    131 
    132 // Returns info for an attribute, uniform, or varying.
    133 void getVariableInfo(const TType& type,
    134                      const TString& name,
    135                      const TString& mappedName,
    136                      TVariableInfoList& infoList,
    137                      ShHashFunction64 hashFunction)
    138 {
    139     if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
    140         if (type.isArray()) {
    141             for (int i = 0; i < type.getArraySize(); ++i) {
    142                 TString lname = name + arrayBrackets(i);
    143                 TString lmappedName = mappedName + arrayBrackets(i);
    144                 getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
    145             }
    146         } else {
    147             getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
    148         }
    149     } else {
    150         getBuiltInVariableInfo(type, name, mappedName, infoList);
    151     }
    152 }
    153 
    154 void getBuiltInVariableInfo(const TType& type,
    155                             const TString& name,
    156                             const TString& mappedName,
    157                             TVariableInfoList& infoList)
    158 {
    159     ASSERT(type.getBasicType() != EbtStruct);
    160 
    161     TVariableInfo varInfo;
    162     if (type.isArray()) {
    163         varInfo.name = (name + "[0]").c_str();
    164         varInfo.mappedName = (mappedName + "[0]").c_str();
    165         varInfo.size = type.getArraySize();
    166         varInfo.isArray = true;
    167     } else {
    168         varInfo.name = name.c_str();
    169         varInfo.mappedName = mappedName.c_str();
    170         varInfo.size = 1;
    171         varInfo.isArray = false;
    172     }
    173     varInfo.precision = type.getPrecision();
    174     varInfo.type = getVariableDataType(type);
    175     infoList.push_back(varInfo);
    176 }
    177 
    178 void getUserDefinedVariableInfo(const TType& type,
    179                                 const TString& name,
    180                                 const TString& mappedName,
    181                                 TVariableInfoList& infoList,
    182                                 ShHashFunction64 hashFunction)
    183 {
    184     ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock());
    185 
    186     const TFieldList& fields = type.isInterfaceBlock() ?
    187         type.getInterfaceBlock()->fields() :
    188         type.getStruct()->fields();
    189     for (size_t i = 0; i < fields.size(); ++i) {
    190         const TType& fieldType = *(fields[i]->type());
    191         const TString& fieldName = fields[i]->name();
    192         getVariableInfo(fieldType,
    193                         name + "." + fieldName,
    194                         mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
    195                         infoList,
    196                         hashFunction);
    197     }
    198 }
    199 
    200 TVariableInfo* findVariable(const TType& type,
    201                             const TString& name,
    202                             TVariableInfoList& infoList)
    203 {
    204     // TODO(zmo): optimize this function.
    205     TString myName = name;
    206     if (type.isArray())
    207         myName += "[0]";
    208     for (size_t ii = 0; ii < infoList.size(); ++ii)
    209     {
    210         if (infoList[ii].name.c_str() == myName)
    211             return &(infoList[ii]);
    212     }
    213     return NULL;
    214 }
    215 
    216 }  // namespace anonymous
    217 
    218 TVariableInfo::TVariableInfo()
    219     : type(SH_NONE),
    220       size(0),
    221       isArray(false),
    222       precision(EbpUndefined),
    223       staticUse(false)
    224 {
    225 }
    226 
    227 TVariableInfo::TVariableInfo(ShDataType type, int size)
    228     : type(type),
    229       size(size),
    230       isArray(false),
    231       precision(EbpUndefined),
    232       staticUse(false)
    233 {
    234 }
    235 
    236 CollectVariables::CollectVariables(TVariableInfoList& attribs,
    237                                    TVariableInfoList& uniforms,
    238                                    TVariableInfoList& varyings,
    239                                    ShHashFunction64 hashFunction)
    240     : mAttribs(attribs),
    241       mUniforms(uniforms),
    242       mVaryings(varyings),
    243       mPointCoordAdded(false),
    244       mFrontFacingAdded(false),
    245       mFragCoordAdded(false),
    246       mHashFunction(hashFunction)
    247 {
    248 }
    249 
    250 // We want to check whether a uniform/varying is statically used
    251 // because we only count the used ones in packing computing.
    252 // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
    253 // toward varying counting if they are statically used in a fragment
    254 // shader.
    255 void CollectVariables::visitSymbol(TIntermSymbol* symbol)
    256 {
    257     ASSERT(symbol != NULL);
    258     TVariableInfo* var = NULL;
    259     switch (symbol->getQualifier())
    260     {
    261     case EvqVaryingOut:
    262     case EvqInvariantVaryingOut:
    263     case EvqVaryingIn:
    264     case EvqInvariantVaryingIn:
    265         var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
    266         break;
    267     case EvqUniform:
    268         var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
    269         break;
    270     case EvqFragCoord:
    271         if (!mFragCoordAdded) {
    272             TVariableInfo info;
    273             info.name = "gl_FragCoord";
    274             info.mappedName = "gl_FragCoord";
    275             info.type = SH_FLOAT_VEC4;
    276             info.size = 1;
    277             info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
    278             info.staticUse = true;
    279 	    mVaryings.push_back(info);
    280             mFragCoordAdded = true;
    281         }
    282         return;
    283     case EvqFrontFacing:
    284         if (!mFrontFacingAdded) {
    285             TVariableInfo info;
    286             info.name = "gl_FrontFacing";
    287             info.mappedName = "gl_FrontFacing";
    288             info.type = SH_BOOL;
    289             info.size = 1;
    290             info.precision = EbpUndefined;
    291             info.staticUse = true;
    292 	    mVaryings.push_back(info);
    293             mFrontFacingAdded = true;
    294         }
    295         return;
    296     case EvqPointCoord:
    297         if (!mPointCoordAdded) {
    298             TVariableInfo info;
    299             info.name = "gl_PointCoord";
    300             info.mappedName = "gl_PointCoord";
    301             info.type = SH_FLOAT_VEC2;
    302             info.size = 1;
    303             info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
    304             info.staticUse = true;
    305 	    mVaryings.push_back(info);
    306             mPointCoordAdded = true;
    307         }
    308         return;
    309     default:
    310         break;
    311     }
    312     if (var)
    313         var->staticUse = true;
    314 }
    315 
    316 bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
    317 {
    318     bool visitChildren = true;
    319 
    320     switch (node->getOp())
    321     {
    322     case EOpDeclaration: {
    323         const TIntermSequence& sequence = node->getSequence();
    324         TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
    325         if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform ||
    326             qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
    327             qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
    328         {
    329             TVariableInfoList *infoList = NULL;
    330 
    331             switch (qualifier)
    332             {
    333               case EvqAttribute:
    334               case EvqVertexIn:
    335                 infoList = &mAttribs;
    336                 break;
    337               case EvqUniform:
    338                 infoList = &mUniforms;
    339                 break;
    340               default:
    341                 infoList = &mVaryings;
    342                 break;
    343             }
    344 
    345             for (TIntermSequence::const_iterator i = sequence.begin();
    346                  i != sequence.end(); ++i)
    347             {
    348                 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
    349                 // The only case in which the sequence will not contain a
    350                 // TIntermSymbol node is initialization. It will contain a
    351                 // TInterBinary node in that case. Since attributes, uniforms,
    352                 // and varyings cannot be initialized in a shader, we must have
    353                 // only TIntermSymbol nodes in the sequence.
    354                 ASSERT(variable != NULL);
    355                 TString processedSymbol;
    356                 if (mHashFunction == NULL)
    357                     processedSymbol = variable->getSymbol();
    358                 else
    359                     processedSymbol = TIntermTraverser::hash(variable->getSymbol(), mHashFunction);
    360                 getVariableInfo(variable->getType(),
    361                                 variable->getSymbol(),
    362                                 processedSymbol,
    363                                 *infoList,
    364                                 mHashFunction);
    365                 visitChildren = false;
    366             }
    367         }
    368         break;
    369     }
    370     default: break;
    371     }
    372 
    373     return visitChildren;
    374 }
    375