Translator: Be more explicit about precisions

GLSL ES requires that every symbol (variable, block member, function
parameter and return value) is appropriately qualified with a precision,
either individually or through the global precision specifier.

Some tree transformations however produced symbols with EbpUndefined
precision.  In text GLSL output, these would produce unqualified symbols
which was often incorrect.

In this change, the transformations are made to produce explicit / more
consistent precisions.  The validation (that caught these issues) is not
included in this change as there are still a few corner cases left to
address.

Bug: angleproject:4889
Bug: angleproject:6132
Change-Id: Icca8a0a5476f8646226e7243aa8f501f44acc164
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3075127
Reviewed-by: Tim Van Patten <timvp@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/compiler/translator/StaticType.h b/src/compiler/translator/StaticType.h
index 90b3f11..9d3a058 100644
--- a/src/compiler/translator/StaticType.h
+++ b/src/compiler/translator/StaticType.h
@@ -194,25 +194,32 @@
 // Overloads
 //
 
-template <TBasicType basicType, unsigned char primarySize = 1, unsigned char secondarySize = 1>
+template <TBasicType basicType,
+          TPrecision precision,
+          unsigned char primarySize   = 1,
+          unsigned char secondarySize = 1>
 constexpr const TType *GetBasic()
 {
-    return Get<basicType, EbpUndefined, EvqGlobal, primarySize, secondarySize>();
-}
-
-template <TBasicType basicType, unsigned char primarySize = 1, unsigned char secondarySize = 1>
-constexpr const TType *GetTemporary()
-{
-    return Get<basicType, EbpUndefined, EvqTemporary, primarySize, secondarySize>();
+    return Get<basicType, precision, EvqGlobal, primarySize, secondarySize>();
 }
 
 template <TBasicType basicType,
+          TPrecision precision,
+          unsigned char primarySize   = 1,
+          unsigned char secondarySize = 1>
+constexpr const TType *GetTemporary()
+{
+    return Get<basicType, precision, EvqTemporary, primarySize, secondarySize>();
+}
+
+template <TBasicType basicType,
+          TPrecision precision,
           TQualifier qualifier,
           unsigned char primarySize   = 1,
           unsigned char secondarySize = 1>
 const TType *GetQualified()
 {
-    return Get<basicType, EbpUndefined, qualifier, primarySize, secondarySize>();
+    return Get<basicType, precision, qualifier, primarySize, secondarySize>();
 }
 
 // Dynamic lookup methods (convert runtime values to template args)
@@ -242,15 +249,13 @@
             return Get<basicType, precision, qualifier, 4, secondarySize>();
         default:
             UNREACHABLE();
-            return GetBasic<EbtVoid>();
+            return GetBasic<EbtVoid, EbpUndefined>();
     }
 }
 
 }  // namespace Helpers
 
-template <TBasicType basicType,
-          TPrecision precision = EbpUndefined,
-          TQualifier qualifier = EvqGlobal>
+template <TBasicType basicType, TPrecision precision, TQualifier qualifier = EvqGlobal>
 constexpr const TType *GetForVecMat(unsigned char primarySize, unsigned char secondarySize = 1)
 {
     static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt ||
@@ -268,11 +273,11 @@
             return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 4>(primarySize);
         default:
             UNREACHABLE();
-            return GetBasic<EbtVoid>();
+            return GetBasic<EbtVoid, EbpUndefined>();
     }
 }
 
-template <TBasicType basicType, TPrecision precision = EbpUndefined>
+template <TBasicType basicType, TPrecision precision>
 constexpr const TType *GetForVec(TQualifier qualifier, unsigned char size)
 {
     switch (qualifier)
@@ -283,7 +288,7 @@
             return Helpers::GetForVecMatHelper<basicType, precision, EvqParamOut, 1>(size);
         default:
             UNREACHABLE();
-            return GetBasic<EbtVoid>();
+            return GetBasic<EbtVoid, EbpUndefined>();
     }
 }
 
diff --git a/src/compiler/translator/TranslatorMetal.cpp b/src/compiler/translator/TranslatorMetal.cpp
index a806b5a..0745abd 100644
--- a/src/compiler/translator/TranslatorMetal.cpp
+++ b/src/compiler/translator/TranslatorMetal.cpp
@@ -313,7 +313,7 @@
 
     TFunction *sampleMaskWriteFunc =
         new TFunction(symbolTable, kSampleMaskWriteFuncName, SymbolType::AngleInternal,
-                      StaticType::GetBasic<EbtVoid>(), false);
+                      StaticType::GetBasic<EbtVoid, EbpUndefined>(), false);
 
     TType *uintType = new TType(EbtUInt);
     TVariable *maskArg =
