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