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