diff --git a/src/compiler/translator/TranslatorMetalDirect.cpp b/src/compiler/translator/TranslatorMetalDirect.cpp
index 2cdf053..91eb44d 100644
--- a/src/compiler/translator/TranslatorMetalDirect.cpp
+++ b/src/compiler/translator/TranslatorMetalDirect.cpp
@@ -266,7 +266,7 @@
     TIntermSwizzle *builtinXY    = new TIntermSwizzle(builtinRef, swizzleOffsetXY);
 
     // Create a symbol reference to our new variable that will hold the modified builtin.
-    const TType *type = StaticType::GetForVec<EbtFloat>(
+    const TType *type = StaticType::GetForVec<EbtFloat, EbpHigh>(
         EvqGlobal, static_cast<unsigned char>(builtin->getType().getNominalSize()));
     TVariable *replacementVar =
         new TVariable(symbolTable, flippedVariableName.rawName(), type, SymbolType::AngleInternal);
@@ -506,9 +506,9 @@
         new TVariable(symbolTable, sh::ImmutableString(sh::mtl::kCoverageMaskEnabledConstName),
                       boolType, SymbolType::AngleInternal);
 
-    TFunction *sampleMaskWriteFunc = new TFunction(symbolTable, kSampleMaskWriteFuncName.rawName(),
-                                                   kSampleMaskWriteFuncName.symbolType(),
-                                                   StaticType::GetBasic<EbtVoid>(), false);
+    TFunction *sampleMaskWriteFunc = new TFunction(
+        symbolTable, kSampleMaskWriteFuncName.rawName(), kSampleMaskWriteFuncName.symbolType(),
+        StaticType::GetBasic<EbtVoid, EbpUndefined>(), false);
 
     TType *uintType = new TType(EbtUInt);
     TVariable *maskArg =
diff --git a/src/compiler/translator/TranslatorVulkan.cpp b/src/compiler/translator/TranslatorVulkan.cpp
index c482cd6..5a2a1de 100644
--- a/src/compiler/translator/TranslatorVulkan.cpp
+++ b/src/compiler/translator/TranslatorVulkan.cpp
@@ -203,8 +203,9 @@
     TIntermSwizzle *builtinXY    = new TIntermSwizzle(builtinRef, swizzleOffsetXY);
 
     // Create a symbol reference to our new variable that will hold the modified builtin.
-    const TType *type = StaticType::GetForVec<EbtFloat>(
-        EvqGlobal, static_cast<unsigned char>(builtin->getType().getNominalSize()));
+    TType *type = new TType(builtin->getType());
+    type->setQualifier(EvqGlobal);
+    type->setPrimarySize(static_cast<unsigned char>(builtin->getType().getNominalSize()));
     TVariable *replacementVar =
         new TVariable(symbolTable, flippedVariableName, type, SymbolType::AngleInternal);
     DeclareGlobalVariable(root, replacementVar);
@@ -336,7 +337,7 @@
     // Clamp position to subpixel grid.
     // Do perspective divide (get normalized device coords)
     // "vec2 ndc = gl_Position.xy / gl_Position.w"
-    const TType *vec2Type        = StaticType::GetTemporary<EbtFloat, 2>();
+    const TType *vec2Type        = StaticType::GetTemporary<EbtFloat, EbpHigh, 2>();
     TIntermBinary *viewportRef   = driverUniforms->getViewportRef();
     TIntermSymbol *glPos         = new TIntermSymbol(BuiltInVariable::gl_Position());
     TIntermSwizzle *glPosXY      = CreateSwizzle(glPos, 0, 1);
@@ -414,7 +415,7 @@
 
     constexpr uint32_t kMaxXfbBuffers = 4;
 
-    const TType *ivec4Type = StaticType::GetBasic<EbtInt, kMaxXfbBuffers>();
+    const TType *ivec4Type = StaticType::GetBasic<EbtInt, EbpHigh, kMaxXfbBuffers>();
     TType *stridesType     = new TType(*ivec4Type);
     stridesType->setQualifier(EvqParamConst);
 
@@ -468,7 +469,7 @@
     //     void ANGLECaptureXfb()
     //     {
     //     }
-    const TType *voidType = StaticType::GetBasic<EbtVoid>();
+    const TType *voidType = StaticType::GetBasic<EbtVoid, EbpUndefined>();
 
     // Create the function body, which is empty.
     body = new TIntermBlock;
@@ -537,7 +538,7 @@
     for (uint32_t bufferIndex = 0; bufferIndex < kMaxXfbBuffers; ++bufferIndex)
     {
         TFieldList *fieldList = new TFieldList;
-        TType *xfbOutType     = new TType(EbtFloat);
+        TType *xfbOutType     = new TType(EbtFloat, EbpHigh, EvqGlobal);
         xfbOutType->makeArray(0);
 
         TField *field = new TField(xfbOutType, ImmutableString(vk::kXfbEmulationBufferFieldName),
@@ -685,7 +686,7 @@
                                               bool usesFragCoord)
 {
     TVariable *anglePosition = AddANGLEPositionVaryingDeclaration(root, symbolTable, EvqVaryingIn);
-    const TType *vec2Type    = StaticType::GetTemporary<EbtFloat, 2>();
+    const TType *vec2Type    = StaticType::GetTemporary<EbtFloat, EbpHigh, 2>();
 
     TIntermBinary *viewportRef = driverUniforms->getViewportRef();
 
diff --git a/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp b/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp
index 21b11a5..92b01df 100644
--- a/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp
+++ b/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp
@@ -67,8 +67,8 @@
             if (useFloatClamp)
             {
                 TIntermSequence constructorArgs = {max};
-                max = TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat>(),
-                                                          &constructorArgs);
+                max                             = TIntermAggregate::CreateConstructor(
+                    *StaticType::GetBasic<EbtFloat, EbpHigh>(), &constructorArgs);
             }
         }
         else if (leftType.isArray())
@@ -88,8 +88,8 @@
         const TBasicType requiredBasicType = useFloatClamp ? EbtFloat : EbtInt;
         if (rightType.getBasicType() != requiredBasicType)
         {
-            const TType *clampType =
-                useFloatClamp ? StaticType::GetBasic<EbtFloat>() : StaticType::GetBasic<EbtInt>();
+            const TType *clampType = useFloatClamp ? StaticType::GetBasic<EbtFloat, EbpHigh>()
+                                                   : StaticType::GetBasic<EbtInt, EbpHigh>();
             TIntermSequence constructorArgs = {index};
             index = TIntermAggregate::CreateConstructor(*clampType, &constructorArgs);
         }
@@ -106,7 +106,7 @@
         if (useFloatClamp)
         {
             TIntermSequence constructorArgs = {clamped};
-            clamped = TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtInt>(),
+            clamped = TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtInt, EbpHigh>(),
                                                           &constructorArgs);
         }
 
