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