1//
2// Copyright (c) 2002-2010 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/VariableInfo.h"
8
9static TString arrayBrackets(int index)
10{
11    TStringStream stream;
12    stream << "[" << index << "]";
13    return stream.str();
14}
15
16// Returns the data type for an attribute or uniform.
17static ShDataType getVariableDataType(const TType& type)
18{
19    switch (type.getBasicType()) {
20      case EbtFloat:
21          if (type.isMatrix()) {
22              switch (type.getNominalSize()) {
23                case 2: return SH_FLOAT_MAT2;
24                case 3: return SH_FLOAT_MAT3;
25                case 4: return SH_FLOAT_MAT4;
26                default: UNREACHABLE();
27              }
28          } else if (type.isVector()) {
29              switch (type.getNominalSize()) {
30                case 2: return SH_FLOAT_VEC2;
31                case 3: return SH_FLOAT_VEC3;
32                case 4: return SH_FLOAT_VEC4;
33                default: UNREACHABLE();
34              }
35          } else {
36              return SH_FLOAT;
37          }
38      case EbtInt:
39          if (type.isMatrix()) {
40              UNREACHABLE();
41          } else if (type.isVector()) {
42              switch (type.getNominalSize()) {
43                case 2: return SH_INT_VEC2;
44                case 3: return SH_INT_VEC3;
45                case 4: return SH_INT_VEC4;
46                default: UNREACHABLE();
47              }
48          } else {
49              return SH_INT;
50          }
51      case EbtBool:
52          if (type.isMatrix()) {
53              UNREACHABLE();
54          } else if (type.isVector()) {
55              switch (type.getNominalSize()) {
56                case 2: return SH_BOOL_VEC2;
57                case 3: return SH_BOOL_VEC3;
58                case 4: return SH_BOOL_VEC4;
59                default: UNREACHABLE();
60              }
61          } else {
62              return SH_BOOL;
63          }
64      case EbtSampler2D: return SH_SAMPLER_2D;
65      case EbtSamplerCube: return SH_SAMPLER_CUBE;
66      case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
67      case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
68      default: UNREACHABLE();
69    }
70    return SH_NONE;
71}
72
73static void getBuiltInVariableInfo(const TType& type,
74                                   const TString& name,
75                                   const TString& mappedName,
76                                   TVariableInfoList& infoList);
77static void getUserDefinedVariableInfo(const TType& type,
78                                       const TString& name,
79                                       const TString& mappedName,
80                                       TVariableInfoList& infoList,
81                                       ShHashFunction64 hashFunction);
82
83// Returns info for an attribute or uniform.
84static void getVariableInfo(const TType& type,
85                            const TString& name,
86                            const TString& mappedName,
87                            TVariableInfoList& infoList,
88                            ShHashFunction64 hashFunction)
89{
90    if (type.getBasicType() == EbtStruct) {
91        if (type.isArray()) {
92            for (int i = 0; i < type.getArraySize(); ++i) {
93                TString lname = name + arrayBrackets(i);
94                TString lmappedName = mappedName + arrayBrackets(i);
95                getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
96            }
97        } else {
98            getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
99        }
100    } else {
101        getBuiltInVariableInfo(type, name, mappedName, infoList);
102    }
103}
104
105void getBuiltInVariableInfo(const TType& type,
106                            const TString& name,
107                            const TString& mappedName,
108                            TVariableInfoList& infoList)
109{
110    ASSERT(type.getBasicType() != EbtStruct);
111
112    TVariableInfo varInfo;
113    if (type.isArray()) {
114        varInfo.name = (name + "[0]").c_str();
115        varInfo.mappedName = (mappedName + "[0]").c_str();
116        varInfo.size = type.getArraySize();
117    } else {
118        varInfo.name = name.c_str();
119        varInfo.mappedName = mappedName.c_str();
120        varInfo.size = 1;
121    }
122    varInfo.type = getVariableDataType(type);
123    infoList.push_back(varInfo);
124}
125
126void getUserDefinedVariableInfo(const TType& type,
127                                const TString& name,
128                                const TString& mappedName,
129                                TVariableInfoList& infoList,
130                                ShHashFunction64 hashFunction)
131{
132    ASSERT(type.getBasicType() == EbtStruct);
133
134    const TFieldList& fields = type.getStruct()->fields();
135    for (size_t i = 0; i < fields.size(); ++i) {
136        const TType& fieldType = *(fields[i]->type());
137        const TString& fieldName = fields[i]->name();
138        getVariableInfo(fieldType,
139                        name + "." + fieldName,
140                        mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
141                        infoList,
142                        hashFunction);
143    }
144}
145
146TVariableInfo::TVariableInfo()
147{
148}
149
150TVariableInfo::TVariableInfo(ShDataType type, int size)
151    : type(type),
152      size(size)
153{
154}
155
156CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
157                                               TVariableInfoList& uniforms,
158                                               ShHashFunction64 hashFunction)
159    : mAttribs(attribs),
160      mUniforms(uniforms),
161      mHashFunction(hashFunction)
162{
163}
164
165// We are only interested in attribute and uniform variable declaration.
166void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
167{
168}
169
170void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
171{
172}
173
174bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
175{
176    return false;
177}
178
179bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
180{
181    return false;
182}
183
184bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
185{
186    return false;
187}
188
189bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
190{
191    bool visitChildren = false;
192
193    switch (node->getOp())
194    {
195    case EOpSequence:
196        // We need to visit sequence children to get to variable declarations.
197        visitChildren = true;
198        break;
199    case EOpDeclaration: {
200        const TIntermSequence& sequence = node->getSequence();
201        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
202        if (qualifier == EvqAttribute || qualifier == EvqUniform)
203        {
204            TVariableInfoList& infoList = qualifier == EvqAttribute ?
205                mAttribs : mUniforms;
206            for (TIntermSequence::const_iterator i = sequence.begin();
207                 i != sequence.end(); ++i)
208            {
209                const TIntermSymbol* variable = (*i)->getAsSymbolNode();
210                // The only case in which the sequence will not contain a
211                // TIntermSymbol node is initialization. It will contain a
212                // TInterBinary node in that case. Since attributes and unifroms
213                // cannot be initialized in a shader, we must have only
214                // TIntermSymbol nodes in the sequence.
215                ASSERT(variable != NULL);
216                TString processedSymbol;
217                if (mHashFunction == NULL)
218                    processedSymbol = variable->getSymbol();
219                else
220                    processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
221                getVariableInfo(variable->getType(),
222                                variable->getOriginalSymbol(),
223                                processedSymbol,
224                                infoList,
225                                mHashFunction);
226            }
227        }
228        break;
229    }
230    default: break;
231    }
232
233    return visitChildren;
234}
235
236bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
237{
238    return false;
239}
240
241bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
242{
243    return false;
244}
245
246