diff --git a/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp b/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp
index 0a34bf8..0b6ba7d 100644
--- a/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp
+++ b/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp
@@ -109,7 +109,7 @@
 
     TFunction *initGlobalsFunction =
         new TFunction(symbolTable, kInitGlobalsString, SymbolType::AngleInternal,
-                      StaticType::GetBasic<EbtVoid>(), false);
+                      StaticType::GetBasic<EbtVoid, EbpUndefined>(), false);
 
     TIntermFunctionPrototype *initGlobalsFunctionPrototype =
         CreateInternalFunctionPrototypeNode(*initGlobalsFunction);
diff --git a/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp b/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp
index 8ab2380..9659bd9 100644
--- a/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp
@@ -459,7 +459,7 @@
                         GetIndexFunctionName(node->getLeft()->getType(), true));
                     indexedWriteFunction =
                         new TFunction(mSymbolTable, functionName, SymbolType::AngleInternal,
-                                      StaticType::GetBasic<EbtVoid>(), false);
+                                      StaticType::GetBasic<EbtVoid, EbpUndefined>(), false);
                     indexedWriteFunction->addParameter(new TVariable(mSymbolTable, kBaseName,
                                                                      GetBaseType(type, true),
                                                                      SymbolType::AngleInternal));
diff --git a/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp b/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp
index d6cb90f..defc59b 100644
--- a/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp
+++ b/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp
@@ -27,7 +27,7 @@
 {
     // Define `uint counters[];` as the only field in the interface block.
     TFieldList *fieldList = new TFieldList;
-    TType *counterType    = new TType(EbtUInt);
+    TType *counterType    = new TType(EbtUInt, EbpHigh, EvqGlobal);
     counterType->makeArray(0);
 
     TField *countersField =
diff --git a/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp b/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp
index 9b19292..8a0d94a 100644
--- a/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp
+++ b/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp
@@ -394,7 +394,7 @@
 
         // Create the function parameters: vec3 P, vec3 dPdx, vec3 dPdy,
         //                                 out vec2 dUVdx, out vec2 dUVdy
-        const TType *vec3Type = StaticType::GetBasic<EbtFloat, 3>();
+        const TType *vec3Type = StaticType::GetBasic<EbtFloat, EbpHigh, 3>();
         TType *inVec3Type     = new TType(*vec3Type);
         inVec3Type->setQualifier(EvqParamIn);
 
@@ -405,7 +405,7 @@
         TVariable *dPdyVar = new TVariable(mSymbolTable, ImmutableString("dPdy"), inVec3Type,
                                            SymbolType::AngleInternal);
 
-        const TType *vec2Type = StaticType::GetBasic<EbtFloat, 2>();
+        const TType *vec2Type = StaticType::GetBasic<EbtFloat, EbpHigh, 2>();
         TType *outVec2Type    = new TType(*vec2Type);
         outVec2Type->setQualifier(EvqParamOut);
 
@@ -429,7 +429,7 @@
         TIntermSwizzle *z = new TIntermSwizzle(p->deepCopy(), {2});
 
         // Create abs and "< 0" expressions from the channels.
-        const TType *floatType = StaticType::GetBasic<EbtFloat>();
+        const TType *floatType = StaticType::GetBasic<EbtFloat, EbpHigh>();
 
         TIntermTyped *isNegX = new TIntermBinary(EOpLessThan, x, CreateZeroNode(*floatType));
         TIntermTyped *isNegY = new TIntermBinary(EOpLessThan, y, CreateZeroNode(*floatType));
@@ -456,7 +456,7 @@
         // Create temporary variable for division outer product matrix and its
         // derivatives.
         // recipOuter[i][j] = 0.5 * P[j] / P[i]
-        const TType *mat3Type     = StaticType::GetBasic<EbtFloat, 3, 3>();
+        const TType *mat3Type     = StaticType::GetBasic<EbtFloat, EbpHigh, 3, 3>();
         TIntermSymbol *recipOuter = new TIntermSymbol(CreateTempVariable(mSymbolTable, mat3Type));
 
         TIntermTyped *pRecip     = new TIntermBinary(EOpDiv, CreateFloatNode(1.0), p->deepCopy());
@@ -712,7 +712,7 @@
                                                         TIntermTyped *dUVdx,
                                                         TIntermTyped *dUVdy)
     {
-        const TType *vec3Type = StaticType::GetBasic<EbtFloat, 3>();
+        const TType *vec3Type = StaticType::GetBasic<EbtFloat, EbpHigh, 3>();
         TIntermTyped *dPdx    = CreateZeroNode(*vec3Type);
         TIntermTyped *dPdy    = CreateZeroNode(*vec3Type);
         TIntermSequence args  = {P, dPdx, dPdy, dUVdx, dUVdy};
@@ -840,8 +840,8 @@
         TIntermSequence *arguments = node->getSequence();
         ASSERT(arguments->size() >= 2);
 
-        const TType *vec2Type = StaticType::GetBasic<EbtFloat, 2>();
-        const TType *vec3Type = StaticType::GetBasic<EbtFloat, 3>();
+        const TType *vec2Type = StaticType::GetBasic<EbtFloat, EbpHigh, 2>();
+        const TType *vec3Type = StaticType::GetBasic<EbtFloat, EbpHigh, 3>();
         TIntermSymbol *uvl    = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type));
         TIntermSymbol *dUVdx  = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec2Type));
         TIntermSymbol *dUVdy  = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec2Type));
