blob: a6c885d9948d4a620c4b1256df6b430e028cfd3f [file] [log] [blame]
Jamie Madill6a729792014-07-18 10:33:14 -04001//
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//
Jamie Madilla2ad4e82014-07-17 14:16:32 -04006// ShaderVars.cpp:
Jamie Madill6a729792014-07-18 10:33:14 -04007// Methods for GL variable types (varyings, uniforms, etc)
8//
9
Jamie Madille294bb82014-07-17 14:16:26 -040010#include <GLSLANG/ShaderLang.h>
Jamie Madill6a729792014-07-18 10:33:14 -040011
Olli Etuahod57e0db2015-04-24 15:05:08 +030012#include "common/debug.h"
Zhenyao Moed136362014-10-03 13:23:01 -070013
Jamie Madill6a729792014-07-18 10:33:14 -040014namespace sh
15{
16
Jamie Madille9cc4692015-02-19 16:00:13 -050017namespace
18{
19
20InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation)
21{
22 return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation);
23}
Jamie Madille9cc4692015-02-19 16:00:13 -050024}
25// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion
26// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error,
27// but auxiliary qualifier mismatch (centroid) does not.
28bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
29{
30 return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b));
31}
32
Jamie Madilld7b1ab52016-12-12 14:42:19 -050033ShaderVariable::ShaderVariable() : type(0), precision(0), arraySize(0), staticUse(false)
34{
35}
Jamie Madill6a729792014-07-18 10:33:14 -040036
37ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
Jamie Madilld7b1ab52016-12-12 14:42:19 -050038 : type(typeIn), precision(0), arraySize(arraySizeIn), staticUse(false)
39{
40}
Jamie Madill6a729792014-07-18 10:33:14 -040041
42ShaderVariable::~ShaderVariable()
Jamie Madilld7b1ab52016-12-12 14:42:19 -050043{
44}
Jamie Madill6a729792014-07-18 10:33:14 -040045
46ShaderVariable::ShaderVariable(const ShaderVariable &other)
47 : type(other.type),
48 precision(other.precision),
49 name(other.name),
50 mappedName(other.mappedName),
51 arraySize(other.arraySize),
Jamie Madill42bcf322014-08-25 16:20:46 -040052 staticUse(other.staticUse),
53 fields(other.fields),
54 structName(other.structName)
Jamie Madilld7b1ab52016-12-12 14:42:19 -050055{
56}
Jamie Madill6a729792014-07-18 10:33:14 -040057
58ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
59{
Jamie Madilld7b1ab52016-12-12 14:42:19 -050060 type = other.type;
61 precision = other.precision;
62 name = other.name;
Jamie Madill6a729792014-07-18 10:33:14 -040063 mappedName = other.mappedName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -050064 arraySize = other.arraySize;
65 staticUse = other.staticUse;
66 fields = other.fields;
Jamie Madill42bcf322014-08-25 16:20:46 -040067 structName = other.structName;
Jamie Madill6a729792014-07-18 10:33:14 -040068 return *this;
69}
70
Zhenyao Moed136362014-10-03 13:23:01 -070071bool ShaderVariable::operator==(const ShaderVariable &other) const
72{
Jamie Madilld7b1ab52016-12-12 14:42:19 -050073 if (type != other.type || precision != other.precision || name != other.name ||
74 mappedName != other.mappedName || arraySize != other.arraySize ||
75 staticUse != other.staticUse || fields.size() != other.fields.size() ||
Zhenyao Moed136362014-10-03 13:23:01 -070076 structName != other.structName)
77 {
78 return false;
79 }
80 for (size_t ii = 0; ii < fields.size(); ++ii)
81 {
82 if (fields[ii] != other.fields[ii])
83 return false;
84 }
85 return true;
86}
87
Jamie Madilld7b1ab52016-12-12 14:42:19 -050088bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName,
89 const ShaderVariable **leafVar,
90 std::string *originalFullName) const
Zhenyao Moed136362014-10-03 13:23:01 -070091{
92 ASSERT(leafVar && originalFullName);
93 // There are three cases:
94 // 1) the top variable is of struct type;
95 // 2) the top variable is an array;
96 // 3) otherwise.
97 size_t pos = mappedFullName.find_first_of(".[");
Zhenyao Moed136362014-10-03 13:23:01 -070098
99 if (pos == std::string::npos)
100 {
101 // Case 3.
102 if (mappedFullName != this->mappedName)
103 return false;
104 *originalFullName = this->name;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500105 *leafVar = this;
Zhenyao Moed136362014-10-03 13:23:01 -0700106 return true;
107 }
108 else
109 {
110 std::string topName = mappedFullName.substr(0, pos);
111 if (topName != this->mappedName)
112 return false;
113 std::string originalName = this->name;
114 std::string remaining;
115 if (mappedFullName[pos] == '[')
116 {
117 // Case 2.
118 size_t closePos = mappedFullName.find_first_of(']');
119 if (closePos < pos || closePos == std::string::npos)
120 return false;
121 // Append '[index]'.
122 originalName += mappedFullName.substr(pos, closePos - pos + 1);
123 if (closePos + 1 == mappedFullName.size())
124 {
125 *originalFullName = originalName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500126 *leafVar = this;
Zhenyao Moed136362014-10-03 13:23:01 -0700127 return true;
128 }
129 else
130 {
131 // In the form of 'a[0].b', so after ']', '.' is expected.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500132 if (mappedFullName[closePos + 1] != '.')
Zhenyao Moed136362014-10-03 13:23:01 -0700133 return false;
134 remaining = mappedFullName.substr(closePos + 2); // Skip "]."
135 }
136 }
137 else
138 {
139 // Case 1.
140 remaining = mappedFullName.substr(pos + 1); // Skip "."
141 }
142 for (size_t ii = 0; ii < this->fields.size(); ++ii)
143 {
144 const ShaderVariable *fieldVar = NULL;
145 std::string originalFieldName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500146 bool found = fields[ii].findInfoByMappedName(remaining, &fieldVar, &originalFieldName);
Zhenyao Moed136362014-10-03 13:23:01 -0700147 if (found)
148 {
149 *originalFullName = originalName + "." + originalFieldName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500150 *leafVar = fieldVar;
Zhenyao Moed136362014-10-03 13:23:01 -0700151 return true;
152 }
153 }
154 return false;
155 }
156}
157
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500158bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
159 bool matchPrecision) const
Zhenyao Moed136362014-10-03 13:23:01 -0700160{
161 if (type != other.type)
162 return false;
163 if (matchPrecision && precision != other.precision)
164 return false;
165 if (name != other.name)
166 return false;
167 ASSERT(mappedName == other.mappedName);
168 if (arraySize != other.arraySize)
169 return false;
170 if (fields.size() != other.fields.size())
171 return false;
172 for (size_t ii = 0; ii < fields.size(); ++ii)
173 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500174 if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], matchPrecision))
Zhenyao Moed136362014-10-03 13:23:01 -0700175 {
176 return false;
177 }
178 }
179 if (structName != other.structName)
180 return false;
181 return true;
182}
183
Olli Etuaho547cbd42017-02-27 11:54:00 +0200184Uniform::Uniform() : binding(-1)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500185{
186}
Jamie Madill6a729792014-07-18 10:33:14 -0400187
188Uniform::~Uniform()
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500189{
190}
Jamie Madill6a729792014-07-18 10:33:14 -0400191
Olli Etuaho547cbd42017-02-27 11:54:00 +0200192Uniform::Uniform(const Uniform &other) : ShaderVariable(other), binding(other.binding)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500193{
194}
Jamie Madill6a729792014-07-18 10:33:14 -0400195
196Uniform &Uniform::operator=(const Uniform &other)
197{
198 ShaderVariable::operator=(other);
Olli Etuaho547cbd42017-02-27 11:54:00 +0200199 binding = other.binding;
Jamie Madill6a729792014-07-18 10:33:14 -0400200 return *this;
201}
202
Zhenyao Moed136362014-10-03 13:23:01 -0700203bool Uniform::operator==(const Uniform &other) const
204{
Olli Etuaho547cbd42017-02-27 11:54:00 +0200205 return ShaderVariable::operator==(other) && binding == other.binding;
Zhenyao Moed136362014-10-03 13:23:01 -0700206}
207
208bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
209{
Olli Etuaho547cbd42017-02-27 11:54:00 +0200210 if (binding != -1 && other.binding != -1 && binding != other.binding)
211 {
212 return false;
213 }
Zhenyao Moed136362014-10-03 13:23:01 -0700214 return ShaderVariable::isSameVariableAtLinkTime(other, true);
215}
216
Jamie Madilla0a9e122015-09-02 15:54:30 -0400217InterfaceVariable::InterfaceVariable() : location(-1)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500218{
219}
Jamie Madill6a729792014-07-18 10:33:14 -0400220
Jamie Madilla0a9e122015-09-02 15:54:30 -0400221InterfaceVariable::~InterfaceVariable()
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500222{
223}
Jamie Madill6a729792014-07-18 10:33:14 -0400224
Jamie Madilla0a9e122015-09-02 15:54:30 -0400225InterfaceVariable::InterfaceVariable(const InterfaceVariable &other)
226 : ShaderVariable(other), location(other.location)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500227{
228}
Jamie Madill6a729792014-07-18 10:33:14 -0400229
Jamie Madilla0a9e122015-09-02 15:54:30 -0400230InterfaceVariable &InterfaceVariable::operator=(const InterfaceVariable &other)
Jamie Madill6a729792014-07-18 10:33:14 -0400231{
232 ShaderVariable::operator=(other);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500233 location = other.location;
Jamie Madill6a729792014-07-18 10:33:14 -0400234 return *this;
235}
236
Jamie Madilla0a9e122015-09-02 15:54:30 -0400237bool InterfaceVariable::operator==(const InterfaceVariable &other) const
Zhenyao Moed136362014-10-03 13:23:01 -0700238{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500239 return (ShaderVariable::operator==(other) && location == other.location);
Zhenyao Moed136362014-10-03 13:23:01 -0700240}
241
Jamie Madilla0a9e122015-09-02 15:54:30 -0400242Attribute::Attribute()
243{
244}
245
246Attribute::~Attribute()
247{
248}
249
250Attribute::Attribute(const Attribute &other) : InterfaceVariable(other)
251{
252}
253
254Attribute &Attribute::operator=(const Attribute &other)
255{
256 InterfaceVariable::operator=(other);
257 return *this;
258}
259
260bool Attribute::operator==(const Attribute &other) const
261{
262 return InterfaceVariable::operator==(other);
263}
264
265OutputVariable::OutputVariable()
266{
267}
268
269OutputVariable::~OutputVariable()
270{
271}
272
273OutputVariable::OutputVariable(const OutputVariable &other) : InterfaceVariable(other)
274{
275}
276
277OutputVariable &OutputVariable::operator=(const OutputVariable &other)
278{
279 InterfaceVariable::operator=(other);
280 return *this;
281}
282
283bool OutputVariable::operator==(const OutputVariable &other) const
284{
285 return InterfaceVariable::operator==(other);
286}
287
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500288InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false)
289{
290}
Jamie Madill6a729792014-07-18 10:33:14 -0400291
292InterfaceBlockField::~InterfaceBlockField()
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500293{
294}
Jamie Madill6a729792014-07-18 10:33:14 -0400295
296InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500297 : ShaderVariable(other), isRowMajorLayout(other.isRowMajorLayout)
298{
299}
Jamie Madill6a729792014-07-18 10:33:14 -0400300
301InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other)
302{
303 ShaderVariable::operator=(other);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500304 isRowMajorLayout = other.isRowMajorLayout;
Jamie Madill6a729792014-07-18 10:33:14 -0400305 return *this;
306}
307
Zhenyao Moed136362014-10-03 13:23:01 -0700308bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
309{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500310 return (ShaderVariable::operator==(other) && isRowMajorLayout == other.isRowMajorLayout);
Zhenyao Moed136362014-10-03 13:23:01 -0700311}
312
313bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
314 const InterfaceBlockField &other) const
315{
316 return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
317 isRowMajorLayout == other.isRowMajorLayout);
318}
319
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500320Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false)
321{
322}
Jamie Madill6a729792014-07-18 10:33:14 -0400323
324Varying::~Varying()
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500325{
326}
Jamie Madill6a729792014-07-18 10:33:14 -0400327
328Varying::Varying(const Varying &other)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500329 : ShaderVariable(other), interpolation(other.interpolation), isInvariant(other.isInvariant)
330{
331}
Jamie Madill6a729792014-07-18 10:33:14 -0400332
333Varying &Varying::operator=(const Varying &other)
334{
335 ShaderVariable::operator=(other);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500336 interpolation = other.interpolation;
337 isInvariant = other.isInvariant;
Jamie Madill6a729792014-07-18 10:33:14 -0400338 return *this;
339}
340
Zhenyao Moed136362014-10-03 13:23:01 -0700341bool Varying::operator==(const Varying &other) const
342{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500343 return (ShaderVariable::operator==(other) && interpolation == other.interpolation &&
Zhenyao Moed136362014-10-03 13:23:01 -0700344 isInvariant == other.isInvariant);
345}
346
Jamie Madill9e64edc2015-05-07 14:08:06 +0000347bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
Zhenyao Moed136362014-10-03 13:23:01 -0700348{
Olli Etuaho37ad4742015-04-27 13:18:50 +0300349 return isSameVaryingAtLinkTime(other, 100);
350}
351
352bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const
353{
Zhenyao Moed136362014-10-03 13:23:01 -0700354 return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
Corentin Wallez84954982016-07-12 15:42:18 -0400355 InterpolationTypesMatch(interpolation, other.interpolation) &&
Olli Etuaho37ad4742015-04-27 13:18:50 +0300356 (shaderVersion >= 300 || isInvariant == other.isInvariant));
Zhenyao Moed136362014-10-03 13:23:01 -0700357}
358
Jamie Madill6a729792014-07-18 10:33:14 -0400359InterfaceBlock::InterfaceBlock()
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500360 : arraySize(0), layout(BLOCKLAYOUT_PACKED), isRowMajorLayout(false), staticUse(false)
361{
362}
Jamie Madill6a729792014-07-18 10:33:14 -0400363
364InterfaceBlock::~InterfaceBlock()
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500365{
366}
Jamie Madill6a729792014-07-18 10:33:14 -0400367
368InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
369 : name(other.name),
370 mappedName(other.mappedName),
Jamie Madill42bcf322014-08-25 16:20:46 -0400371 instanceName(other.instanceName),
Jamie Madill6a729792014-07-18 10:33:14 -0400372 arraySize(other.arraySize),
373 layout(other.layout),
374 isRowMajorLayout(other.isRowMajorLayout),
375 staticUse(other.staticUse),
376 fields(other.fields)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500377{
378}
Jamie Madill6a729792014-07-18 10:33:14 -0400379
380InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
381{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500382 name = other.name;
383 mappedName = other.mappedName;
384 instanceName = other.instanceName;
385 arraySize = other.arraySize;
386 layout = other.layout;
Jamie Madill6a729792014-07-18 10:33:14 -0400387 isRowMajorLayout = other.isRowMajorLayout;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500388 staticUse = other.staticUse;
389 fields = other.fields;
Jamie Madill6a729792014-07-18 10:33:14 -0400390 return *this;
391}
392
Jamie Madill39046162016-02-08 15:05:17 -0500393std::string InterfaceBlock::fieldPrefix() const
394{
395 return instanceName.empty() ? "" : name;
Jamie Madill6a729792014-07-18 10:33:14 -0400396}
Jamie Madill39046162016-02-08 15:05:17 -0500397
Corentin Wallez84954982016-07-12 15:42:18 -0400398bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
399{
400 if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize ||
401 layout != other.layout || isRowMajorLayout != other.isRowMajorLayout ||
402 fields.size() != other.fields.size())
403 {
404 return false;
405 }
406
407 for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
408 {
409 if (!fields[fieldIndex].isSameInterfaceBlockFieldAtLinkTime(other.fields[fieldIndex]))
410 {
411 return false;
412 }
413 }
414
415 return true;
416}
417
Martin Radev4c4c8e72016-08-04 12:25:34 +0300418void WorkGroupSize::fill(int fillValue)
419{
420 localSizeQualifiers[0] = fillValue;
421 localSizeQualifiers[1] = fillValue;
422 localSizeQualifiers[2] = fillValue;
423}
424
425void WorkGroupSize::setLocalSize(int localSizeX, int localSizeY, int localSizeZ)
426{
427 localSizeQualifiers[0] = localSizeX;
428 localSizeQualifiers[1] = localSizeY;
429 localSizeQualifiers[2] = localSizeZ;
430}
431
432// check that if one of them is less than 1, then all of them are.
433// Or if one is positive, then all of them are positive.
434bool WorkGroupSize::isLocalSizeValid() const
435{
436 return (
437 (localSizeQualifiers[0] < 1 && localSizeQualifiers[1] < 1 && localSizeQualifiers[2] < 1) ||
438 (localSizeQualifiers[0] > 0 && localSizeQualifiers[1] > 0 && localSizeQualifiers[2] > 0));
439}
440
441bool WorkGroupSize::isAnyValueSet() const
442{
443 return localSizeQualifiers[0] > 0 || localSizeQualifiers[1] > 0 || localSizeQualifiers[2] > 0;
444}
445
446bool WorkGroupSize::isDeclared() const
447{
448 bool localSizeDeclared = localSizeQualifiers[0] > 0;
449 ASSERT(isLocalSizeValid());
450 return localSizeDeclared;
451}
452
453bool WorkGroupSize::isWorkGroupSizeMatching(const WorkGroupSize &right) const
454{
455 for (size_t i = 0u; i < size(); ++i)
456 {
457 bool result = (localSizeQualifiers[i] == right.localSizeQualifiers[i] ||
458 (localSizeQualifiers[i] == 1 && right.localSizeQualifiers[i] == -1) ||
459 (localSizeQualifiers[i] == -1 && right.localSizeQualifiers[i] == 1));
460 if (!result)
461 {
462 return false;
463 }
464 }
465 return true;
466}
467
468int &WorkGroupSize::operator[](size_t index)
469{
470 ASSERT(index < size());
471 return localSizeQualifiers[index];
472}
473
474int WorkGroupSize::operator[](size_t index) const
475{
476 ASSERT(index < size());
477 return localSizeQualifiers[index];
478}
479
480size_t WorkGroupSize::size() const
481{
482 return 3u;
483}
484
Jamie Madill39046162016-02-08 15:05:17 -0500485} // namespace sh