Edit

kc3-lang/angle/src/compiler/VariableInfo.cpp

Branch :

  • Show log

    Commit

  • Author : zmo@google.com
    Date : 2011-04-23 01:30:07
    Hash : fd747b86
    Message : Implement shader identifier name mapping. The name mapping happens when an identifier is longer than 32 characters. The name mapping is behind a flag, so it won't happen by default. Also, functions to query the mapped names are added. The purpose of this CL is for the drivers that can't handle long names. For example, linux NVIDIA driver can't handle 256 character name, whereas WebGL spec requires that. This CL also fixes the issue that some of the TIntermSymbols' ids are 0s. ANGLEBUG=144 TEST=test manually with shaders with long identifier names. Review URL: http://codereview.appspot.com/4428058 git-svn-id: https://angleproject.googlecode.com/svn/trunk@619 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/VariableInfo.cpp
  • //
    // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include "compiler/VariableInfo.h"
    
    static TString arrayBrackets(int index)
    {
        TStringStream stream;
        stream << "[" << index << "]";
        return stream.str();
    }
    
    // Returns the data type for an attribute or uniform.
    static ShDataType getVariableDataType(const TType& type)
    {
        switch (type.getBasicType()) {
          case EbtFloat:
              if (type.isMatrix()) {
                  switch (type.getNominalSize()) {
                    case 2: return SH_FLOAT_MAT2;
                    case 3: return SH_FLOAT_MAT3;
                    case 4: return SH_FLOAT_MAT4;
                    default: UNREACHABLE();
                  }
              } else if (type.isVector()) {
                  switch (type.getNominalSize()) {
                    case 2: return SH_FLOAT_VEC2;
                    case 3: return SH_FLOAT_VEC3;
                    case 4: return SH_FLOAT_VEC4;
                    default: UNREACHABLE();
                  }
              } else {
                  return SH_FLOAT;
              }
          case EbtInt:
              if (type.isMatrix()) {
                  UNREACHABLE();
              } else if (type.isVector()) {
                  switch (type.getNominalSize()) {
                    case 2: return SH_INT_VEC2;
                    case 3: return SH_INT_VEC3;
                    case 4: return SH_INT_VEC4;
                    default: UNREACHABLE();
                  }
              } else {
                  return SH_INT;
              }
          case EbtBool:
              if (type.isMatrix()) {
                  UNREACHABLE();
              } else if (type.isVector()) {
                  switch (type.getNominalSize()) {
                    case 2: return SH_BOOL_VEC2;
                    case 3: return SH_BOOL_VEC3;
                    case 4: return SH_BOOL_VEC4;
                    default: UNREACHABLE();
                  }
              } else {
                  return SH_BOOL;
              }
          case EbtSampler2D: return SH_SAMPLER_2D;
          case EbtSamplerCube: return SH_SAMPLER_CUBE;
          default: UNREACHABLE();
        }
        return SH_NONE;
    }
    
    static void getBuiltInVariableInfo(const TType& type,
                                       const TString& name,
                                       const TString& mappedName,
                                       TVariableInfoList& infoList);
    static void getUserDefinedVariableInfo(const TType& type,
                                           const TString& name,
                                           const TString& mappedName,
                                           TVariableInfoList& infoList);
    
    // Returns info for an attribute or uniform.
    static void getVariableInfo(const TType& type,
                                const TString& name,
                                const TString& mappedName,
                                TVariableInfoList& infoList)
    {
        if (type.getBasicType() == EbtStruct) {
            if (type.isArray()) {
                for (int i = 0; i < type.getArraySize(); ++i) {
                    TString lname = name + arrayBrackets(i);
                    TString lmappedName = mappedName + arrayBrackets(i);
                    getUserDefinedVariableInfo(type, lname, lmappedName, infoList);
                }
            } else {
                getUserDefinedVariableInfo(type, name, mappedName, infoList);
            }
        } else {
            getBuiltInVariableInfo(type, name, mappedName, infoList);
        }
    }
    
    void getBuiltInVariableInfo(const TType& type,
                                const TString& name,
                                const TString& mappedName,
                                TVariableInfoList& infoList)
    {
        ASSERT(type.getBasicType() != EbtStruct);
    
        TVariableInfo varInfo;
        if (type.isArray()) {
            varInfo.name = (name + "[0]").c_str();
            varInfo.mappedName = (mappedName + "[0]").c_str();
            varInfo.size = type.getArraySize();
        } else {
            varInfo.name = name.c_str();
            varInfo.mappedName = mappedName.c_str();
            varInfo.size = 1;
        }
        varInfo.type = getVariableDataType(type);
        infoList.push_back(varInfo);
    }
    
    void getUserDefinedVariableInfo(const TType& type,
                                    const TString& name,
                                    const TString& mappedName,
                                    TVariableInfoList& infoList)
    {
        ASSERT(type.getBasicType() == EbtStruct);
    
        const TTypeList* structure = type.getStruct();
        for (size_t i = 0; i < structure->size(); ++i) {
            const TType* fieldType = (*structure)[i].type;
            getVariableInfo(*fieldType,
                            name + "." + fieldType->getFieldName(),
                            mappedName + "." + fieldType->getFieldName(),
                            infoList);
        }
    }
    
    CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
                                                   TVariableInfoList& uniforms)
        : mAttribs(attribs),
          mUniforms(uniforms)
    {
    }
    
    // We are only interested in attribute and uniform variable declaration.
    void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
    {
    }
    
    void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
    {
    }
    
    bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
    {
        return false;
    }
    
    bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
    {
        return false;
    }
    
    bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
    {
        return false;
    }
    
    bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
    {
        bool visitChildren = false;
    
        switch (node->getOp())
        {
        case EOpSequence:
            // We need to visit sequence children to get to variable declarations.
            visitChildren = true;
            break;
        case EOpDeclaration: {
            const TIntermSequence& sequence = node->getSequence();
            TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
            if (qualifier == EvqAttribute || qualifier == EvqUniform)
            {
                TVariableInfoList& infoList = qualifier == EvqAttribute ?
                    mAttribs : mUniforms;
                for (TIntermSequence::const_iterator i = sequence.begin();
                     i != sequence.end(); ++i)
                {
                    const TIntermSymbol* variable = (*i)->getAsSymbolNode();
                    // The only case in which the sequence will not contain a
                    // TIntermSymbol node is initialization. It will contain a
                    // TInterBinary node in that case. Since attributes and unifroms
                    // cannot be initialized in a shader, we must have only
                    // TIntermSymbol nodes in the sequence.
                    ASSERT(variable != NULL);
                    getVariableInfo(variable->getType(),
                                    variable->getOriginalSymbol(),
                                    variable->getSymbol(),
                                    infoList);
                }
            }
            break;
        }
        default: break;
        }
    
        return visitChildren;
    }
    
    bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
    {
        return false;
    }
    
    bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
    {
        return false;
    }