@@ -893,7 +893,7 @@
         TIntermTyped *dUVdyArg = dUVdy;
         if (hasBias)
         {
-            const TType *floatType   = StaticType::GetBasic<EbtFloat>();
+            const TType *floatType   = StaticType::GetBasic<EbtFloat, EbpHigh>();
             TIntermTyped *bias       = (*arguments)[2]->getAsTyped()->deepCopy();
             TIntermSequence exp2Args = {bias};
             TIntermTyped *exp2Call =
diff --git a/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp b/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp
index 540e7ed..466753e 100644
--- a/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp
+++ b/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp
@@ -713,8 +713,8 @@
         // a name autogenerated similar to temp variables, as nameless structs exist.  A fake
         // variable is created for the sole purpose of generating a temp name.
         TVariable *newStructTypeName =
-            new TVariable(mSymbolTable, kEmptyImmutableString, StaticType::GetBasic<EbtUInt>(),
-                          SymbolType::Empty);
+            new TVariable(mSymbolTable, kEmptyImmutableString,
+                          StaticType::GetBasic<EbtUInt, EbpUndefined>(), SymbolType::Empty);
 
         TStructure *newStruct = new TStructure(mSymbolTable, newStructTypeName->name(), newFields,
                                                SymbolType::AngleInternal);
diff --git a/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp b/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp
index 71f44e3..a5e0b62 100644
--- a/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp
+++ b/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp
@@ -121,7 +121,7 @@
                               SymbolType::AngleInternal);
             TFunction *func = new TFunction(mSymbolTable, node->getFunction()->name(),
                                             node->getFunction()->symbolType(),
-                                            StaticType::GetBasic<EbtVoid>(), false);
+                                            StaticType::GetBasic<EbtVoid, EbpUndefined>(), false);
             for (size_t i = 0; i < node->getFunction()->getParamCount(); ++i)
             {
                 func->addParameter(node->getFunction()->getParam(i));
diff --git a/src/compiler/translator/tree_ops/vulkan/DeclarePerVertexBlocks.cpp b/src/compiler/translator/tree_ops/vulkan/DeclarePerVertexBlocks.cpp
index 8b7f265..8643d71 100644
--- a/src/compiler/translator/tree_ops/vulkan/DeclarePerVertexBlocks.cpp
+++ b/src/compiler/translator/tree_ops/vulkan/DeclarePerVertexBlocks.cpp
@@ -281,8 +281,8 @@
     {
         TFieldList *fields = new TFieldList;
 
-        const TType *vec4Type  = StaticType::GetBasic<EbtFloat, 4>();
-        const TType *floatType = StaticType::GetBasic<EbtFloat, 1>();
+        const TType *vec4Type  = StaticType::GetBasic<EbtFloat, EbpHigh, 4>();
+        const TType *floatType = StaticType::GetBasic<EbtFloat, EbpHigh, 1>();
 
         TType *positionType     = new TType(*vec4Type);
         TType *pointSizeType    = new TType(*floatType);
@@ -294,6 +294,8 @@
         clipDistanceType->setQualifier(EvqClipDistance);
         cullDistanceType->setQualifier(EvqCullDistance);
 
+        pointSizeType->setPrecision(EbpMedium);
+
         // TODO: handle interaction with GS and T*S where the two can have different sizes.  These
         // values are valid for EvqPerVertexOut only.  For EvqPerVertexIn, the size should come from
         // the declaration of gl_in.  http://anglebug.com/5466.
diff --git a/src/compiler/translator/tree_ops/vulkan/RewriteR32fImages.cpp b/src/compiler/translator/tree_ops/vulkan/RewriteR32fImages.cpp
index ddf0277..901c685 100644
--- a/src/compiler/translator/tree_ops/vulkan/RewriteR32fImages.cpp
+++ b/src/compiler/translator/tree_ops/vulkan/RewriteR32fImages.cpp
@@ -237,7 +237,7 @@
         if (isImageLoad)
         {
             // vec4(uintBitsToFloat(imageLoad().rgb), 1.0)
-            const TType &vec4Type           = *StaticType::GetBasic<EbtFloat, 4>();
+            const TType &vec4Type           = *StaticType::GetBasic<EbtFloat, EbpHigh, 4>();
             TIntermSequence constructorArgs = {replacementCall, CreateFloatNode(1.0f)};
             replacementCall = TIntermAggregate::CreateConstructor(vec4Type, &constructorArgs);
         }
diff --git a/src/compiler/translator/tree_util/DriverUniform.cpp b/src/compiler/translator/tree_util/DriverUniform.cpp
index 9ab5067..bb963a5 100644
--- a/src/compiler/translator/tree_util/DriverUniform.cpp
+++ b/src/compiler/translator/tree_util/DriverUniform.cpp
@@ -54,7 +54,7 @@
     TFieldList *driverFieldList = new TFieldList;
 
     const std::array<TType *, kNumComputeDriverUniforms> kDriverUniformTypes = {{
-        new TType(EbtUInt, 4),
+        new TType(EbtUInt, EbpHigh, EvqGlobal, 4),
     }};
 
     for (size_t uniformIndex = 0; uniformIndex < kNumComputeDriverUniforms; ++uniformIndex)
@@ -88,13 +88,14 @@
     TFieldList *driverFieldList = new TFieldList;
 
     const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{
-        new TType(EbtFloat, 4),
-        new TType(EbtUInt),  // uint clipDistancesEnabled;  // 32 bits for 32 clip distances max
-        new TType(EbtUInt),
-        new TType(EbtInt),
-        new TType(EbtInt),
-        new TType(EbtInt, 4),
-        new TType(EbtUInt, 4),
+        new TType(EbtFloat, EbpHigh, EvqGlobal, 4),
+        new TType(EbtUInt, EbpHigh,
+                  EvqGlobal),  // uint clipDistancesEnabled;  // 32 bits for 32 clip distances max
+        new TType(EbtUInt, EbpLow, EvqGlobal),  // uint xfbActiveUnpaused;  // 1 bit
+        new TType(EbtInt, EbpHigh, EvqGlobal),
+        new TType(EbtInt, EbpLow, EvqGlobal),  // uint numSamples;         // Up to 16
+        new TType(EbtInt, EbpHigh, EvqGlobal, 4),
+        new TType(EbtUInt, EbpHigh, EvqGlobal, 4),
         createEmulatedDepthRangeType(symbolTable),
     }};
 
@@ -120,19 +121,16 @@
 
     // Create the depth range type.
     TFieldList *depthRangeParamsFields = new TFieldList();
-    depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
-                                                 ImmutableString("near"), TSourceLoc(),
-                                                 SymbolType::AngleInternal));
-    depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
-                                                 ImmutableString("far"), TSourceLoc(),
-                                                 SymbolType::AngleInternal));
-    depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
-                                                 ImmutableString("diff"), TSourceLoc(),
-                                                 SymbolType::AngleInternal));
+    TType *floatType                   = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1);
+    depthRangeParamsFields->push_back(
+        new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal));
+    depthRangeParamsFields->push_back(
+        new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal));
+    depthRangeParamsFields->push_back(
+        new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal));
     // This additional field might be used by subclass such as TranslatorMetal.
