1 //
2 // Copyright 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/translator/util.h"
8 
9 #include <limits>
10 
11 #include "common/utilities.h"
12 #include "compiler/preprocessor/numeric_lex.h"
13 #include "compiler/translator/ImmutableStringBuilder.h"
14 #include "compiler/translator/SymbolTable.h"
15 
atoi_clamp(const char * str,unsigned int * value)16 bool atoi_clamp(const char *str, unsigned int *value)
17 {
18     bool success = angle::pp::numeric_lex_int(str, value);
19     if (!success)
20         *value = std::numeric_limits<unsigned int>::max();
21     return success;
22 }
23 
24 namespace sh
25 {
26 
27 namespace
28 {
29 
IsInterpolationIn(TQualifier qualifier)30 bool IsInterpolationIn(TQualifier qualifier)
31 {
32     switch (qualifier)
33     {
34         case EvqSmoothIn:
35         case EvqFlatIn:
36         case EvqNoPerspectiveIn:
37         case EvqCentroidIn:
38         case EvqSampleIn:
39             return true;
40         default:
41             return false;
42     }
43 }
44 
45 }  // anonymous namespace
46 
NumericLexFloat32OutOfRangeToInfinity(const std::string & str)47 float NumericLexFloat32OutOfRangeToInfinity(const std::string &str)
48 {
49     // Parses a decimal string using scientific notation into a floating point number.
50     // Out-of-range values are converted to infinity. Values that are too small to be
51     // represented are converted to zero.
52 
53     // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not
54     // matter.
55     unsigned int decimalMantissa = 0;
56     size_t i                     = 0;
57     bool decimalPointSeen        = false;
58     bool nonZeroSeenInMantissa   = false;
59 
60     // The exponent offset reflects the position of the decimal point.
61     int exponentOffset = -1;
62 
63     // This is just a counter for how many decimal digits are written to decimalMantissa.
64     int mantissaDecimalDigits = 0;
65 
66     while (i < str.length())
67     {
68         const char c = str[i];
69         if (c == 'e' || c == 'E')
70         {
71             break;
72         }
73         if (c == '.')
74         {
75             decimalPointSeen = true;
76             ++i;
77             continue;
78         }
79 
80         unsigned int digit = static_cast<unsigned int>(c - '0');
81         ASSERT(digit < 10u);
82         if (digit != 0u)
83         {
84             nonZeroSeenInMantissa = true;
85         }
86         if (nonZeroSeenInMantissa)
87         {
88             // Add bits to the mantissa until space runs out in 32-bit int. This should be
89             // enough precision to make the resulting binary mantissa accurate to 1 ULP.
90             if (decimalMantissa <= (std::numeric_limits<unsigned int>::max() - 9u) / 10u)
91             {
92                 decimalMantissa = decimalMantissa * 10u + digit;
93                 ++mantissaDecimalDigits;
94             }
95             if (!decimalPointSeen)
96             {
97                 ++exponentOffset;
98             }
99         }
100         else if (decimalPointSeen)
101         {
102             --exponentOffset;
103         }
104         ++i;
105     }
106     if (decimalMantissa == 0)
107     {
108         return 0.0f;
109     }
110     int exponent = 0;
111     if (i < str.length())
112     {
113         ASSERT(str[i] == 'e' || str[i] == 'E');
114         ++i;
115         bool exponentOutOfRange = false;
116         bool negativeExponent   = false;
117         if (str[i] == '-')
118         {
119             negativeExponent = true;
120             ++i;
121         }
122         else if (str[i] == '+')
123         {
124             ++i;
125         }
126         while (i < str.length())
127         {
128             const char c       = str[i];
129             unsigned int digit = static_cast<unsigned int>(c - '0');
130             ASSERT(digit < 10u);
131             if (exponent <= (std::numeric_limits<int>::max() - 9) / 10)
132             {
133                 exponent = exponent * 10 + digit;
134             }
135             else
136             {
137                 exponentOutOfRange = true;
138             }
139             ++i;
140         }
141         if (negativeExponent)
142         {
143             exponent = -exponent;
144         }
145         if (exponentOutOfRange)
146         {
147             if (negativeExponent)
148             {
149                 return 0.0f;
150             }
151             else
152             {
153                 return std::numeric_limits<float>::infinity();
154             }
155         }
156     }
157     // Do the calculation in 64-bit to avoid overflow.
158     long long exponentLong =
159         static_cast<long long>(exponent) + static_cast<long long>(exponentOffset);
160     if (exponentLong > std::numeric_limits<float>::max_exponent10)
161     {
162         return std::numeric_limits<float>::infinity();
163     }
164     else if (exponentLong < std::numeric_limits<float>::min_exponent10)
165     {
166         return 0.0f;
167     }
168     // The exponent is in range, so we need to actually evaluate the float.
169     exponent     = static_cast<int>(exponentLong);
170     double value = decimalMantissa;
171 
172     // Calculate the exponent offset to normalize the mantissa.
173     int normalizationExponentOffset = 1 - mantissaDecimalDigits;
174     // Apply the exponent.
175     value *= std::pow(10.0, static_cast<double>(exponent + normalizationExponentOffset));
176     if (value > static_cast<double>(std::numeric_limits<float>::max()))
177     {
178         return std::numeric_limits<float>::infinity();
179     }
180     if (value < static_cast<double>(std::numeric_limits<float>::min()))
181     {
182         return 0.0f;
183     }
184     return static_cast<float>(value);
185 }
186 
strtof_clamp(const std::string & str,float * value)187 bool strtof_clamp(const std::string &str, float *value)
188 {
189     // Custom float parsing that can handle the following corner cases:
190     //   1. The decimal mantissa is very small but the exponent is very large, putting the resulting
191     //   number inside the float range.
192     //   2. The decimal mantissa is very large but the exponent is very small, putting the resulting
193     //   number inside the float range.
194     //   3. The value is out-of-range and should be evaluated as infinity.
195     //   4. The value is too small and should be evaluated as zero.
196     // See ESSL 3.00.6 section 4.1.4 for the relevant specification.
197     *value = NumericLexFloat32OutOfRangeToInfinity(str);
198     return !gl::isInf(*value);
199 }
200 
GLVariableType(const TType & type)201 GLenum GLVariableType(const TType &type)
202 {
203     if (type.getBasicType() == EbtFloat)
204     {
205         if (type.isVector())
206         {
207             switch (type.getNominalSize())
208             {
209                 case 2:
210                     return GL_FLOAT_VEC2;
211                 case 3:
212                     return GL_FLOAT_VEC3;
213                 case 4:
214                     return GL_FLOAT_VEC4;
215                 default:
216                     UNREACHABLE();
217 #if !UNREACHABLE_IS_NORETURN
218                     return GL_NONE;
219 #endif
220             }
221         }
222         else if (type.isMatrix())
223         {
224             switch (type.getCols())
225             {
226                 case 2:
227                     switch (type.getRows())
228                     {
229                         case 2:
230                             return GL_FLOAT_MAT2;
231                         case 3:
232                             return GL_FLOAT_MAT2x3;
233                         case 4:
234                             return GL_FLOAT_MAT2x4;
235                         default:
236                             UNREACHABLE();
237 #if !UNREACHABLE_IS_NORETURN
238                             return GL_NONE;
239 #endif
240                     }
241 
242                 case 3:
243                     switch (type.getRows())
244                     {
245                         case 2:
246                             return GL_FLOAT_MAT3x2;
247                         case 3:
248                             return GL_FLOAT_MAT3;
249                         case 4:
250                             return GL_FLOAT_MAT3x4;
251                         default:
252                             UNREACHABLE();
253 #if !UNREACHABLE_IS_NORETURN
254                             return GL_NONE;
255 #endif
256                     }
257 
258                 case 4:
259                     switch (type.getRows())
260                     {
261                         case 2:
262                             return GL_FLOAT_MAT4x2;
263                         case 3:
264                             return GL_FLOAT_MAT4x3;
265                         case 4:
266                             return GL_FLOAT_MAT4;
267                         default:
268                             UNREACHABLE();
269 #if !UNREACHABLE_IS_NORETURN
270                             return GL_NONE;
271 #endif
272                     }
273 
274                 default:
275                     UNREACHABLE();
276 #if !UNREACHABLE_IS_NORETURN
277                     return GL_NONE;
278 #endif
279             }
280         }
281         else
282         {
283             return GL_FLOAT;
284         }
285     }
286     else if (type.getBasicType() == EbtInt)
287     {
288         if (type.isVector())
289         {
290             switch (type.getNominalSize())
291             {
292                 case 2:
293                     return GL_INT_VEC2;
294                 case 3:
295                     return GL_INT_VEC3;
296                 case 4:
297                     return GL_INT_VEC4;
298                 default:
299                     UNREACHABLE();
300 #if !UNREACHABLE_IS_NORETURN
301                     return GL_NONE;
302 #endif
303             }
304         }
305         else
306         {
307             ASSERT(!type.isMatrix());
308             return GL_INT;
309         }
310     }
311     else if (type.getBasicType() == EbtUInt)
312     {
313         if (type.isVector())
314         {
315             switch (type.getNominalSize())
316             {
317                 case 2:
318                     return GL_UNSIGNED_INT_VEC2;
319                 case 3:
320                     return GL_UNSIGNED_INT_VEC3;
321                 case 4:
322                     return GL_UNSIGNED_INT_VEC4;
323                 default:
324                     UNREACHABLE();
325 #if !UNREACHABLE_IS_NORETURN
326                     return GL_NONE;
327 #endif
328             }
329         }
330         else
331         {
332             ASSERT(!type.isMatrix());
333             return GL_UNSIGNED_INT;
334         }
335     }
336     else if (type.getBasicType() == EbtBool)
337     {
338         if (type.isVector())
339         {
340             switch (type.getNominalSize())
341             {
342                 case 2:
343                     return GL_BOOL_VEC2;
344                 case 3:
345                     return GL_BOOL_VEC3;
346                 case 4:
347                     return GL_BOOL_VEC4;
348                 default:
349                     UNREACHABLE();
350 #if !UNREACHABLE_IS_NORETURN
351                     return GL_NONE;
352 #endif
353             }
354         }
355         else
356         {
357             ASSERT(!type.isMatrix());
358             return GL_BOOL;
359         }
360     }
361 
362     switch (type.getBasicType())
363     {
364         case EbtSampler2D:
365             return GL_SAMPLER_2D;
366         case EbtSampler3D:
367             return GL_SAMPLER_3D;
368         case EbtSamplerCube:
369             return GL_SAMPLER_CUBE;
370         case EbtSamplerExternalOES:
371             return GL_SAMPLER_EXTERNAL_OES;
372         case EbtSamplerExternal2DY2YEXT:
373             return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
374         case EbtSampler2DRect:
375             return GL_SAMPLER_2D_RECT_ANGLE;
376         case EbtSampler2DArray:
377             return GL_SAMPLER_2D_ARRAY;
378         case EbtSampler2DMS:
379             return GL_SAMPLER_2D_MULTISAMPLE;
380         case EbtSampler2DMSArray:
381             return GL_SAMPLER_2D_MULTISAMPLE_ARRAY;
382         case EbtSamplerCubeArray:
383             return GL_SAMPLER_CUBE_MAP_ARRAY;
384         case EbtSamplerBuffer:
385             return GL_SAMPLER_BUFFER;
386         case EbtISampler2D:
387             return GL_INT_SAMPLER_2D;
388         case EbtISampler3D:
389             return GL_INT_SAMPLER_3D;
390         case EbtISamplerCube:
391             return GL_INT_SAMPLER_CUBE;
392         case EbtISampler2DArray:
393             return GL_INT_SAMPLER_2D_ARRAY;
394         case EbtISampler2DMS:
395             return GL_INT_SAMPLER_2D_MULTISAMPLE;
396         case EbtISampler2DMSArray:
397             return GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY;
398         case EbtISamplerCubeArray:
399             return GL_INT_SAMPLER_CUBE_MAP_ARRAY;
400         case EbtISamplerBuffer:
401             return GL_INT_SAMPLER_BUFFER;
402         case EbtUSampler2D:
403             return GL_UNSIGNED_INT_SAMPLER_2D;
404         case EbtUSampler3D:
405             return GL_UNSIGNED_INT_SAMPLER_3D;
406         case EbtUSamplerCube:
407             return GL_UNSIGNED_INT_SAMPLER_CUBE;
408         case EbtUSampler2DArray:
409             return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
410         case EbtUSampler2DMS:
411             return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
412         case EbtUSampler2DMSArray:
413             return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY;
414         case EbtUSamplerCubeArray:
415             return GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
416         case EbtUSamplerBuffer:
417             return GL_UNSIGNED_INT_SAMPLER_BUFFER;
418         case EbtSampler2DShadow:
419             return GL_SAMPLER_2D_SHADOW;
420         case EbtSamplerCubeShadow:
421             return GL_SAMPLER_CUBE_SHADOW;
422         case EbtSampler2DArrayShadow:
423             return GL_SAMPLER_2D_ARRAY_SHADOW;
424         case EbtSamplerCubeArrayShadow:
425             return GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW;
426         case EbtImage2D:
427             return GL_IMAGE_2D;
428         case EbtIImage2D:
429             return GL_INT_IMAGE_2D;
430         case EbtUImage2D:
431             return GL_UNSIGNED_INT_IMAGE_2D;
432         case EbtImage2DArray:
433             return GL_IMAGE_2D_ARRAY;
434         case EbtIImage2DArray:
435             return GL_INT_IMAGE_2D_ARRAY;
436         case EbtUImage2DArray:
437             return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
438         case EbtImage3D:
439             return GL_IMAGE_3D;
440         case EbtIImage3D:
441             return GL_INT_IMAGE_3D;
442         case EbtUImage3D:
443             return GL_UNSIGNED_INT_IMAGE_3D;
444         case EbtImageCube:
445             return GL_IMAGE_CUBE;
446         case EbtIImageCube:
447             return GL_INT_IMAGE_CUBE;
448         case EbtUImageCube:
449             return GL_UNSIGNED_INT_IMAGE_CUBE;
450         case EbtImageCubeArray:
451             return GL_IMAGE_CUBE_MAP_ARRAY;
452         case EbtIImageCubeArray:
453             return GL_INT_IMAGE_CUBE_MAP_ARRAY;
454         case EbtUImageCubeArray:
455             return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
456         case EbtImageBuffer:
457             return GL_IMAGE_BUFFER;
458         case EbtIImageBuffer:
459             return GL_INT_IMAGE_BUFFER;
460         case EbtUImageBuffer:
461             return GL_UNSIGNED_INT_IMAGE_BUFFER;
462         case EbtAtomicCounter:
463             return GL_UNSIGNED_INT_ATOMIC_COUNTER;
464         case EbtSamplerVideoWEBGL:
465             return GL_SAMPLER_VIDEO_IMAGE_WEBGL;
466         default:
467             UNREACHABLE();
468     }
469 
470     return GL_NONE;
471 }
472 
GLVariablePrecision(const TType & type)473 GLenum GLVariablePrecision(const TType &type)
474 {
475     if (type.getBasicType() == EbtFloat)
476     {
477         switch (type.getPrecision())
478         {
479             case EbpHigh:
480                 return GL_HIGH_FLOAT;
481             case EbpMedium:
482                 return GL_MEDIUM_FLOAT;
483             case EbpLow:
484                 return GL_LOW_FLOAT;
485             case EbpUndefined:
486                 // Desktop specs do not use precision
487                 return GL_NONE;
488             default:
489                 UNREACHABLE();
490         }
491     }
492     else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
493     {
494         switch (type.getPrecision())
495         {
496             case EbpHigh:
497                 return GL_HIGH_INT;
498             case EbpMedium:
499                 return GL_MEDIUM_INT;
500             case EbpLow:
501                 return GL_LOW_INT;
502             case EbpUndefined:
503                 // Desktop specs do not use precision
504                 return GL_NONE;
505             default:
506                 UNREACHABLE();
507         }
508     }
509 
510     // Other types (boolean, sampler) don't have a precision
511     return GL_NONE;
512 }
513 
ArrayString(const TType & type)514 ImmutableString ArrayString(const TType &type)
515 {
516     if (!type.isArray())
517         return ImmutableString("");
518 
519     const TSpan<const unsigned int> &arraySizes     = type.getArraySizes();
520     constexpr const size_t kMaxDecimalDigitsPerSize = 10u;
521     ImmutableStringBuilder arrayString(arraySizes.size() * (kMaxDecimalDigitsPerSize + 2u));
522     for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend();
523          ++arraySizeIter)
524     {
525         arrayString << "[";
526         if (*arraySizeIter > 0)
527         {
528             arrayString.appendDecimal(*arraySizeIter);
529         }
530         arrayString << "]";
531     }
532     return arrayString;
533 }
534 
GetTypeName(const TType & type,ShHashFunction64 hashFunction,NameMap * nameMap)535 ImmutableString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap)
536 {
537     if (type.getBasicType() == EbtStruct)
538         return HashName(type.getStruct(), hashFunction, nameMap);
539     else
540         return ImmutableString(type.getBuiltInTypeNameString());
541 }
542 
IsVaryingOut(TQualifier qualifier)543 bool IsVaryingOut(TQualifier qualifier)
544 {
545     switch (qualifier)
546     {
547         case EvqVaryingOut:
548         case EvqSmoothOut:
549         case EvqFlatOut:
550         case EvqNoPerspectiveOut:
551         case EvqCentroidOut:
552         case EvqVertexOut:
553         case EvqGeometryOut:
554         case EvqSampleOut:
555             return true;
556 
557         default:
558             break;
559     }
560 
561     return false;
562 }
563 
IsVaryingIn(TQualifier qualifier)564 bool IsVaryingIn(TQualifier qualifier)
565 {
566     switch (qualifier)
567     {
568         case EvqVaryingIn:
569         case EvqSmoothIn:
570         case EvqFlatIn:
571         case EvqNoPerspectiveIn:
572         case EvqCentroidIn:
573         case EvqFragmentIn:
574         case EvqGeometryIn:
575         case EvqSampleIn:
576             return true;
577 
578         default:
579             break;
580     }
581 
582     return false;
583 }
584 
IsVarying(TQualifier qualifier)585 bool IsVarying(TQualifier qualifier)
586 {
587     return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
588 }
589 
IsGeometryShaderInput(GLenum shaderType,TQualifier qualifier)590 bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier)
591 {
592     return (qualifier == EvqGeometryIn) ||
593            ((shaderType == GL_GEOMETRY_SHADER_EXT) && IsInterpolationIn(qualifier));
594 }
595 
GetInterpolationType(TQualifier qualifier)596 InterpolationType GetInterpolationType(TQualifier qualifier)
597 {
598     switch (qualifier)
599     {
600         case EvqFlatIn:
601         case EvqFlatOut:
602             return INTERPOLATION_FLAT;
603 
604         case EvqNoPerspectiveIn:
605         case EvqNoPerspectiveOut:
606             return INTERPOLATION_NOPERSPECTIVE;
607 
608         case EvqSmoothIn:
609         case EvqSmoothOut:
610         case EvqVertexOut:
611         case EvqFragmentIn:
612         case EvqVaryingIn:
613         case EvqVaryingOut:
614         case EvqGeometryIn:
615         case EvqGeometryOut:
616             return INTERPOLATION_SMOOTH;
617 
618         case EvqCentroidIn:
619         case EvqCentroidOut:
620             return INTERPOLATION_CENTROID;
621 
622         case EvqSampleIn:
623         case EvqSampleOut:
624             return INTERPOLATION_SAMPLE;
625         default:
626             UNREACHABLE();
627 #if !UNREACHABLE_IS_NORETURN
628             return INTERPOLATION_SMOOTH;
629 #endif
630     }
631 }
632 
GetShaderVariableBasicType(const sh::ShaderVariable & var)633 TType GetShaderVariableBasicType(const sh::ShaderVariable &var)
634 {
635     switch (var.type)
636     {
637         case GL_BOOL:
638             return TType(EbtBool);
639         case GL_BOOL_VEC2:
640             return TType(EbtBool, 2);
641         case GL_BOOL_VEC3:
642             return TType(EbtBool, 3);
643         case GL_BOOL_VEC4:
644             return TType(EbtBool, 4);
645         case GL_FLOAT:
646             return TType(EbtFloat);
647         case GL_FLOAT_VEC2:
648             return TType(EbtFloat, 2);
649         case GL_FLOAT_VEC3:
650             return TType(EbtFloat, 3);
651         case GL_FLOAT_VEC4:
652             return TType(EbtFloat, 4);
653         case GL_FLOAT_MAT2:
654             return TType(EbtFloat, 2, 2);
655         case GL_FLOAT_MAT3:
656             return TType(EbtFloat, 3, 3);
657         case GL_FLOAT_MAT4:
658             return TType(EbtFloat, 4, 4);
659         case GL_FLOAT_MAT2x3:
660             return TType(EbtFloat, 2, 3);
661         case GL_FLOAT_MAT2x4:
662             return TType(EbtFloat, 2, 4);
663         case GL_FLOAT_MAT3x2:
664             return TType(EbtFloat, 3, 2);
665         case GL_FLOAT_MAT3x4:
666             return TType(EbtFloat, 3, 4);
667         case GL_FLOAT_MAT4x2:
668             return TType(EbtFloat, 4, 2);
669         case GL_FLOAT_MAT4x3:
670             return TType(EbtFloat, 4, 3);
671         case GL_INT:
672             return TType(EbtInt);
673         case GL_INT_VEC2:
674             return TType(EbtInt, 2);
675         case GL_INT_VEC3:
676             return TType(EbtInt, 3);
677         case GL_INT_VEC4:
678             return TType(EbtInt, 4);
679         case GL_UNSIGNED_INT:
680             return TType(EbtUInt);
681         case GL_UNSIGNED_INT_VEC2:
682             return TType(EbtUInt, 2);
683         case GL_UNSIGNED_INT_VEC3:
684             return TType(EbtUInt, 3);
685         case GL_UNSIGNED_INT_VEC4:
686             return TType(EbtUInt, 4);
687         default:
688             UNREACHABLE();
689 #if !UNREACHABLE_IS_NORETURN
690             return TType();
691 #endif
692     }
693 }
694 
DeclareGlobalVariable(TIntermBlock * root,const TVariable * variable)695 void DeclareGlobalVariable(TIntermBlock *root, const TVariable *variable)
696 {
697     TIntermDeclaration *declaration = new TIntermDeclaration();
698     declaration->appendDeclarator(new TIntermSymbol(variable));
699 
700     TIntermSequence *globalSequence = root->getSequence();
701     globalSequence->insert(globalSequence->begin(), declaration);
702 }
703 
704 // GLSL ES 1.0.17 4.6.1 The Invariant Qualifier
CanBeInvariantESSL1(TQualifier qualifier)705 bool CanBeInvariantESSL1(TQualifier qualifier)
706 {
707     return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) ||
708            IsBuiltinOutputVariable(qualifier) ||
709            (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing);
710 }
711 
712 // GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier
713 // GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier
CanBeInvariantESSL3OrGreater(TQualifier qualifier)714 bool CanBeInvariantESSL3OrGreater(TQualifier qualifier)
715 {
716     return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut ||
717            IsBuiltinOutputVariable(qualifier);
718 }
719 
IsBuiltinOutputVariable(TQualifier qualifier)720 bool IsBuiltinOutputVariable(TQualifier qualifier)
721 {
722     switch (qualifier)
723     {
724         case EvqPosition:
725         case EvqPointSize:
726         case EvqFragDepth:
727         case EvqFragDepthEXT:
728         case EvqFragColor:
729         case EvqSecondaryFragColorEXT:
730         case EvqFragData:
731         case EvqSecondaryFragDataEXT:
732         case EvqClipDistance:
733             return true;
734         default:
735             break;
736     }
737     return false;
738 }
739 
IsBuiltinFragmentInputVariable(TQualifier qualifier)740 bool IsBuiltinFragmentInputVariable(TQualifier qualifier)
741 {
742     switch (qualifier)
743     {
744         case EvqFragCoord:
745         case EvqPointCoord:
746         case EvqFrontFacing:
747         case EvqHelperInvocation:
748             return true;
749         default:
750             break;
751     }
752     return false;
753 }
754 
IsShaderOutput(TQualifier qualifier)755 bool IsShaderOutput(TQualifier qualifier)
756 {
757     return IsVaryingOut(qualifier) || IsBuiltinOutputVariable(qualifier);
758 }
759 
IsOutputESSL(ShShaderOutput output)760 bool IsOutputESSL(ShShaderOutput output)
761 {
762     return output == SH_ESSL_OUTPUT;
763 }
764 
IsOutputGLSL(ShShaderOutput output)765 bool IsOutputGLSL(ShShaderOutput output)
766 {
767     switch (output)
768     {
769         case SH_GLSL_130_OUTPUT:
770         case SH_GLSL_140_OUTPUT:
771         case SH_GLSL_150_CORE_OUTPUT:
772         case SH_GLSL_330_CORE_OUTPUT:
773         case SH_GLSL_400_CORE_OUTPUT:
774         case SH_GLSL_410_CORE_OUTPUT:
775         case SH_GLSL_420_CORE_OUTPUT:
776         case SH_GLSL_430_CORE_OUTPUT:
777         case SH_GLSL_440_CORE_OUTPUT:
778         case SH_GLSL_450_CORE_OUTPUT:
779         case SH_GLSL_COMPATIBILITY_OUTPUT:
780             return true;
781         default:
782             break;
783     }
784     return false;
785 }
IsOutputHLSL(ShShaderOutput output)786 bool IsOutputHLSL(ShShaderOutput output)
787 {
788     switch (output)
789     {
790         case SH_HLSL_3_0_OUTPUT:
791         case SH_HLSL_4_1_OUTPUT:
792         case SH_HLSL_4_0_FL9_3_OUTPUT:
793             return true;
794         default:
795             break;
796     }
797     return false;
798 }
IsOutputVulkan(ShShaderOutput output)799 bool IsOutputVulkan(ShShaderOutput output)
800 {
801     return output == SH_GLSL_VULKAN_OUTPUT;
802 }
IsOutputMetal(ShShaderOutput output)803 bool IsOutputMetal(ShShaderOutput output)
804 {
805     return output == SH_GLSL_METAL_OUTPUT;
806 }
807 
IsInShaderStorageBlock(TIntermTyped * node)808 bool IsInShaderStorageBlock(TIntermTyped *node)
809 {
810     TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
811     if (swizzleNode)
812     {
813         return IsInShaderStorageBlock(swizzleNode->getOperand());
814     }
815 
816     TIntermBinary *binaryNode = node->getAsBinaryNode();
817     if (binaryNode)
818     {
819         switch (binaryNode->getOp())
820         {
821             case EOpIndexDirectInterfaceBlock:
822             case EOpIndexIndirect:
823             case EOpIndexDirect:
824             case EOpIndexDirectStruct:
825                 return IsInShaderStorageBlock(binaryNode->getLeft());
826             default:
827                 return false;
828         }
829     }
830 
831     const TType &type = node->getType();
832     return type.getQualifier() == EvqBuffer;
833 }
834 
GetImageInternalFormatType(TLayoutImageInternalFormat iifq)835 GLenum GetImageInternalFormatType(TLayoutImageInternalFormat iifq)
836 {
837     switch (iifq)
838     {
839         case EiifRGBA32F:
840             return GL_RGBA32F;
841         case EiifRGBA16F:
842             return GL_RGBA16F;
843         case EiifR32F:
844             return GL_R32F;
845         case EiifRGBA32UI:
846             return GL_RGBA32UI;
847         case EiifRGBA16UI:
848             return GL_RGBA16UI;
849         case EiifRGBA8UI:
850             return GL_RGBA8UI;
851         case EiifR32UI:
852             return GL_R32UI;
853         case EiifRGBA32I:
854             return GL_RGBA32I;
855         case EiifRGBA16I:
856             return GL_RGBA16I;
857         case EiifRGBA8I:
858             return GL_RGBA8I;
859         case EiifR32I:
860             return GL_R32I;
861         case EiifRGBA8:
862             return GL_RGBA8;
863         case EiifRGBA8_SNORM:
864             return GL_RGBA8_SNORM;
865         default:
866             return GL_NONE;
867     }
868 }
869 
IsSpecWithFunctionBodyNewScope(ShShaderSpec shaderSpec,int shaderVersion)870 bool IsSpecWithFunctionBodyNewScope(ShShaderSpec shaderSpec, int shaderVersion)
871 {
872     return (shaderVersion == 100 && !sh::IsWebGLBasedSpec(shaderSpec));
873 }
874 
GetConversion(TBasicType t1,TBasicType t2)875 ImplicitTypeConversion GetConversion(TBasicType t1, TBasicType t2)
876 {
877     if (t1 == t2)
878         return ImplicitTypeConversion::Same;
879 
880     switch (t1)
881     {
882         case EbtInt:
883             switch (t2)
884             {
885                 case EbtInt:
886                     UNREACHABLE();
887                     break;
888                 case EbtUInt:
889                     return ImplicitTypeConversion::Invalid;
890                 case EbtFloat:
891                     return ImplicitTypeConversion::Left;
892                 default:
893                     return ImplicitTypeConversion::Invalid;
894             }
895             break;
896         case EbtUInt:
897             switch (t2)
898             {
899                 case EbtInt:
900                     return ImplicitTypeConversion::Invalid;
901                 case EbtUInt:
902                     UNREACHABLE();
903                     break;
904                 case EbtFloat:
905                     return ImplicitTypeConversion::Left;
906                 default:
907                     return ImplicitTypeConversion::Invalid;
908             }
909             break;
910         case EbtFloat:
911             switch (t2)
912             {
913                 case EbtInt:
914                 case EbtUInt:
915                     return ImplicitTypeConversion::Right;
916                 case EbtFloat:
917                     UNREACHABLE();
918                     break;
919                 default:
920                     return ImplicitTypeConversion::Invalid;
921             }
922             break;
923         default:
924             return ImplicitTypeConversion::Invalid;
925     }
926     return ImplicitTypeConversion::Invalid;
927 }
928 
IsValidImplicitConversion(sh::ImplicitTypeConversion conversion,TOperator op)929 bool IsValidImplicitConversion(sh::ImplicitTypeConversion conversion, TOperator op)
930 {
931     switch (conversion)
932     {
933         case sh::ImplicitTypeConversion::Same:
934             return true;
935         case sh::ImplicitTypeConversion::Left:
936             switch (op)
937             {
938                 case EOpEqual:
939                 case EOpNotEqual:
940                 case EOpLessThan:
941                 case EOpGreaterThan:
942                 case EOpLessThanEqual:
943                 case EOpGreaterThanEqual:
944                 case EOpAdd:
945                 case EOpSub:
946                 case EOpMul:
947                 case EOpDiv:
948                     return true;
949                 default:
950                     break;
951             }
952             break;
953         case sh::ImplicitTypeConversion::Right:
954             switch (op)
955             {
956                 case EOpAssign:
957                 case EOpInitialize:
958                 case EOpEqual:
959                 case EOpNotEqual:
960                 case EOpLessThan:
961                 case EOpGreaterThan:
962                 case EOpLessThanEqual:
963                 case EOpGreaterThanEqual:
964                 case EOpAdd:
965                 case EOpSub:
966                 case EOpMul:
967                 case EOpDiv:
968                 case EOpAddAssign:
969                 case EOpSubAssign:
970                 case EOpMulAssign:
971                 case EOpDivAssign:
972                     return true;
973                 default:
974                     break;
975             }
976             break;
977         case sh::ImplicitTypeConversion::Invalid:
978             break;
979     }
980     return false;
981 }
982 
FindFieldIndex(const TFieldList & fieldList,const char * fieldName)983 size_t FindFieldIndex(const TFieldList &fieldList, const char *fieldName)
984 {
985     for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
986     {
987         if (strcmp(fieldList[fieldIndex]->name().data(), fieldName) == 0)
988         {
989             return fieldIndex;
990         }
991     }
992     UNREACHABLE();
993     return 0;
994 }
995 
996 }  // namespace sh
997