Line data Source code
1 : //
2 : // Copyright (c) 2014 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 : // ShaderVars.cpp:
7 : // Methods for GL variable types (varyings, uniforms, etc)
8 : //
9 :
10 : #include <GLSLANG/ShaderLang.h>
11 :
12 : #include "common/debug.h"
13 :
14 : namespace sh
15 : {
16 :
17 : namespace
18 : {
19 :
20 0 : InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation)
21 : {
22 0 : return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation);
23 : }
24 :
25 : }
26 : // The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion
27 : // on Khronos.org, clarifies that a smooth/flat mismatch produces a link error,
28 : // but auxiliary qualifier mismatch (centroid) does not.
29 0 : bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
30 : {
31 0 : return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b));
32 : }
33 :
34 0 : ShaderVariable::ShaderVariable()
35 : : type(0),
36 : precision(0),
37 : arraySize(0),
38 0 : staticUse(false)
39 0 : {}
40 :
41 0 : ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
42 : : type(typeIn),
43 : precision(0),
44 : arraySize(arraySizeIn),
45 0 : staticUse(false)
46 0 : {}
47 :
48 0 : ShaderVariable::~ShaderVariable()
49 0 : {}
50 :
51 0 : ShaderVariable::ShaderVariable(const ShaderVariable &other)
52 0 : : type(other.type),
53 0 : precision(other.precision),
54 : name(other.name),
55 : mappedName(other.mappedName),
56 0 : arraySize(other.arraySize),
57 0 : staticUse(other.staticUse),
58 : fields(other.fields),
59 0 : structName(other.structName)
60 0 : {}
61 :
62 0 : ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
63 : {
64 0 : type = other.type;
65 0 : precision = other.precision;
66 0 : name = other.name;
67 0 : mappedName = other.mappedName;
68 0 : arraySize = other.arraySize;
69 0 : staticUse = other.staticUse;
70 0 : fields = other.fields;
71 0 : structName = other.structName;
72 0 : return *this;
73 : }
74 :
75 0 : bool ShaderVariable::operator==(const ShaderVariable &other) const
76 : {
77 0 : if (type != other.type ||
78 0 : precision != other.precision ||
79 0 : name != other.name ||
80 0 : mappedName != other.mappedName ||
81 0 : arraySize != other.arraySize ||
82 0 : staticUse != other.staticUse ||
83 0 : fields.size() != other.fields.size() ||
84 0 : structName != other.structName)
85 : {
86 0 : return false;
87 : }
88 0 : for (size_t ii = 0; ii < fields.size(); ++ii)
89 : {
90 0 : if (fields[ii] != other.fields[ii])
91 0 : return false;
92 : }
93 0 : return true;
94 : }
95 :
96 0 : bool ShaderVariable::findInfoByMappedName(
97 : const std::string &mappedFullName,
98 : const ShaderVariable **leafVar, std::string *originalFullName) const
99 : {
100 0 : ASSERT(leafVar && originalFullName);
101 : // There are three cases:
102 : // 1) the top variable is of struct type;
103 : // 2) the top variable is an array;
104 : // 3) otherwise.
105 0 : size_t pos = mappedFullName.find_first_of(".[");
106 :
107 0 : if (pos == std::string::npos)
108 : {
109 : // Case 3.
110 0 : if (mappedFullName != this->mappedName)
111 0 : return false;
112 0 : *originalFullName = this->name;
113 0 : *leafVar = this;
114 0 : return true;
115 : }
116 : else
117 : {
118 0 : std::string topName = mappedFullName.substr(0, pos);
119 0 : if (topName != this->mappedName)
120 0 : return false;
121 0 : std::string originalName = this->name;
122 0 : std::string remaining;
123 0 : if (mappedFullName[pos] == '[')
124 : {
125 : // Case 2.
126 0 : size_t closePos = mappedFullName.find_first_of(']');
127 0 : if (closePos < pos || closePos == std::string::npos)
128 0 : return false;
129 : // Append '[index]'.
130 0 : originalName += mappedFullName.substr(pos, closePos - pos + 1);
131 0 : if (closePos + 1 == mappedFullName.size())
132 : {
133 0 : *originalFullName = originalName;
134 0 : *leafVar = this;
135 0 : return true;
136 : }
137 : else
138 : {
139 : // In the form of 'a[0].b', so after ']', '.' is expected.
140 0 : if (mappedFullName[closePos + 1] != '.')
141 0 : return false;
142 0 : remaining = mappedFullName.substr(closePos + 2); // Skip "]."
143 : }
144 : }
145 : else
146 : {
147 : // Case 1.
148 0 : remaining = mappedFullName.substr(pos + 1); // Skip "."
149 : }
150 0 : for (size_t ii = 0; ii < this->fields.size(); ++ii)
151 : {
152 0 : const ShaderVariable *fieldVar = NULL;
153 0 : std::string originalFieldName;
154 0 : bool found = fields[ii].findInfoByMappedName(
155 0 : remaining, &fieldVar, &originalFieldName);
156 0 : if (found)
157 : {
158 0 : *originalFullName = originalName + "." + originalFieldName;
159 0 : *leafVar = fieldVar;
160 0 : return true;
161 : }
162 : }
163 0 : return false;
164 : }
165 : }
166 :
167 0 : bool ShaderVariable::isSameVariableAtLinkTime(
168 : const ShaderVariable &other, bool matchPrecision) const
169 : {
170 0 : if (type != other.type)
171 0 : return false;
172 0 : if (matchPrecision && precision != other.precision)
173 0 : return false;
174 0 : if (name != other.name)
175 0 : return false;
176 0 : ASSERT(mappedName == other.mappedName);
177 0 : if (arraySize != other.arraySize)
178 0 : return false;
179 0 : if (fields.size() != other.fields.size())
180 0 : return false;
181 0 : for (size_t ii = 0; ii < fields.size(); ++ii)
182 : {
183 0 : if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii],
184 : matchPrecision))
185 : {
186 0 : return false;
187 : }
188 : }
189 0 : if (structName != other.structName)
190 0 : return false;
191 0 : return true;
192 : }
193 :
194 0 : Uniform::Uniform()
195 0 : {}
196 :
197 0 : Uniform::~Uniform()
198 0 : {}
199 :
200 0 : Uniform::Uniform(const Uniform &other)
201 0 : : ShaderVariable(other)
202 0 : {}
203 :
204 0 : Uniform &Uniform::operator=(const Uniform &other)
205 : {
206 0 : ShaderVariable::operator=(other);
207 0 : return *this;
208 : }
209 :
210 0 : bool Uniform::operator==(const Uniform &other) const
211 : {
212 0 : return ShaderVariable::operator==(other);
213 : }
214 :
215 0 : bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
216 : {
217 0 : return ShaderVariable::isSameVariableAtLinkTime(other, true);
218 : }
219 :
220 0 : InterfaceVariable::InterfaceVariable() : location(-1)
221 0 : {}
222 :
223 0 : InterfaceVariable::~InterfaceVariable()
224 0 : {}
225 :
226 0 : InterfaceVariable::InterfaceVariable(const InterfaceVariable &other)
227 0 : : ShaderVariable(other), location(other.location)
228 0 : {}
229 :
230 0 : InterfaceVariable &InterfaceVariable::operator=(const InterfaceVariable &other)
231 : {
232 0 : ShaderVariable::operator=(other);
233 0 : location = other.location;
234 0 : return *this;
235 : }
236 :
237 0 : bool InterfaceVariable::operator==(const InterfaceVariable &other) const
238 : {
239 0 : return (ShaderVariable::operator==(other) &&
240 0 : location == other.location);
241 : }
242 :
243 0 : Attribute::Attribute()
244 : {
245 0 : }
246 :
247 0 : Attribute::~Attribute()
248 : {
249 0 : }
250 :
251 0 : Attribute::Attribute(const Attribute &other) : InterfaceVariable(other)
252 : {
253 0 : }
254 :
255 0 : Attribute &Attribute::operator=(const Attribute &other)
256 : {
257 0 : InterfaceVariable::operator=(other);
258 0 : return *this;
259 : }
260 :
261 0 : bool Attribute::operator==(const Attribute &other) const
262 : {
263 0 : return InterfaceVariable::operator==(other);
264 : }
265 :
266 0 : OutputVariable::OutputVariable()
267 : {
268 0 : }
269 :
270 0 : OutputVariable::~OutputVariable()
271 : {
272 0 : }
273 :
274 0 : OutputVariable::OutputVariable(const OutputVariable &other) : InterfaceVariable(other)
275 : {
276 0 : }
277 :
278 0 : OutputVariable &OutputVariable::operator=(const OutputVariable &other)
279 : {
280 0 : InterfaceVariable::operator=(other);
281 0 : return *this;
282 : }
283 :
284 0 : bool OutputVariable::operator==(const OutputVariable &other) const
285 : {
286 0 : return InterfaceVariable::operator==(other);
287 : }
288 :
289 0 : InterfaceBlockField::InterfaceBlockField()
290 0 : : isRowMajorLayout(false)
291 0 : {}
292 :
293 0 : InterfaceBlockField::~InterfaceBlockField()
294 0 : {}
295 :
296 0 : InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other)
297 : : ShaderVariable(other),
298 0 : isRowMajorLayout(other.isRowMajorLayout)
299 0 : {}
300 :
301 0 : InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other)
302 : {
303 0 : ShaderVariable::operator=(other);
304 0 : isRowMajorLayout = other.isRowMajorLayout;
305 0 : return *this;
306 : }
307 :
308 0 : bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
309 : {
310 0 : return (ShaderVariable::operator==(other) &&
311 0 : isRowMajorLayout == other.isRowMajorLayout);
312 : }
313 :
314 0 : bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
315 : const InterfaceBlockField &other) const
316 : {
317 0 : return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
318 0 : isRowMajorLayout == other.isRowMajorLayout);
319 : }
320 :
321 0 : Varying::Varying()
322 : : interpolation(INTERPOLATION_SMOOTH),
323 0 : isInvariant(false)
324 0 : {}
325 :
326 0 : Varying::~Varying()
327 0 : {}
328 :
329 0 : Varying::Varying(const Varying &other)
330 : : ShaderVariable(other),
331 0 : interpolation(other.interpolation),
332 0 : isInvariant(other.isInvariant)
333 0 : {}
334 :
335 0 : Varying &Varying::operator=(const Varying &other)
336 : {
337 0 : ShaderVariable::operator=(other);
338 0 : interpolation = other.interpolation;
339 0 : isInvariant = other.isInvariant;
340 0 : return *this;
341 : }
342 :
343 0 : bool Varying::operator==(const Varying &other) const
344 : {
345 0 : return (ShaderVariable::operator==(other) &&
346 0 : interpolation == other.interpolation &&
347 0 : isInvariant == other.isInvariant);
348 : }
349 :
350 0 : bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
351 : {
352 0 : return isSameVaryingAtLinkTime(other, 100);
353 : }
354 :
355 0 : bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const
356 : {
357 0 : return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
358 0 : InterpolationTypesMatch(interpolation, other.interpolation) &&
359 0 : (shaderVersion >= 300 || isInvariant == other.isInvariant));
360 : }
361 :
362 0 : InterfaceBlock::InterfaceBlock()
363 : : arraySize(0),
364 : layout(BLOCKLAYOUT_PACKED),
365 : isRowMajorLayout(false),
366 0 : staticUse(false)
367 0 : {}
368 :
369 0 : InterfaceBlock::~InterfaceBlock()
370 0 : {}
371 :
372 0 : InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
373 : : name(other.name),
374 : mappedName(other.mappedName),
375 : instanceName(other.instanceName),
376 0 : arraySize(other.arraySize),
377 0 : layout(other.layout),
378 0 : isRowMajorLayout(other.isRowMajorLayout),
379 0 : staticUse(other.staticUse),
380 0 : fields(other.fields)
381 0 : {}
382 :
383 0 : InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
384 : {
385 0 : name = other.name;
386 0 : mappedName = other.mappedName;
387 0 : instanceName = other.instanceName;
388 0 : arraySize = other.arraySize;
389 0 : layout = other.layout;
390 0 : isRowMajorLayout = other.isRowMajorLayout;
391 0 : staticUse = other.staticUse;
392 0 : fields = other.fields;
393 0 : return *this;
394 : }
395 :
396 0 : std::string InterfaceBlock::fieldPrefix() const
397 : {
398 0 : return instanceName.empty() ? "" : name;
399 : }
400 :
401 0 : bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
402 : {
403 0 : if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize ||
404 0 : layout != other.layout || isRowMajorLayout != other.isRowMajorLayout ||
405 0 : fields.size() != other.fields.size())
406 : {
407 0 : return false;
408 : }
409 :
410 0 : for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
411 : {
412 0 : if (!fields[fieldIndex].isSameInterfaceBlockFieldAtLinkTime(other.fields[fieldIndex]))
413 : {
414 0 : return false;
415 : }
416 : }
417 :
418 0 : return true;
419 : }
420 :
421 0 : void WorkGroupSize::fill(int fillValue)
422 : {
423 0 : localSizeQualifiers[0] = fillValue;
424 0 : localSizeQualifiers[1] = fillValue;
425 0 : localSizeQualifiers[2] = fillValue;
426 0 : }
427 :
428 0 : void WorkGroupSize::setLocalSize(int localSizeX, int localSizeY, int localSizeZ)
429 : {
430 0 : localSizeQualifiers[0] = localSizeX;
431 0 : localSizeQualifiers[1] = localSizeY;
432 0 : localSizeQualifiers[2] = localSizeZ;
433 0 : }
434 :
435 : // check that if one of them is less than 1, then all of them are.
436 : // Or if one is positive, then all of them are positive.
437 0 : bool WorkGroupSize::isLocalSizeValid() const
438 : {
439 : return (
440 0 : (localSizeQualifiers[0] < 1 && localSizeQualifiers[1] < 1 && localSizeQualifiers[2] < 1) ||
441 0 : (localSizeQualifiers[0] > 0 && localSizeQualifiers[1] > 0 && localSizeQualifiers[2] > 0));
442 : }
443 :
444 0 : bool WorkGroupSize::isAnyValueSet() const
445 : {
446 0 : return localSizeQualifiers[0] > 0 || localSizeQualifiers[1] > 0 || localSizeQualifiers[2] > 0;
447 : }
448 :
449 0 : bool WorkGroupSize::isDeclared() const
450 : {
451 0 : bool localSizeDeclared = localSizeQualifiers[0] > 0;
452 0 : ASSERT(isLocalSizeValid());
453 0 : return localSizeDeclared;
454 : }
455 :
456 0 : bool WorkGroupSize::isWorkGroupSizeMatching(const WorkGroupSize &right) const
457 : {
458 0 : for (size_t i = 0u; i < size(); ++i)
459 : {
460 0 : bool result = (localSizeQualifiers[i] == right.localSizeQualifiers[i] ||
461 0 : (localSizeQualifiers[i] == 1 && right.localSizeQualifiers[i] == -1) ||
462 0 : (localSizeQualifiers[i] == -1 && right.localSizeQualifiers[i] == 1));
463 0 : if (!result)
464 : {
465 0 : return false;
466 : }
467 : }
468 0 : return true;
469 : }
470 :
471 0 : int &WorkGroupSize::operator[](size_t index)
472 : {
473 0 : ASSERT(index < size());
474 0 : return localSizeQualifiers[index];
475 : }
476 :
477 0 : int WorkGroupSize::operator[](size_t index) const
478 : {
479 0 : ASSERT(index < size());
480 0 : return localSizeQualifiers[index];
481 : }
482 :
483 0 : size_t WorkGroupSize::size() const
484 : {
485 0 : return 3u;
486 : }
487 :
488 : } // namespace sh
|