-    depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
-                                                 ImmutableString("reserved"), TSourceLoc(),
-                                                 SymbolType::AngleInternal));
+    depthRangeParamsFields->push_back(new TField(floatType, ImmutableString("reserved"),
+                                                 TSourceLoc(), SymbolType::AngleInternal));
 
     TStructure *emulatedDepthRangeParams = new TStructure(
         symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
@@ -208,7 +206,7 @@
     TConstantUnion *uniformIndex    = new TConstantUnion;
     uniformIndex->setIConst(static_cast<int>(fieldIndex));
     TIntermConstantUnion *indexRef =
-        new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt>());
+        new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt, EbpLow>());
     if (mMode == DriverUniformMode::InterfaceBlock)
     {
         return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef);
@@ -277,13 +275,13 @@
                                            kPreRotation}};
 
     const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{
-        new TType(EbtFloat, 2),
-        new TType(EbtFloat, 2),
-        new TType(EbtFloat, 2),
-        new TType(EbtUInt),
-        new TType(EbtUInt),
-        new TType(EbtFloat, 2, 2),
-        new TType(EbtFloat, 2, 2),
+        new TType(EbtFloat, EbpHigh, EvqGlobal, 2),
+        new TType(EbtFloat, EbpLow, EvqGlobal, 2),
+        new TType(EbtFloat, EbpLow, EvqGlobal, 2),
+        new TType(EbtUInt, EbpHigh, EvqGlobal),
+        new TType(EbtUInt, EbpHigh, EvqGlobal),
+        new TType(EbtFloat, EbpLow, EvqGlobal, 2, 2),
+        new TType(EbtFloat, EbpLow, EvqGlobal, 2, 2),
     }};
 
     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex)
