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