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