diff --git a/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp b/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp
index 7bf26cd..739fade 100644
--- a/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp
+++ b/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp
@@ -259,7 +259,7 @@
 
     unsigned int getEnabledClipCullDistance(const bool useNonConstIndex,
                                             const unsigned int maxConstIndex);
-    const TVariable *declareANGLEVariable();
+    const TVariable *declareANGLEVariable(const TVariable *originalVariable);
     bool assignOriginalValueToANGLEVariable(const GLenum shaderType);
     bool assignANGLEValueToOriginalVariable(const GLenum shaderType,
                                             const bool isRedeclared,
@@ -305,11 +305,14 @@
     return mEnabledDistances;
 }
 
-const TVariable *ReplaceClipCullDistanceAssignments::declareANGLEVariable()
+const TVariable *ReplaceClipCullDistanceAssignments::declareANGLEVariable(
+    const TVariable *originalVariable)
 {
     ASSERT(mEnabledDistances > 0);
 
-    TType *clipCullDistanceType = new TType(EbtFloat, EbpMedium, EvqGlobal, 1);
+    TType *clipCullDistanceType = new TType(originalVariable->getType());
+    clipCullDistanceType->setQualifier(EvqGlobal);
+    clipCullDistanceType->toArrayBaseType();
     clipCullDistanceType->makeArray(mEnabledDistances);
 
     mANGLEVar =
@@ -522,7 +525,7 @@
         return false;
     }
 
