|
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 |
|
9 static 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. |
|
17 static 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 |
|
73 static void getBuiltInVariableInfo(const TType& type, |
|
74 const TString& name, |
|
75 const TString& mappedName, |
|
76 TVariableInfoList& infoList); |
|
77 static 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. |
|
84 static 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 |
|
105 void 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 |
|
126 void 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 |
|
146 TVariableInfo::TVariableInfo() |
|
147 { |
|
148 } |
|
149 |
|
150 TVariableInfo::TVariableInfo(ShDataType type, int size) |
|
151 : type(type), |
|
152 size(size) |
|
153 { |
|
154 } |
|
155 |
|
156 CollectAttribsUniforms::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. |
|
166 void CollectAttribsUniforms::visitSymbol(TIntermSymbol*) |
|
167 { |
|
168 } |
|
169 |
|
170 void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*) |
|
171 { |
|
172 } |
|
173 |
|
174 bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*) |
|
175 { |
|
176 return false; |
|
177 } |
|
178 |
|
179 bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*) |
|
180 { |
|
181 return false; |
|
182 } |
|
183 |
|
184 bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*) |
|
185 { |
|
186 return false; |
|
187 } |
|
188 |
|
189 bool 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 |
|
236 bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*) |
|
237 { |
|
238 return false; |
|
239 } |
|
240 |
|
241 bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*) |
|
242 { |
|
243 return false; |
|
244 } |
|
245 |