-    const TVariable *replacementVar = replacementUtils.declareANGLEVariable();
+    const TVariable *replacementVar = replacementUtils.declareANGLEVariable(builtInVar);
 
     // Replace gl_ClipDistance reference with ANGLEClipDistance, except the declaration
     ReplaceVariableExceptOneTraverser replaceTraverser(builtInVar,
diff --git a/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp b/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp
index 68723ee..2996ef8 100644
--- a/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp
+++ b/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp
@@ -72,7 +72,7 @@
     // Replace main() with main0() with the same body.
     TFunction *oldMain =
         new TFunction(symbolTable, kEmptyImmutableString, SymbolType::AngleInternal,
-                      StaticType::GetBasic<EbtVoid>(), false);
+                      StaticType::GetBasic<EbtVoid, EbpUndefined>(), false);
     TIntermFunctionDefinition *oldMainDefinition =
         CreateInternalFunctionDefinitionNode(*oldMain, main->getBody());
 
@@ -81,7 +81,7 @@
 
     // void main()
     TFunction *newMain = new TFunction(symbolTable, kMainString, SymbolType::UserDefined,
-                                       StaticType::GetBasic<EbtVoid>(), false);
+                                       StaticType::GetBasic<EbtVoid, EbpUndefined>(), false);
     TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype(newMain);
 
     // {
diff --git a/src/compiler/translator/tree_util/SpecializationConstant.cpp b/src/compiler/translator/tree_util/SpecializationConstant.cpp
index a23aa98..45106c7 100644
--- a/src/compiler/translator/tree_util/SpecializationConstant.cpp
+++ b/src/compiler/translator/tree_util/SpecializationConstant.cpp
@@ -211,7 +211,7 @@
                                                 float scale,
                                                 TIntermSymbol *rotation)
 {
-    const TType *floatType = StaticType::GetBasic<EbtFloat>();
+    const TType *floatType = StaticType::GetBasic<EbtFloat, EbpHigh>();
     TType *typeFloat8      = new TType(*floatType);
     typeFloat8->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
 
@@ -318,7 +318,7 @@
     }
     if (mLineRasterEmulationVar == nullptr)
     {
-        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtBool>(),
+        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
                                           vk::SpecializationConstantId::LineRasterEmulation);
 
         mLineRasterEmulationVar = new TVariable(mSymbolTable, kLineRasterEmulationSpecConstVarName,
@@ -332,7 +332,7 @@
 {
     if (mSurfaceRotationVar == nullptr)
     {
-        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtUInt>(),
+        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtUInt, EbpHigh>(),
                                           vk::SpecializationConstantId::SurfaceRotation);
 
         mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type,
@@ -489,7 +489,7 @@
 {
     if (mDrawableWidthVar == nullptr)
     {
-        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
+        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat, EbpHigh>(),
                                           vk::SpecializationConstantId::DrawableWidth);
 
         mDrawableWidthVar = new TVariable(mSymbolTable, kDrawableWidthSpecConstVarName, type,
@@ -502,7 +502,7 @@
 {
     if (mDrawableHeightVar == nullptr)
     {
-        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
+        const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat, EbpHigh>(),
                                           vk::SpecializationConstantId::DrawableHeight);
 
         mDrawableHeightVar = new TVariable(mSymbolTable, kDrawableHeightSpecConstVarName, type,
diff --git a/src/libANGLE/renderer/glslang_wrapper_utils.cpp b/src/libANGLE/renderer/glslang_wrapper_utils.cpp
index 0cc3daa..57f91d7 100644
--- a/src/libANGLE/renderer/glslang_wrapper_utils.cpp
+++ b/src/libANGLE/renderer/glslang_wrapper_utils.cpp
@@ -1395,8 +1395,10 @@
     //
     // - OpMemberDecorate %gl_PerVertex N BuiltIn B
     // - OpMemberDecorate %gl_PerVertex N Invariant
+    // - OpMemberDecorate %gl_PerVertex N RelaxedPrecision
     if (!ids.isPerVertex(typeId) ||
-        (decoration != spv::DecorationBuiltIn && decoration != spv::DecorationInvariant))
+        (decoration != spv::DecorationBuiltIn && decoration != spv::DecorationInvariant &&
+         decoration != spv::DecorationRelaxedPrecision))
     {
         return TransformationState::Unchanged;
     }
diff --git a/src/tests/compiler_tests/ShaderImage_test.cpp b/src/tests/compiler_tests/ShaderImage_test.cpp
index 321b7fe..993b59e 100644
--- a/src/tests/compiler_tests/ShaderImage_test.cpp
+++ b/src/tests/compiler_tests/ShaderImage_test.cpp
@@ -190,14 +190,14 @@
 
     // imageLoad call with image2D passed
     std::string mangledName2D = "imageLoad(";
-    mangledName2D += StaticType::GetBasic<EbtImage2D>()->getMangledName();
-    mangledName2D += StaticType::GetBasic<EbtInt, 2>()->getMangledName();
+    mangledName2D += StaticType::GetBasic<EbtImage2D, EbpUndefined>()->getMangledName();
+    mangledName2D += StaticType::GetBasic<EbtInt, EbpUndefined, 2>()->getMangledName();
     CheckImageLoadCall(mASTRoot, mangledName2D.c_str(), EbtImage2D, 2);
 
     // imageLoad call with image3D passed
     std::string mangledName3D = "imageLoad(";
-    mangledName3D += StaticType::GetBasic<EbtIImage3D>()->getMangledName();
-    mangledName3D += StaticType::GetBasic<EbtInt, 3>()->getMangledName();
+    mangledName3D += StaticType::GetBasic<EbtIImage3D, EbpUndefined>()->getMangledName();
+    mangledName3D += StaticType::GetBasic<EbtInt, EbpUndefined, 3>()->getMangledName();
     CheckImageLoadCall(mASTRoot, mangledName3D.c_str(), EbtIImage3D, 3);
 }
 
@@ -220,16 +220,16 @@
 
     // imageStore call with image2D
     std::string mangledName2D = "imageStore(";
-    mangledName2D += StaticType::GetBasic<EbtImage2D>()->getMangledName();
-    mangledName2D += StaticType::GetBasic<EbtInt, 2>()->getMangledName();
-    mangledName2D += StaticType::GetBasic<EbtFloat, 4>()->getMangledName();
+    mangledName2D += StaticType::GetBasic<EbtImage2D, EbpUndefined>()->getMangledName();
+    mangledName2D += StaticType::GetBasic<EbtInt, EbpUndefined, 2>()->getMangledName();
+    mangledName2D += StaticType::GetBasic<EbtFloat, EbpUndefined, 4>()->getMangledName();
     CheckImageStoreCall(mASTRoot, mangledName2D.c_str(), EbtImage2D, 2, EbtFloat, 4);
 
     // imageStore call with image2DArray
     std::string mangledName2DArray = "imageStore(";
-    mangledName2DArray += StaticType::GetBasic<EbtUImage2DArray>()->getMangledName();
-    mangledName2DArray += StaticType::GetBasic<EbtInt, 3>()->getMangledName();
-    mangledName2DArray += StaticType::GetBasic<EbtUInt, 4>()->getMangledName();
+    mangledName2DArray += StaticType::GetBasic<EbtUImage2DArray, EbpUndefined>()->getMangledName();
+    mangledName2DArray += StaticType::GetBasic<EbtInt, EbpUndefined, 3>()->getMangledName();
+    mangledName2DArray += StaticType::GetBasic<EbtUInt, EbpUndefined, 4>()->getMangledName();
     CheckImageStoreCall(mASTRoot, mangledName2DArray.c_str(), EbtUImage2DArray, 3, EbtUInt, 4);
 }