re-land of new SkSL precisions

Bug: skia:
Change-Id: Ic1deb3db2cbda6ca45f93dee99832971a36a2119
Reviewed-on: https://skia-review.googlesource.com/47841
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/bench/GLInstancedArraysBench.cpp b/bench/GLInstancedArraysBench.cpp
index 37d1f2c..a5348d5 100644
--- a/bench/GLInstancedArraysBench.cpp
+++ b/bench/GLInstancedArraysBench.cpp
@@ -111,9 +111,9 @@
     const char* version = shaderCaps->versionDeclString();
 
     // setup vertex shader
-    GrShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
-    GrShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kIn_TypeModifier);
-    GrShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar aPosition("a_position", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar aColor("a_color", kHalf3_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar oColor("o_color", kHalf3_GrSLType, GrShaderVar::kOut_TypeModifier);
 
     SkString vshaderTxt(version);
     aPosition.appendDecl(shaderCaps, &vshaderTxt);
@@ -126,14 +126,13 @@
     vshaderTxt.append(
             "void main()\n"
             "{\n"
-                "gl_Position = float4(a_position, 0., 1.);\n"
+                "gl_Position = highfloat4(a_position, 0., 1.);\n"
                 "o_color = a_color;\n"
             "}\n");
 
     // setup fragment shader
-    GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
     SkString fshaderTxt(version);
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
     oColor.setTypeModifier(GrShaderVar::kIn_TypeModifier);
     oColor.appendDecl(shaderCaps, &fshaderTxt);
     fshaderTxt.append(";\n");
@@ -150,7 +149,7 @@
     fshaderTxt.appendf(
             "void main()\n"
             "{\n"
-                "%s = float4(o_color, 1.0);\n"
+                "%s = highfloat4(o_color, 1.0);\n"
             "}\n", fsOutName);
 
     return CreateProgram(ctx, vshaderTxt.c_str(), fshaderTxt.c_str());
diff --git a/bench/GLVec4ScalarBench.cpp b/bench/GLVec4ScalarBench.cpp
index fab397b..413e766 100644
--- a/bench/GLVec4ScalarBench.cpp
+++ b/bench/GLVec4ScalarBench.cpp
@@ -101,10 +101,10 @@
     // corner of the screen than the previous circle.
 
     // set up vertex shader; this is a trivial vertex shader that passes through position and color
-    GrShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
-    GrShaderVar oPosition("o_position", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier);
-    GrShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kIn_TypeModifier);
-    GrShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar aPosition("a_position", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar oPosition("o_position", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar aColor("a_color", kHalf3_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar oColor("o_color", kHalf3_GrSLType, GrShaderVar::kOut_TypeModifier);
 
     SkString vshaderTxt(version);
     aPosition.appendDecl(shaderCaps, &vshaderTxt);
@@ -119,7 +119,7 @@
     vshaderTxt.append(
             "void main()\n"
             "{\n"
-            "    gl_Position = float4(a_position, 0.0, 1.0);\n"
+            "    gl_Position = highfloat4(a_position, 0.0, 1.0);\n"
             "    o_position = a_position;\n"
             "    o_color = a_color;\n"
             "}\n");
@@ -129,9 +129,8 @@
     // coded center and compare that to some hard-coded circle radius to compute a coverage.
     // Then, this coverage is mixed with the coverage from the previous stage and passed to the
     // next stage.
-    GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
     SkString fshaderTxt(version);
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
     oPosition.setTypeModifier(GrShaderVar::kIn_TypeModifier);
     oPosition.appendDecl(shaderCaps, &fshaderTxt);
     fshaderTxt.append(";\n");
@@ -152,13 +151,13 @@
     fshaderTxt.appendf(
             "void main()\n"
             "{\n"
-            "    float4 outputColor;\n"
+            "    half4 outputColor;\n"
             "    %s outputCoverage;\n"
-            "    outputColor = float4(%s, 1.0);\n"
+            "    outputColor = half4(%s, 1.0);\n"
             "    outputCoverage = %s;\n",
-            fCoverageSetup == kUseVec4_CoverageSetup ? "float4" : "float",
+            fCoverageSetup == kUseVec4_CoverageSetup ? "half4" : "half",
             oColor.getName().c_str(),
-            fCoverageSetup == kUseVec4_CoverageSetup ? "float4(1.0)" : "1.0"
+            fCoverageSetup == kUseVec4_CoverageSetup ? "half4(1.0)" : "1.0"
             );
 
     float radius = 1.0f;
@@ -167,13 +166,13 @@
         float centerY = 1.0f - radius;
         fshaderTxt.appendf(
             "    {\n"
-            "        float d = length(%s - float2(%f, %f));\n"
-            "        float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n"
+            "        half d = length(%s - half2(%f, %f));\n"
+            "        half edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n"
             "        outputCoverage = 0.5 * outputCoverage + 0.5 * %s;\n"
             "    }\n",
             oPosition.getName().c_str(), centerX, centerY,
             radius,
-            fCoverageSetup == kUseVec4_CoverageSetup ? "float4(edgeAlpha)" : "edgeAlpha"
+            fCoverageSetup == kUseVec4_CoverageSetup ? "half4(edgeAlpha)" : "edgeAlpha"
             );
         radius *= 0.8f;
     }
diff --git a/bench/GLVertexAttributesBench.cpp b/bench/GLVertexAttributesBench.cpp
index 3980a0b..f10bd11 100644
--- a/bench/GLVertexAttributesBench.cpp
+++ b/bench/GLVertexAttributesBench.cpp
@@ -69,7 +69,7 @@
     const char* version = shaderCaps->versionDeclString();
 
     // setup vertex shader
-    GrShaderVar aPosition("a_position", kVec4f_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar aPosition("a_position", kHighFloat4_GrSLType, GrShaderVar::kIn_TypeModifier);
     SkTArray<GrShaderVar> aVars;
     SkTArray<GrShaderVar> oVars;
 
@@ -81,7 +81,7 @@
         SkString aname;
         aname.appendf("a_color_%d", i);
         aVars.push_back(GrShaderVar(aname.c_str(),
-                                    kVec4f_GrSLType,
+                                    kHalf4_GrSLType,
                                     GrShaderVar::kIn_TypeModifier));
         aVars.back().appendDecl(shaderCaps, &vshaderTxt);
         vshaderTxt.append(";\n");
@@ -92,7 +92,7 @@
         SkString oname;
         oname.appendf("o_color_%d", i);
         oVars.push_back(GrShaderVar(oname.c_str(),
-                                    kVec4f_GrSLType,
+                                    kHalf4_GrSLType,
                                     GrShaderVar::kOut_TypeModifier));
         oVars.back().appendDecl(shaderCaps, &vshaderTxt);
         vshaderTxt.append(";\n");
@@ -109,15 +109,14 @@
 
     // Passthrough position as a dummy
     for (uint32_t i = attribs; i < maxAttribs; i++) {
-        vshaderTxt.appendf("%s = float4(0, 0, 0, 1);\n", oVars[i].c_str());
+        vshaderTxt.appendf("%s = highfloat4(0, 0, 0, 1);\n", oVars[i].c_str());
     }
 
     vshaderTxt.append("}\n");
 
     // setup fragment shader
-    GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
     SkString fshaderTxt(version);
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps, &fshaderTxt);
 
     const char* fsOutName;
     if (shaderCaps->mustDeclareFragmentShaderOutput()) {
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 9c5d3c0..cfa5bbc 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -95,19 +95,28 @@
 enum GrSLType {
     kVoid_GrSLType,
     kBool_GrSLType,
+    kShort_GrSLType,
+    kUShort_GrSLType,
+    kHighFloat_GrSLType,
+    kHighFloat2_GrSLType,
+    kHighFloat3_GrSLType,
+    kHighFloat4_GrSLType,
+    kHighFloat2x2_GrSLType,
+    kHighFloat3x3_GrSLType,
+    kHighFloat4x4_GrSLType,
+    kHalf_GrSLType,
+    kHalf2_GrSLType,
+    kHalf3_GrSLType,
+    kHalf4_GrSLType,
+    kHalf2x2_GrSLType,
+    kHalf3x3_GrSLType,
+    kHalf4x4_GrSLType,
     kInt_GrSLType,
+    kInt2_GrSLType,
+    kInt3_GrSLType,
+    kInt4_GrSLType,
     kUint_GrSLType,
-    kFloat_GrSLType,
-    kVec2f_GrSLType,
-    kVec3f_GrSLType,
-    kVec4f_GrSLType,
-    kVec2us_GrSLType,
-    kVec2i_GrSLType,
-    kVec3i_GrSLType,
-    kVec4i_GrSLType,
-    kMat22f_GrSLType,
-    kMat33f_GrSLType,
-    kMat44f_GrSLType,
+    kUint2_GrSLType,
     kTexture2DSampler_GrSLType,
     kITexture2DSampler_GrSLType,
     kTextureExternalSampler_GrSLType,
@@ -161,13 +170,20 @@
 /** Is the shading language type float (including vectors/matrices)? */
 static inline bool GrSLTypeIsFloatType(GrSLType type) {
     switch (type) {
-        case kFloat_GrSLType:
-        case kVec2f_GrSLType:
-        case kVec3f_GrSLType:
-        case kVec4f_GrSLType:
-        case kMat22f_GrSLType:
-        case kMat33f_GrSLType:
-        case kMat44f_GrSLType:
+        case kHighFloat_GrSLType:
+        case kHighFloat2_GrSLType:
+        case kHighFloat3_GrSLType:
+        case kHighFloat4_GrSLType:
+        case kHighFloat2x2_GrSLType:
+        case kHighFloat3x3_GrSLType:
+        case kHighFloat4x4_GrSLType:
+        case kHalf_GrSLType:
+        case kHalf2_GrSLType:
+        case kHalf3_GrSLType:
+        case kHalf4_GrSLType:
+        case kHalf2x2_GrSLType:
+        case kHalf3x3_GrSLType:
+        case kHalf4x4_GrSLType:
             return true;
 
         case kVoid_GrSLType:
@@ -177,12 +193,14 @@
         case kTexture2DRectSampler_GrSLType:
         case kBufferSampler_GrSLType:
         case kBool_GrSLType:
+        case kShort_GrSLType:
+        case kUShort_GrSLType:
         case kInt_GrSLType:
+        case kInt2_GrSLType:
+        case kInt3_GrSLType:
+        case kInt4_GrSLType:
         case kUint_GrSLType:
-        case kVec2us_GrSLType:
-        case kVec2i_GrSLType:
-        case kVec3i_GrSLType:
-        case kVec4i_GrSLType:
+        case kUint2_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
         case kImageStorage2D_GrSLType:
@@ -202,21 +220,30 @@
             return true;
 
         case kVoid_GrSLType:
-        case kFloat_GrSLType:
-        case kVec2f_GrSLType:
-        case kVec3f_GrSLType:
-        case kVec4f_GrSLType:
-        case kVec2us_GrSLType:
-        case kVec2i_GrSLType:
-        case kVec3i_GrSLType:
-        case kVec4i_GrSLType:
-        case kMat22f_GrSLType:
-        case kMat33f_GrSLType:
-        case kMat44f_GrSLType:
-        case kBufferSampler_GrSLType:
+        case kHighFloat_GrSLType:
+        case kHighFloat2_GrSLType:
+        case kHighFloat3_GrSLType:
+        case kHighFloat4_GrSLType:
+        case kHighFloat2x2_GrSLType:
+        case kHighFloat3x3_GrSLType:
+        case kHighFloat4x4_GrSLType:
+        case kHalf_GrSLType:
+        case kHalf2_GrSLType:
+        case kHalf3_GrSLType:
+        case kHalf4_GrSLType:
+        case kHalf2x2_GrSLType:
+        case kHalf3x3_GrSLType:
+        case kHalf4x4_GrSLType:
         case kInt_GrSLType:
+        case kInt2_GrSLType:
+        case kInt3_GrSLType:
+        case kInt4_GrSLType:
         case kUint_GrSLType:
+        case kUint2_GrSLType:
+        case kBufferSampler_GrSLType:
         case kBool_GrSLType:
+        case kShort_GrSLType:
+        case kUShort_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
         case kImageStorage2D_GrSLType:
@@ -237,20 +264,29 @@
             return true;
 
         case kVoid_GrSLType:
-        case kFloat_GrSLType:
-        case kVec2f_GrSLType:
-        case kVec3f_GrSLType:
-        case kVec4f_GrSLType:
-        case kVec2us_GrSLType:
-        case kVec2i_GrSLType:
-        case kVec3i_GrSLType:
-        case kVec4i_GrSLType:
-        case kMat22f_GrSLType:
-        case kMat33f_GrSLType:
-        case kMat44f_GrSLType:
+        case kHighFloat_GrSLType:
+        case kHighFloat2_GrSLType:
+        case kHighFloat3_GrSLType:
+        case kHighFloat4_GrSLType:
+        case kHighFloat2x2_GrSLType:
+        case kHighFloat3x3_GrSLType:
+        case kHighFloat4x4_GrSLType:
+        case kHalf_GrSLType:
+        case kHalf2_GrSLType:
+        case kHalf3_GrSLType:
+        case kHalf4_GrSLType:
+        case kHalf2x2_GrSLType:
+        case kHalf3x3_GrSLType:
+        case kHalf4x4_GrSLType:
         case kInt_GrSLType:
+        case kInt2_GrSLType:
+        case kInt3_GrSLType:
+        case kInt4_GrSLType:
         case kUint_GrSLType:
+        case kUint2_GrSLType:
         case kBool_GrSLType:
+        case kShort_GrSLType:
+        case kUShort_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
         case kImageStorage2D_GrSLType:
@@ -268,20 +304,29 @@
             return true;
 
         case kVoid_GrSLType:
-        case kFloat_GrSLType:
-        case kVec2f_GrSLType:
-        case kVec3f_GrSLType:
-        case kVec4f_GrSLType:
-        case kVec2us_GrSLType:
-        case kVec2i_GrSLType:
-        case kVec3i_GrSLType:
-        case kVec4i_GrSLType:
-        case kMat22f_GrSLType:
-        case kMat33f_GrSLType:
-        case kMat44f_GrSLType:
+        case kHighFloat_GrSLType:
+        case kHighFloat2_GrSLType:
+        case kHighFloat3_GrSLType:
+        case kHighFloat4_GrSLType:
+        case kHighFloat2x2_GrSLType:
+        case kHighFloat3x3_GrSLType:
+        case kHighFloat4x4_GrSLType:
+        case kHalf_GrSLType:
+        case kHalf2_GrSLType:
+        case kHalf3_GrSLType:
+        case kHalf4_GrSLType:
+        case kHalf2x2_GrSLType:
+        case kHalf3x3_GrSLType:
+        case kHalf4x4_GrSLType:
         case kInt_GrSLType:
+        case kInt2_GrSLType:
+        case kInt3_GrSLType:
+        case kInt4_GrSLType:
         case kUint_GrSLType:
+        case kUint2_GrSLType:
         case kBool_GrSLType:
+        case kShort_GrSLType:
+        case kUShort_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
         case kTexture2DSampler_GrSLType:
@@ -297,19 +342,73 @@
 
 static inline bool GrSLTypeAcceptsPrecision(GrSLType type) {
     switch (type) {
+        case kTexture2DSampler_GrSLType:
+        case kITexture2DSampler_GrSLType:
+        case kTextureExternalSampler_GrSLType:
+        case kTexture2DRectSampler_GrSLType:
+        case kBufferSampler_GrSLType:
+        case kTexture2D_GrSLType:
+        case kSampler_GrSLType:
+        case kImageStorage2D_GrSLType:
+        case kIImageStorage2D_GrSLType:
+            return true;
+
+        case kVoid_GrSLType:
+        case kBool_GrSLType:
+        case kShort_GrSLType:
+        case kUShort_GrSLType:
+        case kHighFloat_GrSLType:
+        case kHighFloat2_GrSLType:
+        case kHighFloat3_GrSLType:
+        case kHighFloat4_GrSLType:
+        case kHighFloat2x2_GrSLType:
+        case kHighFloat3x3_GrSLType:
+        case kHighFloat4x4_GrSLType:
+        case kHalf_GrSLType:
+        case kHalf2_GrSLType:
+        case kHalf3_GrSLType:
+        case kHalf4_GrSLType:
+        case kHalf2x2_GrSLType:
+        case kHalf3x3_GrSLType:
+        case kHalf4x4_GrSLType:
         case kInt_GrSLType:
+        case kInt2_GrSLType:
+        case kInt3_GrSLType:
+        case kInt4_GrSLType:
         case kUint_GrSLType:
-        case kFloat_GrSLType:
-        case kVec2f_GrSLType:
-        case kVec3f_GrSLType:
-        case kVec4f_GrSLType:
-        case kVec2us_GrSLType:
-        case kVec2i_GrSLType:
-        case kVec3i_GrSLType:
-        case kVec4i_GrSLType:
-        case kMat22f_GrSLType:
-        case kMat33f_GrSLType:
-        case kMat44f_GrSLType:
+        case kUint2_GrSLType:
+            return false;
+    }
+    SK_ABORT("Unexpected type");
+    return false;
+}
+
+// temporarily accepting (but ignoring) precision modifiers on the new types; this will be killed
+// in a future CL
+static inline bool GrSLTypeTemporarilyAcceptsPrecision(GrSLType type) {
+    switch (type) {
+        case kShort_GrSLType:
+        case kUShort_GrSLType:
+        case kHighFloat_GrSLType:
+        case kHighFloat2_GrSLType:
+        case kHighFloat3_GrSLType:
+        case kHighFloat4_GrSLType:
+        case kHighFloat2x2_GrSLType:
+        case kHighFloat3x3_GrSLType:
+        case kHighFloat4x4_GrSLType:
+        case kHalf_GrSLType:
+        case kHalf2_GrSLType:
+        case kHalf3_GrSLType:
+        case kHalf4_GrSLType:
+        case kHalf2x2_GrSLType:
+        case kHalf3x3_GrSLType:
+        case kHalf4x4_GrSLType:
+        case kInt_GrSLType:
+        case kInt2_GrSLType:
+        case kInt3_GrSLType:
+        case kInt4_GrSLType:
+        case kUint_GrSLType:
+        case kUint2_GrSLType:
         case kTexture2DSampler_GrSLType:
         case kITexture2DSampler_GrSLType:
         case kTextureExternalSampler_GrSLType:
@@ -398,25 +497,25 @@
 static inline GrSLType GrVertexAttribTypeToSLType(GrVertexAttribType type) {
     switch (type) {
         case kVec2us_norm_GrVertexAttribType: // fall through
-            return kVec2f_GrSLType;
+            return kHighFloat2_GrSLType;
         case kVec2us_uint_GrVertexAttribType:
-            return kVec2us_GrSLType;
+            return kUint2_GrSLType;
         case kUByte_GrVertexAttribType:       // fall through
         case kFloat_GrVertexAttribType:
-            return kFloat_GrSLType;
+            return kHighFloat_GrSLType;
         case kVec2f_GrVertexAttribType:
-            return kVec2f_GrSLType;
+            return kHighFloat2_GrSLType;
         case kVec3f_GrVertexAttribType:
-            return kVec3f_GrSLType;
+            return kHighFloat3_GrSLType;
         case kVec4ub_GrVertexAttribType:
         case kVec4f_GrVertexAttribType:
-            return kVec4f_GrSLType;
+            return kHighFloat4_GrSLType;
         case kVec2i_GrVertexAttribType:
-            return kVec2i_GrSLType;
+            return kInt2_GrSLType;
         case kVec3i_GrVertexAttribType:
-            return kVec3i_GrSLType;
+            return kInt3_GrSLType;
         case kVec4i_GrVertexAttribType:
-            return kVec4i_GrSLType;
+            return kInt4_GrSLType;
         case kInt_GrVertexAttribType:
             return kInt_GrSLType;
         case kUint_GrVertexAttribType:
diff --git a/src/core/SkColorMatrixFilterRowMajor255.cpp b/src/core/SkColorMatrixFilterRowMajor255.cpp
index 17a549f..9c9aa1a 100644
--- a/src/core/SkColorMatrixFilterRowMajor255.cpp
+++ b/src/core/SkColorMatrixFilterRowMajor255.cpp
@@ -201,23 +201,21 @@
 
         void emitCode(EmitArgs& args) override {
             GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-            fMatrixHandle = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                       kMat44f_GrSLType, kDefault_GrSLPrecision,
+            fMatrixHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
                                                        "ColorMatrix");
-            fVectorHandle = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
+            fVectorHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                        "ColorMatrixVector");
 
             if (nullptr == args.fInputColor) {
                 // could optimize this case, but we aren't for now.
-                args.fInputColor = "float4(1)";
+                args.fInputColor = "half4(1)";
             }
             GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
             // The max() is to guard against 0 / 0 during unpremul when the incoming color is
             // transparent black.
-            fragBuilder->codeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n",
+            fragBuilder->codeAppendf("\thalf nonZeroAlpha = max(%s.a, 0.00001);\n",
                                      args.fInputColor);
-            fragBuilder->codeAppendf("\t%s = %s * float4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + "
+            fragBuilder->codeAppendf("\t%s = %s * half4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + "
                                      "%s;\n",
                                      args.fOutputColor,
                                      uniformHandler->getUniformCStr(fMatrixHandle),
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
index aebb7d3..3611e169 100644
--- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
@@ -36,24 +36,25 @@
         (void)_outer;
         fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get());
         fInnerThresholdVar = args.fUniformHandler->addUniform(
-                kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "innerThreshold");
+                kFragment_GrShaderFlag, kHalf_GrSLType, kDefault_GrSLPrecision, "innerThreshold");
         fOuterThresholdVar = args.fUniformHandler->addUniform(
-                kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "outerThreshold");
+                kFragment_GrShaderFlag, kHalf_GrSLType, kDefault_GrSLPrecision, "outerThreshold");
         SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
         SkString sk_TransformedCoords2D_1 = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
         fragBuilder->codeAppendf(
-                "float4 _tmpVar1;float4 color = %stexture(%s, %s).%s%s;\nfloat4 mask_color = "
-                "texture(%s, %s).%s;\nif (mask_color.w < 0.5) {\n    if (color.w > %s) {\n        "
-                "float scale = %s / color.w;\n        color.xyz *= scale;\n        color.w = %s;\n "
-                "   }\n} else if (color.w < %s) {\n    float scale = %s / max(0.001, color.w);\n   "
-                " color.xyz *= scale;\n    color.w = %s;\n}\n%s = color;\n",
+                "half4 _tmpVar1;half4 color = %stexture(%s, %s).%s%s;\nhalf4 mask_color = "
+                "texture(%s, %s).%s;\nif (highfloat(mask_color.w) < 0.5) {\n    if (color.w > %s) "
+                "{\n        half scale = %s / color.w;\n        color.xyz *= scale;\n        "
+                "color.w = %s;\n    }\n} else if (color.w < %s) {\n    half scale = highfloat(%s) "
+                "/ max(0.001, highfloat(color.w));\n    color.xyz *= scale;\n    color.w = "
+                "%s;\n}\n%s = color;\n",
                 fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "",
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 sk_TransformedCoords2D_0.c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
                 fColorSpaceHelper.isValid()
-                        ? SkStringPrintf(", float4(clamp((%s * float4(_tmpVar1.rgb, 1.0)).rgb, "
-                                         "0.0, _tmpVar1.a), _tmpVar1.a))",
+                        ? SkStringPrintf(", half4(clamp((%s * half4(_tmpVar1.rgb, 1.0)).rgb, 0.0, "
+                                         "_tmpVar1.a), _tmpVar1.a))",
                                          args.fUniformHandler->getUniformCStr(
                                                  fColorSpaceHelper.gamutXformUniform()))
                                   .c_str()
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.fp b/src/effects/GrAlphaThresholdFragmentProcessor.fp
index 481549e..c3b3fbf 100644
--- a/src/effects/GrAlphaThresholdFragmentProcessor.fp
+++ b/src/effects/GrAlphaThresholdFragmentProcessor.fp
@@ -1,8 +1,8 @@
 in uniform sampler2D image;
 in uniform colorSpaceXform colorXform;
 in uniform sampler2D mask;
-in uniform float innerThreshold;
-in uniform float outerThreshold;
+in uniform half innerThreshold;
+in uniform half outerThreshold;
 
 @class {
     inline OptimizationFlags optFlags(float outerThreshold);
@@ -49,16 +49,16 @@
 }
 
 void main() {
-    float4 color = texture(image, sk_TransformedCoords2D[0], colorXform);
-    float4 mask_color = texture(mask, sk_TransformedCoords2D[1]);
+    half4 color = texture(image, sk_TransformedCoords2D[0], colorXform);
+    half4 mask_color = texture(mask, sk_TransformedCoords2D[1]);
     if (mask_color.a < 0.5) {
         if (color.a > outerThreshold) {
-            float scale = outerThreshold / color.a;
+            half scale = outerThreshold / color.a;
             color.rgb *= scale;
             color.a = outerThreshold;
         }
     } else if (color.a < innerThreshold) {
-        float scale = innerThreshold / max(0.001, color.a);
+        half scale = innerThreshold / max(0.001, color.a);
         color.rgb *= scale;
         color.a = innerThreshold;
     }
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp
index 75d73bd..b3d28f4 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/effects/GrCircleBlurFragmentProcessor.cpp
@@ -263,19 +263,20 @@
         const GrCircleBlurFragmentProcessor& _outer =
                 args.fFp.cast<GrCircleBlurFragmentProcessor>();
         (void)_outer;
-        fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
+        fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                           kDefault_GrSLPrecision, "circleData");
         fragBuilder->codeAppendf(
-                "float2 vec = float2((sk_FragCoord.x - %s.x) * %s.w, (sk_FragCoord.y - %s.y) * "
-                "%s.w);\nfloat dist = length(vec) + (0.5 - %s.z) * %s.w;\n%s = %s * texture(%s, "
-                "float2(dist, 0.5)).%s.w;\n",
+                "half2 vec = half2(half((sk_FragCoord.x - highfloat(%s.x)) * highfloat(%s.w)), "
+                "half((sk_FragCoord.y - highfloat(%s.y)) * highfloat(%s.w)));\nhalf dist = "
+                "highfloat(length(vec)) + (0.5 - highfloat(%s.z)) * highfloat(%s.w);\n%s = %s * "
+                "texture(%s, highfloat2(half2(dist, 0.5))).%s.w;\n",
                 args.fUniformHandler->getUniformCStr(fCircleDataVar),
                 args.fUniformHandler->getUniformCStr(fCircleDataVar),
                 args.fUniformHandler->getUniformCStr(fCircleDataVar),
                 args.fUniformHandler->getUniformCStr(fCircleDataVar),
                 args.fUniformHandler->getUniformCStr(fCircleDataVar),
                 args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "float4(1)",
+                args.fInputColor ? args.fInputColor : "half4(1)",
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
     }
diff --git a/src/effects/GrCircleBlurFragmentProcessor.fp b/src/effects/GrCircleBlurFragmentProcessor.fp
index 856a468..d91bad8 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.fp
+++ b/src/effects/GrCircleBlurFragmentProcessor.fp
@@ -1,13 +1,13 @@
-in float4 circleRect;
-in float textureRadius;
-in float solidRadius;
+in half4 circleRect;
+in half textureRadius;
+in half solidRadius;
 in uniform sampler2D blurProfileSampler;
 
 // The data is formatted as:
 // x, y - the center of the circle
 // z    - inner radius that should map to 0th entry in the texture.
 // w    - the inverse of the distance over which the texture is stretched.
-uniform float4 circleData;
+uniform half4 circleData;
 
 @optimizationFlags {
     kCompatibleWithCoverageAsAlpha_OptimizationFlag
@@ -273,10 +273,10 @@
 void main() {
     // We just want to compute "(length(vec) - circleData.z + 0.5) * circleData.w" but need to
     // rearrange for precision.
-    float2 vec = float2((sk_FragCoord.x - circleData.x) * circleData.w,
-                    (sk_FragCoord.y - circleData.y) * circleData.w);
-    float dist = length(vec) + (0.5 - circleData.z) * circleData.w;
-    sk_OutColor = sk_InColor * texture(blurProfileSampler, float2(dist, 0.5)).a;
+    half2 vec = half2((sk_FragCoord.x - circleData.x) * circleData.w,
+                      (sk_FragCoord.y - circleData.y) * circleData.w);
+    half dist = length(vec) + (0.5 - circleData.z) * circleData.w;
+    sk_OutColor = sk_InColor * texture(blurProfileSampler, half2(dist, 0.5)).a;
 }
 
 @test(testData) {
diff --git a/src/effects/SkArithmeticImageFilter.cpp b/src/effects/SkArithmeticImageFilter.cpp
index 8c0f1ef..1bc3d06 100644
--- a/src/effects/SkArithmeticImageFilter.cpp
+++ b/src/effects/SkArithmeticImageFilter.cpp
@@ -302,18 +302,18 @@
                 SkString dstColor("dstColor");
                 this->emitChild(0, &dstColor, args);
 
-                fKUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
-                                                         kDefault_GrSLPrecision, "k");
+                fKUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
+                                                         "k");
                 const char* kUni = args.fUniformHandler->getUniformCStr(fKUni);
 
                 // We don't try to optimize for this case at all
                 if (!args.fInputColor) {
-                    fragBuilder->codeAppend("const float4 src = float4(1);");
+                    fragBuilder->codeAppend("const half4 src = half4(1);");
                 } else {
-                    fragBuilder->codeAppendf("float4 src = %s;", args.fInputColor);
+                    fragBuilder->codeAppendf("half4 src = %s;", args.fInputColor);
                 }
 
-                fragBuilder->codeAppendf("float4 dst = %s;", dstColor.c_str());
+                fragBuilder->codeAppendf("half4 dst = %s;", dstColor.c_str());
                 fragBuilder->codeAppendf("%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;",
                                          args.fOutputColor, kUni, kUni, kUni, kUni);
                 fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", args.fOutputColor,
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 2fc10ed..861a66d 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -862,12 +862,12 @@
                                  const char *profileSize, const char *loc,
                                  const char *blurred_width,
                                  const char *sharp_width) {
-    fragBuilder->codeAppendf("float %s;", output);
+    fragBuilder->codeAppendf("half %s;", output);
     fragBuilder->codeAppendf("{");
-    fragBuilder->codeAppendf("float coord = ((abs(%s - 0.5 * %s) - 0.5 * %s)) / %s;",
+    fragBuilder->codeAppendf("half coord = ((abs(%s - 0.5 * %s) - 0.5 * %s)) / %s;",
                            loc, blurred_width, sharp_width, profileSize);
     fragBuilder->codeAppendf("%s = ", output);
-    fragBuilder->appendTextureLookup(sampler, "float2(coord,0.5)");
+    fragBuilder->appendTextureLookup(sampler, "half2(coord,0.5)");
     fragBuilder->codeAppend(".a;");
     fragBuilder->codeAppendf("}");
 }
@@ -889,49 +889,41 @@
     const char *rectName;
     const char *profileSizeName;
 
-    SkString precisionString;
-    if (args.fShaderCaps->usesPrecisionModifiers()) {
-        precisionString.printf("%s ", GrGLSLPrecisionString(rbe.precision()));
-    }
+    const char* floatType = rbe.precision() == kHigh_GrSLPrecision ? "highfloat" : "half";
     fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec4f_GrSLType,
-                                                   rbe.precision(),
+                                                   rbe.precision() == kHigh_GrSLPrecision ?
+                                                             kHighFloat4_GrSLType : kHalf4_GrSLType,
                                                    "proxyRect",
                                                    &rectName);
     fProfileSizeUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                     kFloat_GrSLType,
-                                                     kDefault_GrSLPrecision,
+                                                     kHalf_GrSLType,
                                                      "profileSize",
                                                      &profileSizeName);
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
 
     if (args.fInputColor) {
-        fragBuilder->codeAppendf("float4 src=%s;", args.fInputColor);
+        fragBuilder->codeAppendf("half4 src=%s;", args.fInputColor);
     } else {
-        fragBuilder->codeAppendf("float4 src=float4(1);");
+        fragBuilder->codeAppendf("half4 src=half4(1);");
     }
 
-    fragBuilder->codeAppendf("%s float2 translatedPos = sk_FragCoord.xy - %s.xy;",
-                             precisionString.c_str(), rectName);
-    fragBuilder->codeAppendf("%s float width = %s.z - %s.x;", precisionString.c_str(), rectName,
-                             rectName);
-    fragBuilder->codeAppendf("%s float height = %s.w - %s.y;", precisionString.c_str(), rectName,
-                             rectName);
+    fragBuilder->codeAppendf("%s2 translatedPos = sk_FragCoord.xy - %s.xy;", floatType, rectName);
+    fragBuilder->codeAppendf("%s width = %s.z - %s.x;", floatType, rectName, rectName);
+    fragBuilder->codeAppendf("%s height = %s.w - %s.y;", floatType, rectName, rectName);
 
-    fragBuilder->codeAppendf("%s float2 smallDims = float2(width - %s, height - %s);",
-                             precisionString.c_str(), profileSizeName, profileSizeName);
-    fragBuilder->codeAppendf("%s float center = 2.0 * floor(%s/2.0 + .25) - 1.0;",
-                             precisionString.c_str(), profileSizeName);
-    fragBuilder->codeAppendf("%s float2 wh = smallDims - float2(center,center);",
-                             precisionString.c_str());
+    fragBuilder->codeAppendf("%s2 smallDims = half2(width - %s, height - %s);", floatType,
+                             profileSizeName, profileSizeName);
+    fragBuilder->codeAppendf("%s center = 2.0 * floor(%s/2.0 + .25) - 1.0;", floatType,
+                             profileSizeName);
+    fragBuilder->codeAppendf("%s2 wh = smallDims - half2(center,center);", floatType);
 
     OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "horiz_lookup", profileSizeName,
                                 "translatedPos.x", "width", "wh.x");
     OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "vert_lookup", profileSizeName,
                                 "translatedPos.y", "height", "wh.y");
 
-    fragBuilder->codeAppendf("float final = horiz_lookup * vert_lookup;");
+    fragBuilder->codeAppendf("half final = horiz_lookup * vert_lookup;");
     fragBuilder->codeAppendf("%s = src * final;", args.fOutputColor);
 }
 
@@ -1277,18 +1269,15 @@
     // components x, y, z, and w, respectively.
 
     fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec4f_GrSLType,
-                                                   kDefault_GrSLPrecision,
+                                                   kHalf4_GrSLType,
                                                    "proxyRect",
                                                    &rectName);
     fCornerRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                      kFloat_GrSLType,
-                                                      kDefault_GrSLPrecision,
+                                                      kHalf_GrSLType,
                                                       "cornerRadius",
                                                       &cornerRadiusName);
     fBlurRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kFloat_GrSLType,
-                                                    kDefault_GrSLPrecision,
+                                                    kHalf_GrSLType,
                                                     "blurRadius",
                                                     &blurRadiusName);
 
@@ -1296,10 +1285,10 @@
 
     // warp the fragment position to the appropriate part of the 9patch blur texture
 
-    fragBuilder->codeAppendf("float2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName);
-    fragBuilder->codeAppendf("float2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName);
-    fragBuilder->codeAppendf("float threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName);
-    fragBuilder->codeAppendf("float2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName);
+    fragBuilder->codeAppendf("half2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName);
+    fragBuilder->codeAppendf("half2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName);
+    fragBuilder->codeAppendf("half threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName);
+    fragBuilder->codeAppendf("half2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName);
 
     fragBuilder->codeAppendf(
            "if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {");
@@ -1315,8 +1304,8 @@
     fragBuilder->codeAppendf("translatedFragPos.y -= middle.y - 1.0;");
     fragBuilder->codeAppendf("}");
 
-    fragBuilder->codeAppendf("float2 proxyDims = float2(2.0*threshold+1.0);");
-    fragBuilder->codeAppendf("float2 texCoord = translatedFragPos / proxyDims;");
+    fragBuilder->codeAppendf("half2 proxyDims = half2(2.0*threshold+1.0);");
+    fragBuilder->codeAppendf("half2 texCoord = translatedFragPos / proxyDims;");
 
     fragBuilder->codeAppendf("%s = ", args.fOutputColor);
     fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.fTexSamplers[0], "texCoord");
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 2c26cce..0ba6a29 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -552,8 +552,7 @@
     const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>();
     const GrTextureDomain& domain = displacementMap.domain();
 
-    fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                 kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale");
+    fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "Scale");
     const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni);
     const char* dColor = "dColor";
     const char* cCoords = "cCoords";
@@ -564,17 +563,17 @@
     fColorSpaceHelper.emitCode(args.fUniformHandler, displacementMap.colorSpaceXform());
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-    fragBuilder->codeAppendf("\t\tfloat4 %s = ", dColor);
+    fragBuilder->codeAppendf("\t\thalf4 %s = ", dColor);
     fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(),
                                    args.fTransformedCoords[0].getType());
     fragBuilder->codeAppend(";\n");
 
     // Unpremultiply the displacement
     fragBuilder->codeAppendf(
-        "\t\t%s.rgb = (%s.a < %s) ? float3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
+        "\t\t%s.rgb = (%s.a < %s) ? half3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
         dColor, dColor, nearZero, dColor, dColor);
     SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
-    fragBuilder->codeAppendf("\t\tfloat2 %s = %s + %s*(%s.",
+    fragBuilder->codeAppendf("\t\thighfloat2 %s = %s + %s*(%s.",
                              cCoords, coords2D.c_str(), scaleUni, dColor);
 
     switch (displacementMap.xChannelSelector()) {
@@ -612,7 +611,7 @@
       default:
         SkDEBUGFAIL("Unknown Y channel selector");
     }
-    fragBuilder->codeAppend("-float2(0.5));\t\t");
+    fragBuilder->codeAppend("-half2(0.5));\t\t");
 
     fGLDomain.sampleTexture(fragBuilder,
                             args.fUniformHandler,
diff --git a/src/effects/SkHighContrastFilter.cpp b/src/effects/SkHighContrastFilter.cpp
index 3de7603..7618861 100644
--- a/src/effects/SkHighContrastFilter.cpp
+++ b/src/effects/SkHighContrastFilter.cpp
@@ -247,47 +247,46 @@
 
 void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
     const char* contrast;
-    fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kFloat_GrSLType, kDefault_GrSLPrecision,
+    fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                     "contrast", &contrast);
 
     if (nullptr == args.fInputColor) {
-        args.fInputColor = "float4(1)";
+        args.fInputColor = "half4(1)";
     }
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
 
-    fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor);
+    fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
 
     // Unpremultiply. The max() is to guard against 0 / 0.
-    fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
-    fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
+    fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
+    fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
 
     // Grayscale.
     if (fConfig.fGrayscale) {
-        fragBuilder->codeAppendf("float luma = dot(color, float4(%f, %f, %f, 0));",
+        fragBuilder->codeAppendf("half luma = dot(color, half4(%f, %f, %f, 0));",
                                  SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B);
-        fragBuilder->codeAppendf("color = float4(luma, luma, luma, 0);");
+        fragBuilder->codeAppendf("color = half4(luma, luma, luma, 0);");
     }
 
     if (fConfig.fInvertStyle == InvertStyle::kInvertBrightness) {
-        fragBuilder->codeAppendf("color = float4(1, 1, 1, 1) - color;");
+        fragBuilder->codeAppendf("color = half4(1, 1, 1, 1) - color;");
     }
 
     if (fConfig.fInvertStyle == InvertStyle::kInvertLightness) {
         // Convert from RGB to HSL.
-        fragBuilder->codeAppendf("float fmax = max(color.r, max(color.g, color.b));");
-        fragBuilder->codeAppendf("float fmin = min(color.r, min(color.g, color.b));");
-        fragBuilder->codeAppendf("float l = (fmax + fmin) / 2;");
+        fragBuilder->codeAppendf("half fmax = max(color.r, max(color.g, color.b));");
+        fragBuilder->codeAppendf("half fmin = min(color.r, min(color.g, color.b));");
+        fragBuilder->codeAppendf("half l = (fmax + fmin) / 2;");
 
-        fragBuilder->codeAppendf("float h;");
-        fragBuilder->codeAppendf("float s;");
+        fragBuilder->codeAppendf("half h;");
+        fragBuilder->codeAppendf("half s;");
 
         fragBuilder->codeAppendf("if (fmax == fmin) {");
         fragBuilder->codeAppendf("  h = 0;");
         fragBuilder->codeAppendf("  s = 0;");
         fragBuilder->codeAppendf("} else {");
-        fragBuilder->codeAppendf("  float d = fmax - fmin;");
+        fragBuilder->codeAppendf("  half d = fmax - fmin;");
         fragBuilder->codeAppendf("  s = l > 0.5 ?");
         fragBuilder->codeAppendf("      d / (2 - fmax - fmin) :");
         fragBuilder->codeAppendf("      d / (fmax + fmin);");
@@ -305,11 +304,11 @@
         // Convert back from HSL to RGB.
         SkString hue2rgbFuncName;
         static const GrShaderVar gHue2rgbArgs[] = {
-            GrShaderVar("p", kFloat_GrSLType),
-            GrShaderVar("q", kFloat_GrSLType),
-            GrShaderVar("t", kFloat_GrSLType),
+            GrShaderVar("p", kHalf_GrSLType),
+            GrShaderVar("q", kHalf_GrSLType),
+            GrShaderVar("t", kHalf_GrSLType),
         };
-        fragBuilder->emitFunction(kFloat_GrSLType,
+        fragBuilder->emitFunction(kHalf_GrSLType,
                                   "hue2rgb",
                                   SK_ARRAY_COUNT(gHue2rgbArgs),
                                   gHue2rgbArgs,
@@ -326,10 +325,10 @@
                                   "return p;",
                                   &hue2rgbFuncName);
         fragBuilder->codeAppendf("if (s == 0) {");
-        fragBuilder->codeAppendf("  color = float4(l, l, l, 0);");
+        fragBuilder->codeAppendf("  color = half4(l, l, l, 0);");
         fragBuilder->codeAppendf("} else {");
-        fragBuilder->codeAppendf("  float q = l < 0.5 ? l * (1 + s) : l + s - l * s;");
-        fragBuilder->codeAppendf("  float p = 2 * l - q;");
+        fragBuilder->codeAppendf("  half q = l < 0.5 ? l * (1 + s) : l + s - l * s;");
+        fragBuilder->codeAppendf("  half p = 2 * l - q;");
         fragBuilder->codeAppendf("  color.r = %s(p, q, h + 1/3.);", hue2rgbFuncName.c_str());
         fragBuilder->codeAppendf("  color.g = %s(p, q, h);", hue2rgbFuncName.c_str());
         fragBuilder->codeAppendf("  color.b = %s(p, q, h - 1/3.);", hue2rgbFuncName.c_str());
@@ -338,8 +337,8 @@
 
     // Contrast.
     fragBuilder->codeAppendf("if (%s != 0) {", contrast);
-    fragBuilder->codeAppendf("  float m = (1 + %s) / (1 - %s);", contrast, contrast);
-    fragBuilder->codeAppendf("  float off = (-0.5 * m + 0.5);");
+    fragBuilder->codeAppendf("  half m = (1 + %s) / (1 - %s);", contrast, contrast);
+    fragBuilder->codeAppendf("  half off = (-0.5 * m + 0.5);");
     fragBuilder->codeAppendf("  color = m * color + off;");
     fragBuilder->codeAppendf("}");
 
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index d9fae43..10056e2 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -724,7 +724,7 @@
 
     /**
      * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
-     * below. It adds a vec3f uniform visible in the FS that represents the constant light color.
+     * below. It adds a half3 uniform visible in the FS that represents the constant light color.
      */
     void emitLightColorUniform(GrGLSLUniformHandler*);
 
@@ -1827,63 +1827,61 @@
 
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                                    "ImageIncrement");
+                                                    kHalf2_GrSLType, "ImageIncrement");
     fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                  kFloat_GrSLType, kDefault_GrSLPrecision,
-                                                  "SurfaceScale");
+                                                  kHalf_GrSLType, "SurfaceScale");
     fLight->emitLightColorUniform(uniformHandler);
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     SkString lightFunc;
     this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc);
     static const GrShaderVar gSobelArgs[] =  {
-        GrShaderVar("a", kFloat_GrSLType),
-        GrShaderVar("b", kFloat_GrSLType),
-        GrShaderVar("c", kFloat_GrSLType),
-        GrShaderVar("d", kFloat_GrSLType),
-        GrShaderVar("e", kFloat_GrSLType),
-        GrShaderVar("f", kFloat_GrSLType),
-        GrShaderVar("scale", kFloat_GrSLType),
+        GrShaderVar("a", kHalf_GrSLType),
+        GrShaderVar("b", kHalf_GrSLType),
+        GrShaderVar("c", kHalf_GrSLType),
+        GrShaderVar("d", kHalf_GrSLType),
+        GrShaderVar("e", kHalf_GrSLType),
+        GrShaderVar("f", kHalf_GrSLType),
+        GrShaderVar("scale", kHalf_GrSLType),
     };
     SkString sobelFuncName;
     SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
 
-    fragBuilder->emitFunction(kFloat_GrSLType,
+    fragBuilder->emitFunction(kHalf_GrSLType,
                               "sobel",
                               SK_ARRAY_COUNT(gSobelArgs),
                               gSobelArgs,
                               "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
                               &sobelFuncName);
     static const GrShaderVar gPointToNormalArgs[] =  {
-        GrShaderVar("x", kFloat_GrSLType),
-        GrShaderVar("y", kFloat_GrSLType),
-        GrShaderVar("scale", kFloat_GrSLType),
+        GrShaderVar("x", kHalf_GrSLType),
+        GrShaderVar("y", kHalf_GrSLType),
+        GrShaderVar("scale", kHalf_GrSLType),
     };
     SkString pointToNormalName;
-    fragBuilder->emitFunction(kVec3f_GrSLType,
+    fragBuilder->emitFunction(kHalf3_GrSLType,
                               "pointToNormal",
                               SK_ARRAY_COUNT(gPointToNormalArgs),
                               gPointToNormalArgs,
-                              "\treturn normalize(float3(-x * scale, -y * scale, 1));\n",
+                              "\treturn normalize(half3(-x * scale, -y * scale, 1));\n",
                               &pointToNormalName);
 
     static const GrShaderVar gInteriorNormalArgs[] =  {
-        GrShaderVar("m", kFloat_GrSLType, 9),
-        GrShaderVar("surfaceScale", kFloat_GrSLType),
+        GrShaderVar("m", kHalf_GrSLType, 9),
+        GrShaderVar("surfaceScale", kHalf_GrSLType),
     };
     SkString normalBody = emitNormalFunc(le.boundaryMode(),
                                          pointToNormalName.c_str(),
                                          sobelFuncName.c_str());
     SkString normalName;
-    fragBuilder->emitFunction(kVec3f_GrSLType,
+    fragBuilder->emitFunction(kHalf3_GrSLType,
                               "normal",
                               SK_ARRAY_COUNT(gInteriorNormalArgs),
                               gInteriorNormalArgs,
                               normalBody.c_str(),
                               &normalName);
 
-    fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
-    fragBuilder->codeAppend("\t\tfloat m[9];\n");
+    fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
+    fragBuilder->codeAppend("\t\thalf m[9];\n");
 
     const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
     const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
@@ -1892,10 +1890,10 @@
     for (int dy = 1; dy >= -1; dy--) {
         for (int dx = -1; dx <= 1; dx++) {
             SkString texCoords;
-            texCoords.appendf("coord + float2(%d, %d) * %s", dx, dy, imgInc);
+            texCoords.appendf("coord + half2(%d, %d) * %s", dx, dy, imgInc);
             SkString temp;
             temp.appendf("temp%d", index);
-            fragBuilder->codeAppendf("float4 %s;", temp.c_str());
+            fragBuilder->codeAppendf("half4 %s;", temp.c_str());
             fDomain.sampleTexture(fragBuilder,
                                   args.fUniformHandler,
                                   args.fShaderCaps,
@@ -1907,7 +1905,7 @@
             index++;
         }
     }
-    fragBuilder->codeAppend("\t\tfloat3 surfaceToLight = ");
+    fragBuilder->codeAppend("\t\thalf3 surfaceToLight = ");
     SkString arg;
     arg.appendf("%s * m[4]", surfScale);
     fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str());
@@ -1953,19 +1951,17 @@
                                               GrGLSLFPFragmentBuilder* fragBuilder,
                                               SkString* funcName) {
     const char* kd;
-    fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                 kFloat_GrSLType, kDefault_GrSLPrecision,
-                                 "KD", &kd);
+    fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
 
     static const GrShaderVar gLightArgs[] = {
-        GrShaderVar("normal", kVec3f_GrSLType),
-        GrShaderVar("surfaceToLight", kVec3f_GrSLType),
-        GrShaderVar("lightColor", kVec3f_GrSLType)
+        GrShaderVar("normal", kHalf3_GrSLType),
+        GrShaderVar("surfaceToLight", kHalf3_GrSLType),
+        GrShaderVar("lightColor", kHalf3_GrSLType)
     };
     SkString lightBody;
-    lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
-    lightBody.appendf("\treturn float4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
-    fragBuilder->emitFunction(kVec4f_GrSLType,
+    lightBody.appendf("\thalf colorScale = %s * dot(normal, surfaceToLight);\n", kd);
+    lightBody.appendf("\treturn half4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
+    fragBuilder->emitFunction(kHalf4_GrSLType,
                               "light",
                               SK_ARRAY_COUNT(gLightArgs),
                               gLightArgs,
@@ -2051,26 +2047,24 @@
     const char* ks;
     const char* shininess;
 
-    fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                        kFloat_GrSLType, kDefault_GrSLPrecision, "KS", &ks);
+    fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
     fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                               kFloat_GrSLType,
-                                               kDefault_GrSLPrecision,
+                                               kHalf_GrSLType,
                                                "Shininess",
                                                &shininess);
 
     static const GrShaderVar gLightArgs[] = {
-        GrShaderVar("normal", kVec3f_GrSLType),
-        GrShaderVar("surfaceToLight", kVec3f_GrSLType),
-        GrShaderVar("lightColor", kVec3f_GrSLType)
+        GrShaderVar("normal", kHalf3_GrSLType),
+        GrShaderVar("surfaceToLight", kHalf3_GrSLType),
+        GrShaderVar("lightColor", kHalf3_GrSLType)
     };
     SkString lightBody;
-    lightBody.appendf("\tfloat3 halfDir = float3(normalize(surfaceToLight + float3(0, 0, 1)));\n");
-    lightBody.appendf("\thighp float colorScale = %s * pow(dot(normal, halfDir), %s);\n",
+    lightBody.appendf("\thalf3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));\n");
+    lightBody.appendf("\thighfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
                       ks, shininess);
-    lightBody.appendf("\tfloat3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
-    lightBody.appendf("\treturn float4(color, max(max(color.r, color.g), color.b));\n");
-    fragBuilder->emitFunction(kVec4f_GrSLType,
+    lightBody.appendf("\thalf3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
+    lightBody.appendf("\treturn half4(color, max(max(color.r, color.g), color.b));\n");
+    fragBuilder->emitFunction(kHalf4_GrSLType,
                               "light",
                               SK_ARRAY_COUNT(gLightArgs),
                               gLightArgs,
@@ -2088,9 +2082,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 void GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) {
-    fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                           kVec3f_GrSLType, kDefault_GrSLPrecision,
-                                           "LightColor");
+    fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "LightColor");
 }
 
 void GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
@@ -2119,8 +2111,7 @@
                                           GrGLSLFPFragmentBuilder* fragBuilder,
                                           const char* z) {
     const char* dir;
-    fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                               kVec3f_GrSLType, kDefault_GrSLPrecision,
+    fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
                                                "LightDirection", &dir);
     fragBuilder->codeAppend(dir);
 }
@@ -2139,10 +2130,9 @@
                                         GrGLSLFPFragmentBuilder* fragBuilder,
                                         const char* z) {
     const char* loc;
-    fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                              kVec3f_GrSLType, kDefault_GrSLPrecision,
+    fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
                                               "LightLocation", &loc);
-    fragBuilder->codeAppendf("normalize(%s - float3(sk_FragCoord.xy, %s))",
+    fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
                              loc, z);
 }
 
@@ -2165,11 +2155,10 @@
                                        GrGLSLFPFragmentBuilder* fragBuilder,
                                        const char* z) {
     const char* location;
-    fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                              kVec3f_GrSLType, kDefault_GrSLPrecision,
+    fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
                                               "LightLocation", &location);
 
-    fragBuilder->codeAppendf("normalize(%s - float3(sk_FragCoord.xy, %s))",
+    fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
                              location, z);
 }
 
@@ -2184,36 +2173,31 @@
     const char* cosOuter;
     const char* coneScale;
     const char* s;
-    fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                              kFloat_GrSLType, kDefault_GrSLPrecision,
+    fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                               "Exponent", &exponent);
-    fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                       kFloat_GrSLType, kDefault_GrSLPrecision,
+    fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                        "CosInnerConeAngle", &cosInner);
-    fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                       kFloat_GrSLType, kDefault_GrSLPrecision,
+    fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                        "CosOuterConeAngle", &cosOuter);
-    fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                               kFloat_GrSLType, kDefault_GrSLPrecision,
+    fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                "ConeScale", &coneScale);
-    fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                       kVec3f_GrSLType, kDefault_GrSLPrecision, "S", &s);
+    fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
 
     static const GrShaderVar gLightColorArgs[] = {
-        GrShaderVar("surfaceToLight", kVec3f_GrSLType)
+        GrShaderVar("surfaceToLight", kHalf3_GrSLType)
     };
     SkString lightColorBody;
-    lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
+    lightColorBody.appendf("\thalf cosAngle = -dot(surfaceToLight, %s);\n", s);
     lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
-    lightColorBody.appendf("\t\treturn float3(0);\n");
+    lightColorBody.appendf("\t\treturn half3(0);\n");
     lightColorBody.appendf("\t}\n");
-    lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
+    lightColorBody.appendf("\thalf scale = pow(cosAngle, %s);\n", exponent);
     lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
     lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
                            color, cosOuter, coneScale);
     lightColorBody.appendf("\t}\n");
     lightColorBody.appendf("\treturn %s;\n", color);
-    fragBuilder->emitFunction(kVec3f_GrSLType,
+    fragBuilder->emitFunction(kHalf3_GrSLType,
                               "lightColor",
                               SK_ARRAY_COUNT(gLightColorArgs),
                               gLightColorArgs,
diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp
index 5c5edcd..ecd1a3a 100644
--- a/src/effects/SkLumaColorFilter.cpp
+++ b/src/effects/SkLumaColorFilter.cpp
@@ -60,16 +60,16 @@
 
         void emitCode(EmitArgs& args) override {
             if (nullptr == args.fInputColor) {
-                args.fInputColor = "float4(1)";
+                args.fInputColor = "half4(1)";
             }
 
             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-            fragBuilder->codeAppendf("\tfloat luma = dot(float3(%f, %f, %f), %s.rgb);\n",
+            fragBuilder->codeAppendf("\thalf luma = dot(half3(%f, %f, %f), %s.rgb);\n",
                                      SK_ITU_BT709_LUM_COEFF_R,
                                      SK_ITU_BT709_LUM_COEFF_G,
                                      SK_ITU_BT709_LUM_COEFF_B,
                                      args.fInputColor);
-            fragBuilder->codeAppendf("\t%s = float4(0, 0, 0, luma);\n",
+            fragBuilder->codeAppendf("\t%s = half4(0, 0, 0, luma);\n",
                                      args.fOutputColor);
 
         }
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index 4af375b..d989037 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -180,48 +180,44 @@
 void GrGLMagnifierEffect::emitCode(EmitArgs& args) {
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     fOffsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                            kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                            "Offset");
+                                            kHalf2_GrSLType, "Offset");
     fInvZoomVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                             kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                             "InvZoom");
+                                             kHalf2_GrSLType, "InvZoom");
     fInvInsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                              "InvInset");
+                                              kHalf2_GrSLType, "InvInset");
     fBoundsVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                            kVec4f_GrSLType, kDefault_GrSLPrecision,
-                                            "Bounds");
+                                            kHalf4_GrSLType, "Bounds");
 
     const GrMagnifierEffect& zoom = args.fFp.cast<GrMagnifierEffect>();
     fColorSpaceHelper.emitCode(uniformHandler, zoom.colorSpaceXform());
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
-    fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
-    fragBuilder->codeAppendf("\t\tfloat2 zoom_coord = %s + %s * %s;\n",
+    fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
+    fragBuilder->codeAppendf("\t\thighfloat2 zoom_coord = %s + %s * %s;\n",
                              uniformHandler->getUniformCStr(fOffsetVar),
                              coords2D.c_str(),
                              uniformHandler->getUniformCStr(fInvZoomVar));
     const char* bounds = uniformHandler->getUniformCStr(fBoundsVar);
-    fragBuilder->codeAppendf("\t\tfloat2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
-    fragBuilder->codeAppendf("\t\tdelta = min(delta, float2(1.0, 1.0) - delta);\n");
+    fragBuilder->codeAppendf("\t\thighfloat2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
+    fragBuilder->codeAppendf("\t\tdelta = min(delta, half2(1.0, 1.0) - delta);\n");
     fragBuilder->codeAppendf("\t\tdelta = delta * %s;\n",
                              uniformHandler->getUniformCStr(fInvInsetVar));
 
-    fragBuilder->codeAppend("\t\tfloat weight = 0.0;\n");
+    fragBuilder->codeAppend("\t\thalf weight = 0.0;\n");
     fragBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n");
-    fragBuilder->codeAppend("\t\t\tdelta = float2(2.0, 2.0) - delta;\n");
-    fragBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n");
+    fragBuilder->codeAppend("\t\t\tdelta = half2(2.0, 2.0) - delta;\n");
+    fragBuilder->codeAppend("\t\t\thalf dist = length(delta);\n");
     fragBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n");
     fragBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n");
     fragBuilder->codeAppend("\t\t} else {\n");
-    fragBuilder->codeAppend("\t\t\tfloat2 delta_squared = delta * delta;\n");
+    fragBuilder->codeAppend("\t\t\thighfloat2 delta_squared = delta * delta;\n");
     fragBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n");
     fragBuilder->codeAppend("\t\t}\n");
 
-    fragBuilder->codeAppend("\t\tfloat2 mix_coord = mix(coord, zoom_coord, weight);\n");
-    fragBuilder->codeAppend("\t\tfloat4 output_color = ");
-    fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kVec2f_GrSLType,
+    fragBuilder->codeAppend("\t\thighfloat2 mix_coord = mix(coord, zoom_coord, weight);\n");
+    fragBuilder->codeAppend("\t\thalf4 output_color = ");
+    fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kHalf2_GrSLType,
                                      &fColorSpaceHelper);
     fragBuilder->codeAppend(";\n");
 
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 629222d..a67e45a 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -212,13 +212,9 @@
     const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();
 
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-    fPixelSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                               kFloat_GrSLType, kDefault_GrSLPrecision,
-                                               "PixelSize");
+    fPixelSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "PixelSize");
     const char* pixelSizeInc = uniformHandler->getUniformCStr(fPixelSizeUni);
-    fRangeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                           kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                           "Range");
+    fRangeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat2_GrSLType, "Range");
     const char* range = uniformHandler->getUniformCStr(fRangeUni);
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -226,11 +222,11 @@
     const char* func;
     switch (me.type()) {
         case GrMorphologyEffect::Type::kErode:
-            fragBuilder->codeAppendf("\t\t%s = float4(1, 1, 1, 1);\n", args.fOutputColor);
+            fragBuilder->codeAppendf("\t\t%s = half4(1, 1, 1, 1);\n", args.fOutputColor);
             func = "min";
             break;
         case GrMorphologyEffect::Type::kDilate:
-            fragBuilder->codeAppendf("\t\t%s = float4(0, 0, 0, 0);\n", args.fOutputColor);
+            fragBuilder->codeAppendf("\t\t%s = half4(0, 0, 0, 0);\n", args.fOutputColor);
             func = "max";
             break;
         default:
@@ -255,12 +251,12 @@
     int width = me.width();
 
     // float2 coord = coord2D;
-    fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
+    fragBuilder->codeAppendf("\t\thighfloat2 coord = %s;\n", coords2D.c_str());
     // coord.x -= radius * pixelSize;
     fragBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, me.radius(), pixelSizeInc);
     if (me.useRange()) {
         // highBound = min(highBound, coord.x + (width-1) * pixelSize);
-        fragBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %f * %s);",
+        fragBuilder->codeAppendf("\t\thighfloat highBound = min(%s.y, coord.%s + %f * %s);",
                                  range, dir, float(width - 1), pixelSizeInc);
         // coord.x = max(lowBound, coord.x);
         fragBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);
diff --git a/src/effects/SkOverdrawColorFilter.cpp b/src/effects/SkOverdrawColorFilter.cpp
index 8ca699e..be5a623 100644
--- a/src/effects/SkOverdrawColorFilter.cpp
+++ b/src/effects/SkOverdrawColorFilter.cpp
@@ -150,49 +150,49 @@
 void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     if (nullptr == args.fInputColor) {
-        fragBuilder->codeAppendf("%s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                    fColors[5].fRGBA[0],
-                                                                    fColors[5].fRGBA[1],
-                                                                    fColors[5].fRGBA[2],
-                                                                    fColors[5].fRGBA[3]);
+        fragBuilder->codeAppendf("%s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
+                                                                     fColors[5].fRGBA[0],
+                                                                     fColors[5].fRGBA[1],
+                                                                     fColors[5].fRGBA[2],
+                                                                     fColors[5].fRGBA[3]);
     } else {
-        fragBuilder->codeAppendf("float alpha = 255.0 * %s.a;", args.fInputColor);
+        fragBuilder->codeAppendf("half alpha = 255.0 * %s.a;", args.fInputColor);
         fragBuilder->codeAppendf("if (alpha < 0.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                        fColors[0].fRGBA[0],
-                                                                        fColors[0].fRGBA[1],
-                                                                        fColors[0].fRGBA[2],
-                                                                        fColors[0].fRGBA[3]);
+        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
+                                                                         fColors[0].fRGBA[0],
+                                                                         fColors[0].fRGBA[1],
+                                                                         fColors[0].fRGBA[2],
+                                                                         fColors[0].fRGBA[3]);
         fragBuilder->codeAppendf("} else if (alpha < 1.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                        fColors[1].fRGBA[0],
-                                                                        fColors[1].fRGBA[1],
-                                                                        fColors[1].fRGBA[2],
-                                                                        fColors[1].fRGBA[3]);
+        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
+                                                                         fColors[1].fRGBA[0],
+                                                                         fColors[1].fRGBA[1],
+                                                                         fColors[1].fRGBA[2],
+                                                                         fColors[1].fRGBA[3]);
         fragBuilder->codeAppendf("} else if (alpha < 2.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                        fColors[2].fRGBA[0],
-                                                                        fColors[2].fRGBA[1],
-                                                                        fColors[2].fRGBA[2],
-                                                                        fColors[2].fRGBA[3]);
+        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
+                                                                         fColors[2].fRGBA[0],
+                                                                         fColors[2].fRGBA[1],
+                                                                         fColors[2].fRGBA[2],
+                                                                         fColors[2].fRGBA[3]);
         fragBuilder->codeAppendf("} else if (alpha < 3.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                        fColors[3].fRGBA[0],
-                                                                        fColors[3].fRGBA[1],
-                                                                        fColors[3].fRGBA[2],
-                                                                        fColors[3].fRGBA[3]);
+        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
+                                                                         fColors[3].fRGBA[0],
+                                                                         fColors[3].fRGBA[1],
+                                                                         fColors[3].fRGBA[2],
+                                                                         fColors[3].fRGBA[3]);
         fragBuilder->codeAppendf("} else if (alpha < 4.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                        fColors[4].fRGBA[0],
-                                                                        fColors[4].fRGBA[1],
-                                                                        fColors[4].fRGBA[2],
-                                                                        fColors[4].fRGBA[3]);
+        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
+                                                                         fColors[4].fRGBA[0],
+                                                                         fColors[4].fRGBA[1],
+                                                                         fColors[4].fRGBA[2],
+                                                                         fColors[4].fRGBA[3]);
         fragBuilder->codeAppendf("} else {");
-        fragBuilder->codeAppendf("    %s.rgba = float4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                        fColors[5].fRGBA[0],
-                                                                        fColors[5].fRGBA[1],
-                                                                        fColors[5].fRGBA[2],
-                                                                        fColors[5].fRGBA[3]);
+        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
+                                                                         fColors[5].fRGBA[0],
+                                                                         fColors[5].fRGBA[1],
+                                                                         fColors[5].fRGBA[2],
+                                                                         fColors[5].fRGBA[3]);
         fragBuilder->codeAppendf("}");
     }
 }
diff --git a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
index 2f045f1..b0e7ca3 100644
--- a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
+++ b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
@@ -241,7 +241,7 @@
 
             // Positive distance is towards the center of the circle.
             // Map all the cases to the lower right quadrant.
-            fragBuilder->codeAppendf("float2 delta = abs(sk_FragCoord.xy - %s.%s);",
+            fragBuilder->codeAppendf("half2 delta = abs(sk_FragCoord.xy - %s.%s);",
                                      posName, indices);
 
             switch (mode) {
@@ -249,14 +249,14 @@
                     // When a shadow circle gets large we can have some precision issues if
                     // we do "length(delta)/radius". The scaleDist temporary cuts the
                     // delta vector down a bit before invoking length.
-                    fragBuilder->codeAppendf("float scaledDist = length(delta/%s);", radName);
+                    fragBuilder->codeAppendf("half scaledDist = length(delta/%s);", radName);
                     fragBuilder->codeAppendf("%s = clamp((%s.%c/%s - scaledDist), 0.0, 1.0);",
                                              outputName, sizesName, indices[0], radName);
                     break;
                 case kRect_Mode:
                     fragBuilder->codeAppendf(
-                        "float2 rectDist = float2(1.0 - clamp((%s.%c - delta.x)/%s, 0.0, 1.0),"
-                                             "1.0 - clamp((%s.%c - delta.y)/%s, 0.0, 1.0));",
+                        "half2 rectDist = half2(1.0 - clamp((%s.%c - delta.x)/%s, 0.0, 1.0),"
+                                               "1.0 - clamp((%s.%c - delta.y)/%s, 0.0, 1.0));",
                         sizesName, indices[0], radName,
                         sizesName, indices[1], radName);
                     fragBuilder->codeAppendf("%s = clamp(1.0 - length(rectDist), 0.0, 1.0);",
@@ -273,11 +273,11 @@
 
                     //----------------
                     // rect distance computation
-                    fragBuilder->codeAppendf("float xDist = (%s.%c - delta.x) / %s;",
+                    fragBuilder->codeAppendf("half xDist = (%s.%c - delta.x) / %s;",
                                              sizesName, indices[0], radName);
-                    fragBuilder->codeAppendf("float yDist = (%s.%c - delta.y) / %s;",
+                    fragBuilder->codeAppendf("half yDist = (%s.%c - delta.y) / %s;",
                                              sizesName, indices[1], radName);
-                    fragBuilder->codeAppend("float rectDist = clamp(min(xDist, yDist), 0.0, 1.0);");
+                    fragBuilder->codeAppend("half rectDist = clamp(min(xDist, yDist), 0.0, 1.0);");
 
                     //----------------
                     // ice-cream-cone fractional distance computation
@@ -286,59 +286,59 @@
                     // compute the pointy end of the ice cream cone. If it smaller we just want to
                     // use the center of the corner's circle. When using the blurRadius the inset
                     // amount can't exceed the halfwidths of the RRect.
-                    fragBuilder->codeAppendf("float insetDist = min(max(%s, %s.%c),"
+                    fragBuilder->codeAppendf("half insetDist = min(max(%s, %s.%c),"
                                                                    "min(%s.%c, %s.%c));",
                                              radName, radiiName, indices[0],
                                              sizesName, indices[0], sizesName, indices[1]);
                     // "maxValue" is a correction term for if the blurRadius is larger than the
                     // size of the RRect. In that case we don't want to go all the way to black.
-                    fragBuilder->codeAppendf("float maxValue = insetDist/%s;", radName);
+                    fragBuilder->codeAppendf("half maxValue = insetDist/%s;", radName);
 
-                    fragBuilder->codeAppendf("float2 coneBottom = float2(%s.%c - insetDist,"
-                                                                    "%s.%c - insetDist);",
+                    fragBuilder->codeAppendf("half2 coneBottom = half2(%s.%c - insetDist,"
+                                                                       "%s.%c - insetDist);",
                                              sizesName, indices[0], sizesName, indices[1]);
 
-                    fragBuilder->codeAppendf("float2 cornerTop = float2(%s.%c - %s.%c, %s.%c) -"
+                    fragBuilder->codeAppendf("half2 cornerTop = half2(%s.%c - %s.%c, %s.%c) -"
                                                                         "coneBottom;",
                                              sizesName, indices[0], radiiName, indices[0],
                                              sizesName, indices[1]);
-                    fragBuilder->codeAppendf("float2 cornerRight = float2(%s.%c, %s.%c - %s.%c) -"
+                    fragBuilder->codeAppendf("half2 cornerRight = half2(%s.%c, %s.%c - %s.%c) -"
                                                                         "coneBottom;",
                                              sizesName, indices[0],
                                              sizesName, indices[1], radiiName, indices[1]);
 
-                    fragBuilder->codeAppend("float2 ptInConeSpace = delta - coneBottom;");
-                    fragBuilder->codeAppend("float distToPtInConeSpace = length(ptInConeSpace);");
+                    fragBuilder->codeAppend("half2 ptInConeSpace = delta - coneBottom;");
+                    fragBuilder->codeAppend("half distToPtInConeSpace = length(ptInConeSpace);");
 
-                    fragBuilder->codeAppend("float cross1 =  ptInConeSpace.x * cornerTop.y -"
-                                                            "ptInConeSpace.y * cornerTop.x;");
-                    fragBuilder->codeAppend("float cross2 = -ptInConeSpace.x * cornerRight.y + "
-                                                            "ptInConeSpace.y * cornerRight.x;");
+                    fragBuilder->codeAppend("half cross1 =  ptInConeSpace.x * cornerTop.y -"
+                                                           "ptInConeSpace.y * cornerTop.x;");
+                    fragBuilder->codeAppend("half cross2 = -ptInConeSpace.x * cornerRight.y + "
+                                                           "ptInConeSpace.y * cornerRight.x;");
 
-                    fragBuilder->codeAppend("float inCone = step(0.0, cross1) *"
-                                                           "step(0.0, cross2);");
+                    fragBuilder->codeAppend("half inCone = step(0.0, cross1) *"
+                                                          "step(0.0, cross2);");
 
-                    fragBuilder->codeAppendf("float2 cornerCenterInConeSpace = float2(insetDist -"
+                    fragBuilder->codeAppendf("half2 cornerCenterInConeSpace = half2(insetDist -"
                                                                                  "%s.%c);",
                                              radiiName, indices[0]);
 
-                    fragBuilder->codeAppend("float2 connectingVec = ptInConeSpace -"
+                    fragBuilder->codeAppend("half2 connectingVec = ptInConeSpace -"
                                                                         "cornerCenterInConeSpace;");
                     fragBuilder->codeAppend("ptInConeSpace = normalize(ptInConeSpace);");
 
                     // "a" (i.e., dot(ptInConeSpace, ptInConeSpace) should always be 1.0f since
                     // ptInConeSpace is now normalized
-                    fragBuilder->codeAppend("float b = 2.0 * dot(ptInConeSpace, connectingVec);");
-                    fragBuilder->codeAppendf("float c = dot(connectingVec, connectingVec) - "
+                    fragBuilder->codeAppend("half b = 2.0 * dot(ptInConeSpace, connectingVec);");
+                    fragBuilder->codeAppendf("half c = dot(connectingVec, connectingVec) - "
                                                                                    "%s.%c * %s.%c;",
                                              radiiName, indices[0], radiiName, indices[0]);
 
-                    fragBuilder->codeAppend("float fourAC = 4*c;");
+                    fragBuilder->codeAppend("half fourAC = 4*c;");
                     // This max prevents sqrt(-1) when outside the cone
-                    fragBuilder->codeAppend("float bSq = max(b*b, fourAC);");
+                    fragBuilder->codeAppend("half bSq = max(b*b, fourAC);");
 
                     // lop off negative values that are outside the cone
-                    fragBuilder->codeAppend("float coneDist = "
+                    fragBuilder->codeAppend("half coneDist = "
                                                     "max(0.0, 0.5 * (-b + sqrt(bSq - fourAC)));");
                     // make the coneDist a fraction of how far it is from the edge to the
                     // cone's base
@@ -358,42 +358,38 @@
             GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
 
             const char* positionsUniName = nullptr;
-            fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
+            fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                        "Positions", &positionsUniName);
             const char* sizesUniName = nullptr;
-            fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec4f_GrSLType, kDefault_GrSLPrecision,
-                                                   "Sizes", &sizesUniName);
+            fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
+                                                   kDefault_GrSLPrecision, "Sizes", &sizesUniName);
             const char* radiiUniName = nullptr;
             if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimpleCircular_Mode) {
-                fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
+                fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                        "Radii", &radiiUniName);
             }
             const char* radUniName = nullptr;
-            fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kFloat_GrSLType, kDefault_GrSLPrecision,
+            fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                     "Radius", &radUniName);
 
-            fragBuilder->codeAppend("float firstDist;");
+            fragBuilder->codeAppend("half firstDist;");
             fragBuilder->codeAppend("{");
             this->emitModeCode(fp.firstMode(), fragBuilder,
                                positionsUniName, sizesUniName, radiiUniName,
                                radUniName, "firstDist", "xy");
             fragBuilder->codeAppend("}");
 
-            fragBuilder->codeAppend("float secondDist;");
+            fragBuilder->codeAppend("half secondDist;");
             fragBuilder->codeAppend("{");
             this->emitModeCode(fp.secondMode(), fragBuilder,
                                positionsUniName, sizesUniName, radiiUniName,
                                radUniName, "secondDist", "zw");
             fragBuilder->codeAppend("}");
 
-            fragBuilder->codeAppend("float2 distVec = float2(1.0 - firstDist, 1.0 - secondDist);");
+            fragBuilder->codeAppend("half2 distVec = half2(1.0 - firstDist, 1.0 - secondDist);");
 
             // Finally use the distance to apply the Gaussian edge
-            fragBuilder->codeAppend("float factor = clamp(length(distVec), 0.0, 1.0);");
+            fragBuilder->codeAppend("half factor = clamp(length(distVec), 0.0, 1.0);");
             fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
             fragBuilder->codeAppendf("%s = factor*%s;",
                                      args.fOutputColor, args.fInputColor);
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 0cda713..6ebcfa6 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -396,8 +396,7 @@
 
 void GLColorTableEffect::emitCode(EmitArgs& args) {
     const char* yoffsets;
-    fRGBAYValuesUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
+    fRGBAYValuesUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                        "yoffsets", &yoffsets);
     static const float kColorScaleFactor = 255.0f / 256.0f;
     static const float kColorOffsetFactor = 1.0f / 512.0f;
@@ -405,14 +404,14 @@
     if (nullptr == args.fInputColor) {
         // the input color is solid white (all ones).
         static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
-        fragBuilder->codeAppendf("\t\tfloat4 coord = float4(%f, %f, %f, %f);\n",
+        fragBuilder->codeAppendf("\t\thalf4 coord = half4(%f, %f, %f, %f);\n",
                                  kMaxValue, kMaxValue, kMaxValue, kMaxValue);
 
     } else {
-        fragBuilder->codeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor);
-        fragBuilder->codeAppendf("\t\tfloat4 coord = float4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n",
+        fragBuilder->codeAppendf("\t\thalf nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor);
+        fragBuilder->codeAppendf("\t\thalf4 coord = half4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n",
                                  args.fInputColor);
-        fragBuilder->codeAppendf("\t\tcoord = coord * %f + float4(%f, %f, %f, %f);\n",
+        fragBuilder->codeAppendf("\t\tcoord = coord * %f + half4(%f, %f, %f, %f);\n",
                                  kColorScaleFactor,
                                  kColorOffsetFactor, kColorOffsetFactor,
                                  kColorOffsetFactor, kColorOffsetFactor);
@@ -421,22 +420,22 @@
     SkString coord;
 
     fragBuilder->codeAppendf("\t\t%s.a = ", args.fOutputColor);
-    coord.printf("float2(coord.a, %s.a)", yoffsets);
+    coord.printf("half2(coord.a, %s.a)", yoffsets);
     fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
     fragBuilder->codeAppend(".a;\n");
 
     fragBuilder->codeAppendf("\t\t%s.r = ", args.fOutputColor);
-    coord.printf("float2(coord.r, %s.r)", yoffsets);
+    coord.printf("half2(coord.r, %s.r)", yoffsets);
     fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
     fragBuilder->codeAppend(".a;\n");
 
     fragBuilder->codeAppendf("\t\t%s.g = ", args.fOutputColor);
-    coord.printf("float2(coord.g, %s.g)", yoffsets);
+    coord.printf("half2(coord.g, %s.g)", yoffsets);
     fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
     fragBuilder->codeAppend(".a;\n");
 
     fragBuilder->codeAppendf("\t\t%s.b = ", args.fOutputColor);
-    coord.printf("float2(coord.b, %s.b)", yoffsets);
+    coord.printf("half2(coord.b, %s.b)", yoffsets);
     fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
     fragBuilder->codeAppend(".a;\n");
 
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp
index 659d333..58ae2a9 100644
--- a/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -82,26 +82,26 @@
 
             // Setup pass through color
             if (gp.hasVertexColor()) {
-                GrGLSLVertToFrag varying(kVec4f_GrSLType);
+                GrGLSLVertToFrag varying(kHalf4_GrSLType);
                 varyingHandler->addVarying("color", &varying);
 
                 // There are several optional steps to process the color. Start with the attribute:
-                vertBuilder->codeAppendf("float4 color = %s;", gp.inColor()->fName);
+                vertBuilder->codeAppendf("half4 color = %s;", gp.inColor()->fName);
 
                 // Linearize
                 if (gp.linearizeColor()) {
                     SkString srgbFuncName;
                     static const GrShaderVar gSrgbArgs[] = {
-                        GrShaderVar("x", kFloat_GrSLType),
+                        GrShaderVar("x", kHalf_GrSLType),
                     };
-                    vertBuilder->emitFunction(kFloat_GrSLType,
+                    vertBuilder->emitFunction(kHalf_GrSLType,
                                               "srgb_to_linear",
                                               SK_ARRAY_COUNT(gSrgbArgs),
                                               gSrgbArgs,
                                               "return (x <= 0.04045) ? (x / 12.92) "
                                               ": pow((x + 0.055) / 1.055, 2.4);",
                                               &srgbFuncName);
-                    vertBuilder->codeAppendf("color = float4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);",
+                    vertBuilder->codeAppendf("color = half4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);",
                                              srgbFuncName.c_str(), gp.inColor()->fName,
                                              srgbFuncName.c_str(), gp.inColor()->fName,
                                              srgbFuncName.c_str(), gp.inColor()->fName,
@@ -110,7 +110,7 @@
 
                 // For SkColor, do a red/blue swap and premul
                 if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) {
-                    vertBuilder->codeAppend("color = float4(color.a * color.bgr, color.a);");
+                    vertBuilder->codeAppend("color = half4(color.a * color.bgr, color.a);");
                 }
 
                 // Do color-correction to destination gamut
@@ -161,19 +161,18 @@
 
             // Setup coverage as pass through
             if (gp.hasVertexCoverage()) {
-                fragBuilder->codeAppendf("float alpha = 1.0;");
+                fragBuilder->codeAppendf("half alpha = 1.0;");
                 varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha");
-                fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage);
+                fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
             } else if (gp.coverage() == 0xff) {
-                fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+                fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
             } else {
                 const char* fragCoverage;
                 fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                              kFloat_GrSLType,
-                                                              kDefault_GrSLPrecision,
+                                                              kHalf_GrSLType,
                                                               "Coverage",
                                                               &fragCoverage);
-                fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, fragCoverage);
+                fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, fragCoverage);
             }
         }
 
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 060cde5..ca49da8 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -177,7 +177,7 @@
                 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
 
                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
-                fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
+                fragBuilder->codeAppendf("half invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
                                          args.fInputColor, args.fInputColor);
                 fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
             }
@@ -387,8 +387,7 @@
                 void emitCode(EmitArgs& args) override {
                     const char* colorName;
                     fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                                 kVec4f_GrSLType,
-                                                                 kDefault_GrSLPrecision,
+                                                                 kHalf4_GrSLType,
                                                                  "Color", &colorName);
                     this->emitChild(0, colorName, args);
                 }
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index 3237684..0c3efd1 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -18,7 +18,7 @@
 class GrShaderCaps;
 class GrSwizzle;
 
-/** Provides custom fragment shader code. Fragment processors receive an input color (float4) and
+/** Provides custom fragment shader code. Fragment processors receive an input color (half4) and
     produce an output color. They may reference textures and uniforms. They may use
     GrCoordTransforms to receive a transformation of the local coordinates that map from local space
     to the fragment being processed.
diff --git a/src/gpu/GrPathProcessor.cpp b/src/gpu/GrPathProcessor.cpp
index 42668bc..24326e9 100644
--- a/src/gpu/GrPathProcessor.cpp
+++ b/src/gpu/GrPathProcessor.cpp
@@ -37,14 +37,13 @@
         // Setup uniform color
         const char* stagedLocalVarName;
         fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                         kVec4f_GrSLType,
-                                                         kDefault_GrSLPrecision,
+                                                         kHalf4_GrSLType,
                                                          "Color",
                                                          &stagedLocalVarName);
         fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
 
         // setup constant solid coverage
-        fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+        fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
     }
 
     void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
@@ -52,8 +51,8 @@
         int i = 0;
         while (const GrCoordTransform* coordTransform = transformHandler->nextCoordTransform()) {
             GrSLType varyingType =
-                    coordTransform->getMatrix().hasPerspective() ? kVec3f_GrSLType
-                                                                 : kVec2f_GrSLType;
+                    coordTransform->getMatrix().hasPerspective() ? kHalf3_GrSLType
+                                                                 : kHalf2_GrSLType;
 
             SkString strVaryingName;
             strVaryingName.printf("TransformedCoord_%d", i);
@@ -89,9 +88,9 @@
             }
             fInstalledTransforms[t].fCurrentValue = m;
 
-            SkASSERT(fInstalledTransforms[t].fType == kVec2f_GrSLType ||
-                     fInstalledTransforms[t].fType == kVec3f_GrSLType);
-            unsigned components = fInstalledTransforms[t].fType == kVec2f_GrSLType ? 2 : 3;
+            SkASSERT(fInstalledTransforms[t].fType == kHalf2_GrSLType ||
+                     fInstalledTransforms[t].fType == kHalf3_GrSLType);
+            unsigned components = fInstalledTransforms[t].fType == kHalf2_GrSLType ? 2 : 3;
             pd.setPathFragmentInputTransform(fInstalledTransforms[t].fHandle, components, m);
             ++t;
         }
diff --git a/src/gpu/GrShaderVar.cpp b/src/gpu/GrShaderVar.cpp
index 09e98f8..fcc05c0 100644
--- a/src/gpu/GrShaderVar.cpp
+++ b/src/gpu/GrShaderVar.cpp
@@ -81,7 +81,7 @@
 }
 
 void GrShaderVar::appendDecl(const GrShaderCaps* shaderCaps, SkString* out) const {
-    SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeAcceptsPrecision(fType));
+    SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeTemporarilyAcceptsPrecision(fType));
     SkString layout = fLayoutQualifier;
     if (!fLayoutQualifier.isEmpty()) {
         out->appendf("layout(%s) ", fLayoutQualifier.c_str());
diff --git a/src/gpu/GrShaderVar.h b/src/gpu/GrShaderVar.h
index 7f09f8c..5a379b9 100644
--- a/src/gpu/GrShaderVar.h
+++ b/src/gpu/GrShaderVar.h
@@ -37,13 +37,12 @@
     };
 
     /**
-     * Defaults to a non-arry float with no precision specifier, type modifier, or layout qualifier.
+     * Defaults to a non-arry half with no type modifier or layout qualifier.
      */
     GrShaderVar()
-        : fType(kFloat_GrSLType)
+        : fType(kHalf_GrSLType)
         , fTypeModifier(kNone_TypeModifier)
         , fCount(kNonArray)
-        , fPrecision(kDefault_GrSLPrecision)
         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
     }
 
@@ -116,7 +115,7 @@
              const char* extraModifiers = nullptr,
              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
         SkASSERT(kVoid_GrSLType != type);
-        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
         fType = type;
         fTypeModifier = typeModifier;
         fName = name;
@@ -140,7 +139,7 @@
              const char* extraModifiers = nullptr,
              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
         SkASSERT(kVoid_GrSLType != type);
-        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
         fType = type;
         fTypeModifier = typeModifier;
         fName = name;
@@ -165,7 +164,7 @@
              const char* extraModifiers = nullptr,
              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
         SkASSERT(kVoid_GrSLType != type);
-        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
         fType = type;
         fTypeModifier = typeModifier;
         fName = name;
@@ -190,7 +189,7 @@
              const char* extraModifiers = nullptr,
              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
         SkASSERT(kVoid_GrSLType != type);
-        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
         fType = type;
         fTypeModifier = typeModifier;
         fName = name;
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp b/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
index 079f240..4aac3d3 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
@@ -122,8 +122,8 @@
                                           const TexelBufferHandle& pointsBuffer,
                                           const char* rtAdjust, GrGPArgs* gpArgs) const {
     v->codeAppendf("int packedoffset = %s[%i];", proc.instanceAttrib(), proc.atlasOffsetIdx());
-    v->codeAppend ("highp float2 atlasoffset = float2((packedoffset<<16) >> 16, "
-                                                     "packedoffset >> 16);");
+    v->codeAppend ("highfloat2 atlasoffset = highfloat2((packedoffset<<16) >> 16, "
+                                                       "packedoffset >> 16);");
 
     this->onEmitVertexShader(proc, v, pointsBuffer, "atlasoffset", rtAdjust, gpArgs);
 }
@@ -135,12 +135,10 @@
 
     SkString emitVertexFn;
     SkSTArray<2, GrShaderVar> emitArgs;
-    const char* position = emitArgs.emplace_back("position", kVec2f_GrSLType,
-                                                 GrShaderVar::kNonArray,
-                                                 kHigh_GrSLPrecision).c_str();
-    const char* coverage = emitArgs.emplace_back("coverage", kFloat_GrSLType,
-                                                 GrShaderVar::kNonArray,
-                                                 kHigh_GrSLPrecision).c_str();
+    const char* position = emitArgs.emplace_back("position", kHighFloat2_GrSLType,
+                                                 GrShaderVar::kNonArray).c_str();
+    const char* coverage = emitArgs.emplace_back("coverage", kHighFloat_GrSLType,
+                                                 GrShaderVar::kNonArray).c_str();
     g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
         SkString fnBody;
         this->emitPerVertexGeometryCode(&fnBody, position, coverage, fGeomWind.c_str());
@@ -151,12 +149,12 @@
             fnBody.appendf("%s = %s * %s;",
                            fFragCoverageTimesWind.gsOut(), coverage, fGeomWind.c_str());
         }
-        fnBody.append ("gl_Position = float4(position, 0, 1);");
+        fnBody.append ("gl_Position = highfloat4(position, 0, 1);");
         fnBody.append ("EmitVertex();");
         return fnBody;
     }().c_str(), &emitVertexFn);
 
-    g->codeAppendf("highp float2 bloat = %f * abs(%s.xz);", kAABloatRadius, rtAdjust);
+    g->codeAppendf("highfloat2 bloat = %f * abs(%s.xz);", kAABloatRadius, rtAdjust);
 
 #ifdef SK_DEBUG
     if (proc.debugVisualizationsEnabled()) {
@@ -173,7 +171,7 @@
     SkASSERT(numSides >= 3);
 
     if (!midpoint) {
-        g->codeAppendf("highp float2 midpoint = %s * float%i(%f);",
+        g->codeAppendf("highfloat2 midpoint = %s * highfloat%i(%f);",
                        polygonPts, numSides, 1.0 / numSides);
         midpoint = "midpoint";
     }
@@ -182,42 +180,42 @@
                        "nextidx = (%s + 1) %% %i;",
                    wedgeIdx, numSides - 1, numSides, wedgeIdx, numSides);
 
-    g->codeAppendf("highp float2 self = %s[%s];"
-                   "highp int leftidx = %s > 0 ? previdx : nextidx;"
-                   "highp int rightidx = %s > 0 ? nextidx : previdx;",
+    g->codeAppendf("highfloat2 self = %s[%s];"
+                   "int leftidx = %s > 0 ? previdx : nextidx;"
+                   "int rightidx = %s > 0 ? nextidx : previdx;",
                    polygonPts, wedgeIdx, fGeomWind.c_str(), fGeomWind.c_str());
 
     // Which quadrant does the vector from self -> right fall into?
-    g->codeAppendf("highp float2 right = %s[rightidx];", polygonPts);
+    g->codeAppendf("highfloat2 right = %s[rightidx];", polygonPts);
     if (3 == numSides) {
         // TODO: evaluate perf gains.
-        g->codeAppend ("highp float2 qsr = sign(right - self);");
+        g->codeAppend ("highfloat2 qsr = sign(right - self);");
     } else {
         SkASSERT(4 == numSides);
-        g->codeAppendf("highp float2 diag = %s[(%s + 2) %% 4];", polygonPts, wedgeIdx);
-        g->codeAppend ("highp float2 qsr = sign((right != self ? right : diag) - self);");
+        g->codeAppendf("highfloat2 diag = %s[(%s + 2) %% 4];", polygonPts, wedgeIdx);
+        g->codeAppend ("highfloat2 qsr = sign((right != self ? right : diag) - self);");
     }
 
     // Which quadrant does the vector from left -> self fall into?
-    g->codeAppendf("highp float2 qls = sign(self - %s[leftidx]);", polygonPts);
+    g->codeAppendf("highfloat2 qls = sign(self - %s[leftidx]);", polygonPts);
 
     // d2 just helps us reduce triangle counts with orthogonal, axis-aligned lines.
     // TODO: evaluate perf gains.
     const char* dr2 = "dr";
     if (3 == numSides) {
         // TODO: evaluate perf gains.
-        g->codeAppend ("highp float2 dr = float2(qsr.y != 0 ? +qsr.y : +qsr.x, "
-                                            "qsr.x != 0 ? -qsr.x : +qsr.y);");
-        g->codeAppend ("highp float2 dr2 = float2(qsr.y != 0 ? +qsr.y : -qsr.x, "
-                                             "qsr.x != 0 ? -qsr.x : -qsr.y);");
-        g->codeAppend ("highp float2 dl = float2(qls.y != 0 ? +qls.y : +qls.x, "
-                                            "qls.x != 0 ? -qls.x : +qls.y);");
+        g->codeAppend ("highfloat2 dr = highfloat2(qsr.y != 0 ? +qsr.y : +qsr.x, "
+                                                  "qsr.x != 0 ? -qsr.x : +qsr.y);");
+        g->codeAppend ("highfloat2 dr2 = highfloat2(qsr.y != 0 ? +qsr.y : -qsr.x, "
+                                                   "qsr.x != 0 ? -qsr.x : -qsr.y);");
+        g->codeAppend ("highfloat2 dl = highfloat2(qls.y != 0 ? +qls.y : +qls.x, "
+                                                  "qls.x != 0 ? -qls.x : +qls.y);");
         dr2 = "dr2";
     } else {
-        g->codeAppend ("highp float2 dr = float2(qsr.y != 0 ? +qsr.y : 1, "
-                                            "qsr.x != 0 ? -qsr.x : 1);");
-        g->codeAppend ("highp float2 dl = (qls == float2(0)) ? dr : "
-                                       "float2(qls.y != 0 ? +qls.y : 1, qls.x != 0 ? -qls.x : 1);");
+        g->codeAppend ("highfloat2 dr = highfloat2(qsr.y != 0 ? +qsr.y : 1, "
+                                                  "qsr.x != 0 ? -qsr.x : 1);");
+        g->codeAppend ("highfloat2 dl = (qls == highfloat2(0)) ? dr : "
+                                   "highfloat2(qls.y != 0 ? +qls.y : 1, qls.x != 0 ? -qls.x : 1);");
     }
     g->codeAppendf("bool2 dnotequal = notEqual(%s, dl);", dr2);
 
@@ -230,7 +228,7 @@
     g->codeAppendf(    "%s(self + bloat * dl, 1);", emitVertexFn);
     g->codeAppend ("}");
     g->codeAppend ("if (all(dnotequal)) {");
-    g->codeAppendf(    "%s(self + bloat * float2(-dl.y, dl.x), 1);", emitVertexFn);
+    g->codeAppendf(    "%s(self + bloat * highfloat2(-dl.y, dl.x), 1);", emitVertexFn);
     g->codeAppend ("}");
     g->codeAppend ("EndPrimitive();");
 
@@ -241,18 +239,18 @@
                                          const char* leftPt, const char* rightPt,
                                          const char* distanceEquation) const {
     if (!distanceEquation) {
-        this->emitEdgeDistanceEquation(g, leftPt, rightPt, "highp float3 edge_distance_equation");
+        this->emitEdgeDistanceEquation(g, leftPt, rightPt, "highfloat3 edge_distance_equation");
         distanceEquation = "edge_distance_equation";
     }
 
     // qlr is defined in emitEdgeDistanceEquation.
-    g->codeAppendf("highp float2x2 endpts = float2x2(%s - bloat * qlr, %s + bloat * qlr);",
+    g->codeAppendf("highfloat2x2 endpts = highfloat2x2(%s - bloat * qlr, %s + bloat * qlr);",
                    leftPt, rightPt);
-    g->codeAppendf("mediump float2 endpts_coverage = %s.xy * endpts + %s.z;",
+    g->codeAppendf("half2 endpts_coverage = %s.xy * endpts + %s.z;",
                    distanceEquation, distanceEquation);
 
     // d1 is defined in emitEdgeDistanceEquation.
-    g->codeAppend ("highp float2 d2 = d1;");
+    g->codeAppend ("highfloat2 d2 = d1;");
     g->codeAppend ("bool aligned = qlr.x == 0 || qlr.y == 0;");
     g->codeAppend ("if (aligned) {");
     g->codeAppend (    "d1 -= qlr;");
@@ -281,25 +279,25 @@
                                                   const char* leftPt, const char* rightPt,
                                                   const char* outputDistanceEquation) const {
     // Which quadrant does the vector from left -> right fall into?
-    g->codeAppendf("highp float2 qlr = sign(%s - %s);", rightPt, leftPt);
-    g->codeAppend ("highp float2 d1 = float2(qlr.y, -qlr.x);");
+    g->codeAppendf("highfloat2 qlr = sign(%s - %s);", rightPt, leftPt);
+    g->codeAppend ("highfloat2 d1 = highfloat2(qlr.y, -qlr.x);");
 
-    g->codeAppendf("highp float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
+    g->codeAppendf("highfloat2 n = highfloat2(%s.y - %s.y, %s.x - %s.x);",
                    rightPt, leftPt, leftPt, rightPt);
-    g->codeAppendf("highp float2 kk = n * float2x2(%s + bloat * d1, %s - bloat * d1);",
+    g->codeAppendf("highfloat2 kk = n * highfloat2x2(%s + bloat * d1, %s - bloat * d1);",
                    leftPt, leftPt);
     // Clamp for when n=0. wind=0 when n=0 so as long as we don't get Inf or NaN we are fine.
-    g->codeAppendf("highp float scale = 1 / max(kk[0] - kk[1], 1e-30);");
+    g->codeAppendf("highfloat scale = 1 / max(kk[0] - kk[1], 1e-30);");
 
-    g->codeAppendf("%s = float3(-n, kk[1]) * scale;", outputDistanceEquation);
+    g->codeAppendf("%s = half3(-n, kk[1]) * scale;", outputDistanceEquation);
 }
 
 int PrimitiveProcessor::emitCornerGeometry(GrGLSLGeometryBuilder* g, const char* emitVertexFn,
                                            const char* pt) const {
-    g->codeAppendf("%s(%s + float2(-bloat.x, -bloat.y), 1);", emitVertexFn, pt);
-    g->codeAppendf("%s(%s + float2(-bloat.x, +bloat.y), 1);", emitVertexFn, pt);
-    g->codeAppendf("%s(%s + float2(+bloat.x, -bloat.y), 1);", emitVertexFn, pt);
-    g->codeAppendf("%s(%s + float2(+bloat.x, +bloat.y), 1);", emitVertexFn, pt);
+    g->codeAppendf("%s(%s + highfloat2(-bloat.x, -bloat.y), 1);", emitVertexFn, pt);
+    g->codeAppendf("%s(%s + highfloat2(-bloat.x, +bloat.y), 1);", emitVertexFn, pt);
+    g->codeAppendf("%s(%s + highfloat2(+bloat.x, -bloat.y), 1);", emitVertexFn, pt);
+    g->codeAppendf("%s(%s + highfloat2(+bloat.x, +bloat.y), 1);", emitVertexFn, pt);
     g->codeAppend ("EndPrimitive();");
 
     return 4;
@@ -315,17 +313,17 @@
             f->codeAppendf("%s.a = %s;", outputColor, fFragCoverageTimesWind.fsIn());
             break;
         case CoverageType::kShader:
-            f->codeAppendf("mediump float coverage = 0;");
+            f->codeAppendf("half coverage = 0;");
             this->emitShaderCoverage(f, "coverage");
             f->codeAppendf("%s.a = coverage * %s;", outputColor, fFragWind.fsIn());
             break;
     }
 
-    f->codeAppendf("%s = float4(1);", outputCoverage);
+    f->codeAppendf("%s = half4(1);", outputCoverage);
 
 #ifdef SK_DEBUG
     if (proc.debugVisualizationsEnabled()) {
-        f->codeAppendf("%s = float4(-%s.a, %s.a, 0, 1);", outputColor, outputColor, outputColor);
+        f->codeAppendf("%s = half4(-%s.a, %s.a, 0, 1);", outputColor, outputColor, outputColor);
     }
 #endif
 }
@@ -334,17 +332,17 @@
                                                   const char* samplesName) const {
     // Standard DX11 sample locations.
 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
-    f->defineConstant("highp float2[8]", samplesName, "float2[8]("
-        "float2(+1, -3)/16, float2(-1, +3)/16, float2(+5, +1)/16, float2(-3, -5)/16, "
-        "float2(-5, +5)/16, float2(-7, -1)/16, float2(+3, +7)/16, float2(+7, -7)/16."
+    f->defineConstant("highfloat2[8]", samplesName, "highfloat2[8]("
+        "highfloat2(+1, -3)/16, highfloat2(-1, +3)/16, highfloat2(+5, +1)/16, highfloat2(-3, -5)/16, "
+        "highfloat2(-5, +5)/16, highfloat2(-7, -1)/16, highfloat2(+3, +7)/16, highfloat2(+7, -7)/16."
     ")");
     return 8;
 #else
-    f->defineConstant("highp float2[16]", samplesName, "float2[16]("
-        "float2(+1, +1)/16, float2(-1, -3)/16, float2(-3, +2)/16, float2(+4, -1)/16, "
-        "float2(-5, -2)/16, float2(+2, +5)/16, float2(+5, +3)/16, float2(+3, -5)/16, "
-        "float2(-2, +6)/16, float2( 0, -7)/16, float2(-4, -6)/16, float2(-6, +4)/16, "
-        "float2(-8,  0)/16, float2(+7, -4)/16, float2(+6, +7)/16, float2(-7, -8)/16."
+    f->defineConstant("highfloat2[16]", samplesName, "highfloat2[16]("
+        "highfloat2(+1, +1)/16, highfloat2(-1, -3)/16, highfloat2(-3, +2)/16, highfloat2(+4, -1)/16, "
+        "highfloat2(-5, -2)/16, highfloat2(+2, +5)/16, highfloat2(+5, +3)/16, highfloat2(+3, -5)/16, "
+        "highfloat2(-2, +6)/16, highfloat2( 0, -7)/16, highfloat2(-4, -6)/16, highfloat2(-6, +4)/16, "
+        "highfloat2(-8,  0)/16, highfloat2(+7, -4)/16, highfloat2(+6, +7)/16, highfloat2(-7, -8)/16."
     ")");
     return 16;
 #endif
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.h b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
index b8032d9..8120136 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
@@ -133,9 +133,9 @@
 
     PrimitiveProcessor(CoverageType coverageType)
             : fCoverageType(coverageType)
-            , fGeomWind("wind", kFloat_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision)
-            , fFragWind(kFloat_GrSLType)
-            , fFragCoverageTimesWind(kFloat_GrSLType) {}
+            , fGeomWind("wind", kHalf_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision)
+            , fFragWind(kHalf_GrSLType)
+            , fFragCoverageTimesWind(kHalf_GrSLType) {}
 
     // Called before generating shader code. Subclass should add its custom varyings to the handler
     // and update its corresponding internal member variables.
diff --git a/src/gpu/ccpr/GrCCPRCubicProcessor.cpp b/src/gpu/ccpr/GrCCPRCubicProcessor.cpp
index 0ac4517..1fc2a29 100644
--- a/src/gpu/ccpr/GrCCPRCubicProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRCubicProcessor.cpp
@@ -16,18 +16,18 @@
                                               const TexelBufferHandle& pointsBuffer,
                                               const char* atlasOffset, const char* rtAdjust,
                                               GrGPArgs* gpArgs) const {
-    v->codeAppend ("highp float2 self = ");
+    v->codeAppend ("highfloat2 self = ");
     v->appendTexelFetch(pointsBuffer,
                         SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str());
     v->codeAppendf(".xy + %s;", atlasOffset);
-    gpArgs->fPositionVar.set(kVec2f_GrSLType, "self");
+    gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "self");
 }
 
 void GrCCPRCubicProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* rtAdjust,
                                     const char* outputWind) const {
     // We will define bezierpts in onEmitGeometryShader.
-    g->codeAppend ("highp float area_times_2 = "
-                                          "determinant(float3x3(1, bezierpts[0], "
+    g->codeAppend ("highfloat area_times_2 = "
+                                      "determinant(highfloat3x3(1, bezierpts[0], "
                                                                "1, bezierpts[2], "
                                                                "0, bezierpts[3] - bezierpts[1]));");
     // Drop curves that are nearly flat. The KLM  math becomes unstable in this case.
@@ -46,61 +46,61 @@
 void GrCCPRCubicProcessor::onEmitGeometryShader(GrGLSLGeometryBuilder* g, const char* emitVertexFn,
                                                 const char* wind, const char* rtAdjust) const {
     // Prepend bezierpts at the start of the shader.
-    g->codePrependf("highp float4x2 bezierpts = float4x2(sk_in[0].gl_Position.xy, "
-                                                        "sk_in[1].gl_Position.xy, "
-                                                        "sk_in[2].gl_Position.xy, "
-                                                        "sk_in[3].gl_Position.xy);");
+    g->codePrependf("highfloat4x2 bezierpts = highfloat4x2(sk_in[0].gl_Position.xy, "
+                                                          "sk_in[1].gl_Position.xy, "
+                                                          "sk_in[2].gl_Position.xy, "
+                                                          "sk_in[3].gl_Position.xy);");
 
     // Evaluate the cubic at T=.5 for an mid-ish point.
-    g->codeAppendf("highp float2 midpoint = bezierpts * float4(.125, .375, .375, .125);");
+    g->codeAppendf("highfloat2 midpoint = bezierpts * highfloat4(.125, .375, .375, .125);");
 
     // Find the cubic's power basis coefficients.
-    g->codeAppend ("highp float2x4 C = float4x4(-1,  3, -3,  1, "
-                                               " 3, -6,  3,  0, "
-                                               "-3,  3,  0,  0, "
-                                               " 1,  0,  0,  0) * transpose(bezierpts);");
+    g->codeAppend ("highfloat2x4 C = highfloat4x4(-1,  3, -3,  1, "
+                                                 " 3, -6,  3,  0, "
+                                                 "-3,  3,  0,  0, "
+                                                 " 1,  0,  0,  0) * transpose(bezierpts);");
 
     // Find the cubic's inflection function.
-    g->codeAppend ("highp float D3 = +determinant(float2x2(C[0].yz, C[1].yz));");
-    g->codeAppend ("highp float D2 = -determinant(float2x2(C[0].xz, C[1].xz));");
-    g->codeAppend ("highp float D1 = +determinant(float2x2(C));");
+    g->codeAppend ("highfloat D3 = +determinant(highfloat2x2(C[0].yz, C[1].yz));");
+    g->codeAppend ("highfloat D2 = -determinant(highfloat2x2(C[0].xz, C[1].xz));");
+    g->codeAppend ("highfloat D1 = +determinant(highfloat2x2(C));");
 
     // Calculate the KLM matrix.
     g->declareGlobal(fKLMMatrix);
-    g->codeAppend ("highp float4 K, L, M;");
-    g->codeAppend ("highp float2 l, m;");
-    g->codeAppend ("highp float discr = 3*D2*D2 - 4*D1*D3;");
+    g->codeAppend ("highfloat4 K, L, M;");
+    g->codeAppend ("highfloat2 l, m;");
+    g->codeAppend ("highfloat discr = 3*D2*D2 - 4*D1*D3;");
     if (CubicType::kSerpentine == fCubicType) {
         // This math also works out for the "cusp" and "cusp at infinity" cases.
-        g->codeAppend ("highp float q = 3*D2 + sign(D2) * sqrt(max(3*discr, 0));");
-        g->codeAppend ("l.ts = normalize(float2(q, 6*D1));");
-        g->codeAppend ("m.ts = discr <= 0 ? l.ts : normalize(float2(2*D3, q));");
-        g->codeAppend ("K = float4(0, l.s * m.s, -l.t * m.s - m.t * l.s, l.t * m.t);");
-        g->codeAppend ("L = float4(-1,3,-3,1) * l.ssst * l.sstt * l.sttt;");
-        g->codeAppend ("M = float4(-1,3,-3,1) * m.ssst * m.sstt * m.sttt;");
+        g->codeAppend ("highfloat q = 3*D2 + sign(D2) * sqrt(max(3*discr, 0));");
+        g->codeAppend ("l.ts = normalize(highfloat2(q, 6*D1));");
+        g->codeAppend ("m.ts = discr <= 0 ? l.ts : normalize(highfloat2(2*D3, q));");
+        g->codeAppend ("K = highfloat4(0, l.s * m.s, -l.t * m.s - m.t * l.s, l.t * m.t);");
+        g->codeAppend ("L = highfloat4(-1,3,-3,1) * l.ssst * l.sstt * l.sttt;");
+        g->codeAppend ("M = highfloat4(-1,3,-3,1) * m.ssst * m.sstt * m.sttt;");
     } else {
-        g->codeAppend ("highp float q = D2 + sign(D2) * sqrt(max(-discr, 0));");
-        g->codeAppend ("l.ts = normalize(float2(q, 2*D1));");
-        g->codeAppend ("m.ts = discr >= 0 ? l.ts : normalize(float2(2 * (D2*D2 - D3*D1), D1*q));");
-        g->codeAppend ("highp float4 lxm = float4(l.s * m.s, l.s * m.t, l.t * m.s, l.t * m.t);");
-        g->codeAppend ("K = float4(0, lxm.x, -lxm.y - lxm.z, lxm.w);");
-        g->codeAppend ("L = float4(-1,1,-1,1) * l.sstt * (lxm.xyzw + float4(0, 2*lxm.zy, 0));");
-        g->codeAppend ("M = float4(-1,1,-1,1) * m.sstt * (lxm.xzyw + float4(0, 2*lxm.yz, 0));");
+        g->codeAppend ("highfloat q = D2 + sign(D2) * sqrt(max(-discr, 0));");
+        g->codeAppend ("l.ts = normalize(highfloat2(q, 2*D1));");
+        g->codeAppend ("m.ts = discr >= 0 ? l.ts : normalize(highfloat2(2 * (D2*D2 - D3*D1), D1*q));");
+        g->codeAppend ("highfloat4 lxm = highfloat4(l.s * m.s, l.s * m.t, l.t * m.s, l.t * m.t);");
+        g->codeAppend ("K = highfloat4(0, lxm.x, -lxm.y - lxm.z, lxm.w);");
+        g->codeAppend ("L = highfloat4(-1,1,-1,1) * l.sstt * (lxm.xyzw + highfloat4(0, 2*lxm.zy, 0));");
+        g->codeAppend ("M = highfloat4(-1,1,-1,1) * m.sstt * (lxm.xzyw + highfloat4(0, 2*lxm.yz, 0));");
     }
-    g->codeAppend ("lowp int middlerow = abs(D2) > abs(D1) ? 2 : 1;");
-    g->codeAppend ("highp float3x3 CI = inverse(float3x3(C[0][0], C[0][middlerow], C[0][3], "
-                                                        "C[1][0], C[1][middlerow], C[1][3], "
-                                                        "      0,               0,       1));");
-    g->codeAppendf("%s = CI * float3x3(K[0], K[middlerow], K[3], "
-                                      "L[0], L[middlerow], L[3], "
-                                      "M[0], M[middlerow], M[3]);", fKLMMatrix.c_str());
+    g->codeAppend ("short middlerow = abs(D2) > abs(D1) ? 2 : 1;");
+    g->codeAppend ("highfloat3x3 CI = inverse(highfloat3x3(C[0][0], C[0][middlerow], C[0][3], "
+                                                          "C[1][0], C[1][middlerow], C[1][3], "
+                                                          "      0,               0,       1));");
+    g->codeAppendf("%s = CI * highfloat3x3(K[0], K[middlerow], K[3], "
+                                          "L[0], L[middlerow], L[3], "
+                                          "M[0], M[middlerow], M[3]);", fKLMMatrix.c_str());
 
     // Orient the KLM matrix so we fill the correct side of the curve.
-    g->codeAppendf("lowp float2 orientation = sign(float3(midpoint, 1) * float2x3(%s[1], %s[2]));",
+    g->codeAppendf("half2 orientation = sign(half3(midpoint, 1) * half2x3(%s[1], %s[2]));",
                    fKLMMatrix.c_str(), fKLMMatrix.c_str());
-    g->codeAppendf("%s *= float3x3(orientation[0] * orientation[1], 0, 0, "
-                                  "0, orientation[0], 0, "
-                                  "0, 0, orientation[1]);", fKLMMatrix.c_str());
+    g->codeAppendf("%s *= highfloat3x3(orientation[0] * orientation[1], 0, 0, "
+                                      "0, orientation[0], 0, "
+                                      "0, 0, orientation[1]);", fKLMMatrix.c_str());
 
     g->declareGlobal(fKLMDerivatives);
     g->codeAppendf("%s[0] = %s[0].xy * %s.xz;",
@@ -112,9 +112,9 @@
 
     // Determine the amount of additional coverage to subtract out for the flat edge (P3 -> P0).
     g->declareGlobal(fEdgeDistanceEquation);
-    g->codeAppendf("int edgeidx0 = %s > 0 ? 3 : 0;", wind);
-    g->codeAppendf("highp float2 edgept0 = bezierpts[edgeidx0];");
-    g->codeAppendf("highp float2 edgept1 = bezierpts[3 - edgeidx0];");
+    g->codeAppendf("short edgeidx0 = %s > 0 ? 3 : 0;", wind);
+    g->codeAppendf("highfloat2 edgept0 = bezierpts[edgeidx0];");
+    g->codeAppendf("highfloat2 edgept1 = bezierpts[3 - edgeidx0];");
     this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
 
     this->emitCubicGeometry(g, emitVertexFn, wind, rtAdjust);
@@ -123,10 +123,10 @@
 void GrCCPRCubicProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position,
                                                      const char* /*coverage*/,
                                                      const char* /*wind*/) const {
-    fnBody->appendf("highp float3 klm = float3(%s, 1) * %s;", position, fKLMMatrix.c_str());
-    fnBody->appendf("highp float d = dot(float3(%s, 1), %s);",
+    fnBody->appendf("highfloat3 klm = highfloat3(%s, 1) * %s;", position, fKLMMatrix.c_str());
+    fnBody->appendf("highfloat d = dot(highfloat3(%s, 1), %s);",
                     position, fEdgeDistanceEquation.c_str());
-    fnBody->appendf("%s = float4(klm, d);", fKLMD.gsOut());
+    fnBody->appendf("%s = highfloat4(klm, d);", fKLMD.gsOut());
     this->onEmitPerVertexGeometryCode(fnBody);
 }
 
@@ -150,10 +150,10 @@
 
 void GrCCPRCubicHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
                                                   const char* outputCoverage) const {
-    f->codeAppendf("highp float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
+    f->codeAppendf("highfloat k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
                    fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
-    f->codeAppend ("highp float f = k*k*k - l*m;");
-    f->codeAppendf("highp float2 grad_f = %s * float2(k, 1);", fGradMatrix.fsIn());
+    f->codeAppend ("highfloat f = k*k*k - l*m;");
+    f->codeAppendf("highfloat2 grad_f = %s * highfloat2(k, 1);", fGradMatrix.fsIn());
     f->codeAppendf("%s = clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);", outputCoverage);
     f->codeAppendf("%s += min(d, 0);", outputCoverage); // Flat closing edge.
 }
@@ -166,7 +166,7 @@
     g->codeAppendf("%s = %s.xy * %s.xz;",
                    fEdgeDistanceDerivatives.c_str(), fEdgeDistanceEquation.c_str(), rtAdjust);
 
-    g->codeAppendf("highp float2 corner = bezierpts[sk_InvocationID * 3];");
+    g->codeAppendf("highfloat2 corner = bezierpts[sk_InvocationID * 3];");
     int numVertices = this->emitCornerGeometry(g, emitVertexFn, "corner");
 
     g->configure(GrGLSLGeometryBuilder::InputType::kLinesAdjacency,
@@ -174,10 +174,10 @@
 }
 
 void GrCCPRCubicCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const {
-    fnBody->appendf("%s = float4(%s[0].x, %s[1].x, %s[2].x, %s.x);",
+    fnBody->appendf("%s = highfloat4(%s[0].x, %s[1].x, %s[2].x, %s.x);",
                     fdKLMDdx.gsOut(), fKLMDerivatives.c_str(), fKLMDerivatives.c_str(),
                     fKLMDerivatives.c_str(), fEdgeDistanceDerivatives.c_str());
-    fnBody->appendf("%s = float4(%s[0].y, %s[1].y, %s[2].y, %s.y);",
+    fnBody->appendf("%s = highfloat4(%s[0].y, %s[1].y, %s[2].y, %s.y);",
                     fdKLMDdy.gsOut(), fKLMDerivatives.c_str(), fKLMDerivatives.c_str(),
                     fKLMDerivatives.c_str(), fEdgeDistanceDerivatives.c_str());
 
@@ -187,28 +187,28 @@
 
 void GrCCPRCubicCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
                                                     const char* outputCoverage) const {
-    f->codeAppendf("highp float2x4 grad_klmd = float2x4(%s, %s);",
+    f->codeAppendf("highfloat2x4 grad_klmd = highfloat2x4(%s, %s);",
                    fdKLMDdx.fsIn(), fdKLMDdy.fsIn());
 
     // Erase what the previous hull shader wrote. We don't worry about the two corners falling on
     // the same pixel because those cases should have been weeded out by this point.
-    f->codeAppendf("highp float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
+    f->codeAppendf("highfloat k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
                    fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
-    f->codeAppend ("highp float f = k*k*k - l*m;");
-    f->codeAppend ("highp float2 grad_f = float3(3*k*k, -m, -l) * float2x3(grad_klmd);");
+    f->codeAppend ("highfloat f = k*k*k - l*m;");
+    f->codeAppend ("highfloat2 grad_f = highfloat3(3*k*k, -m, -l) * highfloat2x3(grad_klmd);");
     f->codeAppendf("%s = -clamp(0.5 - f * inversesqrt(dot(grad_f, grad_f)), 0, 1);",
                    outputCoverage);
     f->codeAppendf("%s -= d;", outputCoverage);
 
     // Use software msaa to estimate actual coverage at the corner pixels.
     const int sampleCount = this->defineSoftSampleLocations(f, "samples");
-    f->codeAppendf("highp float4 klmd_center = float4(%s.xyz, %s.w + 0.5);",
+    f->codeAppendf("highfloat4 klmd_center = highfloat4(%s.xyz, %s.w + 0.5);",
                    fKLMD.fsIn(), fKLMD.fsIn());
     f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount);
-    f->codeAppend (    "highp float4 klmd = grad_klmd * samples[i] + klmd_center;");
-    f->codeAppend (    "lowp float f = klmd.y * klmd.z - klmd.x * klmd.x * klmd.x;");
-    f->codeAppendf(    "%s += all(greaterThan(float4(f, klmd.y, klmd.z, klmd.w), "
-                                             "float4(0))) ? %f : 0;",
+    f->codeAppend (    "highfloat4 klmd = grad_klmd * samples[i] + klmd_center;");
+    f->codeAppend (    "half f = klmd.y * klmd.z - klmd.x * klmd.x * klmd.x;");
+    f->codeAppendf(    "%s += all(greaterThan(half4(f, klmd.y, klmd.z, klmd.w), "
+                                             "half4(0))) ? %f : 0;",
                        outputCoverage, 1.0 / sampleCount);
     f->codeAppend ("}");
 }
diff --git a/src/gpu/ccpr/GrCCPRCubicProcessor.h b/src/gpu/ccpr/GrCCPRCubicProcessor.h
index cfee7bf..20ca3f2 100644
--- a/src/gpu/ccpr/GrCCPRCubicProcessor.h
+++ b/src/gpu/ccpr/GrCCPRCubicProcessor.h
@@ -33,12 +33,12 @@
     GrCCPRCubicProcessor(CubicType cubicType)
             : INHERITED(CoverageType::kShader)
             , fCubicType(cubicType)
-            , fKLMMatrix("klm_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray,
+            , fKLMMatrix("klm_matrix", kHighFloat3x3_GrSLType, GrShaderVar::kNonArray,
                          kHigh_GrSLPrecision)
-            , fKLMDerivatives("klm_derivatives", kVec2f_GrSLType, 3, kHigh_GrSLPrecision)
-            , fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType,
+            , fKLMDerivatives("klm_derivatives", kHighFloat2_GrSLType, 3, kHigh_GrSLPrecision)
+            , fEdgeDistanceEquation("edge_distance_equation", kHighFloat3_GrSLType,
                                     GrShaderVar::kNonArray, kHigh_GrSLPrecision)
-            , fKLMD(kVec4f_GrSLType) {}
+            , fKLMD(kHighFloat4_GrSLType) {}
 
     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
         varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision);
@@ -71,7 +71,7 @@
 public:
     GrCCPRCubicHullProcessor(CubicType cubicType)
             : INHERITED(cubicType)
-            , fGradMatrix(kMat22f_GrSLType) {}
+            , fGradMatrix(kHighFloat2x2_GrSLType) {}
 
     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
         this->INHERITED::resetVaryings(varyingHandler);
@@ -93,10 +93,10 @@
 public:
     GrCCPRCubicCornerProcessor(CubicType cubicType)
             : INHERITED(cubicType)
-            , fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType,
+            , fEdgeDistanceDerivatives("edge_distance_derivatives", kHighFloat2_GrSLType,
                                         GrShaderVar::kNonArray, kHigh_GrSLPrecision)
-            , fdKLMDdx(kVec4f_GrSLType)
-            , fdKLMDdy(kVec4f_GrSLType) {}
+            , fdKLMDdx(kHighFloat4_GrSLType)
+            , fdKLMDdy(kHighFloat4_GrSLType) {}
 
     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
         this->INHERITED::resetVaryings(varyingHandler);
diff --git a/src/gpu/ccpr/GrCCPRPathProcessor.cpp b/src/gpu/ccpr/GrCCPRPathProcessor.cpp
index 429767d..bb0ecc9 100644
--- a/src/gpu/ccpr/GrCCPRPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRPathProcessor.cpp
@@ -121,12 +121,12 @@
     const char* atlasAdjust;
     fAtlasAdjustUniform = uniHandler->addUniform(
             kVertex_GrShaderFlag,
-            kVec2f_GrSLType, kHigh_GrSLPrecision, "atlas_adjust", &atlasAdjust);
+            kHighFloat2_GrSLType, "atlas_adjust", &atlasAdjust);
 
     varyingHandler->emitAttributes(proc);
 
-    GrGLSLVertToFrag texcoord(kVec2f_GrSLType);
-    GrGLSLVertToFrag color(kVec4f_GrSLType);
+    GrGLSLVertToFrag texcoord(kHighFloat2_GrSLType);
+    GrGLSLVertToFrag color(kHalf4_GrSLType);
     varyingHandler->addVarying("texcoord", &texcoord, kHigh_GrSLPrecision);
     varyingHandler->addFlatPassThroughAttribute(&proc.getInstanceAttrib(InstanceAttribs::kColor),
                                                 args.fOutputColor, kLow_GrSLPrecision);
@@ -137,41 +137,41 @@
     // Find the intersections of (bloated) devBounds and devBounds45 in order to come up with an
     // octagon that circumscribes the (bloated) path. A vertex is the intersection of two lines:
     // one edge from the path's bounding box and one edge from its 45-degree bounding box.
-    v->codeAppendf("highp float2x2 N = float2x2(%s);", proc.getEdgeNormsAttrib().fName);
+    v->codeAppendf("highfloat2x2 N = highfloat2x2(%s);", proc.getEdgeNormsAttrib().fName);
 
     // N[0] is the normal for the edge we are intersecting from the regular bounding box, pointing
     // out of the octagon.
-    v->codeAppendf("highp float2 refpt = (min(N[0].x, N[0].y) < 0) ? %s.xy : %s.zw;",
+    v->codeAppendf("highfloat2 refpt = (min(N[0].x, N[0].y) < 0) ? %s.xy : %s.zw;",
                    proc.getInstanceAttrib(InstanceAttribs::kDevBounds).fName,
                    proc.getInstanceAttrib(InstanceAttribs::kDevBounds).fName);
     v->codeAppendf("refpt += N[0] * %f;", kAABloatRadius); // bloat for AA.
 
     // N[1] is the normal for the edge we are intersecting from the 45-degree bounding box, pointing
     // out of the octagon.
-    v->codeAppendf("highp float2 refpt45 = (N[1].x < 0) ? %s.xy : %s.zw;",
+    v->codeAppendf("highfloat2 refpt45 = (N[1].x < 0) ? %s.xy : %s.zw;",
                    proc.getInstanceAttrib(InstanceAttribs::kDevBounds45).fName,
                    proc.getInstanceAttrib(InstanceAttribs::kDevBounds45).fName);
-    v->codeAppendf("refpt45 *= float2x2(.5,.5,-.5,.5);"); // transform back to device space.
+    v->codeAppendf("refpt45 *= highfloat2x2(.5,.5,-.5,.5);"); // transform back to device space.
     v->codeAppendf("refpt45 += N[1] * %f;", kAABloatRadius); // bloat for AA.
 
-    v->codeAppend ("highp float2 K = float2(dot(N[0], refpt), dot(N[1], refpt45));");
-    v->codeAppendf("highp float2 octocoord = K * inverse(N);");
+    v->codeAppend ("highfloat2 K = highfloat2(dot(N[0], refpt), dot(N[1], refpt45));");
+    v->codeAppendf("highfloat2 octocoord = K * inverse(N);");
 
-    gpArgs->fPositionVar.set(kVec2f_GrSLType, "octocoord");
+    gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "octocoord");
 
     // Convert to atlas coordinates in order to do our texture lookup.
-    v->codeAppendf("highp float2 atlascoord = octocoord + float2(%s);",
+    v->codeAppendf("highfloat2 atlascoord = octocoord + highfloat2(%s);",
                    proc.getInstanceAttrib(InstanceAttribs::kAtlasOffset).fName);
     if (kTopLeft_GrSurfaceOrigin == proc.atlasProxy()->origin()) {
         v->codeAppendf("%s = atlascoord * %s;", texcoord.vsOut(), atlasAdjust);
     } else {
         SkASSERT(kBottomLeft_GrSurfaceOrigin == proc.atlasProxy()->origin());
-        v->codeAppendf("%s = float2(atlascoord.x * %s.x, 1 - atlascoord.y * %s.y);",
+        v->codeAppendf("%s = highfloat2(atlascoord.x * %s.x, 1 - atlascoord.y * %s.y);",
                        texcoord.vsOut(), atlasAdjust, atlasAdjust);
     }
 
     // Convert to (local) path cordinates.
-    v->codeAppendf("highp float2 pathcoord = inverse(float2x2(%s)) * (octocoord - %s);",
+    v->codeAppendf("highfloat2 pathcoord = inverse(highfloat2x2(%s)) * (octocoord - %s);",
                    proc.getInstanceAttrib(InstanceAttribs::kViewMatrix).fName,
                    proc.getInstanceAttrib(InstanceAttribs::kViewTranslate).fName);
 
@@ -181,16 +181,16 @@
     // Fragment shader.
     GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
 
-    f->codeAppend ("mediump float coverage_count = ");
-    f->appendTextureLookup(args.fTexSamplers[0], texcoord.fsIn(), kVec2f_GrSLType);
+    f->codeAppend ("half coverage_count = ");
+    f->appendTextureLookup(args.fTexSamplers[0], texcoord.fsIn(), kHighFloat2_GrSLType);
     f->codeAppend (".a;");
 
     if (SkPath::kWinding_FillType == proc.fillType()) {
-        f->codeAppendf("%s = float4(min(abs(coverage_count), 1));", args.fOutputCoverage);
+        f->codeAppendf("%s = half4(min(abs(coverage_count), 1));", args.fOutputCoverage);
     } else {
         SkASSERT(SkPath::kEvenOdd_FillType == proc.fillType());
-        f->codeAppend ("mediump float t = mod(abs(coverage_count), 2);");
-        f->codeAppendf("%s = float4(1 - abs(t - 1));", args.fOutputCoverage);
+        f->codeAppend ("half t = mod(abs(coverage_count), 2);");
+        f->codeAppendf("%s = half4(1 - abs(t - 1));", args.fOutputCoverage);
     }
 }
 
diff --git a/src/gpu/ccpr/GrCCPRQuadraticProcessor.cpp b/src/gpu/ccpr/GrCCPRQuadraticProcessor.cpp
index 73d0d1e..ced5be1 100644
--- a/src/gpu/ccpr/GrCCPRQuadraticProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRQuadraticProcessor.cpp
@@ -16,18 +16,18 @@
                                                   const TexelBufferHandle& pointsBuffer,
                                                   const char* atlasOffset, const char* rtAdjust,
                                                   GrGPArgs* gpArgs) const {
-    v->codeAppend ("highp float2 self = ");
+    v->codeAppend ("highfloat2 self = ");
     v->appendTexelFetch(pointsBuffer,
                         SkStringPrintf("%s.x + sk_VertexID", proc.instanceAttrib()).c_str());
     v->codeAppendf(".xy + %s;", atlasOffset);
-    gpArgs->fPositionVar.set(kVec2f_GrSLType, "self");
+    gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "self");
 }
 
 void GrCCPRQuadraticProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* rtAdjust,
                                         const char* outputWind) const {
     // We will define bezierpts in onEmitGeometryShader.
-    g->codeAppend ("highp float area_times_2 = "
-                                             "determinant(float2x2(bezierpts[1] - bezierpts[0], "
+    g->codeAppend ("highfloat area_times_2 = "
+                                         "determinant(highfloat2x2(bezierpts[1] - bezierpts[0], "
                                                                   "bezierpts[2] - bezierpts[0]));");
     // Drop curves that are nearly flat, in favor of the higher quality triangle antialiasing.
     g->codeAppendf("if (2 * abs(area_times_2) < length((bezierpts[2] - bezierpts[0]) * %s.zx)) {",
@@ -46,26 +46,26 @@
                                                     const char* emitVertexFn, const char* wind,
                                                     const char* rtAdjust) const {
     // Prepend bezierpts at the start of the shader.
-    g->codePrependf("highp float3x2 bezierpts = float3x2(sk_in[0].gl_Position.xy, "
-                                                        "sk_in[1].gl_Position.xy, "
-                                                        "sk_in[2].gl_Position.xy);");
+    g->codePrependf("highfloat3x2 bezierpts = highfloat3x2(sk_in[0].gl_Position.xy, "
+                                                          "sk_in[1].gl_Position.xy, "
+                                                          "sk_in[2].gl_Position.xy);");
 
     g->declareGlobal(fCanonicalMatrix);
-    g->codeAppendf("%s = float3x3(0.0, 0, 1, "
-                                 "0.5, 0, 1, "
-                                 "1.0, 1, 1) * "
-                        "inverse(float3x3(bezierpts[0], 1, "
-                                         "bezierpts[1], 1, "
-                                         "bezierpts[2], 1));",
+    g->codeAppendf("%s = highfloat3x3(0.0, 0, 1, "
+                                     "0.5, 0, 1, "
+                                     "1.0, 1, 1) * "
+                        "inverse(highfloat3x3(bezierpts[0], 1, "
+                                             "bezierpts[1], 1, "
+                                             "bezierpts[2], 1));",
                    fCanonicalMatrix.c_str());
 
     g->declareGlobal(fCanonicalDerivatives);
-    g->codeAppendf("%s = float2x2(%s) * float2x2(%s.x, 0, 0, %s.z);",
+    g->codeAppendf("%s = highfloat2x2(%s) * highfloat2x2(%s.x, 0, 0, %s.z);",
                    fCanonicalDerivatives.c_str(), fCanonicalMatrix.c_str(), rtAdjust, rtAdjust);
 
     g->declareGlobal(fEdgeDistanceEquation);
-    g->codeAppendf("highp float2 edgept0 = bezierpts[%s > 0 ? 2 : 0];", wind);
-    g->codeAppendf("highp float2 edgept1 = bezierpts[%s > 0 ? 0 : 2];", wind);
+    g->codeAppendf("highfloat2 edgept0 = bezierpts[%s > 0 ? 2 : 0];", wind);
+    g->codeAppendf("highfloat2 edgept1 = bezierpts[%s > 0 ? 0 : 2];", wind);
     this->emitEdgeDistanceEquation(g, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
 
     this->emitQuadraticGeometry(g, emitVertexFn, rtAdjust);
@@ -74,7 +74,7 @@
 void GrCCPRQuadraticProcessor::emitPerVertexGeometryCode(SkString* fnBody, const char* position,
                                                          const char* /*coverage*/,
                                                          const char* /*wind*/) const {
-    fnBody->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
+    fnBody->appendf("%s.xy = (%s * highfloat3(%s, 1)).xy;",
                     fXYD.gsOut(), fCanonicalMatrix.c_str(), position);
     fnBody->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
                     fXYD.gsOut(), fEdgeDistanceEquation.c_str(), position,
@@ -87,18 +87,18 @@
                                                          const char* /*rtAdjust*/) const {
     // Find the t value whose tangent is halfway between the tangents at the endpionts.
     // (We defined bezierpts in onEmitGeometryShader.)
-    g->codeAppend ("highp float2 tan0 = bezierpts[1] - bezierpts[0];");
-    g->codeAppend ("highp float2 tan1 = bezierpts[2] - bezierpts[1];");
-    g->codeAppend ("highp float2 midnorm = normalize(tan0) - normalize(tan1);");
-    g->codeAppend ("highp float2 T = midnorm * float2x2(tan0 - tan1, tan0);");
-    g->codeAppend ("highp float t = clamp(T.t / T.s, 0, 1);"); // T.s=0 is weeded out by this point.
+    g->codeAppend ("highfloat2 tan0 = bezierpts[1] - bezierpts[0];");
+    g->codeAppend ("highfloat2 tan1 = bezierpts[2] - bezierpts[1];");
+    g->codeAppend ("highfloat2 midnorm = normalize(tan0) - normalize(tan1);");
+    g->codeAppend ("highfloat2 T = midnorm * highfloat2x2(tan0 - tan1, tan0);");
+    g->codeAppend ("highfloat t = clamp(T.t / T.s, 0, 1);"); // T.s=0 is weeded out by this point.
 
     // Clip the bezier triangle by the tangent at our new t value. This is a simple application for
     // De Casteljau's algorithm.
-    g->codeAppendf("highp float4x2 quadratic_hull = float4x2(bezierpts[0], "
-                                                            "bezierpts[0] + tan0 * t, "
-                                                            "bezierpts[1] + tan1 * t, "
-                                                            "bezierpts[2]);");
+    g->codeAppendf("highfloat4x2 quadratic_hull = highfloat4x2(bezierpts[0], "
+                                                              "bezierpts[0] + tan0 * t, "
+                                                              "bezierpts[1] + tan1 * t, "
+                                                              "bezierpts[2]);");
 
     int maxVerts = this->emitHullGeometry(g, emitVertexFn, "quadratic_hull", 4, "sk_InvocationID");
 
@@ -108,13 +108,13 @@
 }
 
 void GrCCPRQuadraticHullProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const {
-    fnBody->appendf("%s = float2(2 * %s.x, -1) * %s;",
+    fnBody->appendf("%s = highfloat2(2 * %s.x, -1) * %s;",
                     fGradXY.gsOut(), fXYD.gsOut(), fCanonicalDerivatives.c_str());
 }
 
 void GrCCPRQuadraticHullProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
                                                       const char* outputCoverage) const {
-    f->codeAppendf("highp float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
+    f->codeAppendf("highfloat d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
                    fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGradXY.fsIn(), fGradXY.fsIn());
     f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage);
     f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYD.fsIn()); // Flat closing edge.
@@ -127,7 +127,7 @@
     g->codeAppendf("%s = %s.xy * %s.xz;",
                    fEdgeDistanceDerivatives.c_str(), fEdgeDistanceEquation.c_str(), rtAdjust);
 
-    g->codeAppendf("highp float2 corner = bezierpts[sk_InvocationID * 2];");
+    g->codeAppendf("highfloat2 corner = bezierpts[sk_InvocationID * 2];");
     int numVertices = this->emitCornerGeometry(g, emitVertexFn, "corner");
 
     g->configure(GrGLSLGeometryBuilder::InputType::kTriangles,
@@ -135,35 +135,35 @@
 }
 
 void GrCCPRQuadraticCornerProcessor::onEmitPerVertexGeometryCode(SkString* fnBody) const {
-    fnBody->appendf("%s = float3(%s[0].x, %s[0].y, %s.x);",
+    fnBody->appendf("%s = highfloat3(%s[0].x, %s[0].y, %s.x);",
                     fdXYDdx.gsOut(), fCanonicalDerivatives.c_str(), fCanonicalDerivatives.c_str(),
                     fEdgeDistanceDerivatives.c_str());
-    fnBody->appendf("%s = float3(%s[1].x, %s[1].y, %s.y);",
+    fnBody->appendf("%s = highfloat3(%s[1].x, %s[1].y, %s.y);",
                     fdXYDdy.gsOut(), fCanonicalDerivatives.c_str(), fCanonicalDerivatives.c_str(),
                     fEdgeDistanceDerivatives.c_str());
 }
 
 void GrCCPRQuadraticCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
                                                         const char* outputCoverage) const {
-    f->codeAppendf("highp float x = %s.x, y = %s.y, d = %s.z;",
+    f->codeAppendf("highfloat x = %s.x, y = %s.y, d = %s.z;",
                    fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn());
-    f->codeAppendf("highp float2x3 grad_xyd = float2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn());
+    f->codeAppendf("highfloat2x3 grad_xyd = highfloat2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn());
 
     // Erase what the previous hull shader wrote. We don't worry about the two corners falling on
     // the same pixel because those cases should have been weeded out by this point.
-    f->codeAppend ("highp float f = x*x - y;");
-    f->codeAppend ("highp float2 grad_f = float2(2*x, -1) * float2x2(grad_xyd);");
+    f->codeAppend ("highfloat f = x*x - y;");
+    f->codeAppend ("highfloat2 grad_f = highfloat2(2*x, -1) * highfloat2x2(grad_xyd);");
     f->codeAppendf("%s = -(0.5 - f * inversesqrt(dot(grad_f, grad_f)));", outputCoverage);
     f->codeAppendf("%s -= d;", outputCoverage);
 
     // Use software msaa to approximate coverage at the corner pixels.
     int sampleCount = this->defineSoftSampleLocations(f, "samples");
-    f->codeAppendf("highp float3 xyd_center = float3(%s.xy, %s.z + 0.5);",
+    f->codeAppendf("highfloat3 xyd_center = highfloat3(%s.xy, %s.z + 0.5);",
                    fXYD.fsIn(), fXYD.fsIn());
     f->codeAppendf("for (int i = 0; i < %i; ++i) {", sampleCount);
-    f->codeAppend (    "highp float3 xyd = grad_xyd * samples[i] + xyd_center;");
-    f->codeAppend (    "lowp float f = xyd.y - xyd.x * xyd.x;"); // f > 0 -> inside curve.
-    f->codeAppendf(    "%s += all(greaterThan(float2(f,xyd.z), float2(0))) ? %f : 0;",
+    f->codeAppend (    "highfloat3 xyd = grad_xyd * samples[i] + xyd_center;");
+    f->codeAppend (    "half f = xyd.y - xyd.x * xyd.x;"); // f > 0 -> inside curve.
+    f->codeAppendf(    "%s += all(greaterThan(highfloat2(f,xyd.z), highfloat2(0))) ? %f : 0;",
                        outputCoverage, 1.0 / sampleCount);
     f->codeAppendf("}");
 }
diff --git a/src/gpu/ccpr/GrCCPRQuadraticProcessor.h b/src/gpu/ccpr/GrCCPRQuadraticProcessor.h
index 85be23e..80237b6 100644
--- a/src/gpu/ccpr/GrCCPRQuadraticProcessor.h
+++ b/src/gpu/ccpr/GrCCPRQuadraticProcessor.h
@@ -24,13 +24,12 @@
 public:
     GrCCPRQuadraticProcessor()
             : INHERITED(CoverageType::kShader)
-            , fCanonicalMatrix("canonical_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray,
-                               kHigh_GrSLPrecision)
-            , fCanonicalDerivatives("canonical_derivatives", kMat22f_GrSLType,
-                                    GrShaderVar::kNonArray, kHigh_GrSLPrecision)
-            , fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType,
-                                    GrShaderVar::kNonArray, kHigh_GrSLPrecision)
-            , fXYD(kVec3f_GrSLType) {}
+            , fCanonicalMatrix("canonical_matrix", kHighFloat3x3_GrSLType, GrShaderVar::kNonArray)
+            , fCanonicalDerivatives("canonical_derivatives", kHighFloat2x2_GrSLType,
+                                    GrShaderVar::kNonArray)
+            , fEdgeDistanceEquation("edge_distance_equation", kHighFloat3_GrSLType,
+                                    GrShaderVar::kNonArray)
+            , fXYD(kHighFloat3_GrSLType) {}
 
     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
         varyingHandler->addVarying("xyd", &fXYD, kHigh_GrSLPrecision);
@@ -67,7 +66,7 @@
 class GrCCPRQuadraticHullProcessor : public GrCCPRQuadraticProcessor {
 public:
     GrCCPRQuadraticHullProcessor()
-            : fGradXY(kVec2f_GrSLType) {}
+            : fGradXY(kHighFloat2_GrSLType) {}
 
     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
         this->INHERITED::resetVaryings(varyingHandler);
@@ -91,10 +90,10 @@
 class GrCCPRQuadraticCornerProcessor : public GrCCPRQuadraticProcessor {
 public:
     GrCCPRQuadraticCornerProcessor()
-            : fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType,
-                                       GrShaderVar::kNonArray, kHigh_GrSLPrecision)
-            , fdXYDdx(kVec3f_GrSLType)
-            , fdXYDdy(kVec3f_GrSLType) {}
+            : fEdgeDistanceDerivatives("edge_distance_derivatives", kHighFloat2_GrSLType,
+                                       GrShaderVar::kNonArray)
+            , fdXYDdx(kHighFloat3_GrSLType)
+            , fdXYDdy(kHighFloat3_GrSLType) {}
 
     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
         this->INHERITED::resetVaryings(varyingHandler);
diff --git a/src/gpu/ccpr/GrCCPRTriangleProcessor.cpp b/src/gpu/ccpr/GrCCPRTriangleProcessor.cpp
index bb2ad1b..ee25851 100644
--- a/src/gpu/ccpr/GrCCPRTriangleProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRTriangleProcessor.cpp
@@ -16,16 +16,16 @@
                                                  const TexelBufferHandle& pointsBuffer,
                                                  const char* atlasOffset, const char* rtAdjust,
                                                  GrGPArgs* gpArgs) const {
-    v->codeAppend ("highp float2 self = ");
+    v->codeAppend ("highfloat2 self = ");
     v->appendTexelFetch(pointsBuffer,
                         SkStringPrintf("%s[sk_VertexID]", proc.instanceAttrib()).c_str());
     v->codeAppendf(".xy + %s;", atlasOffset);
-    gpArgs->fPositionVar.set(kVec2f_GrSLType, "self");
+    gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "self");
 }
 
 void GrCCPRTriangleProcessor::defineInputVertices(GrGLSLGeometryBuilder* g) const {
     // Prepend in_vertices at the start of the shader.
-    g->codePrependf("highp float3x2 in_vertices = float3x2(sk_in[0].gl_Position.xy, "
+    g->codePrependf("highfloat3x2 in_vertices = highfloat3x2(sk_in[0].gl_Position.xy, "
                                                           "sk_in[1].gl_Position.xy, "
                                                           "sk_in[2].gl_Position.xy);");
 }
@@ -33,8 +33,8 @@
 void GrCCPRTriangleProcessor::emitWind(GrGLSLGeometryBuilder* g, const char* /*rtAdjust*/,
                                        const char* outputWind) const {
     // We will define in_vertices in defineInputVertices.
-    g->codeAppendf("%s = sign(determinant(float2x2(in_vertices[1] - in_vertices[0], "
-                                                  "in_vertices[2] - in_vertices[0])));",
+    g->codeAppendf("%s = sign(determinant(highfloat2x2(in_vertices[1] - in_vertices[0], "
+                                                      "in_vertices[2] - in_vertices[0])));",
                    outputWind);
 }
 
@@ -53,8 +53,8 @@
     if (GeometryType::kHulls != fGeometryType) {
         g->codeAppend ("int edgeidx0 = sk_InvocationID, "
                            "edgeidx1 = (edgeidx0 + 1) % 3;");
-        g->codeAppendf("highp float2 edgept0 = in_vertices[%s > 0 ? edgeidx0 : edgeidx1];", wind);
-        g->codeAppendf("highp float2 edgept1 = in_vertices[%s > 0 ? edgeidx1 : edgeidx0];", wind);
+        g->codeAppendf("highfloat2 edgept0 = in_vertices[%s > 0 ? edgeidx0 : edgeidx1];", wind);
+        g->codeAppendf("highfloat2 edgept1 = in_vertices[%s > 0 ? edgeidx1 : edgeidx0];", wind);
 
         maxOutputVertices += this->emitEdgeGeometry(g, emitVertexFn, "edgept0", "edgept1");
     }
@@ -73,15 +73,15 @@
     this->INHERITED::onEmitVertexShader(proc, v, pointsBuffer, atlasOffset, rtAdjust, gpArgs);
 
     // Fetch and transform the next point in the triangle.
-    v->codeAppend ("highp float2 next = ");
+    v->codeAppend ("highfloat2 next = ");
     v->appendTexelFetch(pointsBuffer,
                         SkStringPrintf("%s[(sk_VertexID+1) %% 3]", proc.instanceAttrib()).c_str());
     v->codeAppendf(".xy + %s;", atlasOffset);
 
     // Find the plane that gives distance from the [self -> next] edge, normalized to its AA
     // bloat width.
-    v->codeAppend ("highp float2 n = float2(next.y - self.y, self.x - next.x);");
-    v->codeAppendf("highp float2 d = n * float2x2(self + %f * sign(n), "
+    v->codeAppend ("highfloat2 n = highfloat2(next.y - self.y, self.x - next.x);");
+    v->codeAppendf("highfloat2 d = n * highfloat2x2(self + %f * sign(n), "
                                                  "self - %f * sign(n));",
                    kAABloatRadius, kAABloatRadius);
 
@@ -98,7 +98,7 @@
                                                          const char* rtAdjust) const {
     this->defineInputVertices(g);
 
-    g->codeAppend ("highp float2 self = in_vertices[sk_InvocationID];");
+    g->codeAppend ("highfloat2 self = in_vertices[sk_InvocationID];");
     int numVertices = this->emitCornerGeometry(g, emitVertexFn, "self");
 
     g->configure(GrGLSLGeometryBuilder::InputType::kTriangles,
@@ -114,7 +114,7 @@
                     fNeighbors.gsOut(), fDevCoord.gsIn());
     fnBody->appendf("%s.zw = %s[(sk_InvocationID + 2) %% 3];",
                     fNeighbors.gsOut(), fDevCoord.gsIn());
-    fnBody->appendf("%s = float3x3(%s[(sk_InvocationID + 2) %% 3], "
+    fnBody->appendf("%s = highfloat3x3(%s[(sk_InvocationID + 2) %% 3], "
                                   "%s[sk_InvocationID], "
                                   "%s[(sk_InvocationID + 1) %% 3]) * %s;",
                     fEdgeDistances.gsOut(), fEdgeDistance.gsIn(), fEdgeDistance.gsIn(),
@@ -129,32 +129,28 @@
 void GrCCPRTriangleCornerProcessor::emitShaderCoverage(GrGLSLFragmentBuilder* f,
                                                        const char* outputCoverage) const {
     // FIXME: Adreno breaks if we don't put the frag coord in an intermediate highp variable.
-    f->codeAppendf("highp float2 fragcoord = sk_FragCoord.xy;");
+    f->codeAppendf("highfloat2 fragcoord = sk_FragCoord.xy;");
 
     // Approximate coverage by tracking where 4 horizontal lines enter and leave the triangle.
-    GrShaderVar samples("samples", kVec4f_GrSLType, GrShaderVar::kNonArray,
-                        kHigh_GrSLPrecision);
+    GrShaderVar samples("samples", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
     f->declareGlobal(samples);
-    f->codeAppendf("%s = fragcoord.y + float4(-0.375, -0.125, 0.125, 0.375);", samples.c_str());
+    f->codeAppendf("%s = fragcoord.y + highfloat4(-0.375, -0.125, 0.125, 0.375);", samples.c_str());
 
-    GrShaderVar leftedge("leftedge", kVec4f_GrSLType, GrShaderVar::kNonArray,
-                         kHigh_GrSLPrecision);
+    GrShaderVar leftedge("leftedge", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
     f->declareGlobal(leftedge);
-    f->codeAppendf("%s = float4(fragcoord.x - 0.5);", leftedge.c_str());
+    f->codeAppendf("%s = highfloat4(fragcoord.x - 0.5);", leftedge.c_str());
 
-    GrShaderVar rightedge("rightedge", kVec4f_GrSLType, GrShaderVar::kNonArray,
-                          kHigh_GrSLPrecision);
+    GrShaderVar rightedge("rightedge", kHighFloat4_GrSLType, GrShaderVar::kNonArray);
     f->declareGlobal(rightedge);
-    f->codeAppendf("%s = float4(fragcoord.x + 0.5);", rightedge.c_str());
+    f->codeAppendf("%s = highfloat4(fragcoord.x + 0.5);", rightedge.c_str());
 
     SkString sampleEdgeFn;
-    GrShaderVar edgeArg("edge_distance", kVec3f_GrSLType, GrShaderVar::kNonArray,
-                        kHigh_GrSLPrecision);
+    GrShaderVar edgeArg("edge_distance", kHighFloat3_GrSLType, GrShaderVar::kNonArray);
     f->emitFunction(kVoid_GrSLType, "sampleEdge", 1, &edgeArg, [&]() {
         SkString b;
-        b.appendf("highp float m = abs(%s.x) < 1e-3 ? 1e18 : -1 / %s.x;",
+        b.appendf("highfloat m = abs(%s.x) < 1e-3 ? 1e18 : -1 / %s.x;",
                   edgeArg.c_str(), edgeArg.c_str());
-        b.appendf("highp float4 edge = m * (%s.y * samples + %s.z);",
+        b.appendf("highfloat4 edge = m * (%s.y * samples + %s.z);",
                   edgeArg.c_str(), edgeArg.c_str());
         b.appendf("if (%s.x <= 1e-3 || (abs(%s.x) < 1e-3 && %s.y > 0)) {",
                   edgeArg.c_str(), edgeArg.c_str(), edgeArg.c_str());
@@ -166,10 +162,10 @@
     }().c_str(), &sampleEdgeFn);
 
     // See if the previous neighbor already handled this pixel.
-    f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.zw), float2(%f)))) {",
+    f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.zw), highfloat2(%f)))) {",
                    fNeighbors.fsIn(), kAABloatRadius);
     // Handle the case where all 3 corners defer to the previous neighbor.
-    f->codeAppendf(    "if (%s != 0 || !all(lessThan(abs(fragcoord - %s.xy), float2(%f)))) {",
+    f->codeAppendf(    "if (%s != 0 || !all(lessThan(abs(fragcoord - %s.xy), highfloat2(%f)))) {",
                        fCornerIdx.fsIn(), fNeighbors.fsIn(), kAABloatRadius);
     f->codeAppend (        "discard;");
     f->codeAppend (    "}");
@@ -177,7 +173,7 @@
 
     // Erase what the hull and two edges wrote at this corner in previous shaders (the two .5's
     // for the edges and the -1 for the hull cancel each other out).
-    f->codeAppendf("%s = dot(float3(fragcoord, 1) * float2x3(%s), float2(1));",
+    f->codeAppendf("%s = dot(highfloat3(fragcoord, 1) * highfloat2x3(%s), highfloat2(1));",
                    outputCoverage, fEdgeDistances.fsIn());
 
     // Sample the two edges at this corner.
@@ -185,15 +181,15 @@
     f->codeAppendf("%s(%s[1]);", sampleEdgeFn.c_str(), fEdgeDistances.fsIn());
 
     // Handle the opposite edge if the next neighbor will defer to us.
-    f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.xy), float2(%f)))) {",
+    f->codeAppendf("if (all(lessThan(abs(fragcoord - %s.xy), highfloat2(%f)))) {",
                    fNeighbors.fsIn(), kAABloatRadius);
     // Erase the coverage the opposite edge wrote to this corner.
-    f->codeAppendf(    "%s += dot(%s[2], float3(fragcoord, 1)) + 0.5;",
+    f->codeAppendf(    "%s += dot(%s[2], highfloat3(fragcoord, 1)) + 0.5;",
                        outputCoverage, fEdgeDistances.fsIn());
     // Sample the opposite edge.
     f->codeAppendf(    "%s(%s[2]);", sampleEdgeFn.c_str(), fEdgeDistances.fsIn());
     f->codeAppend ("}");
 
-    f->codeAppendf("highp float4 widths = max(%s - %s, 0);", rightedge.c_str(), leftedge.c_str());
-    f->codeAppendf("%s += dot(widths, float4(0.25));", outputCoverage);
+    f->codeAppendf("highfloat4 widths = max(%s - %s, 0);", rightedge.c_str(), leftedge.c_str());
+    f->codeAppendf("%s += dot(widths, highfloat4(0.25));", outputCoverage);
 }
diff --git a/src/gpu/ccpr/GrCCPRTriangleProcessor.h b/src/gpu/ccpr/GrCCPRTriangleProcessor.h
index 1e52d51..9ac7652 100644
--- a/src/gpu/ccpr/GrCCPRTriangleProcessor.h
+++ b/src/gpu/ccpr/GrCCPRTriangleProcessor.h
@@ -72,11 +72,11 @@
 public:
     GrCCPRTriangleCornerProcessor()
             : INHERITED(CoverageType::kShader)
-            , fEdgeDistance(kVec3f_GrSLType)
-            , fDevCoord(kVec2f_GrSLType)
-            , fNeighbors(kVec4f_GrSLType)
-            , fEdgeDistances(kMat33f_GrSLType)
-            , fCornerIdx(kInt_GrSLType) {}
+            , fEdgeDistance(kHighFloat3_GrSLType)
+            , fDevCoord(kHighFloat2_GrSLType)
+            , fNeighbors(kHighFloat4_GrSLType)
+            , fEdgeDistances(kHighFloat3x3_GrSLType)
+            , fCornerIdx(kShort_GrSLType) {}
 
     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
         this->INHERITED::resetVaryings(varyingHandler);
diff --git a/src/gpu/effects/GrAtlasedShaderHelpers.h b/src/gpu/effects/GrAtlasedShaderHelpers.h
index 50ac0ef..57e30a3 100644
--- a/src/gpu/effects/GrAtlasedShaderHelpers.h
+++ b/src/gpu/effects/GrAtlasedShaderHelpers.h
@@ -22,11 +22,11 @@
     // This extracts the texture index and texel coordinates from the same variable
     // Packing structure: texel coordinates are multiplied by 2 (or shifted left 1)
     //                    texture index is stored as lower bits of both x and y
-    args.fVertBuilder->codeAppendf("float2 indexTexCoords = float2(%s.x, %s.y);",
+    args.fVertBuilder->codeAppendf("half2 indexTexCoords = half2(%s.x, %s.y);",
                                    inTexCoordsName, inTexCoordsName);
-    args.fVertBuilder->codeAppend("float2 intCoords = floor(0.5*indexTexCoords);");
-    args.fVertBuilder->codeAppend("float2 diff = indexTexCoords - 2.0*intCoords;");
-    args.fVertBuilder->codeAppend("float texIdx = 2.0*diff.x + diff.y;");
+    args.fVertBuilder->codeAppend("half2 intCoords = floor(0.5*indexTexCoords);");
+    args.fVertBuilder->codeAppend("half2 diff = indexTexCoords - 2.0*intCoords;");
+    args.fVertBuilder->codeAppend("half texIdx = 2.0*diff.x + diff.y;");
 
     // Multiply by 1/atlasSize to get normalized texture coordinates
     args.fVaryingHandler->addVarying("TextureCoords", uv, kHigh_GrSLPrecision);
@@ -49,12 +49,13 @@
     // conditionally load from the indexed texture sampler
     for (int i = 0; i < numTextureSamplers-1; ++i) {
         args.fFragBuilder->codeAppendf("if (%s == %d) { %s = ", texIdx.fsIn(), i, colorName);
-        args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i], coordName, kVec2f_GrSLType);
+        args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i], coordName,
+                                               kHighFloat2_GrSLType);
         args.fFragBuilder->codeAppend("; } else ");
     }
     args.fFragBuilder->codeAppendf("{ %s = ", colorName);
     args.fFragBuilder->appendTextureLookup(args.fTexSamplers[numTextureSamplers-1], coordName,
-                                           kVec2f_GrSLType);
+                                           kHighFloat2_GrSLType);
     args.fFragBuilder->codeAppend("; }");
 }
 
diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
index aa9a509..5848888 100644
--- a/src/gpu/effects/GrBezierEffect.cpp
+++ b/src/gpu/effects/GrBezierEffect.cpp
@@ -77,7 +77,7 @@
     // emit attributes
     varyingHandler->emitAttributes(gp);
 
-    GrGLSLVertToFrag v(kVec4f_GrSLType);
+    GrGLSLVertToFrag v(kHighFloat4_GrSLType);
     varyingHandler->addVarying("ConicCoeffs", &v, kHigh_GrSLPrecision);
     vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
 
@@ -102,26 +102,18 @@
                          gp.localMatrix(),
                          args.fFPCoordTransformHandler);
 
-    // TODO: this precision check should actually be a check on the number of bits
-    // high and medium provide and the selection of the lowest level that suffices.
-    // Additionally we should assert that the upstream code only lets us get here if
-    // either high or medium provides the required number of bits.
-    GrSLPrecision precision = kHigh_GrSLPrecision;
-    const GrShaderCaps::PrecisionInfo& highP = args.fShaderCaps->getFloatShaderPrecisionInfo(
-                                                             kFragment_GrShaderType,
-                                                             kHigh_GrSLPrecision);
-    if (!highP.supported()) {
-        precision = kMedium_GrSLPrecision;
-    }
+    // TODO: we should check on the number of bits float and half provide and use the smallest one
+    // that suffices. Additionally we should assert that the upstream code only lets us get here if
+    // either float or half provides the required number of bits.
 
-    GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, precision);
-    GrShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, precision);
-    GrShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, precision);
-    GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0, precision);
-    GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0, precision);
-    GrShaderVar gF("gF", kVec2f_GrSLType, 0, precision);
-    GrShaderVar gFM("gFM", kFloat_GrSLType, 0, precision);
-    GrShaderVar func("func", kFloat_GrSLType, 0, precision);
+    GrShaderVar edgeAlpha("edgeAlpha", kHighFloat_GrSLType, 0);
+    GrShaderVar dklmdx("dklmdx", kHighFloat3_GrSLType, 0);
+    GrShaderVar dklmdy("dklmdy", kHighFloat3_GrSLType, 0);
+    GrShaderVar dfdx("dfdx", kHighFloat_GrSLType, 0);
+    GrShaderVar dfdy("dfdy", kHighFloat_GrSLType, 0);
+    GrShaderVar gF("gF", kHighFloat2_GrSLType, 0);
+    GrShaderVar gFM("gFM", kHighFloat_GrSLType, 0);
+    GrShaderVar func("func", kHighFloat_GrSLType, 0);
 
     fragBuilder->declAppend(edgeAlpha);
     fragBuilder->declAppend(dklmdx);
@@ -146,7 +138,8 @@
                                      v.fsIn(), dklmdy.c_str(),
                                      v.fsIn(), dklmdy.c_str(),
                                      v.fsIn(), dklmdy.c_str());
-            fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
+            fragBuilder->codeAppendf("%s = highfloat2(%s, %s);", gF.c_str(), dfdx.c_str(),
+                                     dfdy.c_str());
             fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
                                      gFM.c_str(), gF.c_str(), gF.c_str());
             fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
@@ -175,7 +168,8 @@
                                      v.fsIn(), dklmdy.c_str(),
                                      v.fsIn(), dklmdy.c_str(),
                                      v.fsIn(), dklmdy.c_str());
-            fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
+            fragBuilder->codeAppendf("%s = highfloat2(%s, %s);", gF.c_str(), dfdx.c_str(),
+                                     dfdy.c_str());
             fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
                                      gFM.c_str(), gF.c_str(), gF.c_str());
             fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
@@ -191,7 +185,7 @@
         case kFillBW_GrProcessorEdgeType: {
             fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
                                      edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
-            fragBuilder->codeAppendf("%s = float(%s < 0.0);",
+            fragBuilder->codeAppendf("%s = highfloat(%s < 0.0);",
                                      edgeAlpha.c_str(), edgeAlpha.c_str());
             break;
         }
@@ -203,14 +197,13 @@
     if (gp.coverageScale() != 0xff) {
         const char* coverageScale;
         fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                           kFloat_GrSLType,
-                                                           kHigh_GrSLPrecision,
+                                                           kHighFloat_GrSLType,
                                                            "Coverage",
                                                            &coverageScale);
-        fragBuilder->codeAppendf("%s = float4(%s * %s);",
+        fragBuilder->codeAppendf("%s = half4(%s * %s);",
                                  args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
     } else {
-        fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
+        fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
     }
 }
 
@@ -338,7 +331,7 @@
     // emit attributes
     varyingHandler->emitAttributes(gp);
 
-    GrGLSLVertToFrag v(kVec4f_GrSLType);
+    GrGLSLVertToFrag v(kHalf4_GrSLType);
     varyingHandler->addVarying("HairQuadEdge", &v);
     vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
 
@@ -363,13 +356,13 @@
                          gp.localMatrix(),
                          args.fFPCoordTransformHandler);
 
-    fragBuilder->codeAppendf("float edgeAlpha;");
+    fragBuilder->codeAppendf("half edgeAlpha;");
 
     switch (fEdgeType) {
         case kHairlineAA_GrProcessorEdgeType: {
-            fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn());
-            fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn());
-            fragBuilder->codeAppendf("float2 gF = float2(2.0 * %s.x * duvdx.x - duvdx.y,"
+            fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
+            fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
+            fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
                                      "               2.0 * %s.x * duvdy.x - duvdy.y);",
                                      v.fsIn(), v.fsIn());
             fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
@@ -381,9 +374,9 @@
             break;
         }
         case kFillAA_GrProcessorEdgeType: {
-            fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn());
-            fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn());
-            fragBuilder->codeAppendf("float2 gF = float2(2.0 * %s.x * duvdx.x - duvdx.y,"
+            fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
+            fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
+            fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
                                      "               2.0 * %s.x * duvdy.x - duvdy.y);",
                                      v.fsIn(), v.fsIn());
             fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
@@ -397,7 +390,7 @@
         case kFillBW_GrProcessorEdgeType: {
             fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
                                      v.fsIn(), v.fsIn(), v.fsIn());
-            fragBuilder->codeAppend("edgeAlpha = float(edgeAlpha < 0.0);");
+            fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);");
             break;
         }
         default:
@@ -407,13 +400,13 @@
     if (0xff != gp.coverageScale()) {
         const char* coverageScale;
         fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                           kFloat_GrSLType,
-                                                           kDefault_GrSLPrecision,
+                                                           kHalf_GrSLType,
                                                            "Coverage",
                                                            &coverageScale);
-        fragBuilder->codeAppendf("%s = float4(%s * edgeAlpha);", args.fOutputCoverage, coverageScale);
+        fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage,
+                                 coverageScale);
     } else {
-        fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage);
+        fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
     }
 }
 
@@ -561,25 +554,25 @@
 
     // Setup KLM
     const char* devkLMMatrixName;
-    fDevKLMUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, kMat33f_GrSLType,
-                                                kHigh_GrSLPrecision, "KLM", &devkLMMatrixName);
-    GrGLSLVertToFrag v(kVec3f_GrSLType);
+    fDevKLMUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, kHighFloat3x3_GrSLType, "KLM",
+                                                &devkLMMatrixName);
+    GrGLSLVertToFrag v(kHighFloat3_GrSLType);
     varyingHandler->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision);
-    vertBuilder->codeAppendf("%s = %s * float3(%s, 1);",
+    vertBuilder->codeAppendf("%s = %s * highfloat3(%s, 1);",
                              v.vsOut(), devkLMMatrixName, gpArgs->fPositionVar.c_str());
 
 
-    GrGLSLVertToFrag gradCoeffs(kVec4f_GrSLType);
+    GrGLSLVertToFrag gradCoeffs(kHighFloat4_GrSLType);
     if (kFillAA_GrProcessorEdgeType == fEdgeType || kHairlineAA_GrProcessorEdgeType == fEdgeType) {
         varyingHandler->addVarying("GradCoeffs", &gradCoeffs, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("highp float k = %s[0], l = %s[1], m = %s[2];",
+        vertBuilder->codeAppendf("highfloat k = %s[0], l = %s[1], m = %s[2];",
                                  v.vsOut(), v.vsOut(), v.vsOut());
-        vertBuilder->codeAppendf("highp float2 gk = float2(%s[0][0], %s[1][0]), "
-                                            "gl = float2(%s[0][1], %s[1][1]), "
-                                            "gm = float2(%s[0][2], %s[1][2]);",
+        vertBuilder->codeAppendf("highfloat2 gk = highfloat2(%s[0][0], %s[1][0]), "
+                                            "gl = highfloat2(%s[0][1], %s[1][1]), "
+                                            "gm = highfloat2(%s[0][2], %s[1][2]);",
                                  devkLMMatrixName, devkLMMatrixName, devkLMMatrixName,
                                  devkLMMatrixName, devkLMMatrixName, devkLMMatrixName);
-        vertBuilder->codeAppendf("%s = float4(3 * k * gk, -m * gl - l * gm);",
+        vertBuilder->codeAppendf("%s = highfloat4(3 * k * gk, -m * gl - l * gm);",
                                  gradCoeffs.vsOut());
     }
 
@@ -592,9 +585,9 @@
                          args.fFPCoordTransformHandler);
 
 
-    GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
-    GrShaderVar gF("gF", kVec2f_GrSLType, 0, kHigh_GrSLPrecision);
-    GrShaderVar func("func", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
+    GrShaderVar edgeAlpha("edgeAlpha", kHighFloat_GrSLType, 0);
+    GrShaderVar gF("gF", kHighFloat2_GrSLType, 0);
+    GrShaderVar func("func", kHighFloat_GrSLType, 0);
 
     fragBuilder->declAppend(edgeAlpha);
     fragBuilder->declAppend(gF);
@@ -638,7 +631,7 @@
             fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
                                      edgeAlpha.c_str(), v.fsIn(), v.fsIn(),
                                      v.fsIn(), v.fsIn(), v.fsIn());
-            fragBuilder->codeAppendf("%s = float(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str());
+            fragBuilder->codeAppendf("%s = half(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str());
             break;
         }
         default:
@@ -646,7 +639,7 @@
     }
 
 
-    fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
+    fragBuilder->codeAppendf("%s = highfloat4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
 }
 
 void GrGLCubicEffect::GenKey(const GrGeometryProcessor& gp,
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index 7417e29..743b9e09 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -42,8 +42,7 @@
     const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>();
 
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-    fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                     "ImageIncrement");
 
     const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
@@ -71,26 +70,26 @@
      *
      * This is GLSL, so the matrix is column-major (transposed from standard matrix notation).
      */
-    fragBuilder->codeAppend("float4x4 kMitchellCoefficients = float4x4("
+    fragBuilder->codeAppend("half4x4 kMitchellCoefficients = half4x4("
                             " 1.0 / 18.0,  16.0 / 18.0,   1.0 / 18.0,  0.0 / 18.0,"
                             "-9.0 / 18.0,   0.0 / 18.0,   9.0 / 18.0,  0.0 / 18.0,"
                             "15.0 / 18.0, -36.0 / 18.0,  27.0 / 18.0, -6.0 / 18.0,"
                             "-7.0 / 18.0,  21.0 / 18.0, -21.0 / 18.0,  7.0 / 18.0);");
-    fragBuilder->codeAppendf("float2 coord = %s - %s * float2(0.5);", coords2D.c_str(), imgInc);
+    fragBuilder->codeAppendf("highfloat2 coord = %s - %s * highfloat2(0.5);", coords2D.c_str(), imgInc);
     // We unnormalize the coord in order to determine our fractional offset (f) within the texel
     // We then snap coord to a texel center and renormalize. The snap prevents cases where the
     // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/
     // double hit a texel.
     fragBuilder->codeAppendf("coord /= %s;", imgInc);
-    fragBuilder->codeAppend("float2 f = fract(coord);");
-    fragBuilder->codeAppendf("coord = (coord - f + float2(0.5)) * %s;", imgInc);
-    fragBuilder->codeAppend("float4 wx = kMitchellCoefficients * float4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
-    fragBuilder->codeAppend("float4 wy = kMitchellCoefficients * float4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
-    fragBuilder->codeAppend("float4 rowColors[4];");
+    fragBuilder->codeAppend("highfloat2 f = fract(coord);");
+    fragBuilder->codeAppendf("coord = (coord - f + highfloat2(0.5)) * %s;", imgInc);
+    fragBuilder->codeAppend("half4 wx = kMitchellCoefficients * half4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
+    fragBuilder->codeAppend("half4 wy = kMitchellCoefficients * half4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
+    fragBuilder->codeAppend("half4 rowColors[4];");
     for (int y = 0; y < 4; ++y) {
         for (int x = 0; x < 4; ++x) {
             SkString coord;
-            coord.printf("coord + %s * float2(%d, %d)", imgInc, x - 1, y - 1);
+            coord.printf("coord + %s * highfloat2(%d, %d)", imgInc, x - 1, y - 1);
             SkString sampleVar;
             sampleVar.printf("rowColors[%d]", x);
             fDomain.sampleTexture(fragBuilder,
@@ -102,7 +101,7 @@
                                   args.fTexSamplers[0]);
         }
         fragBuilder->codeAppendf(
-            "float4 s%d = wx.x * rowColors[0] + wx.y * rowColors[1] + wx.z * rowColors[2] + wx.w * rowColors[3];",
+            "half4 s%d = wx.x * rowColors[0] + wx.y * rowColors[1] + wx.z * rowColors[2] + wx.w * rowColors[3];",
             y);
     }
     SkString bicubicColor("(wy.x * s0 + wy.y * s1 + wy.z * s2 + wy.w * s3)");
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index b10bdb1..ad96951 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -32,13 +32,13 @@
 
         const char* atlasSizeInvName;
         fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
-                                                          kVec2f_GrSLType,
+                                                          kHighFloat2_GrSLType,
                                                           kHigh_GrSLPrecision,
                                                           "AtlasSizeInv",
                                                           &atlasSizeInvName);
 
-        GrGLSLVertToFrag uv(kVec2f_GrSLType);
-        GrGLSLVertToFrag texIdx(kFloat_GrSLType);
+        GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
+        GrGLSLVertToFrag texIdx(kHalf_GrSLType);
         append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName,
                                  &uv, &texIdx, nullptr);
 
@@ -63,14 +63,14 @@
                              btgp.localMatrix(),
                              args.fFPCoordTransformHandler);
 
-        fragBuilder->codeAppend("float4 texColor;");
+        fragBuilder->codeAppend("half4 texColor;");
         append_multitexture_lookup(args, btgp.numTextureSamplers(),
                                    texIdx, uv.fsIn(), "texColor");
 
         if (btgp.maskFormat() == kARGB_GrMaskFormat) {
             // modulate by color
             fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor);
-            fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+            fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
         } else {
             fragBuilder->codeAppendf("%s = texColor;", args.fOutputCoverage);
         }
diff --git a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
index 1b5ea60..ff997cd 100644
--- a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
@@ -25,12 +25,12 @@
                 args.fFp.cast<GrBlurredEdgeFragmentProcessor>();
         (void)_outer;
         fragBuilder->codeAppendf(
-                "float factor = 1.0 - %s.w;\n@switch (%d) {\n    case 0:\n        factor = "
-                "exp((-factor * factor) * 4.0) - 0.017999999999999999;\n        break;\n    case "
-                "1:\n        factor = smoothstep(1.0, 0.0, factor);\n        break;\n}\n%s = "
-                "float4(factor);\n",
-                args.fInputColor ? args.fInputColor : "float4(1)", _outer.mode(),
-                args.fOutputColor);
+                "half factor = half(1.0 - highfloat(%s.w));\n@switch (%d) {\n    case 0:\n        "
+                "factor = half(exp(highfloat(highfloat(-factor * factor) * 4.0)) - "
+                "0.017999999999999999);\n        break;\n    case 1:\n        factor = "
+                "half(smoothstep(1.0, 0.0, highfloat(factor)));\n        break;\n}\n%s = "
+                "half4(factor);\n",
+                args.fInputColor ? args.fInputColor : "half4(1)", _outer.mode(), args.fOutputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp
index 3ff233a..fe5ffd5 100644
--- a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp
+++ b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp
@@ -15,7 +15,7 @@
 layout(key) in int mode;
 
 void main() {
-    float factor = 1.0 - sk_InColor.a;
+    half factor = 1.0 - sk_InColor.a;
     @switch (mode) {
         case 0: // kGaussian_Mode
             factor = exp(-factor * factor * 4.0) - 0.018;
@@ -24,5 +24,5 @@
             factor = smoothstep(1.0, 0.0, factor);
             break;
     }
-    sk_OutColor = float4(factor);
+    sk_OutColor = half4(factor);
 }
diff --git a/src/gpu/effects/GrCircleEffect.cpp b/src/gpu/effects/GrCircleEffect.cpp
index b764559..7b4a9f7 100644
--- a/src/gpu/effects/GrCircleEffect.cpp
+++ b/src/gpu/effects/GrCircleEffect.cpp
@@ -24,14 +24,15 @@
         const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>();
         (void)_outer;
         prevRadius = -1.0;
-        fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
+        fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                       kDefault_GrSLPrecision, "circle");
         fragBuilder->codeAppendf(
-                "float2 prevCenter;\nfloat prevRadius = %f;\nfloat d;\n@if (%d == 2 || %d == 3) "
-                "{\n    d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z;\n} else {\n   "
-                " d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z;\n}\n@if ((%d == 1 "
-                "|| %d == 3) || %d == 4) {\n    d = clamp(d, 0.0, 1.0);\n} else {\n    d = d > 0.5 "
-                "? 1.0 : 0.0;\n}\n%s = %s * d;\n",
+                "half2 prevCenter;\nhalf prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n   "
+                " d = (highfloat(length((%s.xy - half2(sk_FragCoord.xy)) * %s.w)) - 1.0) * "
+                "%s.z;\n} else {\n    d = half((1.0 - highfloat(length((%s.xy - "
+                "half2(sk_FragCoord.xy)) * %s.w))) * highfloat(%s.z));\n}\n@if ((%d == 1 || %d == "
+                "3) || %d == 4) {\n    d = half(clamp(highfloat(d), 0.0, 1.0));\n} else {\n    d = "
+                "half(highfloat(d) > 0.5 ? 1.0 : 0.0);\n}\n%s = %s * d;\n",
                 prevRadius, _outer.edgeType(), _outer.edgeType(),
                 args.fUniformHandler->getUniformCStr(fCircleVar),
                 args.fUniformHandler->getUniformCStr(fCircleVar),
@@ -40,7 +41,7 @@
                 args.fUniformHandler->getUniformCStr(fCircleVar),
                 args.fUniformHandler->getUniformCStr(fCircleVar), _outer.edgeType(),
                 _outer.edgeType(), _outer.edgeType(), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "float4(1)");
+                args.fInputColor ? args.fInputColor : "half4(1)");
     }
 
 private:
diff --git a/src/gpu/effects/GrCircleEffect.fp b/src/gpu/effects/GrCircleEffect.fp
index 884112e..031b2ee 100644
--- a/src/gpu/effects/GrCircleEffect.fp
+++ b/src/gpu/effects/GrCircleEffect.fp
@@ -6,14 +6,14 @@
  */
 
 layout(key) in int edgeType;
-in float2 center;
-in float radius;
+in half2 center;
+in half radius;
 
-float2 prevCenter;
-float prevRadius = -1;
+half2 prevCenter;
+half prevRadius = -1;
 // The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular
 // fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills.
-uniform float4 circle;
+uniform half4 circle;
 
 @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
 
@@ -36,7 +36,7 @@
     // TODO: Right now the distance to circle caclulation is performed in a space normalized to the
     // radius and then denormalized. This is to prevent overflow on devices that have a "real"
     // mediump. It'd be nice to only do this on mediump devices.
-    float d;
+    half d;
     @if (edgeType == 2 /* kInverseFillBW_GrProcessorEdgeType */ ||
          edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */) {
         d = (length((circle.xy - sk_FragCoord.xy) * circle.w) - 1.0) * circle.z;
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 2cf7919..e1ecc7f 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -21,16 +21,16 @@
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
 
         // Use highp throughout the shader to avoid some precision issues on specific GPUs.
-        fragBuilder->elevateDefaultPrecision(kHigh_GrSLPrecision);
+        fragBuilder->forceHighPrecision();
 
         if (nullptr == args.fInputColor) {
             // could optimize this case, but we aren't for now.
-            args.fInputColor = "float4(1)";
+            args.fInputColor = "half4(1)";
         }
 
         // Aggressively round to the nearest exact (N / 255) floating point value. This lets us
         // find a round-trip preserving pair on some GPUs that do odd byte to float conversion.
-        fragBuilder->codeAppendf("float4 color = floor(%s * 255.0 + 0.5) / 255.0;", args.fInputColor);
+        fragBuilder->codeAppendf("half4 color = floor(%s * 255.0 + 0.5) / 255.0;", args.fInputColor);
 
         switch (cce.pmConversion()) {
             case GrConfigConversionEffect::kToPremul_PMConversion:
@@ -40,7 +40,7 @@
 
             case GrConfigConversionEffect::kToUnpremul_PMConversion:
                 fragBuilder->codeAppend(
-                    "color.rgb = color.a <= 0.0 ? float3(0,0,0) : floor(color.rgb / color.a * 255.0 + 0.5) / 255.0;");
+                    "color.rgb = color.a <= 0.0 ? half3(0,0,0) : floor(color.rgb / color.a * 255.0 + 0.5) / 255.0;");
                 break;
 
             default:
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index a8b328e..7051872 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -19,7 +19,7 @@
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
         const char* colorUni;
         fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                         kVec4f_GrSLType, kMedium_GrSLPrecision,
+                                                         kHalf4_GrSLType,
                                                          "constantColor",
                                                          &colorUni);
         GrConstColorProcessor::InputMode mode = args.fFp.cast<GrConstColorProcessor>().inputMode();
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index e61923c..97f4569 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -103,8 +103,7 @@
     // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
     // respectively.
     fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kVec4f_GrSLType,
-                                                    kDefault_GrSLPrecision,
+                                                    kHalf4_GrSLType,
                                                     "rect",
                                                     &rectName);
 
@@ -112,16 +111,16 @@
     if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
         // The amount of coverage removed in x and y by the edges is computed as a pair of negative
         // numbers, xSub and ySub.
-        fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
+        fragBuilder->codeAppend("\t\thalf xSub, ySub;\n");
         fragBuilder->codeAppendf("\t\txSub = min(sk_FragCoord.x - %s.x, 0.0);\n", rectName);
         fragBuilder->codeAppendf("\t\txSub += min(%s.z - sk_FragCoord.x, 0.0);\n", rectName);
         fragBuilder->codeAppendf("\t\tySub = min(sk_FragCoord.y - %s.y, 0.0);\n", rectName);
         fragBuilder->codeAppendf("\t\tySub += min(%s.w - sk_FragCoord.y, 0.0);\n", rectName);
         // Now compute coverage in x and y and multiply them to get the fraction of the pixel
         // covered.
-        fragBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
+        fragBuilder->codeAppendf("\t\thalf alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
     } else {
-        fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
+        fragBuilder->codeAppendf("\t\thalf alpha = 1.0;\n");
         fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.x - %s.x) > -0.5 ? 1.0 : 0.0;\n",
                                  rectName);
         fragBuilder->codeAppendf("\t\talpha *= (%s.z - sk_FragCoord.x) > -0.5 ? 1.0 : 0.0;\n",
@@ -191,16 +190,15 @@
 
     const char *edgeArrayName;
     fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
-                                                         kVec3f_GrSLType,
-                                                         kDefault_GrSLPrecision,
+                                                         kHalf3_GrSLType,
                                                          "edges",
                                                          cpe.getEdgeCount(),
                                                          &edgeArrayName);
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-    fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
-    fragBuilder->codeAppend("\t\tfloat edge;\n");
+    fragBuilder->codeAppend("\t\thalf alpha = 1.0;\n");
+    fragBuilder->codeAppend("\t\thalf edge;\n");
     for (int i = 0; i < cpe.getEdgeCount(); ++i) {
-        fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], float3(sk_FragCoord.x, sk_FragCoord.y, "
+        fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], half3(sk_FragCoord.x, sk_FragCoord.y, "
                                                              "1));\n",
                                  edgeArrayName, i);
         if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp
index 2d66e1e..ab0d835 100644
--- a/src/gpu/effects/GrDisableColorXP.cpp
+++ b/src/gpu/effects/GrDisableColorXP.cpp
@@ -53,7 +53,7 @@
         // you do not give gl_FragColor a value, the gl context is lost and we end up drawing
         // nothing. So this fix just sets the gl_FragColor arbitrarily to 0.
         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
-        fragBuilder->codeAppendf("%s = float4(0);", args.fOutputPrimary);
+        fragBuilder->codeAppendf("%s = half4(0);", args.fOutputPrimary);
     }
 
     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 128d714..c7cd9bb 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -45,7 +45,7 @@
 
         const char* atlasSizeInvName;
         fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
-                                                          kVec2f_GrSLType,
+                                                          kHighFloat2_GrSLType,
                                                           kHigh_GrSLPrecision,
                                                           "AtlasSizeInv",
                                                           &atlasSizeInvName);
@@ -53,8 +53,7 @@
         // adjust based on gamma
         const char* distanceAdjustUniName = nullptr;
         // width, height, 1/(3*width)
-        fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                        kFloat_GrSLType, kDefault_GrSLPrecision,
+        fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                         "DistanceAdjust", &distanceAdjustUniName);
 #endif
 
@@ -78,9 +77,9 @@
                              args.fFPCoordTransformHandler);
 
         // add varyings
-        GrGLSLVertToFrag uv(kVec2f_GrSLType);
-        GrGLSLVertToFrag texIdx(kFloat_GrSLType);
-        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
+        GrGLSLVertToFrag texIdx(kHalf_GrSLType);
+        GrGLSLVertToFrag st(kHighFloat2_GrSLType);
         append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
                                  &uv, &texIdx, &st);
 
@@ -93,19 +92,19 @@
             SkToBool(dfTexEffect.getFlags() & kAliased_DistanceFieldEffectFlag);
 
         // Use highp to work around aliasing issues
-        fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn());
-        fragBuilder->codeAppend("float4 texColor;");
+        fragBuilder->codeAppendf("highfloat2 uv = %s;\n", uv.fsIn());
+        fragBuilder->codeAppend("half4 texColor;");
         append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
                                    texIdx, "uv", "texColor");
 
-        fragBuilder->codeAppend("float distance = "
+        fragBuilder->codeAppend("half distance = "
                       SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
 #ifdef SK_GAMMA_APPLY_TO_A8
         // adjust width based on gamma
         fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
 #endif
 
-        fragBuilder->codeAppend("float afwidth;");
+        fragBuilder->codeAppend("half afwidth;");
         if (isUniformScale) {
             // For uniform scale, we adjust for the effect of the transformation on the distance
             // by using the length of the gradient of the t coordinate in the y direction.
@@ -128,29 +127,29 @@
 
             // this gives us a smooth step across approximately one fragment
 #ifdef SK_VULKAN
-            fragBuilder->codeAppendf("float st_grad_len = length(dFdx(%s));", st.fsIn());
+            fragBuilder->codeAppendf("half st_grad_len = length(dFdx(%s));", st.fsIn());
 #else
             // We use the y gradient because there is a bug in the Mali 400 in the x direction.
-            fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn());
+            fragBuilder->codeAppendf("half st_grad_len = length(dFdy(%s));", st.fsIn());
 #endif
             fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
         } else {
             // For general transforms, to determine the amount of correction we multiply a unit
             // vector pointing along the SDF gradient direction by the Jacobian of the st coords
             // (which is the inverse transform for this fragment) and take the length of the result.
-            fragBuilder->codeAppend("float2 dist_grad = float2(dFdx(distance), dFdy(distance));");
+            fragBuilder->codeAppend("half2 dist_grad = half2(dFdx(distance), dFdy(distance));");
             // the length of the gradient may be 0, so we need to check for this
             // this also compensates for the Adreno, which likes to drop tiles on division by 0
-            fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
+            fragBuilder->codeAppend("half dg_len2 = dot(dist_grad, dist_grad);");
             fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
-            fragBuilder->codeAppend("dist_grad = float2(0.7071, 0.7071);");
+            fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
             fragBuilder->codeAppend("} else {");
             fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
             fragBuilder->codeAppend("}");
 
-            fragBuilder->codeAppendf("float2 Jdx = dFdx(%s);", st.fsIn());
-            fragBuilder->codeAppendf("float2 Jdy = dFdy(%s);", st.fsIn());
-            fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
+            fragBuilder->codeAppendf("half2 Jdx = dFdx(%s);", st.fsIn());
+            fragBuilder->codeAppendf("half2 Jdy = dFdy(%s);", st.fsIn());
+            fragBuilder->codeAppend("half2 grad = half2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
             fragBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
 
             // this gives us a smooth step across approximately one fragment
@@ -158,18 +157,18 @@
         }
 
         if (isAliased) {
-            fragBuilder->codeAppend("float val = distance > 0 ? 1.0 : 0.0;");
+            fragBuilder->codeAppend("half val = distance > 0 ? 1.0 : 0.0;");
         } else if (isGammaCorrect) {
             // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
             // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want
             // distance mapped linearly to coverage, so use a linear step:
             fragBuilder->codeAppend(
-                "float val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);");
+                "half val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);");
         } else {
-            fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
+            fragBuilder->codeAppend("half val = smoothstep(-afwidth, afwidth, distance);");
         }
 
-        fragBuilder->codeAppendf("%s = float4(val);", args.fOutputCoverage);
+        fragBuilder->codeAppendf("%s = half4(val);", args.fOutputCoverage);
     }
 
     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
@@ -341,14 +340,14 @@
 
         const char* atlasSizeInvName;
         fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
-                                                          kVec2f_GrSLType,
+                                                          kHighFloat2_GrSLType,
                                                           kHigh_GrSLPrecision,
                                                           "AtlasSizeInv",
                                                           &atlasSizeInvName);
 
-        GrGLSLVertToFrag uv(kVec2f_GrSLType);
-        GrGLSLVertToFrag texIdx(kFloat_GrSLType);
-        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
+        GrGLSLVertToFrag texIdx(kHalf_GrSLType);
+        GrGLSLVertToFrag st(kHighFloat2_GrSLType);
         append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
                                  &uv, &texIdx, &st);
 
@@ -372,15 +371,15 @@
                              args.fFPCoordTransformHandler);
 
         // Use highp to work around aliasing issues
-        fragBuilder->codeAppendf("highp float2 uv = %s;", uv.fsIn());
-        fragBuilder->codeAppend("float4 texColor;");
+        fragBuilder->codeAppendf("highfloat2 uv = %s;", uv.fsIn());
+        fragBuilder->codeAppend("half4 texColor;");
         append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
                                    texIdx, "uv", "texColor");
 
-        fragBuilder->codeAppend("float distance = "
+        fragBuilder->codeAppend("half distance = "
             SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
 
-        fragBuilder->codeAppend("float afwidth;");
+        fragBuilder->codeAppend("half afwidth;");
         bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
                                kUniformScale_DistanceFieldEffectMask;
         bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
@@ -407,30 +406,30 @@
 
             // this gives us a smooth step across approximately one fragment
 #ifdef SK_VULKAN
-            fragBuilder->codeAppendf("float st_grad_len = length(dFdx(%s));", st.fsIn());
+            fragBuilder->codeAppendf("half st_grad_len = length(dFdx(%s));", st.fsIn());
 #else
             // We use the y gradient because there is a bug in the Mali 400 in the x direction.
-            fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn());
+            fragBuilder->codeAppendf("half st_grad_len = length(dFdy(%s));", st.fsIn());
 #endif
             fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
         } else {
             // For general transforms, to determine the amount of correction we multiply a unit
             // vector pointing along the SDF gradient direction by the Jacobian of the st coords
             // (which is the inverse transform for this fragment) and take the length of the result.
-            fragBuilder->codeAppend("float2 dist_grad = float2(dFdx(distance), dFdy(distance));");
+            fragBuilder->codeAppend("half2 dist_grad = half2(dFdx(distance), dFdy(distance));");
             // the length of the gradient may be 0, so we need to check for this
             // this also compensates for the Adreno, which likes to drop tiles on division by 0
-            fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
+            fragBuilder->codeAppend("half dg_len2 = dot(dist_grad, dist_grad);");
             fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
-            fragBuilder->codeAppend("dist_grad = float2(0.7071, 0.7071);");
+            fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
             fragBuilder->codeAppend("} else {");
             fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
             fragBuilder->codeAppend("}");
 
-            fragBuilder->codeAppendf("float2 Jdx = dFdx(%s);", st.fsIn());
-            fragBuilder->codeAppendf("float2 Jdy = dFdy(%s);", st.fsIn());
-            fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
-            fragBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
+            fragBuilder->codeAppendf("half2 Jdx = dFdx(%s);", st.fsIn());
+            fragBuilder->codeAppendf("half2 Jdy = dFdy(%s);", st.fsIn());
+            fragBuilder->codeAppend("half2 grad = half2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
+            fragBuilder->codeAppend("                   dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
 
             // this gives us a smooth step across approximately one fragment
             fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
@@ -440,12 +439,12 @@
         // mapped linearly to coverage, so use a linear step:
         if (isGammaCorrect) {
             fragBuilder->codeAppend(
-                "float val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);");
+                "half val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);");
         } else {
-            fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
+            fragBuilder->codeAppend("half val = smoothstep(-afwidth, afwidth, distance);");
         }
 
-        fragBuilder->codeAppendf("%s = float4(val);", args.fOutputCoverage);
+        fragBuilder->codeAppendf("%s = half4(val);", args.fOutputCoverage);
     }
 
     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
@@ -600,7 +599,7 @@
 
         const char* atlasSizeInvName;
         fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
-                                                          kVec2f_GrSLType,
+                                                          kHighFloat2_GrSLType,
                                                           kHigh_GrSLPrecision,
                                                           "AtlasSizeInv",
                                                           &atlasSizeInvName);
@@ -627,13 +626,13 @@
                              args.fFPCoordTransformHandler);
 
         // set up varyings
-        GrGLSLVertToFrag uv(kVec2f_GrSLType);
-        GrGLSLVertToFrag texIdx(kFloat_GrSLType);
-        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
+        GrGLSLVertToFrag texIdx(kHalf_GrSLType);
+        GrGLSLVertToFrag st(kHighFloat2_GrSLType);
         append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
                                  &uv, &texIdx, &st);
 
-        GrGLSLVertToFrag delta(kFloat_GrSLType);
+        GrGLSLVertToFrag delta(kHighFloat_GrSLType);
         varyingHandler->addVarying("Delta", &delta, kHigh_GrSLPrecision);
         if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
             vertBuilder->codeAppendf("%s = -%s.x/3.0;", delta.vsOut(), atlasSizeInvName);
@@ -650,48 +649,48 @@
 
         // create LCD offset adjusted by inverse of transform
         // Use highp to work around aliasing issues
-        fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn());
+        fragBuilder->codeAppendf("highfloat2 uv = %s;\n", uv.fsIn());
 
         if (isUniformScale) {
 #ifdef SK_VULKAN
-            fragBuilder->codeAppendf("float st_grad_len = abs(dFdx(%s.x));", st.fsIn());
+            fragBuilder->codeAppendf("half st_grad_len = abs(dFdx(%s.x));", st.fsIn());
 #else
             // We use the y gradient because there is a bug in the Mali 400 in the x direction.
-            fragBuilder->codeAppendf("float st_grad_len = abs(dFdy(%s.y));", st.fsIn());
+            fragBuilder->codeAppendf("half st_grad_len = abs(dFdy(%s.y));", st.fsIn());
 #endif
-            fragBuilder->codeAppendf("float2 offset = float2(st_grad_len*%s, 0.0);", delta.fsIn());
+            fragBuilder->codeAppendf("half2 offset = half2(st_grad_len*%s, 0.0);", delta.fsIn());
         } else if (isSimilarity) {
             // For a similarity matrix with rotation, the gradient will not be aligned
             // with the texel coordinate axes, so we need to calculate it.
 #ifdef SK_VULKAN
-            fragBuilder->codeAppendf("float2 st_grad = dFdx(%s);", st.fsIn());
-            fragBuilder->codeAppendf("float2 offset = %s*st_grad;", delta.fsIn());
+            fragBuilder->codeAppendf("half2 st_grad = dFdx(%s);", st.fsIn());
+            fragBuilder->codeAppendf("half2 offset = %s*st_grad;", delta.fsIn());
 #else
             // We use dFdy because of a Mali 400 bug, and rotate -90 degrees to
             // get the gradient in the x direction.
-            fragBuilder->codeAppendf("float2 st_grad = dFdy(%s);", st.fsIn());
-            fragBuilder->codeAppendf("float2 offset = %s*float2(st_grad.y, -st_grad.x);",
+            fragBuilder->codeAppendf("half2 st_grad = dFdy(%s);", st.fsIn());
+            fragBuilder->codeAppendf("half2 offset = %s*half2(st_grad.y, -st_grad.x);",
                                      delta.fsIn());
 #endif
-            fragBuilder->codeAppend("float st_grad_len = length(st_grad);");
+            fragBuilder->codeAppend("half st_grad_len = length(st_grad);");
         } else {
-            fragBuilder->codeAppendf("float2 st = %s;\n", st.fsIn());
+            fragBuilder->codeAppendf("half2 st = %s;\n", st.fsIn());
 
-            fragBuilder->codeAppend("float2 Jdx = dFdx(st);");
-            fragBuilder->codeAppend("float2 Jdy = dFdy(st);");
-            fragBuilder->codeAppendf("float2 offset = %s*Jdx;", delta.fsIn());
+            fragBuilder->codeAppend("half2 Jdx = dFdx(st);");
+            fragBuilder->codeAppend("half2 Jdy = dFdy(st);");
+            fragBuilder->codeAppendf("half2 offset = %s*Jdx;", delta.fsIn());
         }
 
         // sample the texture by index
-        fragBuilder->codeAppend("float4 texColor;");
+        fragBuilder->codeAppend("half4 texColor;");
         append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
                                    texIdx, "uv", "texColor");
 
         // green is distance to uv center
-        fragBuilder->codeAppend("float3 distance;");
+        fragBuilder->codeAppend("half3 distance;");
         fragBuilder->codeAppend("distance.y = texColor.r;");
         // red is distance to left offset
-        fragBuilder->codeAppend("float2 uv_adjusted = uv - offset;");
+        fragBuilder->codeAppend("half2 uv_adjusted = uv - offset;");
         append_multitexture_lookup(args, dfTexEffect.numTextureSamplers(),
                                    texIdx, "uv_adjusted", "texColor");
         fragBuilder->codeAppend("distance.x = texColor.r;");
@@ -702,12 +701,11 @@
         fragBuilder->codeAppend("distance.z = texColor.r;");
 
         fragBuilder->codeAppend("distance = "
-           "float3(" SK_DistanceFieldMultiplier ")*(distance - float3(" SK_DistanceFieldThreshold"));");
+           "half3(" SK_DistanceFieldMultiplier ")*(distance - half3(" SK_DistanceFieldThreshold"));");
 
         // adjust width based on gamma
         const char* distanceAdjustUniName = nullptr;
-        fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                        kVec3f_GrSLType, kDefault_GrSLPrecision,
+        fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
                                                         "DistanceAdjust", &distanceAdjustUniName);
         fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
 
@@ -715,7 +713,7 @@
         // for each color component. However, this is only important when using perspective
         // transformations, and even then using a single factor seems like a reasonable
         // trade-off between quality and speed.
-        fragBuilder->codeAppend("float afwidth;");
+        fragBuilder->codeAppend("half afwidth;");
         if (isSimilarity) {
             // For similarity transform (uniform scale-only is a subset of this), we adjust for the
             // effect of the transformation on the distance by using the length of the gradient of
@@ -728,16 +726,16 @@
             // For general transforms, to determine the amount of correction we multiply a unit
             // vector pointing along the SDF gradient direction by the Jacobian of the st coords
             // (which is the inverse transform for this fragment) and take the length of the result.
-            fragBuilder->codeAppend("float2 dist_grad = float2(dFdx(distance.r), dFdy(distance.r));");
+            fragBuilder->codeAppend("half2 dist_grad = half2(dFdx(distance.r), dFdy(distance.r));");
             // the length of the gradient may be 0, so we need to check for this
             // this also compensates for the Adreno, which likes to drop tiles on division by 0
-            fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
+            fragBuilder->codeAppend("half dg_len2 = dot(dist_grad, dist_grad);");
             fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
-            fragBuilder->codeAppend("dist_grad = float2(0.7071, 0.7071);");
+            fragBuilder->codeAppend("dist_grad = half2(0.7071, 0.7071);");
             fragBuilder->codeAppend("} else {");
             fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
             fragBuilder->codeAppend("}");
-            fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
+            fragBuilder->codeAppend("half2 grad = half2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
             fragBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
 
             // this gives us a smooth step across approximately one fragment
@@ -749,11 +747,11 @@
         // mapped linearly to coverage, so use a linear step:
         if (isGammaCorrect) {
             fragBuilder->codeAppendf("%s = "
-                "float4(clamp((distance + float3(afwidth)) / float3(2.0 * afwidth), 0.0, 1.0), 1.0);",
+                "half4(clamp((distance + half3(afwidth)) / half3(2.0 * afwidth), 0.0, 1.0), 1.0);",
                 args.fOutputCoverage);
         } else {
             fragBuilder->codeAppendf(
-                "%s = float4(smoothstep(float3(-afwidth), float3(afwidth), distance), 1.0);",
+                "%s = half4(smoothstep(half3(-afwidth), half3(afwidth), distance), 1.0);",
                 args.fOutputCoverage);
         }
     }
diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp
index d78af4e..6f5266e 100644
--- a/src/gpu/effects/GrDitherEffect.cpp
+++ b/src/gpu/effects/GrDitherEffect.cpp
@@ -24,21 +24,22 @@
         const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>();
         (void)_outer;
         fragBuilder->codeAppendf(
-                "float value;\nfloat range;\n@switch (%d) {\n    case 0:\n        range = "
+                "half value;\nhalf range;\n@switch (%d) {\n    case 0:\n        range = "
                 "0.0039215686274509803;\n        break;\n    case 1:\n        range = "
                 "0.015873015873015872;\n        break;\n    default:\n        range = "
                 "0.066666666666666666;\n        break;\n}\n@if (sk_Caps.integerSupport) {\n    "
                 "uint x = uint(sk_FragCoord.x);\n    uint y = uint(sk_FragCoord.y);\n    uint m = "
                 "(((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) >> 1) "
-                "| (x & 4) >> 2;\n    value = float(m) / 64.0 - 0.4921875;\n} else {\n    float4 "
-                "modValues = mod(sk_FragCoord.xyxy, float4(2.0, 2.0, 4.0, 4.0));\n    float4 "
-                "stepValues = step(modValues, float4(1.0, 1.0, 2.0, 2.0));\n    value = "
-                "dot(stepValues, float4(0.5, 0.25, 0.125, 0.0625)) - 0.46875;\n}\n%s = "
-                "float4(clamp(%s.xyz + value * range, 0.0, %s.w), %s.w);\n",
+                "| (x & 4) >> 2;\n    value = highfloat(highfloat(half(m)) / 64.0) - 0.4921875;\n} "
+                "else {\n    half4 modValues = half4(mod(sk_FragCoord.xyxy, highfloat4(half4(2.0, "
+                "2.0, 4.0, 4.0))));\n    half4 stepValues = half4(step(highfloat4(modValues), "
+                "highfloat4(half4(1.0, 1.0, 2.0, 2.0))));\n    value = highfloat(dot(stepValues, "
+                "half4(0.5, 0.25, 0.125, 0.0625))) - 0.46875;\n}\n%s = "
+                "half4(clamp(highfloat3(%s.xyz + value * range), 0.0, highfloat(%s.w)), %s.w);\n",
                 _outer.rangeType(), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "float4(1)",
-                args.fInputColor ? args.fInputColor : "float4(1)",
-                args.fInputColor ? args.fInputColor : "float4(1)");
+                args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fInputColor ? args.fInputColor : "half4(1)");
     }
 
 private:
diff --git a/src/gpu/effects/GrDitherEffect.fp b/src/gpu/effects/GrDitherEffect.fp
index fe641c6..f2d54cf 100644
--- a/src/gpu/effects/GrDitherEffect.fp
+++ b/src/gpu/effects/GrDitherEffect.fp
@@ -32,8 +32,8 @@
 }
 
 void main() {
-    float value;
-    float range;
+    half value;
+    half range;
     @switch (rangeType) {
         case 0:
             range = 1.0 / 255.0;
@@ -53,17 +53,17 @@
         uint m = (y & 1) << 5 | (x & 1) << 4 |
                  (y & 2) << 2 | (x & 2) << 1 |
                  (y & 4) >> 1 | (x & 4) >> 2;
-        value = float(m) * 1.0 / 64.0 - 63.0 / 128.0;
+        value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
     } else {
         // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4
         // dither pattern rather than an 8x8 one.
-        float4 modValues = mod(sk_FragCoord.xyxy, float4(2.0, 2.0, 4.0, 4.0));
-        float4 stepValues = step(modValues, float4(1.0, 1.0, 2.0, 2.0));
-        value = dot(stepValues, float4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
+        half4 modValues = mod(sk_FragCoord.xyxy, half4(2.0, 2.0, 4.0, 4.0));
+        half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0));
+        value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
     }
     // For each color channel, add the random offset to the channel value and then clamp
     // between 0 and alpha to keep the color premultiplied.
-    sk_OutColor = float4(clamp(sk_InColor.rgb + value * range, 0, sk_InColor.a), sk_InColor.a);
+    sk_OutColor = half4(clamp(sk_InColor.rgb + value * range, 0, sk_InColor.a), sk_InColor.a);
 }
 
 @test(testData) {
diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp
index 3039145..3f35311 100644
--- a/src/gpu/effects/GrEllipseEffect.cpp
+++ b/src/gpu/effects/GrEllipseEffect.cpp
@@ -23,35 +23,34 @@
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
         const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>();
         (void)_outer;
-        prevRadii = float2(-1.0);
+        prevRadii = half2(-1.0);
         useScale = sk_Caps.floatPrecisionVaries;
-        fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
-                                                       kHigh_GrSLPrecision, "ellipse");
+        fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat4_GrSLType,
+                                                       kDefault_GrSLPrecision, "ellipse");
         if (useScale) {
-            fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
+            fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                          kDefault_GrSLPrecision, "scale");
         }
         fragBuilder->codeAppendf(
-                "float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool useScale = "
-                "%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n    d *= "
-                "%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat "
-                "grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist "
-                "= implicit * inversesqrt(grad_dot);\n@if (useScale) {\n    approx_dist *= "
-                "%s.x;\n}\nfloat alpha;\n@switch (%d) {\n    case 0:\n        alpha = approx_dist "
-                "> 0.0 ? 0.0 : 1.0;\n        break;\n    case 1:\n        alpha = clamp(0.5 - "
-                "approx_dist, 0.0, 1.0);\n        break;\n    case 2:\n        alpha = approx_dist "
-                "> 0.0 ? 1.0 : 0.0;\n        break;\n    case 3:\n        alpha = clamp(0.5 + "
-                "approx_dist, 0.0, 1.0);\n        break;\n    default:\n        discard;\n}\n%s = "
-                "%s * alpha;\n",
+                "half2 prevCenter;\nhalf2 prevRadii = half2(%f, %f);\nbool useScale = %s;\nhalf2 d "
+                "= half2(sk_FragCoord.xy - %s.xy);\n@if (useScale) {\n    d *= %s.y;\n}\nhalf2 Z = "
+                "d * half2(%s.zw);\nhalf implicit = dot(Z, d) - 1.0;\nhalf grad_dot = 4.0 * dot(Z, "
+                "Z);\ngrad_dot = half(max(highfloat(grad_dot), 0.0001));\nhalf approx_dist = "
+                "highfloat(implicit) * inversesqrt(highfloat(grad_dot));\n@if (useScale) {\n    "
+                "approx_dist *= %s.x;\n}\nhalf alpha;\n@switch (%d) {\n    case 0:\n        alpha "
+                "= half(highfloat(approx_dist) > 0.0 ? 0.0 : 1.0);\n        break;\n    case 1:\n  "
+                "      alpha = half(clamp(0.5 - highfloat(approx_dist), 0.0, 1.0));\n        "
+                "break;\n    case 2:\n        alpha = half(highfloat(approx_dist) > 0.0 ? 1.0 : "
+                "0.0);\n        break;\n    case 3:\n        alpha = half(clamp(0.5 + "
+                "highfloat(approx_dist), 0.0, 1.0));\n        break;\n    default:\n        "
+                "discard;\n}\n%s = %s * alpha;\n",
                 prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"),
                 args.fUniformHandler->getUniformCStr(fEllipseVar),
-                fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar)
-                                    : "float2(0.0)",
+                fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
                 args.fUniformHandler->getUniformCStr(fEllipseVar),
-                fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar)
-                                    : "float2(0.0)",
+                fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
                 _outer.edgeType(), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "float4(1)");
+                args.fInputColor ? args.fInputColor : "half4(1)");
     }
 
 private:
diff --git a/src/gpu/effects/GrEllipseEffect.fp b/src/gpu/effects/GrEllipseEffect.fp
index 85c4c96..3663d56 100644
--- a/src/gpu/effects/GrEllipseEffect.fp
+++ b/src/gpu/effects/GrEllipseEffect.fp
@@ -6,17 +6,17 @@
  */
 
 layout(key) in int edgeType;
-in float2 center;
-in float2 radii;
+in half2 center;
+in half2 radii;
 
-float2 prevCenter;
-float2 prevRadii = float2(-1);
+half2 prevCenter;
+half2 prevRadii = half2(-1);
 // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
-// The last two terms can underflow on mediump, so we use highp.
-uniform highp float4 ellipse;
+// The last two terms can underflow with halfs, so we use floats.
+uniform highfloat4 ellipse;
 
 bool useScale = sk_Caps.floatPrecisionVaries;
-layout(when=useScale) uniform float2 scale;
+layout(when=useScale) uniform half2 scale;
 
 @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
 
@@ -50,7 +50,7 @@
 
 void main() {
     // d is the offset to the ellipse center
-    float2 d = sk_FragCoord.xy - ellipse.xy;
+    half2 d = sk_FragCoord.xy - ellipse.xy;
     // If we're on a device with a "real" mediump then we'll do the distance computation in a space
     // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
     // inverse squared radii uniform values are already in this normalized space. The center is
@@ -58,19 +58,19 @@
     @if (useScale) {
         d *= scale.y;
     }
-    float2 Z = d * ellipse.zw;
+    half2 Z = d * ellipse.zw;
     // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
-    float implicit = dot(Z, d) - 1;
+    half implicit = dot(Z, d) - 1;
     // grad_dot is the squared length of the gradient of the implicit.
-    float grad_dot = 4 * dot(Z, Z);
+    half grad_dot = 4 * dot(Z, Z);
     // Avoid calling inversesqrt on zero.
     grad_dot = max(grad_dot, 1e-4);
-    float approx_dist = implicit * inversesqrt(grad_dot);
+    half approx_dist = implicit * inversesqrt(grad_dot);
     @if (useScale) {
         approx_dist *= scale.x;
     }
 
-    float alpha;
+    half alpha;
     @switch (edgeType) {
         case 0 /* kFillBW_GrProcessorEdgeType */:
             alpha = approx_dist > 0.0 ? 0.0 : 1.0;
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
index 23b6178..dfbe17a 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
@@ -41,11 +41,11 @@
             args.fFp.cast<GrGaussianConvolutionFragmentProcessor>();
 
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-    fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
-                                                    kDefault_GrSLPrecision, "ImageIncrement");
+    fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
+                                                    "ImageIncrement");
     if (ce.useBounds()) {
-        fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
-                                                kDefault_GrSLPrecision, "Bounds");
+        fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
+                                                "Bounds");
     }
 
     int width = ce.width();
@@ -53,19 +53,19 @@
     int arrayCount = (width + 3) / 4;
     SkASSERT(4 * arrayCount >= width);
 
-    fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kVec4f_GrSLType,
-                                                 kDefault_GrSLPrecision, "Kernel", arrayCount);
+    fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kHalf4_GrSLType,
+                                                 "Kernel", arrayCount);
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
 
-    fragBuilder->codeAppendf("%s = float4(0, 0, 0, 0);", args.fOutputColor);
+    fragBuilder->codeAppendf("%s = half4(0, 0, 0, 0);", args.fOutputColor);
 
     const GrShaderVar& kernel = uniformHandler->getUniformVariable(fKernelUni);
     const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
 
-    fragBuilder->codeAppendf("float2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc);
-    fragBuilder->codeAppend("float2 coordSampled = float2(0, 0);");
+    fragBuilder->codeAppendf("highfloat2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc);
+    fragBuilder->codeAppend("highfloat2 coordSampled = half2(0, 0);");
 
     // Manually unroll loop because some drivers don't; yields 20-30% speedup.
     const char* kVecSuffix[4] = {".x", ".y", ".z", ".w"};
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 9d9a03e..063f8f3 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -47,20 +47,15 @@
     SkASSERT(4 * arrayCount >= kWidth * kHeight);
 
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-    fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                     "ImageIncrement");
-    fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
-                                                 kVec4f_GrSLType, kDefault_GrSLPrecision,
+    fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                  "Kernel",
                                                  arrayCount);
-    fKernelOffsetUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                  kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fKernelOffsetUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                   "KernelOffset");
-    fGainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                          kFloat_GrSLType, kDefault_GrSLPrecision, "Gain");
-    fBiasUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                          kFloat_GrSLType, kDefault_GrSLPrecision, "Bias");
+    fGainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Gain");
+    fBiasUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Bias");
 
     const char* kernelOffset = uniformHandler->getUniformCStr(fKernelOffsetUni);
     const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
@@ -70,9 +65,9 @@
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
-    fragBuilder->codeAppend("float4 sum = float4(0, 0, 0, 0);");
-    fragBuilder->codeAppendf("float2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
-    fragBuilder->codeAppend("float4 c;");
+    fragBuilder->codeAppend("half4 sum = half4(0, 0, 0, 0);");
+    fragBuilder->codeAppendf("highfloat2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
+    fragBuilder->codeAppend("half4 c;");
 
     const char* kVecSuffix[4] = { ".x", ".y", ".z", ".w" };
     for (int y = 0; y < kHeight; y++) {
@@ -80,10 +75,10 @@
             GrGLSLShaderBuilder::ShaderBlock block(fragBuilder);
             int offset = y*kWidth + x;
 
-            fragBuilder->codeAppendf("float k = %s[%d]%s;", kernel, offset / 4,
+            fragBuilder->codeAppendf("half k = %s[%d]%s;", kernel, offset / 4,
                                      kVecSuffix[offset & 0x3]);
             SkString coord;
-            coord.printf("coord + float2(%d, %d) * %s", x, y, imgInc);
+            coord.printf("coord + half2(%d, %d) * %s", x, y, imgInc);
             fDomain.sampleTexture(fragBuilder,
                                   uniformHandler,
                                   args.fShaderCaps,
diff --git a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp b/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
index b30746a..fee7f17 100644
--- a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
+++ b/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
@@ -23,24 +23,21 @@
         const char* srcCoeffsName = nullptr;
         if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kSrcTransfer_Op)) {
             fSrcTransferFnUni = uniformHandler->addUniformArray(
-                    kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision,
-                    "SrcTransferFn", GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs,
-                    &srcCoeffsName);
+                    kFragment_GrShaderFlag, kHalf_GrSLType, "SrcTransferFn",
+                    GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &srcCoeffsName);
         }
 
         const char* dstCoeffsName = nullptr;
         if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kDstTransfer_Op)) {
             fDstTransferFnUni = uniformHandler->addUniformArray(
-                    kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision,
-                    "DstTransferFn", GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs,
-                    &dstCoeffsName);
+                    kFragment_GrShaderFlag, kHalf_GrSLType, "DstTransferFn",
+                    GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &dstCoeffsName);
         }
 
         const char* gamutXformName = nullptr;
         if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kGamutXform_Op)) {
-            fGamutXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat44f_GrSLType,
-                                                        kDefault_GrSLPrecision, "GamutXform",
-                                                        &gamutXformName);
+            fGamutXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
+                                                        "GamutXform", &gamutXformName);
         }
 
         // Helper function to apply the src or dst transfer function to a single value
@@ -52,32 +49,32 @@
             }
             const char* fnName = i ? "dst_transfer_fn" : "src_transfer_fn";
             static const GrShaderVar gTransferFnFuncArgs[] = {
-                    GrShaderVar("x", kFloat_GrSLType),
+                    GrShaderVar("x", kHalf_GrSLType),
             };
             SkString transferFnBody;
             // Temporaries to make evaluation line readable
-            transferFnBody.printf("float A = %s[0];", coeffsName);
-            transferFnBody.appendf("float B = %s[1];", coeffsName);
-            transferFnBody.appendf("float C = %s[2];", coeffsName);
-            transferFnBody.appendf("float D = %s[3];", coeffsName);
-            transferFnBody.appendf("float E = %s[4];", coeffsName);
-            transferFnBody.appendf("float F = %s[5];", coeffsName);
-            transferFnBody.appendf("float G = %s[6];", coeffsName);
-            transferFnBody.append("float s = sign(x);");
+            transferFnBody.printf("half A = %s[0];", coeffsName);
+            transferFnBody.appendf("half B = %s[1];", coeffsName);
+            transferFnBody.appendf("half C = %s[2];", coeffsName);
+            transferFnBody.appendf("half D = %s[3];", coeffsName);
+            transferFnBody.appendf("half E = %s[4];", coeffsName);
+            transferFnBody.appendf("half F = %s[5];", coeffsName);
+            transferFnBody.appendf("half G = %s[6];", coeffsName);
+            transferFnBody.append("half s = sign(x);");
             transferFnBody.append("x = abs(x);");
             transferFnBody.appendf("return s * ((x < D) ? (C * x) + F : pow(A * x + B, G) + E);");
-            fragBuilder->emitFunction(kFloat_GrSLType, fnName, SK_ARRAY_COUNT(gTransferFnFuncArgs),
+            fragBuilder->emitFunction(kHalf_GrSLType, fnName, SK_ARRAY_COUNT(gTransferFnFuncArgs),
                                       gTransferFnFuncArgs, transferFnBody.c_str(), &tfFuncNames[i]);
         }
 
         if (nullptr == args.fInputColor) {
-            args.fInputColor = "float4(1)";
+            args.fInputColor = "half4(1)";
         }
-        fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor);
+        fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
 
         // 1: Un-premultiply the input color (if necessary)
-        fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
-        fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
+        fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
+        fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
 
         // 2: Apply src transfer function (to get to linear RGB)
         if (srcCoeffsName) {
@@ -89,7 +86,7 @@
         // 3: Apply gamut matrix
         if (gamutXformName) {
             fragBuilder->codeAppendf(
-                "color.rgb = (%s * float4(color.rgb, 1.0)).rgb;", gamutXformName);
+                "color.rgb = (%s * half4(color.rgb, 1.0)).rgb;", gamutXformName);
         }
 
         // 4: Apply dst transfer fn
@@ -100,7 +97,7 @@
         }
 
         // 5: Premultiply again
-        fragBuilder->codeAppendf("%s = float4(color.rgb * color.a, color.a);", args.fOutputColor);
+        fragBuilder->codeAppendf("%s = half4(color.rgb * color.a, color.a);", args.fOutputColor);
     }
 
     static inline void GenKey(const GrProcessor& processor, const GrShaderCaps&,
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 658f190..e6c7bf9 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -440,7 +440,7 @@
     SkASSERT(inColor);
     switch (outputType) {
         case BlendFormula::kNone_OutputType:
-            fragBuilder->codeAppendf("%s = float4(0.0);", output);
+            fragBuilder->codeAppendf("%s = half4(0.0);", output);
             break;
         case BlendFormula::kCoverage_OutputType:
             // We can have a coverage formula while not reading coverage if there are mixed samples.
@@ -456,7 +456,7 @@
             fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
             break;
         case BlendFormula::kISCModulate_OutputType:
-            fragBuilder->codeAppendf("%s = (float4(1.0) - %s) * %s;", output, inColor, inCoverage);
+            fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage);
             break;
         default:
             SK_ABORT("Unsupported output type.");
@@ -629,8 +629,8 @@
 private:
     void emitOutputsForBlendState(const EmitArgs& args) override {
         const char* alpha;
-        fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
-                                                         kDefault_GrSLPrecision, "alpha", &alpha);
+        fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
+                                                         "alpha", &alpha);
         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
         // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
         // value of the src color. We know that there are no color stages (or we wouldn't have
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 6d47e58..7ad354c 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -160,15 +160,11 @@
     // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
     // only rectangular corners, that side's value corresponds to the rect edge's value outset by
     // half a pixel.
-    fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec4f_GrSLType, kDefault_GrSLPrecision,
-                                                   "innerRect",
-                                                   &rectName);
+    fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
+                                                   "innerRect", &rectName);
     // x is (r + .5) and y is 1/(r + .5)
-    fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                        kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                                        "radiusPlusHalf",
-                                                        &radiusPlusHalfName);
+    fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
+                                                        "radiusPlusHalf", &radiusPlusHalfName);
 
     // If we're on a device with a "real" mediump then the length calculation could overflow.
     SkString clampedCircleDistance;
@@ -197,87 +193,87 @@
     // alphas together.
     switch (crre.getCircularCornerFlags()) {
         case CircularRRectEffect::kAll_CornerFlags:
-            fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
-            fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
-            fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
-            fragBuilder->codeAppendf("float alpha = %s;", clampedCircleDistance.c_str());
+            fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
+            fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+            fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
+            fragBuilder->codeAppendf("half alpha = %s;", clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kTopLeft_CornerFlag:
-            fragBuilder->codeAppendf("float2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);",
+            fragBuilder->codeAppendf("half2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = bottomAlpha * rightAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = bottomAlpha * rightAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kTopRight_CornerFlag:
-            fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.z, "
-                                                         "%s.y - sk_FragCoord.y), 0.0);",
+            fragBuilder->codeAppendf("half2 dxy = max(half2(sk_FragCoord.x - %s.z, "
+                                                           "%s.y - sk_FragCoord.y), 0.0);",
                                      rectName, rectName);
-            fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = bottomAlpha * leftAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = bottomAlpha * leftAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kBottomRight_CornerFlag:
-            fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);",
+            fragBuilder->codeAppendf("half2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = topAlpha * leftAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = topAlpha * leftAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kBottomLeft_CornerFlag:
-            fragBuilder->codeAppendf("float2 dxy = max(float2(%s.x - sk_FragCoord.x, sk_FragCoord.y - "
+            fragBuilder->codeAppendf("half2 dxy = max(half2(%s.x - sk_FragCoord.x, sk_FragCoord.y - "
                                      "%s.w), 0.0);",
                                      rectName, rectName);
-            fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = topAlpha * rightAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = topAlpha * rightAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kLeft_CornerFlags:
-            fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
-            fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName);
-            fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
-            fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
+            fragBuilder->codeAppendf("half dy1 = sk_FragCoord.y - %s.w;", rectName);
+            fragBuilder->codeAppend("half2 dxy = max(half2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
+            fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = rightAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = rightAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kTop_CornerFlags:
-            fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
-            fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName);
-            fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);");
-            fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
+            fragBuilder->codeAppendf("half dx1 = sk_FragCoord.x - %s.z;", rectName);
+            fragBuilder->codeAppend("half2 dxy = max(half2(max(dxy0.x, dx1), dxy0.y), 0.0);");
+            fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = bottomAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = bottomAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kRight_CornerFlags:
-            fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName);
-            fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
-            fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
-            fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half dy0 = %s.y - sk_FragCoord.y;", rectName);
+            fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+            fragBuilder->codeAppend("half2 dxy = max(half2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
+            fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = leftAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = leftAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
         case CircularRRectEffect::kBottom_CornerFlags:
-            fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName);
-            fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
-            fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);");
-            fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
+            fragBuilder->codeAppendf("half dx0 = %s.x - sk_FragCoord.x;", rectName);
+            fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+            fragBuilder->codeAppend("half2 dxy = max(half2(max(dx0, dxy1.x), dxy1.y), 0.0);");
+            fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
                                      rectName);
-            fragBuilder->codeAppendf("float alpha = topAlpha * %s;",
+            fragBuilder->codeAppendf("half alpha = topAlpha * %s;",
                                      clampedCircleDistance.c_str());
             break;
     }
@@ -514,10 +510,8 @@
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     const char *rectName;
     // The inner rect is the rrect bounds inset by the x/y radii
-    fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec4f_GrSLType, kDefault_GrSLPrecision,
-                                                   "innerRect",
-                                                   &rectName);
+    fInnerRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
+                                                   "innerRect", &rectName);
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
@@ -532,17 +526,16 @@
     // The code below is a simplified version of the above that performs maxs on the vector
     // components before computing distances and alpha values so that only one distance computation
     // need be computed to determine the min alpha.
-    fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
-    fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+    fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
+    fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
 
     // If we're on a device with a "real" mediump then we'll do the distance computation in a space
     // that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The
     // radii uniform values are already in this normalized space.
     const char* scaleName = nullptr;
     if (args.fShaderCaps->floatPrecisionVaries()) {
-        fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                                   "scale", &scaleName);
+        fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "scale",
+                                                   &scaleName);
     }
 
     // The uniforms with the inv squared radii are highp to prevent underflow.
@@ -550,34 +543,32 @@
         case SkRRect::kSimple_Type: {
             const char *invRadiiXYSqdName;
             fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                             kVec2f_GrSLType,
-                                                             kDefault_GrSLPrecision,
+                                                             kHalf2_GrSLType,
                                                              "invRadiiXY",
                                                              &invRadiiXYSqdName);
-            fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
+            fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
             if (scaleName) {
                 fragBuilder->codeAppendf("dxy *= %s.y;", scaleName);
             }
             // Z is the x/y offsets divided by squared radii.
-            fragBuilder->codeAppendf("float2 Z = dxy * %s.xy;", invRadiiXYSqdName);
+            fragBuilder->codeAppendf("half2 Z = dxy * %s.xy;", invRadiiXYSqdName);
             break;
         }
         case SkRRect::kNinePatch_Type: {
             const char *invRadiiLTRBSqdName;
             fInvRadiiSqdUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                             kVec4f_GrSLType,
-                                                             kDefault_GrSLPrecision,
+                                                             kHalf4_GrSLType,
                                                              "invRadiiLTRB",
                                                              &invRadiiLTRBSqdName);
             if (scaleName) {
                 fragBuilder->codeAppendf("dxy0 *= %s.y;", scaleName);
                 fragBuilder->codeAppendf("dxy1 *= %s.y;", scaleName);
             }
-            fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
+            fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
             // Z is the x/y offsets divided by squared radii. We only care about the (at most) one
             // corner where both the x and y offsets are positive, hence the maxes. (The inverse
             // squared radii will always be positive.)
-            fragBuilder->codeAppendf("float2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);",
+            fragBuilder->codeAppendf("half2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);",
                                      invRadiiLTRBSqdName, invRadiiLTRBSqdName);
 
             break;
@@ -586,20 +577,20 @@
             SK_ABORT("RRect should always be simple or nine-patch.");
     }
     // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
-    fragBuilder->codeAppend("float implicit = dot(Z, dxy) - 1.0;");
+    fragBuilder->codeAppend("half implicit = dot(Z, dxy) - 1.0;");
     // grad_dot is the squared length of the gradient of the implicit.
-    fragBuilder->codeAppend("float grad_dot = 4.0 * dot(Z, Z);");
+    fragBuilder->codeAppend("half grad_dot = 4.0 * dot(Z, Z);");
     // avoid calling inversesqrt on zero.
     fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
-    fragBuilder->codeAppend("float approx_dist = implicit * inversesqrt(grad_dot);");
+    fragBuilder->codeAppend("half approx_dist = implicit * inversesqrt(grad_dot);");
     if (scaleName) {
         fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
     }
 
     if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) {
-        fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
+        fragBuilder->codeAppend("half alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
     } else {
-        fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
+        fragBuilder->codeAppend("half alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
     }
 
     fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor);
diff --git a/src/gpu/effects/GrSRGBEffect.cpp b/src/gpu/effects/GrSRGBEffect.cpp
index f415a6c..0e56dfc 100644
--- a/src/gpu/effects/GrSRGBEffect.cpp
+++ b/src/gpu/effects/GrSRGBEffect.cpp
@@ -20,11 +20,11 @@
 
         SkString srgbFuncName;
         static const GrShaderVar gSrgbArgs[] = {
-            GrShaderVar("x", kFloat_GrSLType),
+            GrShaderVar("x", kHalf_GrSLType),
         };
         switch (srgbe.mode()) {
             case GrSRGBEffect::Mode::kLinearToSRGB:
-                fragBuilder->emitFunction(kFloat_GrSLType,
+                fragBuilder->emitFunction(kHalf_GrSLType,
                                           "linear_to_srgb",
                                           SK_ARRAY_COUNT(gSrgbArgs),
                                           gSrgbArgs,
@@ -33,7 +33,7 @@
                                           &srgbFuncName);
                 break;
             case GrSRGBEffect::Mode::kSRGBToLinear:
-                fragBuilder->emitFunction(kFloat_GrSLType,
+                fragBuilder->emitFunction(kHalf_GrSLType,
                                           "srgb_to_linear",
                                           SK_ARRAY_COUNT(gSrgbArgs),
                                           gSrgbArgs,
@@ -44,20 +44,20 @@
         }
 
         if (nullptr == args.fInputColor) {
-            args.fInputColor = "float4(1)";
+            args.fInputColor = "half4(1)";
         }
 
-        fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor);
+        fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
         if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
-            fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
-            fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, color.a);");
+            fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
+            fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, color.a);");
         }
-        fragBuilder->codeAppendf("color = float4(%s(color.r), %s(color.g), %s(color.b), color.a);",
+        fragBuilder->codeAppendf("color = half4(%s(color.r), %s(color.g), %s(color.b), color.a);",
                                     srgbFuncName.c_str(),
                                     srgbFuncName.c_str(),
                                     srgbFuncName.c_str());
         if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
-            fragBuilder->codeAppendf("color = float4(color.rgb, 1) * color.a;");
+            fragBuilder->codeAppendf("color = half4(color.rgb, 1) * color.a;");
         }
         fragBuilder->codeAppendf("%s = color;", args.fOutputColor);
     }
diff --git a/src/gpu/effects/GrShadowGeoProc.cpp b/src/gpu/effects/GrShadowGeoProc.cpp
index 297dd50..ca4c5db 100644
--- a/src/gpu/effects/GrShadowGeoProc.cpp
+++ b/src/gpu/effects/GrShadowGeoProc.cpp
@@ -26,7 +26,7 @@
 
         // emit attributes
         varyingHandler->emitAttributes(rsgp);
-        fragBuilder->codeAppend("float4 shadowParams;");
+        fragBuilder->codeAppend("half4 shadowParams;");
         varyingHandler->addPassThroughAttribute(rsgp.inShadowParams(), "shadowParams");
 
         // setup pass through color
@@ -43,12 +43,12 @@
                              rsgp.inPosition()->fName,
                              args.fFPCoordTransformHandler);
 
-        fragBuilder->codeAppend("float d = length(shadowParams.xy);");
-        fragBuilder->codeAppend("float distance = shadowParams.z * (1.0 - d);");
+        fragBuilder->codeAppend("half d = length(shadowParams.xy);");
+        fragBuilder->codeAppend("half distance = shadowParams.z * (1.0 - d);");
 
-        fragBuilder->codeAppend("float factor = 1.0 - clamp(distance, 0.0, shadowParams.w);");
+        fragBuilder->codeAppend("half factor = 1.0 - clamp(distance, 0.0, shadowParams.w);");
         fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
-        fragBuilder->codeAppendf("%s = float4(factor);",
+        fragBuilder->codeAppendf("%s = half4(factor);",
                                  args.fOutputCoverage);
     }
 
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 3301694..ad2a533 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -26,15 +26,15 @@
         fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get());
         SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
         fragBuilder->codeAppendf(
-                "float4 _tmpVar1;%s = %s * %stexture(%s, %s).%s%s;\n", args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "float4(1)",
+                "half4 _tmpVar1;%s = %s * %stexture(%s, %s).%s%s;\n", args.fOutputColor,
+                args.fInputColor ? args.fInputColor : "half4(1)",
                 fColorSpaceHelper.isValid() ? "(_tmpVar1 = " : "",
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 sk_TransformedCoords2D_0.c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
                 fColorSpaceHelper.isValid()
-                        ? SkStringPrintf(", float4(clamp((%s * float4(_tmpVar1.rgb, 1.0)).rgb, "
-                                         "0.0, _tmpVar1.a), _tmpVar1.a))",
+                        ? SkStringPrintf(", half4(clamp((%s * half4(_tmpVar1.rgb, 1.0)).rgb, 0.0, "
+                                         "_tmpVar1.a), _tmpVar1.a))",
                                          args.fUniformHandler->getUniformCStr(
                                                  fColorSpaceHelper.gamutXformUniform()))
                                   .c_str()
diff --git a/src/gpu/effects/GrSimpleTextureEffect.fp b/src/gpu/effects/GrSimpleTextureEffect.fp
index a4275b5..456448a 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.fp
+++ b/src/gpu/effects/GrSimpleTextureEffect.fp
@@ -7,7 +7,7 @@
 
 in uniform sampler2D image;
 in uniform colorSpaceXform colorXform;
-in float4x4 matrix;
+in half4x4 matrix;
 
 @constructorParams {
     GrSamplerState samplerParams
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 3bb96b2..c297560 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -78,8 +78,7 @@
         if (textureDomain.fIndex >= 0) {
             uniName.appendS32(textureDomain.fIndex);
         }
-        fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                kVec4f_GrSLType, kDefault_GrSLPrecision,
+        fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                 uniName.c_str(), &name);
         fDomainName = name;
     }
@@ -88,7 +87,7 @@
         case kIgnore_Mode: {
             builder->codeAppendf("%s = ", outColor);
             builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
-                                                    kVec2f_GrSLType, colorXformHelper);
+                                                    kHighFloat2_GrSLType, colorXformHelper);
             builder->codeAppend(";");
             break;
         }
@@ -99,7 +98,7 @@
 
             builder->codeAppendf("%s = ", outColor);
             builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
-                                                    kVec2f_GrSLType, colorXformHelper);
+                                                    kHighFloat2_GrSLType, colorXformHelper);
             builder->codeAppend(";");
             break;
         }
@@ -115,20 +114,20 @@
                 // may return undefined results". This appears to be an issue with
                 // the 'any' call since even the simple "result=black; if (any())
                 // result=white;" code fails to compile.
-                builder->codeAppend("float4 outside = float4(0.0, 0.0, 0.0, 0.0);");
-                builder->codeAppend("float4 inside = ");
+                builder->codeAppend("half4 outside = half4(0.0, 0.0, 0.0, 0.0);");
+                builder->codeAppend("half4 inside = ");
                 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
-                                                        kVec2f_GrSLType, colorXformHelper);
+                                                        kHighFloat2_GrSLType, colorXformHelper);
                 builder->codeAppend(";");
 
-                builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str());
-                builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str());
+                builder->codeAppendf("highfloat x = (%s).x;", inCoords.c_str());
+                builder->codeAppendf("highfloat y = (%s).y;", inCoords.c_str());
 
                 builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
                                      domain, domain, domain);
                 builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
                                      domain, domain, domain);
-                builder->codeAppend("float blend = step(1.0, max(x, y));");
+                builder->codeAppend("half blend = step(1.0, max(x, y));");
                 builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
             } else {
                 builder->codeAppend("bool4 outside;\n");
@@ -136,10 +135,10 @@
                                        domain);
                 builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
                                        domain);
-                builder->codeAppendf("%s = any(outside) ? float4(0.0, 0.0, 0.0, 0.0) : ",
+                builder->codeAppendf("%s = any(outside) ? half4(0.0, 0.0, 0.0, 0.0) : ",
                                        outColor);
                 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
-                                                        kVec2f_GrSLType, colorXformHelper);
+                                                        kHighFloat2_GrSLType, colorXformHelper);
                 builder->codeAppend(";");
             }
             break;
@@ -152,7 +151,7 @@
 
             builder->codeAppendf("%s = ", outColor);
             builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
-                                                    kVec2f_GrSLType, colorXformHelper);
+                                                    kHighFloat2_GrSLType, colorXformHelper);
             builder->codeAppend(";");
             break;
         }
@@ -377,11 +376,10 @@
                     args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
             const char* scaleAndTranslateName;
             fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                                     kVec4f_GrSLType,
-                                                                     kDefault_GrSLPrecision,
+                                                                     kHalf4_GrSLType,
                                                                      "scaleAndTranslate",
                                                                      &scaleAndTranslateName);
-            args.fFragBuilder->codeAppendf("float2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
+            args.fFragBuilder->codeAppendf("half2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
                                            scaleAndTranslateName, scaleAndTranslateName);
             fGLDomain.sampleTexture(args.fFragBuilder,
                                     args.fUniformHandler,
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index ec0ef4e..6d1f4b2 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -23,7 +23,7 @@
 
 /**
  * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped
- * the edge of the domain or result in a float4 of zeros (decal mode). The domain is clipped to
+ * the edge of the domain or result in a half4 of zeros (decal mode). The domain is clipped to
  * normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the
  * domain to affect the read value unless the caller considers this when calculating the domain.
  */
@@ -98,7 +98,7 @@
          * Call this from GrGLSLFragmentProcessor::emitCode() to sample the texture W.R.T. the
          * domain and mode.
          *
-         * @param outcolor  name of float4 variable to hold the sampled color.
+         * @param outcolor  name of half4 variable to hold the sampled color.
          * @param inCoords  name of float2 variable containing the coords to be used with the domain.
          *                  It is assumed that this is a variable and not an expression.
          * @param inModulateColor   if non-nullptr the sampled color will be modulated with this
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 3b9b44c..11dee67 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -217,7 +217,7 @@
     const char* inputColor = nullptr;
     if (args.fInputColor) {
         inputColor = "inputColor";
-        fragBuilder->codeAppendf("float4 inputColor = float4(%s.rgb, 1.0);", args.fInputColor);
+        fragBuilder->codeAppendf("half4 inputColor = half4(%s.rgb, 1.0);", args.fInputColor);
     }
 
     // declare outputColor and emit the code for each of the two children
@@ -452,7 +452,7 @@
         const char* inputColor = args.fInputColor;
         // We don't try to optimize for this case at all
         if (!inputColor) {
-            fragBuilder->codeAppendf("const float4 ones = float4(1);");
+            fragBuilder->codeAppendf("const half4 ones = half4(1);");
             inputColor = "ones";
         }
 
diff --git a/src/gpu/effects/GrYUVEffect.cpp b/src/gpu/effects/GrYUVEffect.cpp
index c45e9b2..bf9e94f 100644
--- a/src/gpu/effects/GrYUVEffect.cpp
+++ b/src/gpu/effects/GrYUVEffect.cpp
@@ -89,10 +89,9 @@
             const YUVtoRGBEffect& effect = args.fFp.cast<YUVtoRGBEffect>();
 
             const char* colorSpaceMatrix = nullptr;
-            fMatrixUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                          kMat44f_GrSLType, kDefault_GrSLPrecision,
+            fMatrixUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
                                                           "ColorSpaceMatrix", &colorSpaceMatrix);
-            fragBuilder->codeAppendf("%s = float4(", args.fOutputColor);
+            fragBuilder->codeAppendf("%s = half4(", args.fOutputColor);
             fragBuilder->appendTextureLookup(args.fTexSamplers[0],
                                              args.fTransformedCoords[0].c_str(),
                                              args.fTransformedCoords[0].getType());
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 29df888..3f66819 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3474,13 +3474,13 @@
     }
 
     const char* version = shaderCaps->versionDeclString();
-    GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
-    GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
+    GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
                                GrShaderVar::kUniform_TypeModifier);
-    GrShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
+    GrShaderVar uPosXform("u_posXform", kHalf4_GrSLType, GrShaderVar::kUniform_TypeModifier);
     GrShaderVar uTexture("u_texture", samplerType, GrShaderVar::kUniform_TypeModifier);
-    GrShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier);
-    GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar vTexCoord("v_texCoord", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier);
+    GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
 
     SkString vshaderTxt(version);
     if (shaderCaps->noperspectiveInterpolationSupport()) {
@@ -3504,7 +3504,7 @@
         "void main() {"
         "  v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
         "  gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
-        "  gl_Position.zw = float2(0, 1);"
+        "  gl_Position.zw = half2(0, 1);"
         "}"
     );
 
@@ -3518,8 +3518,6 @@
         fshaderTxt.appendf("#extension %s : require\n",
                            shaderCaps->externalTextureExtensionString());
     }
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
-                                                 &fshaderTxt);
     vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier);
     vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
     fshaderTxt.append(";");
@@ -3583,19 +3581,19 @@
     }
 
     const char* version = shaderCaps->versionDeclString();
-    GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
-    GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
+    GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
                                GrShaderVar::kUniform_TypeModifier);
     GrShaderVar uTexture("u_texture", kTexture2DSampler_GrSLType,
                          GrShaderVar::kUniform_TypeModifier);
     // We need 1, 2, or 4 texture coordinates (depending on parity of each dimension):
     GrShaderVar vTexCoords[] = {
-        GrShaderVar("v_texCoord0", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
-        GrShaderVar("v_texCoord1", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
-        GrShaderVar("v_texCoord2", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
-        GrShaderVar("v_texCoord3", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier),
+        GrShaderVar("v_texCoord0", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
+        GrShaderVar("v_texCoord1", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
+        GrShaderVar("v_texCoord2", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
+        GrShaderVar("v_texCoord3", kHalf2_GrSLType, GrShaderVar::kOut_TypeModifier),
     };
-    GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType,GrShaderVar::kOut_TypeModifier);
+    GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType,GrShaderVar::kOut_TypeModifier);
 
     SkString vshaderTxt(version);
     if (shaderCaps->noperspectiveInterpolationSupport()) {
@@ -3620,27 +3618,27 @@
     vshaderTxt.append(
         "// Mipmap Program VS\n"
         "void main() {"
-        "  gl_Position.xy = a_vertex * float2(2, 2) - float2(1, 1);"
-        "  gl_Position.zw = float2(0, 1);"
+        "  gl_Position.xy = a_vertex * half2(2, 2) - half2(1, 1);"
+        "  gl_Position.zw = half2(0, 1);"
     );
 
     // Insert texture coordinate computation:
     if (oddWidth && oddHeight) {
         vshaderTxt.append(
             "  v_texCoord0 = a_vertex.xy * u_texCoordXform.yw;"
-            "  v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + float2(u_texCoordXform.x, 0);"
-            "  v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + float2(0, u_texCoordXform.z);"
+            "  v_texCoord1 = a_vertex.xy * u_texCoordXform.yw + half2(u_texCoordXform.x, 0);"
+            "  v_texCoord2 = a_vertex.xy * u_texCoordXform.yw + half2(0, u_texCoordXform.z);"
             "  v_texCoord3 = a_vertex.xy * u_texCoordXform.yw + u_texCoordXform.xz;"
         );
     } else if (oddWidth) {
         vshaderTxt.append(
-            "  v_texCoord0 = a_vertex.xy * float2(u_texCoordXform.y, 1);"
-            "  v_texCoord1 = a_vertex.xy * float2(u_texCoordXform.y, 1) + float2(u_texCoordXform.x, 0);"
+            "  v_texCoord0 = a_vertex.xy * half2(u_texCoordXform.y, 1);"
+            "  v_texCoord1 = a_vertex.xy * half2(u_texCoordXform.y, 1) + half2(u_texCoordXform.x, 0);"
         );
     } else if (oddHeight) {
         vshaderTxt.append(
-            "  v_texCoord0 = a_vertex.xy * float2(1, u_texCoordXform.w);"
-            "  v_texCoord1 = a_vertex.xy * float2(1, u_texCoordXform.w) + float2(0, u_texCoordXform.z);"
+            "  v_texCoord0 = a_vertex.xy * half2(1, u_texCoordXform.w);"
+            "  v_texCoord1 = a_vertex.xy * half2(1, u_texCoordXform.w) + half2(0, u_texCoordXform.z);"
         );
     } else {
         vshaderTxt.append(
@@ -3656,8 +3654,6 @@
             fshaderTxt.appendf("#extension %s : require\n", extension);
         }
     }
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
-                                                 &fshaderTxt);
     for (int i = 0; i < numTaps; ++i) {
         vTexCoords[i].setTypeModifier(GrShaderVar::kIn_TypeModifier);
         vTexCoords[i].appendDecl(shaderCaps, &fshaderTxt);
@@ -3743,7 +3739,7 @@
         return false;
     }
 
-    GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
+    GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
     const char* version = this->caps()->shaderCaps()->versionDeclString();
 
     SkString vshaderTxt(version);
@@ -3752,17 +3748,14 @@
     vshaderTxt.append(
             "// Stencil Clip Clear Program VS\n"
             "void main() {"
-            "  gl_Position = float4(a_vertex.x, a_vertex.y, 0, 1);"
+            "  gl_Position = highfloat4(a_vertex.x, a_vertex.y, 0, 1);"
             "}");
 
     SkString fshaderTxt(version);
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision,
-                                                 *this->caps()->shaderCaps(),
-                                                 &fshaderTxt);
     fshaderTxt.appendf(
             "// Stencil Clip Clear Program FS\n"
             "void main() {"
-            "  sk_FragColor = float4(0);"
+            "  sk_FragColor = half4(0);"
             "}");
 
     const char* str;
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index 3414aba..a8e3a63 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -73,7 +73,7 @@
 
 void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kInt_GrSLType);
+    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     if (kUnusedUniform != uni.fLocation) {
         GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fLocation, i));
@@ -84,7 +84,7 @@
                                     int arrayCount,
                                     const int v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kInt_GrSLType);
+    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
     SkASSERT(arrayCount > 0);
     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     if (kUnusedUniform != uni.fLocation) {
@@ -94,7 +94,7 @@
 
 void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kFloat_GrSLType);
+    SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     if (kUnusedUniform != uni.fLocation) {
         GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fLocation, v0));
@@ -105,7 +105,7 @@
                                     int arrayCount,
                                     const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kFloat_GrSLType);
+    SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
     SkASSERT(arrayCount > 0);
     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     // This assert fires in some instances of the two-pt gradient for its VSParams.
@@ -119,7 +119,7 @@
 
 void GrGLProgramDataManager::set2f(UniformHandle u, float v0, float v1) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec2f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     if (kUnusedUniform != uni.fLocation) {
         GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fLocation, v0, v1));
@@ -130,7 +130,7 @@
                                     int arrayCount,
                                     const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec2f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
     SkASSERT(arrayCount > 0);
     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     if (kUnusedUniform != uni.fLocation) {
@@ -140,7 +140,7 @@
 
 void GrGLProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec3f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     if (kUnusedUniform != uni.fLocation) {
         GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fLocation, v0, v1, v2));
@@ -151,7 +151,7 @@
                                     int arrayCount,
                                     const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec3f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
     SkASSERT(arrayCount > 0);
     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     if (kUnusedUniform != uni.fLocation) {
@@ -165,7 +165,7 @@
                                    float v2,
                                    float v3) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec4f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     if (kUnusedUniform != uni.fLocation) {
         GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fLocation, v0, v1, v2, v3));
@@ -176,7 +176,7 @@
                                     int arrayCount,
                                     const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec4f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
     SkASSERT(arrayCount > 0);
     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     if (kUnusedUniform != uni.fLocation) {
@@ -214,7 +214,8 @@
                                                                 int arrayCount,
                                                                 const float matrices[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat22f_GrSLType + (N - 2));
+    SkASSERT(uni.fType == kHighFloat2x2_GrSLType + (N - 2) ||
+             uni.fType == kHalf2x2_GrSLType + (N - 2));
     SkASSERT(arrayCount > 0);
     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     if (kUnusedUniform != uni.fLocation) {
@@ -246,8 +247,10 @@
     SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
     const PathProcVarying& fragmentInput = fPathProcVaryings[u.toIndex()];
 
-    SkASSERT((components == 2 && fragmentInput.fType == kVec2f_GrSLType) ||
-              (components == 3 && fragmentInput.fType == kVec3f_GrSLType));
+    SkASSERT((components == 2 && (fragmentInput.fType == kHighFloat2_GrSLType ||
+                                  fragmentInput.fType == kHalf2_GrSLType)) ||
+              (components == 3 && (fragmentInput.fType == kHighFloat3_GrSLType ||
+                                   fragmentInput.fType == kHalf3_GrSLType)));
 
     fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
                                                                   fragmentInput.fLocation,
diff --git a/src/gpu/gl/GrGLUniformHandler.cpp b/src/gpu/gl/GrGLUniformHandler.cpp
index 4d718a0..914f8bc 100644
--- a/src/gpu/gl/GrGLUniformHandler.cpp
+++ b/src/gpu/gl/GrGLUniformHandler.cpp
@@ -24,7 +24,7 @@
                                                                             const char** outName) {
     SkASSERT(name && strlen(name));
     SkASSERT(0 != visibility);
-    SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
+    SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
 
     UniformInfo& uni = fUniforms.push_back();
     uni.fVariable.setType(type);
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index b7d3120..31d20f0 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -139,6 +139,9 @@
         return nullptr;
     }
 
+    if (fFS.fForceHighPrecision) {
+        settings.fForceHighPrecision = true;
+    }
     if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete,
                                        settings, &inputs)) {
         this->cleanupProgram(programID, shadersToDelete);
diff --git a/src/gpu/glsl/GrGLSL.cpp b/src/gpu/glsl/GrGLSL.cpp
index 6fe1e26..db8b7d6 100644
--- a/src/gpu/glsl/GrGLSL.cpp
+++ b/src/gpu/glsl/GrGLSL.cpp
@@ -30,33 +30,47 @@
     switch (t) {
         case kVoid_GrSLType:
             return "void";
-        case kFloat_GrSLType:
-            return "float";
-        case kVec2f_GrSLType:
-            return "float2";
-        case kVec3f_GrSLType:
-            return "float3";
-        case kVec4f_GrSLType:
-            return "float4";
-        case kVec2us_GrSLType:
+        case kHalf_GrSLType:
+            return "half";
+        case kHalf2_GrSLType:
+            return "half2";
+        case kHalf3_GrSLType:
+            return "half3";
+        case kHalf4_GrSLType:
+            return "half4";
+        case kHighFloat_GrSLType:
+            return "highfloat";
+        case kHighFloat2_GrSLType:
+            return "highfloat2";
+        case kHighFloat3_GrSLType:
+            return "highfloat3";
+        case kHighFloat4_GrSLType:
+            return "highfloat4";
+        case kUint2_GrSLType:
             if (shaderCaps->integerSupport()) {
                 return "uint2";
             } else {
                 // uint2 (aka uvec2) isn't supported in GLSL ES 1.00/GLSL 1.20
-                return "float2";
+                return "highfloat2";
             }
-        case kVec2i_GrSLType:
+        case kInt2_GrSLType:
             return "int2";
-        case kVec3i_GrSLType:
+        case kInt3_GrSLType:
             return "int3";
-        case kVec4i_GrSLType:
+        case kInt4_GrSLType:
             return "int4";
-        case kMat22f_GrSLType:
-            return "float2x2";
-        case kMat33f_GrSLType:
-            return "float3x3";
-        case kMat44f_GrSLType:
-            return "float4x4";
+        case kHighFloat2x2_GrSLType:
+            return "highfloat2x2";
+        case kHighFloat3x3_GrSLType:
+            return "highfloat3x3";
+        case kHighFloat4x4_GrSLType:
+            return "highfloat4x4";
+        case kHalf2x2_GrSLType:
+            return "half2x2";
+        case kHalf3x3_GrSLType:
+            return "half3x3";
+        case kHalf4x4_GrSLType:
+            return "half4x4";
         case kTexture2DSampler_GrSLType:
             return "sampler2D";
         case kITexture2DSampler_GrSLType:
@@ -73,6 +87,10 @@
             return "int";
         case kUint_GrSLType:
             return "uint";
+        case kShort_GrSLType:
+            return "short";
+        case kUShort_GrSLType:
+            return "ushort";
         case kTexture2D_GrSLType:
             return "texture2D";
         case kSampler_GrSLType:
diff --git a/src/gpu/glsl/GrGLSLBlend.cpp b/src/gpu/glsl/GrGLSLBlend.cpp
index 34df0df..254f481 100644
--- a/src/gpu/glsl/GrGLSLBlend.cpp
+++ b/src/gpu/glsl/GrGLSLBlend.cpp
@@ -50,7 +50,7 @@
     fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
                            final, component, src, component, dst);
     fsBuilder->codeAppend("} else {");
-    fsBuilder->codeAppendf("float d = %s.a - %s.%c;", src, src, component);
+    fsBuilder->codeAppendf("half d = %s.a - %s.%c;", src, src, component);
     fsBuilder->codeAppend("if (0.0 == d) {");
     fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
                            final, component, src, dst, src, component, dst, dst, component,
@@ -84,7 +84,7 @@
     fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
                            final, component, dst, component, src);
     fsBuilder->codeAppend("} else {");
-    fsBuilder->codeAppendf("float d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / (%s.%c %s));",
+    fsBuilder->codeAppendf("half d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / (%s.%c %s));",
                            dst, dst, dst, component, src, src, component, divisorGuard);
     fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
                            final, component, src, src, component, dst, dst, component, src);
@@ -114,11 +114,11 @@
     // else if (4D < Da)
     fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {",
                            dst, component, dst);
-    fsBuilder->codeAppendf("float DSqd = %s.%c * %s.%c;",
+    fsBuilder->codeAppendf("half DSqd = %s.%c * %s.%c;",
                            dst, component, dst, component);
-    fsBuilder->codeAppendf("float DCub = DSqd * %s.%c;", dst, component);
-    fsBuilder->codeAppendf("float DaSqd = %s.a * %s.a;", dst, dst);
-    fsBuilder->codeAppendf("float DaCub = DaSqd * %s.a;", dst);
+    fsBuilder->codeAppendf("half DCub = DSqd * %s.%c;", dst, component);
+    fsBuilder->codeAppendf("half DaSqd = %s.a * %s.a;", dst, dst);
+    fsBuilder->codeAppendf("half DaCub = DaSqd * %s.a;", dst);
     // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2
     fsBuilder->codeAppendf("%s.%c ="
                            "(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) +"
@@ -144,10 +144,10 @@
     // Emit a helper that gets the luminance of a color.
     SkString getFunction;
     GrShaderVar getLumArgs[] = {
-        GrShaderVar("color", kVec3f_GrSLType),
+        GrShaderVar("color", kHalf3_GrSLType),
     };
-    SkString getLumBody("return dot(float3(0.3, 0.59, 0.11), color);");
-    fsBuilder->emitFunction(kFloat_GrSLType,
+    SkString getLumBody("return dot(highfloat3(0.3, 0.59, 0.11), color);");
+    fsBuilder->emitFunction(kHalf_GrSLType,
                             "luminance",
                             SK_ARRAY_COUNT(getLumArgs), getLumArgs,
                             getLumBody.c_str(),
@@ -155,27 +155,27 @@
 
     // Emit the set luminance function.
     GrShaderVar setLumArgs[] = {
-        GrShaderVar("hueSat", kVec3f_GrSLType),
-        GrShaderVar("alpha", kFloat_GrSLType),
-        GrShaderVar("lumColor", kVec3f_GrSLType),
+        GrShaderVar("hueSat", kHalf3_GrSLType),
+        GrShaderVar("alpha", kHalf_GrSLType),
+        GrShaderVar("lumColor", kHalf3_GrSLType),
     };
     SkString setLumBody;
-    setLumBody.printf("float diff = %s(lumColor - hueSat);", getFunction.c_str());
-    setLumBody.append("float3 outColor = hueSat + diff;");
-    setLumBody.appendf("float outLum = %s(outColor);", getFunction.c_str());
-    setLumBody.append("float minComp = min(min(outColor.r, outColor.g), outColor.b);"
-                      "float maxComp = max(max(outColor.r, outColor.g), outColor.b);"
+    setLumBody.printf("half diff = %s(lumColor - hueSat);", getFunction.c_str());
+    setLumBody.append("half3 outColor = hueSat + diff;");
+    setLumBody.appendf("half outLum = %s(outColor);", getFunction.c_str());
+    setLumBody.append("half minComp = min(min(outColor.r, outColor.g), outColor.b);"
+                      "half maxComp = max(max(outColor.r, outColor.g), outColor.b);"
                       "if (minComp < 0.0 && outLum != minComp) {"
-                      "outColor = outLum + ((outColor - float3(outLum, outLum, outLum)) * outLum) /"
+                      "outColor = outLum + ((outColor - half3(outLum, outLum, outLum)) * outLum) /"
                       "(outLum - minComp);"
                       "}"
                       "if (maxComp > alpha && maxComp != outLum) {"
                       "outColor = outLum +"
-                      "((outColor - float3(outLum, outLum, outLum)) * (alpha - outLum)) /"
+                      "((outColor - half3(outLum, outLum, outLum)) * (alpha - outLum)) /"
                       "(maxComp - outLum);"
                       "}"
                       "return outColor;");
-    fsBuilder->emitFunction(kVec3f_GrSLType,
+    fsBuilder->emitFunction(kHalf3_GrSLType,
                             "set_luminance",
                             SK_ARRAY_COUNT(setLumArgs), setLumArgs,
                             setLumBody.c_str(),
@@ -188,11 +188,11 @@
 static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatFunction) {
     // Emit a helper that gets the saturation of a color
     SkString getFunction;
-    GrShaderVar getSatArgs[] = { GrShaderVar("color", kVec3f_GrSLType) };
+    GrShaderVar getSatArgs[] = { GrShaderVar("color", kHalf3_GrSLType) };
     SkString getSatBody;
     getSatBody.printf("return max(max(color.r, color.g), color.b) - "
                       "min(min(color.r, color.g), color.b);");
-    fsBuilder->emitFunction(kFloat_GrSLType,
+    fsBuilder->emitFunction(kHalf_GrSLType,
                             "saturation",
                             SK_ARRAY_COUNT(getSatArgs), getSatArgs,
                             getSatBody.c_str(),
@@ -204,33 +204,33 @@
     // adjusted min, mid, and max inputs, respectively.
     SkString helperFunction;
     GrShaderVar helperArgs[] = {
-        GrShaderVar("minComp", kFloat_GrSLType),
-        GrShaderVar("midComp", kFloat_GrSLType),
-        GrShaderVar("maxComp", kFloat_GrSLType),
-        GrShaderVar("sat", kFloat_GrSLType),
+        GrShaderVar("minComp", kHalf_GrSLType),
+        GrShaderVar("midComp", kHalf_GrSLType),
+        GrShaderVar("maxComp", kHalf_GrSLType),
+        GrShaderVar("sat", kHalf_GrSLType),
     };
     static const char kHelperBody[] = "if (minComp < maxComp) {"
-        "float3 result;"
+        "half3 result;"
         "result.r = 0.0;"
         "result.g = sat * (midComp - minComp) / (maxComp - minComp);"
         "result.b = sat;"
         "return result;"
         "} else {"
-        "return float3(0, 0, 0);"
+        "return half3(0, 0, 0);"
         "}";
-    fsBuilder->emitFunction(kVec3f_GrSLType,
+    fsBuilder->emitFunction(kHalf3_GrSLType,
                             "set_saturation_helper",
                             SK_ARRAY_COUNT(helperArgs), helperArgs,
                             kHelperBody,
                             &helperFunction);
 
     GrShaderVar setSatArgs[] = {
-        GrShaderVar("hueLumColor", kVec3f_GrSLType),
-        GrShaderVar("satColor", kVec3f_GrSLType),
+        GrShaderVar("hueLumColor", kHalf3_GrSLType),
+        GrShaderVar("satColor", kHalf3_GrSLType),
     };
     const char* helpFunc = helperFunction.c_str();
     SkString setSatBody;
-    setSatBody.appendf("float sat = %s(satColor);"
+    setSatBody.appendf("half sat = %s(satColor);"
                        "if (hueLumColor.r <= hueLumColor.g) {"
                        "if (hueLumColor.g <= hueLumColor.b) {"
                        "hueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);"
@@ -249,7 +249,7 @@
                        "return hueLumColor;",
                        getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
                        helpFunc, helpFunc);
-    fsBuilder->emitFunction(kVec3f_GrSLType,
+    fsBuilder->emitFunction(kHalf3_GrSLType,
                             "set_saturation",
                             SK_ARRAY_COUNT(setSatArgs), setSatArgs,
                             setSatBody.c_str(),
@@ -330,7 +330,7 @@
             SkString setSat, setLum;
             add_sat_function(fsBuilder, &setSat);
             add_lum_function(fsBuilder, &setLum);
-            fsBuilder->codeAppendf("float4 dstSrcAlpha = %s * %s.a;",
+            fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
                                    dstColor, srcColor);
             fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb),"
                                    "dstSrcAlpha.a, dstSrcAlpha.rgb);",
@@ -345,7 +345,7 @@
             SkString setSat, setLum;
             add_sat_function(fsBuilder, &setSat);
             add_lum_function(fsBuilder, &setLum);
-            fsBuilder->codeAppendf("float4 dstSrcAlpha = %s * %s.a;",
+            fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
                                    dstColor, srcColor);
             fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a),"
                                    "dstSrcAlpha.a, dstSrcAlpha.rgb);",
@@ -359,7 +359,7 @@
             //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
             SkString setLum;
             add_lum_function(fsBuilder, &setLum);
-            fsBuilder->codeAppendf("float4 srcDstAlpha = %s * %s.a;",
+            fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
                                    srcColor, dstColor);
             fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);",
                                    outputColor, setLum.c_str(), dstColor, srcColor);
@@ -371,7 +371,7 @@
             //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
             SkString setLum;
             add_lum_function(fsBuilder, &setLum);
-            fsBuilder->codeAppendf("float4 srcDstAlpha = %s * %s.a;",
+            fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
                                    srcColor, dstColor);
             fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);",
                                    outputColor, setLum.c_str(), dstColor, srcColor);
@@ -406,13 +406,13 @@
                 fsBuilder->codeAppendf(" * %s", srcColorName);
                 break;
             case SkBlendModeCoeff::kISC:
-                fsBuilder->codeAppendf(" * (float4(1.0) - %s)", srcColorName);
+                fsBuilder->codeAppendf(" * (half4(1.0) - %s)", srcColorName);
                 break;
             case SkBlendModeCoeff::kDC:
                 fsBuilder->codeAppendf(" * %s", dstColorName);
                 break;
             case SkBlendModeCoeff::kIDC:
-                fsBuilder->codeAppendf(" * (float4(1.0) - %s)", dstColorName);
+                fsBuilder->codeAppendf(" * (half4(1.0) - %s)", dstColorName);
                 break;
             case SkBlendModeCoeff::kSA:
                 fsBuilder->codeAppendf(" * %s.a", srcColorName);
@@ -453,7 +453,7 @@
                                                 false);
         // append dst blend
         if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
-            fsBuilder->codeAppend("float4(0, 0, 0, 0)");
+            fsBuilder->codeAppend("half4(0, 0, 0, 0)");
         }
         if (clamp) {
             fsBuilder->codeAppend(", 0, 1);");
@@ -505,7 +505,7 @@
                                             false);
     // append dst blend
     if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
-        fsBuilder->codeAppend("float4(0, 0, 0, 0)");
+        fsBuilder->codeAppend("half4(0, 0, 0, 0)");
     }
     fsBuilder->codeAppend(";");
 }
diff --git a/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h b/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h
index b4605ba..f9ac30b 100644
--- a/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h
+++ b/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h
@@ -24,8 +24,8 @@
                   uint32_t visibility = kFragment_GrShaderFlag) {
         SkASSERT(uniformHandler);
         if (colorSpaceXform) {
-            fGamutXformVar = uniformHandler->addUniform(visibility, kMat44f_GrSLType,
-                                                        kDefault_GrSLPrecision, "ColorXform");
+            fGamutXformVar = uniformHandler->addUniform(visibility, kHalf4x4_GrSLType,
+                                                        "ColorXform");
             fValid = true;
         }
     }
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index 6f75c16..ac2de13 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -29,7 +29,7 @@
     SkASSERT(outputColor);
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     outputColor->append(fragBuilder->getMangleString());
-    fragBuilder->codeAppendf("float4 %s;", outputColor->c_str());
+    fragBuilder->codeAppendf("half4 %s;", outputColor->c_str());
     this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args);
 }
 
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h
index ed4b71f..68bd1f2 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h
@@ -86,9 +86,9 @@
         @param fp                The processor that generated this program stage.
         @param key               The key that was computed by GenKey() from the generating
                                  GrProcessor.
-        @param outputColor       A predefined float4 in the FS in which the stage should place its
+        @param outputColor       A predefined half4 in the FS in which the stage should place its
                                  output color (or coverage).
-        @param inputColor        A float4 that holds the input color to the stage in the FS. This may
+        @param inputColor        A half4 that holds the input color to the stage in the FS. This may
                                  be nullptr in which case the implied input is solid white (all
                                  ones). TODO: Better system for communicating optimization info
                                  (e.g. input color is solid white, trans black, known to be opaque,
@@ -152,7 +152,7 @@
     }
 
     inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
-        this->emitChild(childIndex, "float4(1.0)", outputColor, parentArgs);
+        this->emitChild(childIndex, "half4(1.0)", outputColor, parentArgs);
     }
 
     /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and
@@ -167,7 +167,7 @@
                    EmitArgs& parentArgs);
 
     inline void emitChild(int childIndex, EmitArgs& args) {
-        this->emitChild(childIndex, "float4(1.0)", args);
+        this->emitChild(childIndex, "half4(1.0)", args);
     }
 
     /** Variation that uses the parent's output color variable to hold the child's output.*/
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index 7e6b8f7..ad39497 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -86,7 +86,7 @@
     , fHasSecondaryOutput(false)
     , fUsedSampleOffsetArrays(0)
     , fHasInitializedSampleMask(false)
-    , fDefaultPrecision(kMedium_GrSLPrecision) {
+    , fForceHighPrecision(false) {
     fSubstageIndices.push_back(0);
 #ifdef SK_DEBUG
     fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
@@ -112,14 +112,14 @@
 }
 
 SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
-    if (kVec3f_GrSLType != coords.getType()) {
-        SkASSERT(kVec2f_GrSLType == coords.getType());
+    if (kHighFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
+        SkASSERT(kHighFloat2_GrSLType == coords.getType() || kHalf2_GrSLType == coords.getType());
         return coords.getName();
     }
 
     SkString coords2D;
     coords2D.printf("%s_ensure2D", coords.c_str());
-    this->codeAppendf("\tfloat2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(),
+    this->codeAppendf("\thighfloat2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(),
                       coords.c_str());
     return coords2D;
 }
@@ -175,10 +175,6 @@
     fHasInitializedSampleMask = true;
 }
 
-void GrGLSLFragmentShaderBuilder::elevateDefaultPrecision(GrSLPrecision precision) {
-    fDefaultPrecision = SkTMax(fDefaultPrecision, precision);
-}
-
 const char* GrGLSLFragmentShaderBuilder::dstColor() {
     SkDEBUGCODE(fHasReadDstColor = true;)
 
@@ -199,7 +195,7 @@
             fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
             fbFetchColorName = DeclaredColorOutputName();
             // Set the dstColor to an intermediate variable so we don't override it with the output
-            this->codeAppendf("float4 %s = %s;", kDstColorName, fbFetchColorName);
+            this->codeAppendf("half4 %s = %s;", kDstColorName, fbFetchColorName);
         } else {
             return fbFetchColorName;
         }
@@ -228,7 +224,7 @@
     if (!fHasCustomColorOutput) {
         fHasCustomColorOutput = true;
         fCustomColorOutputIndex = fOutputs.count();
-        fOutputs.push_back().set(kVec4f_GrSLType, DeclaredColorOutputName(),
+        fOutputs.push_back().set(kHalf4_GrSLType, DeclaredColorOutputName(),
                                  GrShaderVar::kOut_TypeModifier);
         fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back()); 
     }
@@ -247,7 +243,7 @@
     // output. The condition also co-incides with the condition in whici GLES SL 2.0
     // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
     if (caps.mustDeclareFragmentShaderOutput()) {
-        fOutputs.push_back().set(kVec4f_GrSLType, DeclaredSecondaryColorOutputName(),
+        fOutputs.push_back().set(kHalf4_GrSLType, DeclaredSecondaryColorOutputName(),
                                  GrShaderVar::kOut_TypeModifier);
         fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back());
     }
@@ -280,9 +276,6 @@
 
 void GrGLSLFragmentShaderBuilder::onFinalize() {
     fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(fDefaultPrecision,
-                                                 *fProgramBuilder->shaderCaps(),
-                                                 &this->precisionQualifier());
     if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
         this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
                                       SkMatrix::MakeTrans(-0.5f, -0.5f));
@@ -305,9 +298,9 @@
     SkSTArray<16, SkPoint, true> offsets;
     offsets.push_back_n(specs.fEffectiveSampleCnt);
     m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt);
-    this->definitions().appendf("const highp float2 %s[] = float2[](", name);
+    this->definitions().appendf("const highfloat2 %s[] = highfloat2[](", name);
     for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
-        this->definitions().appendf("float2(%f, %f)", offsets[i].x(), offsets[i].y());
+        this->definitions().appendf("highfloat2(%f, %f)", offsets[i].x(), offsets[i].y());
         this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
     }
 }
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index 73fe51f..f124a44 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -40,7 +40,7 @@
 
     /**
      * This returns a variable name to access the 2D, perspective correct version of the coords in
-     * the fragment shader. The passed in coordinates must either be of type kVec2f or kVec3f. If
+     * the fragment shader. The passed in coordinates must either be of type kHalf2 or kHalf3. If
      * the coordinates are 3-dimensional, it a perspective divide into is emitted into the
      * fragment shader (xy / z) to convert them to 2D.
      */
@@ -90,13 +90,6 @@
     virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0;
 
     /**
-     * Overrides the default precision for the entire fragment program. Processors that require
-     * high precision input (eg from incoming texture samples) may use this. For calculations that
-     * are limited to a single processor's code, it is better to annotate individual declarations.
-     */
-    virtual void elevateDefaultPrecision(GrSLPrecision) = 0;
-
-    /**
      * Fragment procs with child procs should call these functions before/after calling emitCode
      * on a child proc.
      */
@@ -104,6 +97,8 @@
     virtual void onAfterChildProcEmitCode() = 0;
 
     virtual const SkString& getMangleString() const = 0;
+
+    virtual void forceHighPrecision() = 0;
 };
 
 /*
@@ -169,10 +164,10 @@
     void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
     void maskSampleCoverage(const char* mask, bool invert = false) override;
     void overrideSampleCoverage(const char* mask) override;
-    void elevateDefaultPrecision(GrSLPrecision) override;
     const SkString& getMangleString() const override { return fMangleString; }
     void onBeforeChildProcEmitCode() override;
     void onAfterChildProcEmitCode() override;
+    void forceHighPrecision() override { fForceHighPrecision = true; }
 
     // GrGLSLXPFragmentBuilder interface.
     bool hasCustomColorOutput() const override { return fHasCustomColorOutput; }
@@ -234,7 +229,7 @@
     bool          fHasSecondaryOutput;
     uint8_t       fUsedSampleOffsetArrays;
     bool          fHasInitializedSampleMask;
-    GrSLPrecision fDefaultPrecision;
+    bool          fForceHighPrecision;
 
 #ifdef SK_DEBUG
     // some state to verify shaders and effects are consistent, this is reset between effects by
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index a390036..072d62c 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -18,7 +18,8 @@
     GrGPArgs gpArgs;
     this->onEmitCode(args, &gpArgs);
     vBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar, args.fRTAdjustName);
-    if (kVec2f_GrSLType == gpArgs.fPositionVar.getType()) {
+    if (kHighFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
+        kHalf2_GrSLType == gpArgs.fPositionVar.getType()) {
         args.fVaryingHandler->setNoPerspective();
     }
 }
@@ -39,32 +40,28 @@
         uint32_t type = coordTransform->getMatrix().getType();
         type |= localMatrix.getType();
 
-        varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
-                                                                     kVec2f_GrSLType;
-        // Coord transforms are always handled at high precision
-        const GrSLPrecision precision = kHigh_GrSLPrecision;
-
+        varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kHighFloat3_GrSLType :
+                                                                     kHighFloat2_GrSLType;
         const char* uniName;
 
 
         fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag,
-                                                                              kMat33f_GrSLType,
-                                                                              precision,
+                                                                              kHighFloat3x3_GrSLType,
                                                                               strUniName.c_str(),
                                                                               &uniName).toIndex();
         SkString strVaryingName;
         strVaryingName.printf("TransformedCoords_%d", i);
 
         GrGLSLVertToFrag v(varyingType);
-        varyingHandler->addVarying(strVaryingName.c_str(), &v, precision);
+        varyingHandler->addVarying(strVaryingName.c_str(), &v, kHigh_GrSLPrecision);
 
-        SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
+        SkASSERT(kHighFloat2_GrSLType == varyingType || kHighFloat3_GrSLType == varyingType);
         handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
 
-        if (kVec2f_GrSLType == varyingType) {
-            vb->codeAppendf("%s = (%s * float3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
+        if (kHighFloat2_GrSLType == varyingType) {
+            vb->codeAppendf("%s = (%s * highfloat3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
         } else {
-            vb->codeAppendf("%s = %s * float3(%s, 1);", v.vsOut(), uniName, localCoords);
+            vb->codeAppendf("%s = %s * highfloat3(%s, 1);", v.vsOut(), uniName, localCoords);
         }
         ++i;
     }
@@ -88,8 +85,8 @@
 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
                                                   GrGPArgs* gpArgs,
                                                   const char* posName) {
-    gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
-    vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
+    gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
+    vertBuilder->codeAppendf("highfloat2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
 }
 
 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
@@ -99,21 +96,21 @@
                                                   const SkMatrix& mat,
                                                   UniformHandle* viewMatrixUniform) {
     if (mat.isIdentity()) {
-        gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
-        vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
+        gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
+        vertBuilder->codeAppendf("highfloat2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
     } else {
         const char* viewMatrixName;
         *viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
-                                                        kMat33f_GrSLType, kHigh_GrSLPrecision,
+                                                        kHighFloat3x3_GrSLType,
                                                         "uViewM",
                                                         &viewMatrixName);
         if (!mat.hasPerspective()) {
-            gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
-            vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;",
+            gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "pos2");
+            vertBuilder->codeAppendf("highfloat2 %s = (%s * highfloat3(%s, 1)).xy;",
                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
         } else {
-            gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
-            vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);",
+            gpArgs->fPositionVar.set(kHighFloat3_GrSLType, "pos3");
+            vertBuilder->codeAppendf("highfloat3 %s = %s * highfloat3(%s, 1);",
                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
         }
     }
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
index d9d17e5..0cb7e4d 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
@@ -43,13 +43,12 @@
     SkASSERT(colorUniform);
     const char* stagedLocalVarName;
     *colorUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                               kVec4f_GrSLType,
-                                               kDefault_GrSLPrecision,
+                                               kHalf4_GrSLType,
                                                "Color",
                                                &stagedLocalVarName);
     fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
     if (fragBuilder->getProgramBuilder()->shaderCaps()->mustObfuscateUniformColor()) {
-        fragBuilder->codeAppendf("%s = max(%s, float4(0, 0, 0, 0));", outputName, outputName);
+        fragBuilder->codeAppendf("%s = max(%s, half4(0, 0, 0, 0));", outputName, outputName);
     }
 }
 
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index bb3dc4f..c2a0d64 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -82,8 +82,7 @@
         rtAdjustVisibility |= kGeometry_GrShaderFlag;
     }
     fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility,
-                                                                          kVec4f_GrSLType,
-                                                                          kHigh_GrSLPrecision,
+                                                                          kHighFloat4_GrSLType,
                                                                           "rtAdjustment");
     const char* rtAdjustName =
         this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);
@@ -455,7 +454,7 @@
     } else {
         this->nameVariable(&outName, '\0', baseName);
     }
-    fFS.codeAppendf("float4 %s;", outName.c_str());
+    fFS.codeAppendf("half4 %s;", outName.c_str());
     *output = outName;
 }
 
@@ -468,7 +467,7 @@
         GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
         fUniformHandles.fRTHeightUni =
             uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
-                                                    kFloat_GrSLType, kDefault_GrSLPrecision,
+                                                    kHalf_GrSLType, kDefault_GrSLPrecision,
                                                     name, false, 0, nullptr);
 }
 
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index 4d54c75..f87194e 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -122,16 +122,16 @@
     // re-insert the original alpha. The supplied srcColor is likely to be of the form
     // "texture(...)", and we don't want to evaluate that twice, so wrap everything in a function.
     static const GrShaderVar gColorGamutXformArgs[] = {
-        GrShaderVar("color", kVec4f_GrSLType),
-        GrShaderVar("xform", kMat44f_GrSLType),
+        GrShaderVar("color", kHalf4_GrSLType),
+        GrShaderVar("xform", kHalf4x4_GrSLType),
     };
     SkString functionBody;
     // Gamut xform, clamp to destination gamut. We only support/have premultiplied textures, so we
     // always just clamp to alpha.
-    functionBody.append("\tcolor.rgb = clamp((xform * float4(color.rgb, 1.0)).rgb, 0.0, color.a);\n");
+    functionBody.append("\tcolor.rgb = clamp((xform * half4(color.rgb, 1.0)).rgb, 0.0, color.a);\n");
     functionBody.append("\treturn color;");
     SkString colorGamutXformFuncName;
-    this->emitFunction(kVec4f_GrSLType,
+    this->emitFunction(kHalf4_GrSLType,
                        "colorGamutXform",
                        SK_ARRAY_COUNT(gColorGamutXformArgs),
                        gColorGamutXformArgs,
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index 4906c03..9ac6ab7 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -37,23 +37,23 @@
     void appendTextureLookup(SkString* out,
                              SamplerHandle,
                              const char* coordName,
-                             GrSLType coordType = kVec2f_GrSLType) const;
+                             GrSLType coordType = kHalf2_GrSLType) const;
 
     /** Version of above that appends the result to the shader code instead.*/
     void appendTextureLookup(SamplerHandle,
                              const char* coordName,
-                             GrSLType coordType = kVec2f_GrSLType,
+                             GrSLType coordType = kHalf2_GrSLType,
                              GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
 
 
     /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
-        always a float4. modulation and the swizzle specified by SamplerHandle must both be
-        float4 or float. If modulation is "" or nullptr it this function acts as though
+        always a half4. modulation and the swizzle specified by SamplerHandle must both be
+        half4 or half. If modulation is "" or nullptr it this function acts as though
         appendTextureLookup were called. */
     void appendTextureLookupAndModulate(const char* modulation,
                                         SamplerHandle,
                                         const char* coordName,
-                                        GrSLType coordType = kVec2f_GrSLType,
+                                        GrSLType coordType = kHalf2_GrSLType,
                                         GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
 
     /** Adds a helper function to facilitate color gamut transformation, and produces code that
diff --git a/src/gpu/glsl/GrGLSLUniformHandler.h b/src/gpu/glsl/GrGLSLUniformHandler.h
index cf80c3f..84bbfa1 100644
--- a/src/gpu/glsl/GrGLSLUniformHandler.h
+++ b/src/gpu/glsl/GrGLSLUniformHandler.h
@@ -38,6 +38,13 @@
         return this->addUniformArray(visibility, type, precision, name, 0, outName);
     }
 
+    UniformHandle addUniform(uint32_t visibility,
+                             GrSLType type,
+                             const char* name,
+                             const char** outName = nullptr) {
+        return this->addUniform(visibility, type, kDefault_GrSLPrecision, name, outName);
+    }
+
     UniformHandle addUniformArray(uint32_t visibility,
                                   GrSLType type,
                                   GrSLPrecision precision,
@@ -49,6 +56,16 @@
                                              outName);
     }
 
+    UniformHandle addUniformArray(uint32_t visibility,
+                                  GrSLType type,
+                                  const char* name,
+                                  int arrayCount,
+                                  const char** outName = nullptr) {
+        SkASSERT(!GrSLTypeIsCombinedSamplerType(type));
+        return this->internalAddUniformArray(visibility, type, kDefault_GrSLPrecision, name, true,
+                                             arrayCount, outName);
+    }
+
     virtual const GrShaderVar& getUniformVariable(UniformHandle u) const = 0;
 
     /**
diff --git a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp b/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
index e06ee2d..4e3b644 100644
--- a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
@@ -18,25 +18,25 @@
                                                            const char* rtAdjustName) {
     // setup RT Uniform
     if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
-        if (kVec3f_GrSLType == posVar.getType()) {
+        if (kHighFloat3_GrSLType == posVar.getType()) {
             const char* p = posVar.c_str();
-            this->codeAppendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
+            this->codeAppendf("{highfloat2 _posTmp = highfloat2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
         } else {
-            SkASSERT(kVec2f_GrSLType == posVar.getType());
-            this->codeAppendf("{float2 _posTmp = %s;", posVar.c_str());
+            SkASSERT(kHighFloat2_GrSLType == posVar.getType());
+            this->codeAppendf("{highfloat2 _posTmp = %s;", posVar.c_str());
         }
-        this->codeAppendf("_posTmp = floor(_posTmp) + float2(0.5, 0.5);"
-                          "gl_Position = float4(_posTmp.x * %s.x + %s.y,"
+        this->codeAppendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
+                          "gl_Position = highfloat4(_posTmp.x * %s.x + %s.y,"
                                                "_posTmp.y * %s.z + %s.w, 0, 1);}",
                           rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName);
-    } else if (kVec3f_GrSLType == posVar.getType()) {
-        this->codeAppendf("gl_Position = float4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
+    } else if (kHighFloat3_GrSLType == posVar.getType()) {
+        this->codeAppendf("gl_Position = highfloat4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
                           posVar.c_str(), rtAdjustName,
                           posVar.c_str(), rtAdjustName,
                           posVar.c_str());
     } else {
-        SkASSERT(kVec2f_GrSLType == posVar.getType());
-        this->codeAppendf("gl_Position = float4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
+        SkASSERT(kHighFloat2_GrSLType == posVar.getType());
+        this->codeAppendf("gl_Position = highfloat4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
                           posVar.c_str(), rtAdjustName, rtAdjustName,
                           posVar.c_str(), rtAdjustName, rtAdjustName);
     }
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.cpp b/src/gpu/glsl/GrGLSLXferProcessor.cpp
index 6c2c460..99862e2 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLXferProcessor.cpp
@@ -52,7 +52,7 @@
             // The discard here also helps for batching text draws together which need to read from
             // a dst copy for blends. Though this only helps the case where the outer bounding boxes
             // of each letter overlap and not two actually parts of the text.
-            fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, float3(0)))) {"
+            fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, half3(0)))) {"
                                      "    discard;"
                                      "}", args.fInputCoverage);
         }
@@ -61,27 +61,25 @@
         const char* dstCoordScaleName;
 
         fDstTopLeftUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kVec2f_GrSLType,
-                                                    kDefault_GrSLPrecision,
+                                                    kHalf2_GrSLType,
                                                     "DstTextureUpperLeft",
                                                     &dstTopLeftName);
         fDstScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                  kVec2f_GrSLType,
-                                                  kDefault_GrSLPrecision,
+                                                  kHalf2_GrSLType,
                                                   "DstTextureCoordScale",
                                                   &dstCoordScaleName);
 
         fragBuilder->codeAppend("// Read color from copy of the destination.\n");
-        fragBuilder->codeAppendf("float2 _dstTexCoord = (sk_FragCoord.xy - %s) * %s;",
+        fragBuilder->codeAppendf("half2 _dstTexCoord = (sk_FragCoord.xy - %s) * %s;",
                                  dstTopLeftName, dstCoordScaleName);
 
         if (flipY) {
             fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
         }
 
-        fragBuilder->codeAppendf("float4 %s = ", dstColor);
+        fragBuilder->codeAppendf("half4 %s = ", dstColor);
         fragBuilder->appendTextureLookup(args.fDstTextureSamplerHandle, "_dstTexCoord",
-                                         kVec2f_GrSLType);
+                                         kHalf2_GrSLType);
         fragBuilder->codeAppend(";");
     } else {
         needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch();
@@ -91,7 +89,7 @@
     if (!needsLocalOutColor) {
         outColor = args.fOutputPrimary;
     } else {
-        fragBuilder->codeAppendf("float4 %s;", outColor);
+        fragBuilder->codeAppendf("half4 %s;", outColor);
     }
 
     this->emitBlendCodeForDstRead(fragBuilder,
@@ -139,18 +137,18 @@
             fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
             fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
         } else {
-            fragBuilder->codeAppendf("%s = float4(1.0);", outColorSecondary);
+            fragBuilder->codeAppendf("%s = half4(1.0);", outColorSecondary);
         }
     } else if (srcCoverage) {
         if (proc.isLCD()) {
-            fragBuilder->codeAppendf("float lerpRed = mix(%s.a, %s.a, %s.r);",
+            fragBuilder->codeAppendf("half lerpRed = mix(%s.a, %s.a, %s.r);",
                                      dstColor, outColor, srcCoverage);
-            fragBuilder->codeAppendf("float lerpBlue = mix(%s.a, %s.a, %s.g);",
+            fragBuilder->codeAppendf("half lerpBlue = mix(%s.a, %s.a, %s.g);",
                                      dstColor, outColor, srcCoverage);
-            fragBuilder->codeAppendf("float lerpGreen = mix(%s.a, %s.a, %s.b);",
+            fragBuilder->codeAppendf("half lerpGreen = mix(%s.a, %s.a, %s.b);",
                                      dstColor, outColor, srcCoverage);
         }
-        fragBuilder->codeAppendf("%s = %s * %s + (float4(1.0) - %s) * %s;",
+        fragBuilder->codeAppendf("%s = %s * %s + (half4(1.0) - %s) * %s;",
                                  outColor, srcCoverage, outColor, srcCoverage, dstColor);
         if (proc.isLCD()) {
             fragBuilder->codeAppendf("%s.a = max(max(lerpRed, lerpBlue), lerpGreen);", outColor);
diff --git a/src/gpu/instanced/InstanceProcessor.cpp b/src/gpu/instanced/InstanceProcessor.cpp
index d1d826c..7527939 100644
--- a/src/gpu/instanced/InstanceProcessor.cpp
+++ b/src/gpu/instanced/InstanceProcessor.cpp
@@ -105,32 +105,38 @@
 
     void initParams(const TexelBufferHandle paramsBuffer) {
         fParamsBuffer = paramsBuffer;
-        fVertexBuilder->codeAppendf("highp int paramsIdx = int(%s & 0x%x);",
+        fVertexBuilder->codeAppendf("int paramsIdx = int(%s & 0x%x);",
                                     this->attr(Attrib::kInstanceInfo),
                                     kParamsIdx_InfoMask);
     }
 
     const char* attr(Attrib attr) const { return fInstProc.getAttrib((int)attr).fName; }
 
-    void fetchNextParam(const GrShaderCaps* shaderCaps, GrSLType type = kVec4f_GrSLType) const {
+    void fetchNextParam(const GrShaderCaps* shaderCaps, GrSLType type = kHalf4_GrSLType) const {
         SkASSERT(fParamsBuffer.isValid());
         switch (type) {
-            case kVec2f_GrSLType: // fall through
-            case kVec3f_GrSLType: // fall through
-            case kVec4f_GrSLType:
+            case kHighFloat2_GrSLType: // fall through
+            case kHighFloat3_GrSLType: // fall through
+            case kHighFloat4_GrSLType: // fall through
+            case kHalf2_GrSLType:      // fall through
+            case kHalf3_GrSLType:      // fall through
+            case kHalf4_GrSLType:
                 break;
             default:
                 fVertexBuilder->codeAppendf("%s(", GrGLSLTypeString(shaderCaps, type));
         }
         fVertexBuilder->appendTexelFetch(fParamsBuffer, "paramsIdx++");
         switch (type) {
-            case kVec2f_GrSLType:
+            case kHighFloat2_GrSLType: // fall through
+            case kHalf2_GrSLType:
                 fVertexBuilder->codeAppend(".xy");
                 break;
-            case kVec3f_GrSLType:
+            case kHighFloat3_GrSLType: // fall through
+            case kHalf3_GrSLType:
                 fVertexBuilder->codeAppend(".xyz");
                 break;
-            case kVec4f_GrSLType:
+            case kHighFloat4_GrSLType: // fall through
+            case kHalf4_GrSLType:
                 break;
             default:
                 fVertexBuilder->codeAppend(")");
@@ -177,11 +183,11 @@
             , fModifiesCoverage(false)
             , fModifiesColor(false)
             , fNeedsNeighborRadii(false)
-            , fColor(kVec4f_GrSLType)
+            , fColor(kHalf4_GrSLType)
             , fTriangleIsArc(kInt_GrSLType)
-            , fArcCoords(kVec2f_GrSLType)
-            , fInnerShapeCoords(kVec2f_GrSLType)
-            , fInnerRRect(kVec4f_GrSLType)
+            , fArcCoords(kHalf2_GrSLType)
+            , fInnerShapeCoords(kHalf2_GrSLType)
+            , fInnerRRect(kHalf4_GrSLType)
             , fModifiedShapeCoords(nullptr) {
         if (fOpInfo.fShapeTypes & kRRect_ShapesMask) {
             fModifiedShapeCoords = "adjustedShapeCoords";
@@ -232,16 +238,16 @@
     }
 
     if (!ip.opInfo().fHasPerspective) {
-        v->codeAppendf("float2x3 shapeMatrix = float2x3(%s, %s);",
+        v->codeAppendf("half2x3 shapeMatrix = half2x3(%s, %s);",
                        inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
     } else {
         v->defineConstantf("int", "PERSPECTIVE_FLAG", "0x%x", kPerspective_InfoFlag);
-        v->codeAppendf("float3x3 shapeMatrix = float3x3(%s, %s, float3(0, 0, 1));",
+        v->codeAppendf("half3x3 shapeMatrix = half3x3(%s, %s, half3(0, 0, 1));",
                        inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
         v->codeAppendf("if (0 != (%s & uint(PERSPECTIVE_FLAG))) {",
                        inputs.attr(Attrib::kInstanceInfo));
         v->codeAppend (    "shapeMatrix[2] = ");
-        inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType);
+        inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
         v->codeAppend (    ";");
         v->codeAppend ("}");
     }
@@ -303,16 +309,16 @@
                            inputs.attr(Attrib::kInstanceInfo));
         }
         // Here we take advantage of the fact that outerRect == localRect in recordDRRect.
-        v->codeAppendf("float4 outer = %s;", inputs.attr(Attrib::kLocalRect));
-        v->codeAppend ("float4 inner = ");
+        v->codeAppendf("half4 outer = %s;", inputs.attr(Attrib::kLocalRect));
+        v->codeAppend ("half4 inner = ");
         inputs.fetchNextParam(args.fShaderCaps);
         v->codeAppend (";");
         // outer2Inner is a transform from shape coords to inner shape coords:
         // e.g. innerShapeCoords = shapeCoords * outer2Inner.xy + outer2Inner.zw
-        v->codeAppend ("float4 outer2Inner = float4(outer.zw - outer.xy, "
-                                               "outer.xy + outer.zw - inner.xy - inner.zw) / "
-                                               "(inner.zw - inner.xy).xyxy;");
-        v->codeAppendf("float2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;",
+        v->codeAppend ("half4 outer2Inner = half4(outer.zw - outer.xy, "
+                                                 "outer.xy + outer.zw - inner.xy - inner.zw) / "
+                                                 "(inner.zw - inner.xy).xyxy;");
+        v->codeAppendf("half2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;",
                        backend->outShapeCoords());
 
         backend->initInnerShape(varyingHandler, v);
@@ -372,8 +378,8 @@
     const char* localCoords = nullptr;
     if (ip.opInfo().fUsesLocalCoords) {
         localCoords = "localCoords";
-        v->codeAppendf("float2 t = 0.5 * (%s + float2(1));", backend->outShapeCoords());
-        v->codeAppendf("float2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;",
+        v->codeAppendf("half2 t = 0.5 * (%s + half2(1));", backend->outShapeCoords());
+        v->codeAppendf("half2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;",
                        inputs.attr(Attrib::kLocalRect), inputs.attr(Attrib::kLocalRect));
     }
     if (ip.opInfo().fHasLocalMatrix && ip.opInfo().fHasParams) {
@@ -383,20 +389,20 @@
         if (!ip.opInfo().fUsesLocalCoords) {
             inputs.skipParams(2);
         } else {
-            v->codeAppendf(    "float2x3 localMatrix;");
+            v->codeAppendf(    "half2x3 localMatrix;");
             v->codeAppend (    "localMatrix[0] = ");
-            inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType);
+            inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
             v->codeAppend (    ";");
             v->codeAppend (    "localMatrix[1] = ");
-            inputs.fetchNextParam(args.fShaderCaps, kVec3f_GrSLType);
+            inputs.fetchNextParam(args.fShaderCaps, kHalf3_GrSLType);
             v->codeAppend (    ";");
-            v->codeAppend (    "localCoords = (float3(localCoords, 1) * localMatrix).xy;");
+            v->codeAppend (    "localCoords = (half3(localCoords, 1) * localMatrix).xy;");
         }
         v->codeAppend("}");
     }
 
-    GrSLType positionType = ip.opInfo().fHasPerspective ? kVec3f_GrSLType : kVec2f_GrSLType;
-    v->codeAppendf("%s deviceCoords = float3(%s, 1) * shapeMatrix;",
+    GrSLType positionType = ip.opInfo().fHasPerspective ? kHighFloat3_GrSLType : kHighFloat2_GrSLType;
+    v->codeAppendf("%s deviceCoords = highfloat3(%s, 1) * shapeMatrix;",
                    GrGLSLTypeString(args.fShaderCaps, positionType), backend->outShapeCoords());
     gpArgs->fPositionVar.set(positionType, "deviceCoords");
 
@@ -409,7 +415,7 @@
 void GLSLInstanceProcessor::Backend::init(GrGLSLVaryingHandler* varyingHandler,
                                           GrGLSLVertexBuilder* v) {
     if (fModifiedShapeCoords) {
-        v->codeAppendf("float2 %s = %s;", fModifiedShapeCoords, fInputs.attr(Attrib::kShapeCoords));
+        v->codeAppendf("half2 %s = %s;", fModifiedShapeCoords, fInputs.attr(Attrib::kShapeCoords));
     }
 
     this->onInit(varyingHandler, v);
@@ -425,10 +431,10 @@
                                                 int* usedShapeDefinitions) {
     v->codeAppendf("uint2 corner = uint2(uint(%s) & 1, (uint(%s) >> 1) & 1);",
                    fInputs.attr(Attrib::kVertexAttrs), fInputs.attr(Attrib::kVertexAttrs));
-    v->codeAppend ("float2 cornerSign = float2(corner) * 2.0 - 1.0;");
-    v->codeAppendf("float2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : "");
-    v->codeAppend ("float2x2 p = ");
-    fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType);
+    v->codeAppend ("half2 cornerSign = half2(corner) * 2.0 - 1.0;");
+    v->codeAppendf("half2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : "");
+    v->codeAppend ("half2x2 p = ");
+    fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
     v->codeAppend (";");
     uint8_t types = fOpInfo.fShapeTypes & kRRect_ShapesMask;
     if (0 == (types & (types - 1))) {
@@ -469,11 +475,11 @@
     this->adjustRRectVertices(v);
 
     if (fArcCoords.vsOut()) {
-        v->codeAppendf("%s = (cornerSign * %s + radii - float2(1)) / radii;",
+        v->codeAppendf("%s = (cornerSign * %s + radii - half2(1)) / radii;",
                        fArcCoords.vsOut(), fModifiedShapeCoords);
     }
     if (fTriangleIsArc.vsOut()) {
-        v->codeAppendf("%s = int(all(equal(float2(1), abs(%s))));",
+        v->codeAppendf("%s = int(all(equal(half2(1), abs(%s))));",
                        fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kShapeCoords));
     }
 
@@ -488,9 +494,9 @@
 }
 
 void GLSLInstanceProcessor::Backend::setupNinePatchRadii(GrGLSLVertexBuilder* v) {
-    v->codeAppend("radii = float2(p[0][corner.x], p[1][corner.y]);");
+    v->codeAppend("radii = half2(p[0][corner.x], p[1][corner.y]);");
     if (fNeedsNeighborRadii) {
-        v->codeAppend("neighborRadii = float2(p[0][1 - corner.x], p[1][1 - corner.y]);");
+        v->codeAppend("neighborRadii = half2(p[0][1 - corner.x], p[1][1 - corner.y]);");
     }
 }
 
@@ -510,12 +516,12 @@
      *          x2       x4
      *
      */
-    v->codeAppend("float2x2 p2 = ");
-    fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType);
+    v->codeAppend("half2x2 p2 = ");
+    fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
     v->codeAppend(";");
-    v->codeAppend("radii = float2(p[corner.x][corner.y], p2[corner.y][corner.x]);");
+    v->codeAppend("radii = half2(p[corner.x][corner.y], p2[corner.y][corner.x]);");
     if (fNeedsNeighborRadii) {
-        v->codeAppend("neighborRadii = float2(p[1 - corner.x][corner.y], "
+        v->codeAppend("neighborRadii = half2(p[1 - corner.x][corner.y], "
                                              "p2[1 - corner.y][corner.x]);");
     }
 }
@@ -544,10 +550,10 @@
 
 void GLSLInstanceProcessor::Backend::setupInnerSimpleRRect(const GrShaderCaps* shaderCaps,
                                                            GrGLSLVertexBuilder* v) {
-    v->codeAppend("float2x2 innerP = ");
-    fInputs.fetchNextParam(shaderCaps, kMat22f_GrSLType);
+    v->codeAppend("half2x2 innerP = ");
+    fInputs.fetchNextParam(shaderCaps, kHalf2x2_GrSLType);
     v->codeAppend(";");
-    v->codeAppend("float2 innerRadii = innerP[0] * 2.0 / innerP[1];");
+    v->codeAppend("half2 innerRadii = innerP[0] * 2.0 / innerP[1];");
     this->onSetupInnerSimpleRRect(v);
 }
 
@@ -558,7 +564,7 @@
                      fModifiesColor ? outColor : nullptr);
     if (outCoverage && !fModifiesCoverage) {
         // Even though the subclass doesn't use coverage, we are expected to assign some value.
-        f->codeAppendf("%s = float4(1);", outCoverage);
+        f->codeAppendf("%s = half4(1);", outCoverage);
     }
     if (!fModifiesColor) {
         // The subclass didn't assign a value to the output color.
@@ -625,18 +631,18 @@
 
 void GLSLInstanceProcessor::BackendNonAA::setupInnerRect(GrGLSLVertexBuilder* v) {
     if (fInnerRRect.vsOut()) {
-        v->codeAppendf("%s = float4(1);", fInnerRRect.vsOut());
+        v->codeAppendf("%s = half4(1);", fInnerRRect.vsOut());
     }
 }
 
 void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) {
     if (fInnerRRect.vsOut()) {
-        v->codeAppendf("%s = float4(0, 0, 1, 1);", fInnerRRect.vsOut());
+        v->codeAppendf("%s = half4(0, 0, 1, 1);", fInnerRRect.vsOut());
     }
 }
 
 void GLSLInstanceProcessor::BackendNonAA::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
-    v->codeAppendf("%s = float4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
+    v->codeAppendf("%s = half4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
 }
 
 void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
@@ -647,11 +653,11 @@
     if (!fOpInfo.fCannotDiscard) {
         dropFragment = "discard";
     } else if (fModifiesCoverage) {
-        f->codeAppend ("lowp float covered = 1.0;");
+        f->codeAppend ("half covered = 1.0;");
         dropFragment = "covered = 0.0";
     } else if (fModifiesColor) {
-        f->codeAppendf("lowp float4 color = %s;", fColor.fsIn());
-        dropFragment = "color = float4(0)";
+        f->codeAppendf("half4 color = %s;", fColor.fsIn());
+        dropFragment = "color = half4(0)";
     }
     if (fTriangleIsArc.fsIn()) {
         SkASSERT(dropFragment);
@@ -662,19 +668,19 @@
         SkASSERT(dropFragment);
         f->codeAppendf("// Inner shape.\n");
         if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
-            f->codeAppendf("if (all(lessThanEqual(abs(%s), float2(1)))) %s;",
+            f->codeAppendf("if (all(lessThanEqual(abs(%s), half2(1)))) %s;",
                            fInnerShapeCoords.fsIn(), dropFragment);
         } else if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
             f->codeAppendf("if ((dot(%s, %s) <= 1.0)) %s;",
                            fInnerShapeCoords.fsIn(), fInnerShapeCoords.fsIn(), dropFragment);
         } else {
-            f->codeAppendf("if (all(lessThan(abs(%s), float2(1)))) {", fInnerShapeCoords.fsIn());
-            f->codeAppendf(    "float2 distanceToArcEdge = abs(%s) - %s.xy;",
+            f->codeAppendf("if (all(lessThan(abs(%s), half2(1)))) {", fInnerShapeCoords.fsIn());
+            f->codeAppendf(    "half2 distanceToArcEdge = abs(%s) - %s.xy;",
                                fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
-            f->codeAppend (    "if (any(lessThan(distanceToArcEdge, float2(0)))) {");
+            f->codeAppend (    "if (any(lessThan(distanceToArcEdge, half2(0)))) {");
             f->codeAppendf(        "%s;", dropFragment);
             f->codeAppend (    "} else {");
-            f->codeAppendf(        "float2 rrectCoords = distanceToArcEdge * %s.zw;",
+            f->codeAppendf(        "half2 rrectCoords = distanceToArcEdge * %s.zw;",
                                    fInnerRRect.fsIn());
             f->codeAppend (        "if (dot(rrectCoords, rrectCoords) <= 1.0) {");
             f->codeAppendf(            "%s;", dropFragment);
@@ -684,7 +690,7 @@
         }
     }
     if (fModifiesCoverage) {
-        f->codeAppendf("%s = float4(covered);", outCoverage);
+        f->codeAppendf("%s = half4(covered);", outCoverage);
     } else if (fModifiesColor) {
         f->codeAppendf("%s = color;", outColor);
     }
@@ -696,15 +702,15 @@
 public:
     BackendCoverage(OpInfo opInfo, const VertexInputs& inputs)
             : INHERITED(opInfo, inputs)
-            , fColorTimesRectCoverage(kVec4f_GrSLType)
-            , fRectCoverage(kFloat_GrSLType)
-            , fEllipseCoords(kVec2f_GrSLType)
-            , fEllipseName(kVec2f_GrSLType)
-            , fBloatedRadius(kFloat_GrSLType)
-            , fDistanceToInnerEdge(kVec2f_GrSLType)
-            , fInnerShapeBloatedHalfSize(kVec2f_GrSLType)
-            , fInnerEllipseCoords(kVec2f_GrSLType)
-            , fInnerEllipseName(kVec2f_GrSLType) {
+            , fColorTimesRectCoverage(kHalf4_GrSLType)
+            , fRectCoverage(kHalf_GrSLType)
+            , fEllipseCoords(kHalf2_GrSLType)
+            , fEllipseName(kHalf2_GrSLType)
+            , fBloatedRadius(kHalf_GrSLType)
+            , fDistanceToInnerEdge(kHalf2_GrSLType)
+            , fInnerShapeBloatedHalfSize(kHalf2_GrSLType)
+            , fInnerEllipseCoords(kHalf2_GrSLType)
+            , fInnerEllipseName(kHalf2_GrSLType) {
         fShapeIsCircle = !fOpInfo.fNonSquare && !(fOpInfo.fShapeTypes & kRRect_ShapesMask);
         fTweakAlphaForCoverage = !fOpInfo.fCannotTweakAlphaForCoverage && !fOpInfo.fInnerShapeTypes;
         fModifiesCoverage = !fTweakAlphaForCoverage;
@@ -751,10 +757,10 @@
 
 void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyingHandler,
                                                     GrGLSLVertexBuilder* v) {
-    v->codeAppend ("float2x2 shapeTransposeMatrix = transpose(float2x2(shapeMatrix));");
-    v->codeAppend ("float2 shapeHalfSize = float2(length(shapeTransposeMatrix[0]), "
+    v->codeAppend ("half2x2 shapeTransposeMatrix = transpose(half2x2(shapeMatrix));");
+    v->codeAppend ("half2 shapeHalfSize = half2(length(shapeTransposeMatrix[0]), "
                                              "length(shapeTransposeMatrix[1]));");
-    v->codeAppend ("float2 bloat = 0.5 / shapeHalfSize;");
+    v->codeAppend ("half2 bloat = 0.5 / shapeHalfSize;");
     v->codeAppendf("bloatedShapeCoords = %s * (1.0 + bloat);", fInputs.attr(Attrib::kShapeCoords));
 
     if (kOval_ShapeFlag != fOpInfo.fShapeTypes) {
@@ -767,7 +773,7 @@
         } else {
             varyingHandler->addVarying("rectCoverage", &fRectCoverage, kLow_GrSLPrecision);
         }
-        v->codeAppend("float rectCoverage = 0.0;");
+        v->codeAppend("half rectCoverage = 0.0;");
     }
     if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
         varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
@@ -783,18 +789,18 @@
 
 void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
     // Make the border one pixel wide. Inner vs outer is indicated by coordAttrs.
-    v->codeAppendf("float2 rectBloat = (%s != 0) ? bloat : -bloat;",
+    v->codeAppendf("half2 rectBloat = (%s != 0) ? bloat : -bloat;",
                    fInputs.attr(Attrib::kVertexAttrs));
     // Here we use the absolute value, because when the rect is thinner than a pixel, this makes it
     // mark the spot where pixel center is within half a pixel of the *opposite* edge. This,
     // combined with the "maxCoverage" logic below gives us mathematically correct coverage even for
     // subpixel rectangles.
-    v->codeAppendf("bloatedShapeCoords = %s * abs(float2(1.0 + rectBloat));",
+    v->codeAppendf("bloatedShapeCoords = %s * abs(half2(1.0 + rectBloat));",
                    fInputs.attr(Attrib::kShapeCoords));
 
     // Determine coverage at the vertex. Coverage naturally ramps from 0 to 1 unless the rect is
     // narrower than a pixel.
-    v->codeAppend ("float maxCoverage = 4.0 * min(0.5, shapeHalfSize.x) *"
+    v->codeAppend ("half maxCoverage = 4.0 * min(0.5, shapeHalfSize.x) *"
                                              "min(0.5, shapeHalfSize.y);");
     v->codeAppendf("rectCoverage = (%s != 0) ? 0.0 : maxCoverage;",
                    fInputs.attr(Attrib::kVertexAttrs));
@@ -806,9 +812,9 @@
 
 void GLSLInstanceProcessor::BackendCoverage::setupOval(GrGLSLVertexBuilder* v) {
     // Offset the inner and outer octagons by one pixel. Inner vs outer is indicated by coordAttrs.
-    v->codeAppendf("float2 ovalBloat = (%s != 0) ? bloat : -bloat;",
+    v->codeAppendf("half2 ovalBloat = (%s != 0) ? bloat : -bloat;",
                    fInputs.attr(Attrib::kVertexAttrs));
-    v->codeAppendf("bloatedShapeCoords = %s * max(float2(1.0 + ovalBloat), float2(0));",
+    v->codeAppendf("bloatedShapeCoords = %s * max(half2(1.0 + ovalBloat), half2(0));",
                    fInputs.attr(Attrib::kShapeCoords));
     v->codeAppendf("%s = bloatedShapeCoords * shapeHalfSize;", fEllipseCoords.vsOut());
     if (fEllipseName.vsOut()) {
@@ -831,8 +837,8 @@
     // We try to let the AA borders line up with the arc edges on their particular side, but we
     // can't allow them to get closer than one half pixel to the edge or they might overlap with
     // their neighboring border.
-    v->codeAppend("float2 innerEdge = max(1.0 - bloat, float2(0));");
-    v->codeAppend ("float2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge, innerEdge);");
+    v->codeAppend("half2 innerEdge = max(1.0 - bloat, half2(0));");
+    v->codeAppend ("half2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge, innerEdge);");
     // 0.5 is a special value that indicates this vertex is an arc edge.
     v->codeAppendf("if (abs(%s.x) == 0.5)"
                        "bloatedShapeCoords.x = borderEdge.x;", fInputs.attr(Attrib::kShapeCoords));
@@ -855,7 +861,7 @@
     // interior edge of the border will necessarily clamp, and we need to match the AA behavior of
     // the arc segments (i.e. distance from bloated edge only; ignoring the fact that the pixel
     // actully has less coverage because it's not completely inside the opposite edge.)
-    v->codeAppend("float2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * shapeHalfSize;");
+    v->codeAppend("half2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * shapeHalfSize;");
     v->codeAppend("rectCoverage = min(d.x, d.y);");
 
     SkASSERT(!fShapeIsCircle);
@@ -863,8 +869,8 @@
     // smooth transition from flat edge to arc, we don't allow the radii to be smaller than one half
     // pixel. (We don't worry about the transition on the opposite side when a radius is so large
     // that the border clamped on that side.)
-    v->codeAppendf("float2 clampedRadii = max(radii, bloat);");
-    v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - float2(1)) * "
+    v->codeAppendf("half2 clampedRadii = max(radii, bloat);");
+    v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - half2(1)) * "
                         "shapeHalfSize;", fEllipseCoords.vsOut());
     v->codeAppendf("%s = 1.0 / (clampedRadii * clampedRadii * shapeHalfSize * shapeHalfSize);",
                    fEllipseName.vsOut());
@@ -872,7 +878,7 @@
 
 void GLSLInstanceProcessor::BackendCoverage::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
                                                               GrGLSLVertexBuilder* v) {
-    v->codeAppend("float2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;");
+    v->codeAppend("half2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;");
 
     if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
         varyingHandler->addVarying("innerEllipseCoords", &fInnerEllipseCoords,
@@ -910,7 +916,7 @@
         v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;", fInnerEllipseCoords.vsOut());
     }
     if (fInnerRRect.vsOut()) {
-        v->codeAppendf("%s = float4(0, 0, innerShapeHalfSize);", fInnerRRect.vsOut());
+        v->codeAppendf("%s = half4(0, 0, innerShapeHalfSize);", fInnerRRect.vsOut());
     }
 }
 
@@ -920,7 +926,7 @@
     v->codeAppendf("%s = 1.0 / (innerRadii * innerRadii * innerShapeHalfSize * "
                                "innerShapeHalfSize);",
                    fInnerEllipseName.vsOut());
-    v->codeAppendf("%s = float4(1.0 - innerRadii, innerShapeHalfSize);", fInnerRRect.vsOut());
+    v->codeAppendf("%s = half4(1.0 - innerRadii, innerShapeHalfSize);", fInnerRRect.vsOut());
 }
 
 void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
@@ -937,7 +943,7 @@
         v->codeAppendf("%s = rectCoverage;", fRectCoverage.vsOut());
     }
 
-    SkString coverage("lowp float coverage");
+    SkString coverage("half coverage");
     if (fOpInfo.fInnerShapeTypes || (!fTweakAlphaForCoverage && fTriangleIsArc.fsIn())) {
         f->codeAppendf("%s;", coverage.c_str());
         coverage = "coverage";
@@ -964,7 +970,7 @@
 
     if (fOpInfo.fInnerShapeTypes) {
         f->codeAppendf("// Inner shape.\n");
-        SkString innerCoverageDecl("lowp float innerCoverage");
+        SkString innerCoverageDecl("half innerCoverage");
         if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
             this->emitArc(f, fInnerEllipseCoords.fsIn(), fInnerEllipseName.fsIn(),
                           true /*ellipseCoordsNeedClamp*/, true /*ellipseCoordsMayBeNegative*/,
@@ -978,12 +984,12 @@
                 this->emitInnerRect(f, innerCoverageDecl.c_str());
             } else {
                 f->codeAppendf("%s = 0.0;", innerCoverageDecl.c_str());
-                f->codeAppendf("mediump float2 distanceToArcEdge = abs(%s) - %s.xy;",
+                f->codeAppendf("half2 distanceToArcEdge = abs(%s) - %s.xy;",
                                fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
-                f->codeAppend ("if (any(lessThan(distanceToArcEdge, float2(1e-5)))) {");
+                f->codeAppend ("if (any(lessThan(distanceToArcEdge, half2(1e-5)))) {");
                 this->emitInnerRect(f, "innerCoverage");
                 f->codeAppend ("} else {");
-                f->codeAppendf(    "mediump float2 ellipseCoords = distanceToArcEdge * %s.zw;",
+                f->codeAppendf(    "half2 ellipseCoords = distanceToArcEdge * %s.zw;",
                                    fInnerRRect.fsIn());
                 this->emitArc(f, "ellipseCoords", fInnerEllipseName.fsIn(),
                               false /*ellipseCoordsNeedClamp*/,
@@ -991,9 +997,9 @@
                 f->codeAppend ("}");
             }
         }
-        f->codeAppendf("%s = float4(max(coverage - innerCoverage, 0.0));", outCoverage);
+        f->codeAppendf("%s = half4(max(coverage - innerCoverage, 0.0));", outCoverage);
     } else if (!fTweakAlphaForCoverage) {
-        f->codeAppendf("%s = float4(coverage);", outCoverage);
+        f->codeAppendf("%s = half4(coverage);", outCoverage);
     }
 }
 
@@ -1016,7 +1022,7 @@
                                                         const char* outCoverage) {
     // TODO: circleCoords = max(circleCoords, 0) if we decide to do this optimization on rrects.
     SkASSERT(!(kRRect_ShapesMask & fOpInfo.fShapeTypes));
-    f->codeAppendf("mediump float distanceToEdge = %s - length(%s);",
+    f->codeAppendf("half distanceToEdge = %s - length(%s);",
                    fBloatedRadius.fsIn(), fEllipseCoords.fsIn());
     f->codeAppendf("%s = clamp(distanceToEdge, 0.0, 1.0);", outCoverage);
 }
@@ -1033,27 +1039,27 @@
         //  - To restrict the arcs of rounded rects to their positive quadrants.
         //  - To avoid inversesqrt(0) in the ellipse formula.
         if (ellipseCoordsMayBeNegative) {
-            f->codeAppendf("mediump float2 ellipseClampedCoords = max(abs(%s), float2(1e-4));",
+            f->codeAppendf("half2 ellipseClampedCoords = max(abs(%s), half2(1e-4));",
                            ellipseCoords);
         } else {
-            f->codeAppendf("mediump float2 ellipseClampedCoords = max(%s, float2(1e-4));",
+            f->codeAppendf("half2 ellipseClampedCoords = max(%s, half2(1e-4));",
                            ellipseCoords);
         }
         ellipseCoords = "ellipseClampedCoords";
     }
     // ellipseCoords are in pixel space and ellipseName is 1 / rx^2, 1 / ry^2.
-    f->codeAppendf("highp float2 Z = %s * %s;", ellipseCoords, ellipseName);
+    f->codeAppendf("highfloat2 Z = %s * %s;", ellipseCoords, ellipseName);
     // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
-    f->codeAppendf("highp float implicit = dot(Z, %s) - 1.0;", ellipseCoords);
+    f->codeAppendf("highfloat implicit = dot(Z, %s) - 1.0;", ellipseCoords);
     // gradDot is the squared length of the gradient of the implicit.
-    f->codeAppendf("highp float gradDot = 4.0 * dot(Z, Z);");
-    f->codeAppend ("mediump float approxDist = implicit * inversesqrt(gradDot);");
+    f->codeAppendf("highfloat gradDot = 4.0 * dot(Z, Z);");
+    f->codeAppend ("half approxDist = implicit * inversesqrt(gradDot);");
     f->codeAppendf("%s = clamp(0.5 - approxDist, 0.0, 1.0);", outCoverage);
 }
 
 void GLSLInstanceProcessor::BackendCoverage::emitInnerRect(GrGLSLPPFragmentBuilder* f,
                                                            const char* outCoverage) {
-    f->codeAppendf("lowp float2 c = %s - abs(%s);",
+    f->codeAppendf("half2 c = %s - abs(%s);",
                    fInnerShapeBloatedHalfSize.fsIn(), fDistanceToInnerEdge.fsIn());
     f->codeAppendf("%s = clamp(min(c.x, c.y), 0.0, 1.0);", outCoverage);
 }
@@ -1065,15 +1071,15 @@
     BackendMultisample(OpInfo opInfo, const VertexInputs& inputs, int effectiveSampleCnt)
             : INHERITED(opInfo, inputs)
             , fEffectiveSampleCnt(effectiveSampleCnt)
-            , fShapeCoords(kVec2f_GrSLType)
-            , fShapeInverseMatrix(kMat22f_GrSLType)
-            , fFragShapeHalfSpan(kVec2f_GrSLType)
-            , fArcTest(kVec2f_GrSLType)
-            , fArcInverseMatrix(kMat22f_GrSLType)
-            , fFragArcHalfSpan(kVec2f_GrSLType)
+            , fShapeCoords(kHalf2_GrSLType)
+            , fShapeInverseMatrix(kHalf2x2_GrSLType)
+            , fFragShapeHalfSpan(kHalf2_GrSLType)
+            , fArcTest(kHalf2_GrSLType)
+            , fArcInverseMatrix(kHalf2x2_GrSLType)
+            , fFragArcHalfSpan(kHalf2_GrSLType)
             , fEarlyAccept(kInt_GrSLType)
-            , fInnerShapeInverseMatrix(kMat22f_GrSLType)
-            , fFragInnerShapeHalfSpan(kVec2f_GrSLType) {
+            , fInnerShapeInverseMatrix(kHalf2x2_GrSLType)
+            , fFragInnerShapeHalfSpan(kHalf2_GrSLType) {
         fRectTrianglesMaySplit = fOpInfo.fHasPerspective;
         fNeedsNeighborRadii = this->isMixedSampled() && !fOpInfo.fHasPerspective;
     }
@@ -1181,9 +1187,9 @@
         }
     }
     if (!fOpInfo.fHasPerspective) {
-        v->codeAppend("float2x2 shapeInverseMatrix = inverse(float2x2(shapeMatrix));");
-        v->codeAppend("float2 fragShapeSpan = abs(float4(shapeInverseMatrix).xz) + "
-                                           "abs(float4(shapeInverseMatrix).yw);");
+        v->codeAppend("half2x2 shapeInverseMatrix = inverse(half2x2(shapeMatrix));");
+        v->codeAppend("half2 fragShapeSpan = abs(half4(shapeInverseMatrix).xz) + "
+                                           "abs(half4(shapeInverseMatrix).yw);");
     }
 }
 
@@ -1199,7 +1205,7 @@
     }
     if (fArcTest.vsOut()) {
         // Pick a value that is not > 0.
-        v->codeAppendf("%s = float2(0);", fArcTest.vsOut());
+        v->codeAppendf("%s = highfloat2(0);", fArcTest.vsOut());
     }
     if (fTriangleIsArc.vsOut()) {
         v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
@@ -1212,8 +1218,8 @@
 void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v) {
     v->codeAppendf("%s = abs(%s);", fArcCoords.vsOut(), this->outShapeCoords());
     if (fArcInverseMatrix.vsOut()) {
-        v->codeAppendf("float2 s = sign(%s);", this->outShapeCoords());
-        v->codeAppendf("%s = shapeInverseMatrix * float2x2(s.x, 0, 0 , s.y);",
+        v->codeAppendf("half2 s = sign(%s);", this->outShapeCoords());
+        v->codeAppendf("%s = shapeInverseMatrix * half2x2(s.x, 0, 0 , s.y);",
                        fArcInverseMatrix.vsOut());
     }
     if (fFragArcHalfSpan.vsOut()) {
@@ -1221,7 +1227,7 @@
     }
     if (fArcTest.vsOut()) {
         // Pick a value that is > 0.
-        v->codeAppendf("%s = float2(1);", fArcTest.vsOut());
+        v->codeAppendf("%s = half2(1);", fArcTest.vsOut());
     }
     if (fTriangleIsArc.vsOut()) {
         if (!this->isMixedSampled()) {
@@ -1247,13 +1253,13 @@
         // For the mixed samples algorithm it's best to bloat the corner triangles a bit so that
         // more of the pixels that cross into the arc region are completely inside the shared edges.
         // We also snap to a regular rect if the radii shrink smaller than a pixel.
-        v->codeAppend ("float2 midpt = 0.5 * (neighborRadii - radii);");
-        v->codeAppend ("float2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
-                           "float2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);");
+        v->codeAppend ("half2 midpt = 0.5 * (neighborRadii - radii);");
+        v->codeAppend ("half2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
+                           "half2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);");
     } else {
         // TODO: We could still bloat the corner triangle in the perspective case; we would just
         // need to find the screen-space derivative of shape coords at this particular point.
-        v->codeAppend ("float2 cornerSize = any(lessThan(radii, float2(1e-3))) ? float2(0) : radii;");
+        v->codeAppend ("half2 cornerSize = any(lessThan(radii, half2(1e-3))) ? half2(0) : radii;");
     }
 
     v->codeAppendf("if (abs(%s.x) == 0.5)"
@@ -1275,12 +1281,12 @@
         v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
     }
     if (fArcInverseMatrix.vsOut()) {
-        v->codeAppend ("float2 s = cornerSign / radii;");
-        v->codeAppendf("%s = shapeInverseMatrix * float2x2(s.x, 0, 0, s.y);",
+        v->codeAppend ("half2 s = cornerSign / radii;");
+        v->codeAppendf("%s = shapeInverseMatrix * half2x2(s.x, 0, 0, s.y);",
                        fArcInverseMatrix.vsOut());
     }
     if (fFragArcHalfSpan.vsOut()) {
-        v->codeAppendf("%s = 0.5 * (abs(float4(%s).xz) + abs(float4(%s).yw));",
+        v->codeAppendf("%s = 0.5 * (abs(half4(%s).xz) + abs(half4(%s).yw));",
                        fFragArcHalfSpan.vsOut(), fArcInverseMatrix.vsOut(),
                        fArcInverseMatrix.vsOut());
     }
@@ -1289,8 +1295,8 @@
         // edges of a fan triangle to a point within that triangle. fArcTest is used to check if a
         // fragment is too close to either shared edge, in which case we point sample the shape as a
         // rect at that point in order to guarantee the mixed samples discard logic works correctly.
-        v->codeAppendf("%s = (cornerSize == float2(0)) ? float2(0) : "
-                       "cornerSign * %s * float2x2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);",
+        v->codeAppendf("%s = (cornerSize == half2(0)) ? half2(0) : "
+                       "cornerSign * %s * half2x2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);",
                        fArcTest.vsOut(), fModifiedShapeCoords);
         if (!fOpInfo.fHasPerspective) {
             // Shift the point at which distances to edges are measured from the center of the pixel
@@ -1303,7 +1309,7 @@
     }
     if (fEarlyAccept.vsOut()) {
         SkASSERT(this->isMixedSampled());
-        v->codeAppendf("%s = all(equal(float2(1), abs(%s))) ? 0 : SAMPLE_MASK_ALL;",
+        v->codeAppendf("%s = all(equal(half2(1), abs(%s))) ? 0 : SAMPLE_MASK_ALL;",
                        fEarlyAccept.vsOut(), fInputs.attr(Attrib::kShapeCoords));
     }
 }
@@ -1319,7 +1325,7 @@
     if (!fOpInfo.fHasPerspective) {
         varyingHandler->addFlatVarying("innerShapeInverseMatrix", &fInnerShapeInverseMatrix,
                                        kHigh_GrSLPrecision);
-        v->codeAppendf("%s = shapeInverseMatrix * float2x2(outer2Inner.x, 0, 0, outer2Inner.y);",
+        v->codeAppendf("%s = shapeInverseMatrix * highfloat2x2(outer2Inner.x, 0, 0, outer2Inner.y);",
                        fInnerShapeInverseMatrix.vsOut());
         varyingHandler->addFlatVarying("fragInnerShapeHalfSpan", &fFragInnerShapeHalfSpan,
                                        kHigh_GrSLPrecision);
@@ -1333,14 +1339,14 @@
         // The fragment shader will generalize every inner shape as a round rect. Since this one
         // is a rect, we simply emit bogus parameters for the round rect (negative radii) that
         // ensure the fragment shader always takes the "sample as rect" codepath.
-        v->codeAppendf("%s = float4(2.0 * (inner.zw - inner.xy) / (outer.zw - outer.xy), float2(0));",
+        v->codeAppendf("%s = half4(2.0 * (inner.zw - inner.xy) / (outer.zw - outer.xy), half2(0));",
                        fInnerRRect.vsOut());
     }
 }
 
 void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuilder* v) {
     if (fInnerRRect.vsOut()) {
-        v->codeAppendf("%s = float4(0, 0, 1, 1);", fInnerRRect.vsOut());
+        v->codeAppendf("%s = half4(0, 0, 1, 1);", fInnerRRect.vsOut());
     }
 }
 
@@ -1349,9 +1355,9 @@
     if (fFragInnerShapeHalfSpan.vsOut()) {
         v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerShapeHalfSpan.vsOut());
     } else {
-        v->codeAppend ("innerRadii = max(innerRadii, float2(1e-4));");
+        v->codeAppend ("innerRadii = max(innerRadii, half2(1e-4));");
     }
-    v->codeAppendf("%s = float4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
+    v->codeAppendf("%s = half4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
 }
 
 void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
@@ -1364,8 +1370,8 @@
     }
 
     if (kRect_ShapeFlag != (fOpInfo.fShapeTypes | fOpInfo.fInnerShapeTypes)) {
-        GrShaderVar x("x", kVec2f_GrSLType, GrShaderVar::kNonArray, kHigh_GrSLPrecision);
-        f->emitFunction(kFloat_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun);
+        GrShaderVar x("x", kHighFloat2_GrSLType, GrShaderVar::kNonArray);
+        f->emitFunction(kHalf_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun);
     }
 
     EmitShapeCoords shapeCoords;
@@ -1387,7 +1393,7 @@
     if (fOpInfo.fHasPerspective && fOpInfo.fInnerShapeTypes) {
         // This determines if the fragment should consider the inner shape in its sample mask.
         // We take the derivative early in case discards may occur before we get to the inner shape.
-        f->codeAppendf("highp float2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
+        f->codeAppendf("highfloat2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
                        fInnerShapeCoords.fsIn());
     }
 
@@ -1404,7 +1410,7 @@
         if (arcTest && fOpInfo.fHasPerspective) {
             // The non-perspective version accounts for fwidth() in the vertex shader.
             // We make sure to take the derivative here, before a neighbor pixel may early accept.
-            f->codeAppendf("highp float2 arcTest = %s - 0.5 * fwidth(%s);",
+            f->codeAppendf("highfloat2 arcTest = %s - 0.5 * fwidth(%s);",
                            fArcTest.fsIn(), fArcTest.fsIn());
             arcTest = "arcTest";
         }
@@ -1415,7 +1421,7 @@
         if (arcTest) {
             // At this point, if the sample mask is all set it means we are inside an arc triangle.
             f->codeAppendf("if (gl_SampleMaskIn[0] == SAMPLE_MASK_ALL || "
-                               "all(greaterThan(%s, float2(0)))) {", arcTest);
+                               "all(greaterThan(%s, highfloat2(0)))) {", arcTest);
             this->emitArc(f, arcCoords, false, clampArcCoords, opts);
             f->codeAppend ("} else {");
             this->emitRect(f, shapeCoords, opts);
@@ -1488,10 +1494,10 @@
     }
     f->codeAppend ("int rectMask = 0;");
     f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
-    f->codeAppend (    "highp float2 pt = ");
+    f->codeAppend (    "highfloat2 pt = ");
     this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
     f->codeAppend (    ";");
-    f->codeAppend (    "if (all(lessThan(abs(pt), float2(1)))) rectMask |= (1 << i);");
+    f->codeAppend (    "if (all(lessThan(abs(pt), highfloat2(1)))) rectMask |= (1 << i);");
     f->codeAppend ("}");
     this->acceptCoverageMask(f, "rectMask", opts);
     if (coords.fFragHalfSpan) {
@@ -1507,7 +1513,7 @@
         SkString absArcCoords;
         absArcCoords.printf(coordsMayBeNegative ? "abs(%s)" : "%s", coords.fVarying->fsIn());
         if (clampCoords) {
-            f->codeAppendf("if (%s(max(%s + %s, float2(0))) < 1.0) {",
+            f->codeAppendf("if (%s(max(%s + %s, half2(0))) < 1.0) {",
                            fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
         } else {
             f->codeAppendf("if (%s(%s + %s) < 1.0) {",
@@ -1515,7 +1521,7 @@
         }
         // The entire pixel is inside the arc.
         this->acceptOrRejectWholeFragment(f, true, opts);
-        f->codeAppendf("} else if (%s(max(%s - %s, float2(0))) >= 1.0) {",
+        f->codeAppendf("} else if (%s(max(%s - %s, half2(0))) >= 1.0) {",
                        fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
         // The entire pixel is outside the arc.
         this->acceptOrRejectWholeFragment(f, false, opts);
@@ -1523,12 +1529,12 @@
     }
     f->codeAppend (    "int arcMask = 0;");
     f->codeAppend (    "for (int i = 0; i < SAMPLE_COUNT; i++) {");
-    f->codeAppend (        "highp float2 pt = ");
+    f->codeAppend (        "highfloat2 pt = ");
     this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
     f->codeAppend (        ";");
     if (clampCoords) {
         SkASSERT(!coordsMayBeNegative);
-        f->codeAppend (    "pt = max(pt, float2(0));");
+        f->codeAppend (    "pt = max(pt, highfloat2(0));");
     }
     f->codeAppendf(        "if (%s(pt) < 1.0) arcMask |= (1 << i);", fSquareFun.c_str());
     f->codeAppend (    "}");
@@ -1542,31 +1548,31 @@
                                                                 const EmitShapeCoords& coords,
                                                                 const char* rrect,
                                                                 const EmitShapeOpts& opts) {
-    f->codeAppendf("highp float2 distanceToArcEdge = abs(%s) - %s.xy;", coords.fVarying->fsIn(),
+    f->codeAppendf("highfloat2 distanceToArcEdge = abs(%s) - %s.xy;", coords.fVarying->fsIn(),
                    rrect);
-    f->codeAppend ("if (any(lessThan(distanceToArcEdge, float2(0)))) {");
+    f->codeAppend ("if (any(lessThan(distanceToArcEdge, highfloat2(0)))) {");
     this->emitRect(f, coords, opts);
     f->codeAppend ("} else {");
     if (coords.fInverseMatrix && coords.fFragHalfSpan) {
-        f->codeAppendf("highp float2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
-        f->codeAppendf("highp float2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect);
+        f->codeAppendf("highfloat2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
+        f->codeAppendf("highfloat2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect);
         f->codeAppendf("if (%s(rrectCoords + fragRRectHalfSpan) <= 1.0) {", fSquareFun.c_str());
         // The entire pixel is inside the round rect.
         this->acceptOrRejectWholeFragment(f, true, opts);
-        f->codeAppendf("} else if (%s(max(rrectCoords - fragRRectHalfSpan, float2(0))) >= 1.0) {",
+        f->codeAppendf("} else if (%s(max(rrectCoords - fragRRectHalfSpan, highfloat2(0))) >= 1.0) {",
                        fSquareFun.c_str());
         // The entire pixel is outside the round rect.
         this->acceptOrRejectWholeFragment(f, false, opts);
         f->codeAppend ("} else {");
-        f->codeAppendf(    "highp float2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn());
-        f->codeAppendf(    "highp float2x2 innerRRectInverseMatrix = %s * "
-                           "float2x2(s.x, 0, 0, s.y);", coords.fInverseMatrix);
+        f->codeAppendf(    "highfloat2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn());
+        f->codeAppendf(    "highfloat2x2 innerRRectInverseMatrix = %s * "
+                           "highfloat2x2(s.x, 0, 0, s.y);", coords.fInverseMatrix);
         f->codeAppend (    "highp int rrectMask = 0;");
         f->codeAppend (    "for (int i = 0; i < SAMPLE_COUNT; i++) {");
-        f->codeAppend (        "highp float2 pt = rrectCoords + ");
+        f->codeAppend (        "highfloat2 pt = rrectCoords + ");
         f->appendOffsetToSample("i", GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
         f->codeAppend (                  "* innerRRectInverseMatrix;");
-        f->codeAppendf(        "if (%s(max(pt, float2(0))) < 1.0) rrectMask |= (1 << i);",
+        f->codeAppendf(        "if (%s(max(pt, highfloat2(0))) < 1.0) rrectMask |= (1 << i);",
                                fSquareFun.c_str());
         f->codeAppend (    "}");
         this->acceptCoverageMask(f, "rrectMask", opts);
@@ -1574,10 +1580,10 @@
     } else {
         f->codeAppend ("int rrectMask = 0;");
         f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
-        f->codeAppend (    "highp float2 shapePt = ");
+        f->codeAppend (    "highfloat2 shapePt = ");
         this->interpolateAtSample(f, *coords.fVarying, "i", nullptr);
         f->codeAppend (    ";");
-        f->codeAppendf(    "highp float2 rrectPt = max(abs(shapePt) - %s.xy, float2(0)) * %s.zw;",
+        f->codeAppendf(    "highfloat2 rrectPt = max(abs(shapePt) - %s.xy, highfloat2(0)) * %s.zw;",
                            rrect, rrect);
         f->codeAppendf(    "if (%s(rrectPt) < 1.0) rrectMask |= (1 << i);", fSquareFun.c_str());
         f->codeAppend ("}");
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 91b54c8..50077a8 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -564,7 +564,7 @@
             // emit attributes
             varyingHandler->emitAttributes(qe);
 
-            GrGLSLVertToFrag v(kVec4f_GrSLType);
+            GrGLSLVertToFrag v(kHalf4_GrSLType);
             varyingHandler->addVarying("QuadEdge", &v);
             vertBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.fInQuadEdge->fName);
 
@@ -585,17 +585,17 @@
                                  qe.fLocalMatrix,
                                  args.fFPCoordTransformHandler);
 
-            fragBuilder->codeAppendf("float edgeAlpha;");
+            fragBuilder->codeAppendf("half edgeAlpha;");
 
             // keep the derivative instructions outside the conditional
-            fragBuilder->codeAppendf("float2 duvdx = dFdx(%s.xy);", v.fsIn());
-            fragBuilder->codeAppendf("float2 duvdy = dFdy(%s.xy);", v.fsIn());
+            fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn());
+            fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn());
             fragBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(), v.fsIn());
             // today we know z and w are in device space. We could use derivatives
             fragBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);", v.fsIn(),
                                      v.fsIn());
             fragBuilder->codeAppendf ("} else {");
-            fragBuilder->codeAppendf("float2 gF = float2(2.0*%s.x*duvdx.x - duvdx.y,"
+            fragBuilder->codeAppendf("half2 gF = half2(2.0*%s.x*duvdx.x - duvdx.y,"
                                      "               2.0*%s.x*duvdy.x - duvdy.y);",
                                      v.fsIn(), v.fsIn());
             fragBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(), v.fsIn(),
@@ -603,7 +603,7 @@
             fragBuilder->codeAppendf("edgeAlpha = "
                                      "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);}");
 
-            fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage);
+            fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
         }
 
         static inline void GenKey(const GrGeometryProcessor& gp,
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index 640e8a9..76f1ff4 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -887,12 +887,12 @@
     varyingHandler->emitAttributes(dce);
 
     // XY are dashPos, Z is dashInterval
-    GrGLSLVertToFrag dashParams(kVec3f_GrSLType);
+    GrGLSLVertToFrag dashParams(kHalf3_GrSLType);
     varyingHandler->addVarying("DashParam", &dashParams);
     vertBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.inDashParams()->fName);
 
     // x refers to circle radius - 0.5, y refers to cicle's center x coord
-    GrGLSLVertToFrag circleParams(kVec2f_GrSLType);
+    GrGLSLVertToFrag circleParams(kHalf2_GrSLType);
     varyingHandler->addVarying("CircleParams", &circleParams);
     vertBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->fName);
 
@@ -913,21 +913,21 @@
                          args.fFPCoordTransformHandler);
 
     // transforms all points so that we can compare them to our test circle
-    fragBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
+    fragBuilder->codeAppendf("half xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
                              dashParams.fsIn(), dashParams.fsIn(), dashParams.fsIn(),
                              dashParams.fsIn());
-    fragBuilder->codeAppendf("float2 fragPosShifted = float2(xShifted, %s.y);", dashParams.fsIn());
-    fragBuilder->codeAppendf("float2 center = float2(%s.y, 0.0);", circleParams.fsIn());
-    fragBuilder->codeAppend("float dist = length(center - fragPosShifted);");
+    fragBuilder->codeAppendf("half2 fragPosShifted = half2(xShifted, %s.y);", dashParams.fsIn());
+    fragBuilder->codeAppendf("half2 center = half2(%s.y, 0.0);", circleParams.fsIn());
+    fragBuilder->codeAppend("half dist = length(center - fragPosShifted);");
     if (dce.aaMode() != AAMode::kNone) {
-        fragBuilder->codeAppendf("float diff = dist - %s.x;", circleParams.fsIn());
+        fragBuilder->codeAppendf("half diff = dist - %s.x;", circleParams.fsIn());
         fragBuilder->codeAppend("diff = 1.0 - diff;");
-        fragBuilder->codeAppend("float alpha = clamp(diff, 0.0, 1.0);");
+        fragBuilder->codeAppend("half alpha = clamp(diff, 0.0, 1.0);");
     } else {
-        fragBuilder->codeAppendf("float alpha = 1.0;");
+        fragBuilder->codeAppendf("half alpha = 1.0;");
         fragBuilder->codeAppendf("alpha *=  dist < %s.x + 0.5 ? 1.0 : 0.0;", circleParams.fsIn());
     }
-    fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage);
+    fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
 }
 
 void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman,
@@ -1090,13 +1090,13 @@
     varyingHandler->emitAttributes(de);
 
     // XY refers to dashPos, Z is the dash interval length
-    GrGLSLVertToFrag inDashParams(kVec3f_GrSLType);
+    GrGLSLVertToFrag inDashParams(kHighFloat3_GrSLType);
     varyingHandler->addVarying("DashParams", &inDashParams, GrSLPrecision::kHigh_GrSLPrecision);
     vertBuilder->codeAppendf("%s = %s;", inDashParams.vsOut(), de.inDashParams()->fName);
 
     // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
     // respectively.
-    GrGLSLVertToFrag inRectParams(kVec4f_GrSLType);
+    GrGLSLVertToFrag inRectParams(kHighFloat4_GrSLType);
     varyingHandler->addVarying("RectParams", &inRectParams, GrSLPrecision::kHigh_GrSLPrecision);
     vertBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->fName);
 
@@ -1117,14 +1117,14 @@
                          args.fFPCoordTransformHandler);
 
     // transforms all points so that we can compare them to our test rect
-    fragBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
+    fragBuilder->codeAppendf("half xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
                              inDashParams.fsIn(), inDashParams.fsIn(), inDashParams.fsIn(),
                              inDashParams.fsIn());
-    fragBuilder->codeAppendf("float2 fragPosShifted = float2(xShifted, %s.y);", inDashParams.fsIn());
+    fragBuilder->codeAppendf("half2 fragPosShifted = half2(xShifted, %s.y);", inDashParams.fsIn());
     if (de.aaMode() == AAMode::kCoverage) {
         // The amount of coverage removed in x and y by the edges is computed as a pair of negative
         // numbers, xSub and ySub.
-        fragBuilder->codeAppend("float xSub, ySub;");
+        fragBuilder->codeAppend("half xSub, ySub;");
         fragBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRectParams.fsIn());
         fragBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRectParams.fsIn());
         fragBuilder->codeAppendf("ySub = min(fragPosShifted.y - %s.y, 0.0);", inRectParams.fsIn());
@@ -1132,24 +1132,24 @@
         // Now compute coverage in x and y and multiply them to get the fraction of the pixel
         // covered.
         fragBuilder->codeAppendf(
-            "float alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));");
+            "half alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));");
     } else if (de.aaMode() == AAMode::kCoverageWithMSAA) {
         // For MSAA, we don't modulate the alpha by the Y distance, since MSAA coverage will handle
         // AA on the the top and bottom edges. The shader is only responsible for intra-dash alpha.
-        fragBuilder->codeAppend("float xSub;");
+        fragBuilder->codeAppend("half xSub;");
         fragBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRectParams.fsIn());
         fragBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRectParams.fsIn());
         // Now compute coverage in x to get the fraction of the pixel covered.
-        fragBuilder->codeAppendf("float alpha = (1.0 + max(xSub, -1.0));");
+        fragBuilder->codeAppendf("half alpha = (1.0 + max(xSub, -1.0));");
     } else {
         // Assuming the bounding geometry is tight so no need to check y values
-        fragBuilder->codeAppendf("float alpha = 1.0;");
+        fragBuilder->codeAppendf("half alpha = 1.0;");
         fragBuilder->codeAppendf("alpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;",
                                  inRectParams.fsIn());
         fragBuilder->codeAppendf("alpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;",
                                  inRectParams.fsIn());
     }
-    fragBuilder->codeAppendf("%s = float4(alpha);", args.fOutputCoverage);
+    fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
 }
 
 void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman,
diff --git a/src/gpu/ops/GrMSAAPathRenderer.cpp b/src/gpu/ops/GrMSAAPathRenderer.cpp
index 3fb1acd..45fe9f3 100644
--- a/src/gpu/ops/GrMSAAPathRenderer.cpp
+++ b/src/gpu/ops/GrMSAAPathRenderer.cpp
@@ -140,7 +140,7 @@
             varyingHandler->emitAttributes(qp);
             varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor);
 
-            GrGLSLVertToFrag uv(kVec2f_GrSLType);
+            GrGLSLVertToFrag uv(kHighFloat2_GrSLType);
             varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
             vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
 
@@ -156,7 +156,7 @@
             GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
             fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
                                                                         uv.fsIn());
-            fsBuilder->codeAppendf("%s = float4(1.0);", args.fOutputCoverage);
+            fsBuilder->codeAppendf("%s = half4(1.0);", args.fOutputCoverage);
         }
 
         static inline void GenKey(const GrGeometryProcessor& gp,
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 243e38b..5580e52 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -119,21 +119,21 @@
 
             // emit attributes
             varyingHandler->emitAttributes(cgp);
-            fragBuilder->codeAppend("highp float4 circleEdge;");
+            fragBuilder->codeAppend("highfloat4 circleEdge;");
             varyingHandler->addPassThroughAttribute(cgp.fInCircleEdge, "circleEdge",
                                                     kHigh_GrSLPrecision);
             if (cgp.fInClipPlane) {
-                fragBuilder->codeAppend("float3 clipPlane;");
+                fragBuilder->codeAppend("half3 clipPlane;");
                 varyingHandler->addPassThroughAttribute(cgp.fInClipPlane, "clipPlane");
             }
             if (cgp.fInIsectPlane) {
                 SkASSERT(cgp.fInClipPlane);
-                fragBuilder->codeAppend("float3 isectPlane;");
+                fragBuilder->codeAppend("half3 isectPlane;");
                 varyingHandler->addPassThroughAttribute(cgp.fInIsectPlane, "isectPlane");
             }
             if (cgp.fInUnionPlane) {
                 SkASSERT(cgp.fInClipPlane);
-                fragBuilder->codeAppend("float3 unionPlane;");
+                fragBuilder->codeAppend("half3 unionPlane;");
                 varyingHandler->addPassThroughAttribute(cgp.fInUnionPlane, "unionPlane");
             }
 
@@ -152,19 +152,19 @@
                                  cgp.fLocalMatrix,
                                  args.fFPCoordTransformHandler);
 
-            fragBuilder->codeAppend("highp float d = length(circleEdge.xy);");
-            fragBuilder->codeAppend("float distanceToOuterEdge = circleEdge.z * (1.0 - d);");
-            fragBuilder->codeAppend("float edgeAlpha = clamp(distanceToOuterEdge, 0.0, 1.0);");
+            fragBuilder->codeAppend("highfloat d = length(circleEdge.xy);");
+            fragBuilder->codeAppend("half distanceToOuterEdge = circleEdge.z * (1.0 - d);");
+            fragBuilder->codeAppend("half edgeAlpha = clamp(distanceToOuterEdge, 0.0, 1.0);");
             if (cgp.fStroke) {
                 fragBuilder->codeAppend(
-                        "float distanceToInnerEdge = circleEdge.z * (d - circleEdge.w);");
-                fragBuilder->codeAppend("float innerAlpha = clamp(distanceToInnerEdge, 0.0, 1.0);");
+                        "half distanceToInnerEdge = circleEdge.z * (d - circleEdge.w);");
+                fragBuilder->codeAppend("half innerAlpha = clamp(distanceToInnerEdge, 0.0, 1.0);");
                 fragBuilder->codeAppend("edgeAlpha *= innerAlpha;");
             }
 
             if (cgp.fInClipPlane) {
                 fragBuilder->codeAppend(
-                        "float clip = clamp(circleEdge.z * dot(circleEdge.xy, clipPlane.xy) + "
+                        "half clip = clamp(circleEdge.z * dot(circleEdge.xy, clipPlane.xy) + "
                         "clipPlane.z, 0.0, 1.0);");
                 if (cgp.fInIsectPlane) {
                     fragBuilder->codeAppend(
@@ -178,7 +178,7 @@
                 }
                 fragBuilder->codeAppend("edgeAlpha *= clip;");
             }
-            fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage);
+            fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
         }
 
         static void GenKey(const GrGeometryProcessor& gp,
@@ -275,12 +275,12 @@
             // emit attributes
             varyingHandler->emitAttributes(egp);
 
-            GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType);
+            GrGLSLVertToFrag ellipseOffsets(kHalf2_GrSLType);
             varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets);
             vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(),
                                      egp.fInEllipseOffset->fName);
 
-            GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType);
+            GrGLSLVertToFrag ellipseRadii(kHalf4_GrSLType);
             varyingHandler->addVarying("EllipseRadii", &ellipseRadii);
             vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii->fName);
 
@@ -301,16 +301,16 @@
                                  args.fFPCoordTransformHandler);
 
             // for outer curve
-            fragBuilder->codeAppendf("float2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(),
+            fragBuilder->codeAppendf("half2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(),
                                      ellipseRadii.fsIn());
-            fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;");
-            fragBuilder->codeAppendf("float2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn());
-            fragBuilder->codeAppend("float grad_dot = dot(grad, grad);");
+            fragBuilder->codeAppend("half test = dot(scaledOffset, scaledOffset) - 1.0;");
+            fragBuilder->codeAppendf("half2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn());
+            fragBuilder->codeAppend("half grad_dot = dot(grad, grad);");
 
             // avoid calling inversesqrt on zero.
             fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
-            fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);");
-            fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
+            fragBuilder->codeAppend("half invlen = inversesqrt(grad_dot);");
+            fragBuilder->codeAppend("half edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
 
             // for inner curve
             if (egp.fStroke) {
@@ -322,7 +322,7 @@
                 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);");
             }
 
-            fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage);
+            fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
         }
 
         static void GenKey(const GrGeometryProcessor& gp,
@@ -417,11 +417,11 @@
             // emit attributes
             varyingHandler->emitAttributes(diegp);
 
-            GrGLSLVertToFrag offsets0(kVec2f_GrSLType);
+            GrGLSLVertToFrag offsets0(kHalf2_GrSLType);
             varyingHandler->addVarying("EllipseOffsets0", &offsets0);
             vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), diegp.fInEllipseOffsets0->fName);
 
-            GrGLSLVertToFrag offsets1(kVec2f_GrSLType);
+            GrGLSLVertToFrag offsets1(kHalf2_GrSLType);
             varyingHandler->addVarying("EllipseOffsets1", &offsets1);
             vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), diegp.fInEllipseOffsets1->fName);
 
@@ -445,25 +445,25 @@
                                  args.fFPCoordTransformHandler);
 
             // for outer curve
-            fragBuilder->codeAppendf("float2 scaledOffset = %s.xy;", offsets0.fsIn());
-            fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;");
-            fragBuilder->codeAppendf("float2 duvdx = dFdx(%s);", offsets0.fsIn());
-            fragBuilder->codeAppendf("float2 duvdy = dFdy(%s);", offsets0.fsIn());
+            fragBuilder->codeAppendf("half2 scaledOffset = %s.xy;", offsets0.fsIn());
+            fragBuilder->codeAppend("half test = dot(scaledOffset, scaledOffset) - 1.0;");
+            fragBuilder->codeAppendf("half2 duvdx = dFdx(%s);", offsets0.fsIn());
+            fragBuilder->codeAppendf("half2 duvdy = dFdy(%s);", offsets0.fsIn());
             fragBuilder->codeAppendf(
-                    "float2 grad = float2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
-                    "                 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);",
+                    "half2 grad = half2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
+                    "                  2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);",
                     offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn());
 
-            fragBuilder->codeAppend("float grad_dot = dot(grad, grad);");
+            fragBuilder->codeAppend("half grad_dot = dot(grad, grad);");
             // avoid calling inversesqrt on zero.
             fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
-            fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);");
+            fragBuilder->codeAppend("half invlen = inversesqrt(grad_dot);");
             if (DIEllipseStyle::kHairline == diegp.fStyle) {
                 // can probably do this with one step
-                fragBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);");
+                fragBuilder->codeAppend("half edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);");
                 fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);");
             } else {
-                fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
+                fragBuilder->codeAppend("half edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);");
             }
 
             // for inner curve
@@ -473,14 +473,14 @@
                 fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn());
                 fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn());
                 fragBuilder->codeAppendf(
-                        "grad = float2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
-                        "            2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);",
+                        "grad = half2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,"
+                        "             2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);",
                         offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn());
                 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));");
                 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);");
             }
 
-            fragBuilder->codeAppendf("%s = float4(edgeAlpha);", args.fOutputCoverage);
+            fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
         }
 
         static void GenKey(const GrGeometryProcessor& gp,
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index e03d98a..732b9c9 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -115,7 +115,7 @@
                     args.fVaryingHandler->addPassThroughAttribute(&textureGP.fColors,
                                                                   args.fOutputColor);
                 }
-                args.fFragBuilder->codeAppend("highp float2 texCoord;");
+                args.fFragBuilder->codeAppend("highfloat2 texCoord;");
                 args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureCoords, "texCoord",
                                                               kHigh_GrSLPrecision);
                 if (textureGP.numTextureSamplers() > 1) {
@@ -134,7 +134,7 @@
                         args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
                                                                           args.fTexSamplers[i],
                                                                           "texCoord",
-                                                                          kVec2f_GrSLType,
+                                                                          kHighFloat2_GrSLType,
                                                                           &fColorSpaceXformHelper);
                         args.fFragBuilder->codeAppend("; break;");
                     }
@@ -144,11 +144,11 @@
                     args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
                                                                       args.fTexSamplers[0],
                                                                       "texCoord",
-                                                                      kVec2f_GrSLType,
+                                                                      kHighFloat2_GrSLType,
                                                                       &fColorSpaceXformHelper);
                 }
                 args.fFragBuilder->codeAppend(";");
-                args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+                args.fFragBuilder->codeAppendf("%s = highfloat4(1);", args.fOutputCoverage);
             }
             GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
         };
diff --git a/src/gpu/vk/GrVkCopyManager.cpp b/src/gpu/vk/GrVkCopyManager.cpp
index 2b54d37..7ab47e9 100644
--- a/src/gpu/vk/GrVkCopyManager.cpp
+++ b/src/gpu/vk/GrVkCopyManager.cpp
@@ -44,17 +44,17 @@
         "#extension GL_ARB_shading_language_420pack : enable\n"
 
         "layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
-            "mediump float4 uPosXform;"
-            "mediump float4 uTexCoordXform;"
+            "half4 uPosXform;"
+            "half4 uTexCoordXform;"
         "};"
-        "layout(location = 0) in highp float2 inPosition;"
-        "layout(location = 1) out mediump float2 vTexCoord;"
+        "layout(location = 0) in highfloat2 inPosition;"
+        "layout(location = 1) out half2 vTexCoord;"
 
         "// Copy Program VS\n"
         "void main() {"
             "vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;"
             "gl_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
-            "gl_Position.zw = float2(0, 1);"
+            "gl_Position.zw = half2(0, 1);"
         "}"
     );
 
@@ -63,11 +63,9 @@
         "#extension GL_ARB_separate_shader_objects : enable\n"
         "#extension GL_ARB_shading_language_420pack : enable\n"
 
-        "precision mediump float;"
-
-        "layout(set = 1, binding = 0) uniform mediump sampler2D uTextureSampler;"
-        "layout(location = 1) in mediump float2 vTexCoord;"
-        "layout(location = 0, index = 0) out mediump float4 fsColorOut;"
+        "layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
+        "layout(location = 1) in half2 vTexCoord;"
+        "layout(location = 0, index = 0) out half4 fsColorOut;"
 
         "// Copy Program FS\n"
         "void main() {"
diff --git a/src/gpu/vk/GrVkPipelineStateDataManager.cpp b/src/gpu/vk/GrVkPipelineStateDataManager.cpp
index ee0b6a7..378ec0f 100644
--- a/src/gpu/vk/GrVkPipelineStateDataManager.cpp
+++ b/src/gpu/vk/GrVkPipelineStateDataManager.cpp
@@ -59,7 +59,7 @@
 
 void GrVkPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kInt_GrSLType);
+    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     void* buffer = this->getBufferPtrAndMarkDirty(uni);
     memcpy(buffer, &i, sizeof(int32_t));
@@ -69,7 +69,7 @@
                                           int arrayCount,
                                           const int32_t v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kInt_GrSLType);
+    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
     SkASSERT(arrayCount > 0);
     SkASSERT(arrayCount <= uni.fArrayCount ||
              (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@@ -85,7 +85,7 @@
 
 void GrVkPipelineStateDataManager::set1f(UniformHandle u, float v0) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kFloat_GrSLType);
+    SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     void* buffer = this->getBufferPtrAndMarkDirty(uni);
     SkASSERT(sizeof(float) == 4);
@@ -96,7 +96,7 @@
                                           int arrayCount,
                                           const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kFloat_GrSLType);
+    SkASSERT(uni.fType == kHighFloat_GrSLType || uni.fType == kHalf_GrSLType);
     SkASSERT(arrayCount > 0);
     SkASSERT(arrayCount <= uni.fArrayCount ||
              (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@@ -112,7 +112,7 @@
 
 void GrVkPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec2f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     void* buffer = this->getBufferPtrAndMarkDirty(uni);
     SkASSERT(sizeof(float) == 4);
@@ -124,7 +124,7 @@
                                           int arrayCount,
                                           const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec2f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
     SkASSERT(arrayCount > 0);
     SkASSERT(arrayCount <= uni.fArrayCount ||
              (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@@ -140,7 +140,7 @@
 
 void GrVkPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec3f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     void* buffer = this->getBufferPtrAndMarkDirty(uni);
     SkASSERT(sizeof(float) == 4);
@@ -152,7 +152,7 @@
                                           int arrayCount,
                                           const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec3f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
     SkASSERT(arrayCount > 0);
     SkASSERT(arrayCount <= uni.fArrayCount ||
              (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@@ -172,7 +172,7 @@
                                          float v2,
                                          float v3) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec4f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
     SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
     void* buffer = this->getBufferPtrAndMarkDirty(uni);
     SkASSERT(sizeof(float) == 4);
@@ -184,7 +184,7 @@
                                           int arrayCount,
                                           const float v[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kVec4f_GrSLType);
+    SkASSERT(uni.fType == kHighFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
     SkASSERT(arrayCount > 0);
     SkASSERT(arrayCount <= uni.fArrayCount ||
              (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
@@ -230,7 +230,8 @@
                                                                       int arrayCount,
                                                                      const float matrices[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat22f_GrSLType + (N - 2));
+    SkASSERT(uni.fType == kHighFloat2x2_GrSLType + (N - 2) ||
+             uni.fType == kHalf2x2_GrSLType + (N - 2));
     SkASSERT(arrayCount > 0);
     SkASSERT(arrayCount <= uni.fArrayCount ||
              (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp
index 98a2751..abd4b08 100644
--- a/src/gpu/vk/GrVkUniformHandler.cpp
+++ b/src/gpu/vk/GrVkUniformHandler.cpp
@@ -16,31 +16,40 @@
 // aligned to 16 bytes (i.e. has mask of 0xF).
 uint32_t grsltype_to_alignment_mask(GrSLType type) {
     switch(type) {
+        case kShort_GrSLType: // fall through
         case kInt_GrSLType:
             return 0x3;
+        case kUShort_GrSLType: // fall through
         case kUint_GrSLType:
             return 0x3;
-        case kFloat_GrSLType:
+        case kHalf_GrSLType: // fall through
+        case kHighFloat_GrSLType:
             return 0x3;
-        case kVec2f_GrSLType:
+        case kHalf2_GrSLType: // fall through
+        case kHighFloat2_GrSLType:
             return 0x7;
-        case kVec3f_GrSLType:
+        case kHalf3_GrSLType: // fall through
+        case kHighFloat3_GrSLType:
             return 0xF;
-        case kVec4f_GrSLType:
+        case kHalf4_GrSLType: // fall through
+        case kHighFloat4_GrSLType:
             return 0xF;
-        case kVec2us_GrSLType:
+        case kUint2_GrSLType:
             return 0x3;
-        case kVec2i_GrSLType:
+        case kInt2_GrSLType:
             return 0x7;
-        case kVec3i_GrSLType:
+        case kInt3_GrSLType:
             return 0xF;
-        case kVec4i_GrSLType:
+        case kInt4_GrSLType:
             return 0xF;
-        case kMat22f_GrSLType:
+        case kHalf2x2_GrSLType: // fall through
+        case kHighFloat2x2_GrSLType:
             return 0x7;
-        case kMat33f_GrSLType:
+        case kHalf3x3_GrSLType: // fall through
+        case kHighFloat3x3_GrSLType:
             return 0xF;
-        case kMat44f_GrSLType:
+        case kHalf4x4_GrSLType: // fall through
+        case kHighFloat4x4_GrSLType:
             return 0xF;
 
         // This query is only valid for certain types.
@@ -66,32 +75,41 @@
     so a float2x2 takes up 8 floats. */
 static inline uint32_t grsltype_to_vk_size(GrSLType type) {
     switch(type) {
+        case kShort_GrSLType: // fall through
         case kInt_GrSLType:
             return sizeof(int32_t);
+        case kUShort_GrSLType: // fall through
         case kUint_GrSLType:
             return sizeof(int32_t);
-        case kFloat_GrSLType:
+        case kHalf_GrSLType: // fall through
+        case kHighFloat_GrSLType:
             return sizeof(float);
-        case kVec2f_GrSLType:
+        case kHalf2_GrSLType: // fall through
+        case kHighFloat2_GrSLType:
             return 2 * sizeof(float);
-        case kVec3f_GrSLType:
+        case kHalf3_GrSLType: // fall through
+        case kHighFloat3_GrSLType:
             return 3 * sizeof(float);
-        case kVec4f_GrSLType:
+        case kHalf4_GrSLType: // fall through
+        case kHighFloat4_GrSLType:
             return 4 * sizeof(float);
-        case kVec2us_GrSLType:
+        case kUint2_GrSLType:
             return 2 * sizeof(uint16_t);
-        case kVec2i_GrSLType:
+        case kInt2_GrSLType:
             return 2 * sizeof(int32_t);
-        case kVec3i_GrSLType:
+        case kInt3_GrSLType:
             return 3 * sizeof(int32_t);
-        case kVec4i_GrSLType:
+        case kInt4_GrSLType:
             return 4 * sizeof(int32_t);
-        case kMat22f_GrSLType:
+        case kHalf2x2_GrSLType: // fall through
+        case kHighFloat2x2_GrSLType:
             //TODO: this will be 4 * szof(float) on std430.
             return 8 * sizeof(float);
-        case kMat33f_GrSLType:
+        case kHalf3x3_GrSLType: // fall through
+        case kHighFloat3x3_GrSLType:
             return 12 * sizeof(float);
-        case kMat44f_GrSLType:
+        case kHalf4x4_GrSLType: // fall through
+        case kHighFloat4x4_GrSLType:
             return 16 * sizeof(float);
 
         // This query is only valid for certain types.
@@ -122,7 +140,7 @@
                             int arrayCount) {
     uint32_t alignmentMask = grsltype_to_alignment_mask(type);
     // We want to use the std140 layout here, so we must make arrays align to 16 bytes.
-    if (arrayCount || type == kMat22f_GrSLType) {
+    if (arrayCount || type == kHighFloat2x2_GrSLType) {
         alignmentMask = 0xF;
     }
     uint32_t offsetDiff = *currentOffset & alignmentMask;
diff --git a/src/gpu/vk/GrVkVaryingHandler.cpp b/src/gpu/vk/GrVkVaryingHandler.cpp
index 5912098..887a422 100644
--- a/src/gpu/vk/GrVkVaryingHandler.cpp
+++ b/src/gpu/vk/GrVkVaryingHandler.cpp
@@ -13,27 +13,34 @@
     switch(type) {
         case kVoid_GrSLType:
             return 0;
-        case kFloat_GrSLType:
+        case kHighFloat_GrSLType: // fall through
+        case kHalf_GrSLType:
             return 1;
-        case kVec2f_GrSLType:
+        case kHighFloat2_GrSLType: // fall through
+        case kHalf2_GrSLType:
             return 1;
-        case kVec3f_GrSLType:
+        case kHighFloat3_GrSLType:
+        case kHalf3_GrSLType:
             return 1;
-        case kVec4f_GrSLType:
+        case kHighFloat4_GrSLType:
+        case kHalf4_GrSLType:
             return 1;
-        case kVec2us_GrSLType:
+        case kUint2_GrSLType:
             return 1;
-        case kVec2i_GrSLType:
+        case kInt2_GrSLType:
             return 1;
-        case kVec3i_GrSLType:
+        case kInt3_GrSLType:
             return 1;
-        case kVec4i_GrSLType:
+        case kInt4_GrSLType:
             return 1;
-        case kMat22f_GrSLType:
+        case kHighFloat2x2_GrSLType:
+        case kHalf2x2_GrSLType:
             return 2;
-        case kMat33f_GrSLType:
+        case kHighFloat3x3_GrSLType:
+        case kHalf3x3_GrSLType:
             return 3;
-        case kMat44f_GrSLType:
+        case kHighFloat4x4_GrSLType:
+        case kHalf4x4_GrSLType:
             return 4;
         case kTexture2DSampler_GrSLType:
             return 0;
@@ -47,9 +54,11 @@
              return 0;
         case kBool_GrSLType:
              return 1;
-        case kInt_GrSLType:
+        case kInt_GrSLType: // fall through
+        case kShort_GrSLType:
              return 1;
         case kUint_GrSLType:
+        case kUShort_GrSLType: // fall through
              return 1;
         case kTexture2D_GrSLType:
              return 0;
diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp
index 0d951cd..bdbd5bd 100644
--- a/src/shaders/SkPerlinNoiseShader.cpp
+++ b/src/shaders/SkPerlinNoiseShader.cpp
@@ -816,15 +816,13 @@
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
 
-    fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                    "baseFrequency");
     const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
 
     const char* stitchDataUni = nullptr;
     if (pne.stitchTiles()) {
-        fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
+        fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                     "stitchData");
         stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
     }
@@ -849,29 +847,29 @@
     const char* inc8bit     = "0.00390625";  // 1.0 / 256.0
     // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
     // [-1,1] vector and perform a dot product between that vector and the provided vector.
-    const char* dotLattice  = "dot(((%s.ga + %s.rb * float2(%s)) * float2(2.0) - float2(1.0)), %s);";
+    const char* dotLattice  = "dot(((%s.ga + %s.rb * half2(%s)) * half2(2.0) - half2(1.0)), %s);";
 
     // Add noise function
     static const GrShaderVar gPerlinNoiseArgs[] =  {
-        GrShaderVar(chanCoord, kFloat_GrSLType),
-        GrShaderVar(noiseVec, kVec2f_GrSLType)
+        GrShaderVar(chanCoord, kHalf_GrSLType),
+        GrShaderVar(noiseVec, kHalf2_GrSLType)
     };
 
     static const GrShaderVar gPerlinNoiseStitchArgs[] =  {
-        GrShaderVar(chanCoord, kFloat_GrSLType),
-        GrShaderVar(noiseVec, kVec2f_GrSLType),
-        GrShaderVar(stitchData, kVec2f_GrSLType)
+        GrShaderVar(chanCoord, kHalf_GrSLType),
+        GrShaderVar(noiseVec, kHalf2_GrSLType),
+        GrShaderVar(stitchData, kHalf2_GrSLType)
     };
 
     SkString noiseCode;
 
-    noiseCode.appendf("\tfloat4 %s;\n", floorVal);
+    noiseCode.appendf("\thalf4 %s;\n", floorVal);
     noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
-    noiseCode.appendf("\t%s.zw = %s.xy + float2(1.0);\n", floorVal, floorVal);
-    noiseCode.appendf("\tfloat2 %s = fract(%s);\n", fractVal, noiseVec);
+    noiseCode.appendf("\t%s.zw = %s.xy + half2(1.0);\n", floorVal, floorVal);
+    noiseCode.appendf("\thalf2 %s = fract(%s);\n", fractVal, noiseVec);
 
     // smooth curve : t * t * (3 - 2 * t)
-    noiseCode.appendf("\n\tfloat2 %s = %s * %s * (float2(3.0) - float2(2.0) * %s);",
+    noiseCode.appendf("\n\thalf2 %s = %s * %s * (half2(3.0) - half2(2.0) * %s);",
         noiseSmooth, fractVal, fractVal, fractVal);
 
     // Adjust frequencies if we're stitching tiles
@@ -887,28 +885,28 @@
     }
 
     // Get texture coordinates and normalize
-    noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / float4(256.0));\n",
+    noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / half4(256.0));\n",
         floorVal, floorVal);
 
     // Get permutation for x
     {
         SkString xCoords("");
-        xCoords.appendf("float2(%s.x, 0.5)", floorVal);
+        xCoords.appendf("half2(%s.x, 0.5)", floorVal);
 
-        noiseCode.appendf("\n\tfloat2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
+        noiseCode.appendf("\n\thalf2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
-                                         kVec2f_GrSLType);
+                                         kHalf2_GrSLType);
         noiseCode.append(".r;");
     }
 
     // Get permutation for x + 1
     {
         SkString xCoords("");
-        xCoords.appendf("float2(%s.z, 0.5)", floorVal);
+        xCoords.appendf("half2(%s.z, 0.5)", floorVal);
 
         noiseCode.appendf("\n\t%s.y = ", latticeIdx);
         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
-                                         kVec2f_GrSLType);
+                                         kHalf2_GrSLType);
         noiseCode.append(".r;");
     }
 
@@ -919,21 +917,21 @@
     // (or 0.484368 here). The following rounding operation prevents these precision issues from
     // affecting the result of the noise by making sure that we only have multiples of 1/255.
     // (Note that 1/255 is about 0.003921569, which is the value used here).
-    noiseCode.appendf("\n\t%s = floor(%s * float2(255.0) + float2(0.5)) * float2(0.003921569);",
+    noiseCode.appendf("\n\t%s = floor(%s * half2(255.0) + half2(0.5)) * half2(0.003921569);",
                       latticeIdx, latticeIdx);
 #endif
 
     // Get (x,y) coordinates with the permutated x
-    noiseCode.appendf("\n\tfloat4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
+    noiseCode.appendf("\n\thalf4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
 
-    noiseCode.appendf("\n\n\tfloat2 %s;", uv);
+    noiseCode.appendf("\n\n\thalf2 %s;", uv);
     // Compute u, at offset (0,0)
     {
         SkString latticeCoords("");
-        latticeCoords.appendf("float2(%s.x, %s)", bcoords, chanCoord);
-        noiseCode.appendf("\n\tfloat4 %s = ", lattice);
+        latticeCoords.appendf("half2(%s.x, %s)", bcoords, chanCoord);
+        noiseCode.appendf("\n\thalf4 %s = ", lattice);
         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
-                                         kVec2f_GrSLType);
+                                         kHalf2_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
     }
@@ -942,26 +940,26 @@
     // Compute v, at offset (-1,0)
     {
         SkString latticeCoords("");
-        latticeCoords.appendf("float2(%s.y, %s)", bcoords, chanCoord);
+        latticeCoords.appendf("half2(%s.y, %s)", bcoords, chanCoord);
         noiseCode.append("\n\tlattice = ");
         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
-                                         kVec2f_GrSLType);
+                                         kHalf2_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
     }
 
     // Compute 'a' as a linear interpolation of 'u' and 'v'
-    noiseCode.appendf("\n\tfloat2 %s;", ab);
+    noiseCode.appendf("\n\thalf2 %s;", ab);
     noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
 
     noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
     // Compute v, at offset (-1,-1)
     {
         SkString latticeCoords("");
-        latticeCoords.appendf("float2(%s.w, %s)", bcoords, chanCoord);
+        latticeCoords.appendf("half2(%s.w, %s)", bcoords, chanCoord);
         noiseCode.append("\n\tlattice = ");
         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
-                                         kVec2f_GrSLType);
+                                         kHalf2_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
     }
@@ -970,10 +968,10 @@
     // Compute u, at offset (0,-1)
     {
         SkString latticeCoords("");
-        latticeCoords.appendf("float2(%s.z, %s)", bcoords, chanCoord);
+        latticeCoords.appendf("half2(%s.z, %s)", bcoords, chanCoord);
         noiseCode.append("\n\tlattice = ");
         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
-                                         kVec2f_GrSLType);
+                                         kHalf2_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
     }
@@ -985,28 +983,28 @@
 
     SkString noiseFuncName;
     if (pne.stitchTiles()) {
-        fragBuilder->emitFunction(kFloat_GrSLType,
+        fragBuilder->emitFunction(kHalf_GrSLType,
                                   "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
                                   gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
     } else {
-        fragBuilder->emitFunction(kFloat_GrSLType,
+        fragBuilder->emitFunction(kHalf_GrSLType,
                                   "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
                                   gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
     }
 
     // There are rounding errors if the floor operation is not performed here
-    fragBuilder->codeAppendf("\n\t\tfloat2 %s = floor(%s.xy) * %s;",
+    fragBuilder->codeAppendf("\n\t\thalf2 %s = floor(%s.xy) * %s;",
                              noiseVec, vCoords.c_str(), baseFrequencyUni);
 
     // Clear the color accumulator
-    fragBuilder->codeAppendf("\n\t\t%s = float4(0.0);", args.fOutputColor);
+    fragBuilder->codeAppendf("\n\t\t%s = half4(0.0);", args.fOutputColor);
 
     if (pne.stitchTiles()) {
         // Set up TurbulenceInitial stitch values.
-        fragBuilder->codeAppendf("\n\t\tfloat2 %s = %s;", stitchData, stitchDataUni);
+        fragBuilder->codeAppendf("\n\t\thalf2 %s = %s;", stitchData, stitchDataUni);
     }
 
-    fragBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
+    fragBuilder->codeAppendf("\n\t\thalf %s = 1.0;", ratio);
 
     // Loop over all octaves
     fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
@@ -1017,7 +1015,7 @@
     }
     if (pne.stitchTiles()) {
         fragBuilder->codeAppendf(
-            "float4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
+            "half4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
                  "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
             noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
             noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
@@ -1025,7 +1023,7 @@
             noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
     } else {
         fragBuilder->codeAppendf(
-            "float4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
+            "half4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
                  "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
             noiseFuncName.c_str(), chanCoordR, noiseVec,
             noiseFuncName.c_str(), chanCoordG, noiseVec,
@@ -1037,18 +1035,18 @@
     }
     fragBuilder->codeAppendf(" * %s;", ratio);
 
-    fragBuilder->codeAppendf("\n\t\t\t%s *= float2(2.0);", noiseVec);
+    fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", noiseVec);
     fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
 
     if (pne.stitchTiles()) {
-        fragBuilder->codeAppendf("\n\t\t\t%s *= float2(2.0);", stitchData);
+        fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", stitchData);
     }
     fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
 
     if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
         // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
         // by fractalNoise and (turbulenceFunctionResult) by turbulence.
-        fragBuilder->codeAppendf("\n\t\t%s = %s * float4(0.5) + float4(0.5);",
+        fragBuilder->codeAppendf("\n\t\t%s = %s * half4(0.5) + half4(0.5);",
                                args.fOutputColor,args.fOutputColor);
     }
 
@@ -1056,7 +1054,7 @@
     fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
 
     // Pre-multiply the result
-    fragBuilder->codeAppendf("\n\t\t%s = float4(%s.rgb * %s.aaa, %s.a);\n",
+    fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
                              args.fOutputColor, args.fOutputColor,
                              args.fOutputColor, args.fOutputColor);
 }
@@ -1235,133 +1233,130 @@
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
 
-    fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                   kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                    "baseFrequency");
     const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
 
-    fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                       kFloat_GrSLType, kDefault_GrSLPrecision,
-                                       "z");
+    fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "z");
     const char* zUni = uniformHandler->getUniformCStr(fZUni);
 
     // fade function
     static const GrShaderVar fadeArgs[] =  {
-        GrShaderVar("t", kVec3f_GrSLType)
+        GrShaderVar("t", kHalf3_GrSLType)
     };
     SkString fadeFuncName;
-    fragBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
+    fragBuilder->emitFunction(kHalf3_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
                               fadeArgs,
                               "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
                               &fadeFuncName);
 
     // perm function
     static const GrShaderVar permArgs[] =  {
-        GrShaderVar("x", kFloat_GrSLType)
+        GrShaderVar("x", kHalf_GrSLType)
     };
     SkString permFuncName;
     SkString permCode("return ");
     // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
     // sure why. Using fract() (here and the next texture lookup) as a workaround.
-    fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "float2(fract(x / 256.0), 0.0)",
-                                     kVec2f_GrSLType);
+    fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "highfloat2(fract(x / 256.0), 0.0)",
+                                     kHalf2_GrSLType);
     permCode.append(".r * 255.0;");
-    fragBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
+    fragBuilder->emitFunction(kHalf_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
                               permCode.c_str(), &permFuncName);
 
     // grad function
     static const GrShaderVar gradArgs[] =  {
-        GrShaderVar("x", kFloat_GrSLType),
-        GrShaderVar("p", kVec3f_GrSLType)
+        GrShaderVar("x", kHalf_GrSLType),
+        GrShaderVar("p", kHalf3_GrSLType)
     };
     SkString gradFuncName;
     SkString gradCode("return dot(");
-    fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "float2(fract(x / 16.0), 0.0)",
-                                     kVec2f_GrSLType);
-    gradCode.append(".rgb * 255.0 - float3(1.0), p);");
-    fragBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
+    fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "highfloat2(fract(x / 16.0), 0.0)",
+                                     kHalf2_GrSLType);
+    gradCode.append(".rgb * 255.0 - highfloat3(1.0), p);");
+    fragBuilder->emitFunction(kHalf_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
                               gradCode.c_str(), &gradFuncName);
 
     // lerp function
     static const GrShaderVar lerpArgs[] =  {
-        GrShaderVar("a", kFloat_GrSLType),
-        GrShaderVar("b", kFloat_GrSLType),
-        GrShaderVar("w", kFloat_GrSLType)
+        GrShaderVar("a", kHalf_GrSLType),
+        GrShaderVar("b", kHalf_GrSLType),
+        GrShaderVar("w", kHalf_GrSLType)
     };
     SkString lerpFuncName;
-    fragBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
+    fragBuilder->emitFunction(kHalf_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
                               "return a + w * (b - a);", &lerpFuncName);
 
     // noise function
     static const GrShaderVar noiseArgs[] =  {
-        GrShaderVar("p", kVec3f_GrSLType),
+        GrShaderVar("p", kHalf3_GrSLType),
     };
     SkString noiseFuncName;
     SkString noiseCode;
-    noiseCode.append("float3 P = mod(floor(p), 256.0);");
+    noiseCode.append("half3 P = mod(floor(p), 256.0);");
     noiseCode.append("p -= floor(p);");
-    noiseCode.appendf("float3 f = %s(p);", fadeFuncName.c_str());
-    noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
-    noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
-    noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
-    noiseCode.appendf("float B =  %s(P.x + 1.0) + P.y;", permFuncName.c_str());
-    noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
-    noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
-    noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
+    noiseCode.appendf("half3 f = %s(p);", fadeFuncName.c_str());
+    noiseCode.appendf("half A = %s(P.x) + P.y;", permFuncName.c_str());
+    noiseCode.appendf("half AA = %s(A) + P.z;", permFuncName.c_str());
+    noiseCode.appendf("half AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
+    noiseCode.appendf("half B =  %s(P.x + 1.0) + P.y;", permFuncName.c_str());
+    noiseCode.appendf("half BA = %s(B) + P.z;", permFuncName.c_str());
+    noiseCode.appendf("half BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
+    noiseCode.appendf("half result = %s(", lerpFuncName.c_str());
     noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
                       gradFuncName.c_str(), permFuncName.c_str());
-    noiseCode.appendf("%s(%s(BA), p + float3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
+    noiseCode.appendf("%s(%s(BA), p + half3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
                       permFuncName.c_str());
-    noiseCode.appendf("%s(%s(%s(AB), p + float3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
+    noiseCode.appendf("%s(%s(%s(AB), p + half3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
                       gradFuncName.c_str(), permFuncName.c_str());
-    noiseCode.appendf("%s(%s(BB), p + float3(-1.0, -1.0, 0.0)), f.x), f.y),",
+    noiseCode.appendf("%s(%s(BB), p + half3(-1.0, -1.0, 0.0)), f.x), f.y),",
                       gradFuncName.c_str(), permFuncName.c_str());
-    noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + float3(0.0, 0.0, -1.0)),",
+    noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + half3(0.0, 0.0, -1.0)),",
                       lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
                       permFuncName.c_str());
-    noiseCode.appendf("%s(%s(BA + 1.0), p + float3(-1.0, 0.0, -1.0)), f.x),",
+    noiseCode.appendf("%s(%s(BA + 1.0), p + half3(-1.0, 0.0, -1.0)), f.x),",
                       gradFuncName.c_str(), permFuncName.c_str());
-    noiseCode.appendf("%s(%s(%s(AB + 1.0), p + float3(0.0, -1.0, -1.0)),",
+    noiseCode.appendf("%s(%s(%s(AB + 1.0), p + half3(0.0, -1.0, -1.0)),",
                       lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
-    noiseCode.appendf("%s(%s(BB + 1.0), p + float3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
+    noiseCode.appendf("%s(%s(BB + 1.0), p + half3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
                       gradFuncName.c_str(), permFuncName.c_str());
     noiseCode.append("return result;");
-    fragBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
+    fragBuilder->emitFunction(kHalf_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
                               noiseCode.c_str(), &noiseFuncName);
 
     // noiseOctaves function
     static const GrShaderVar noiseOctavesArgs[] =  {
-        GrShaderVar("p", kVec3f_GrSLType)
+        GrShaderVar("p", kHalf3_GrSLType)
     };
     SkString noiseOctavesFuncName;
     SkString noiseOctavesCode;
-    noiseOctavesCode.append("float result = 0.0;");
-    noiseOctavesCode.append("float ratio = 1.0;");
-    noiseOctavesCode.appendf("for (float i = 0.0; i < %d; i++) {", pne.octaves());
+    noiseOctavesCode.append("half result = 0.0;");
+    noiseOctavesCode.append("half ratio = 1.0;");
+    noiseOctavesCode.appendf("for (half i = 0.0; i < %d; i++) {", pne.octaves());
     noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
     noiseOctavesCode.append("p *= 2.0;");
     noiseOctavesCode.append("ratio *= 2.0;");
     noiseOctavesCode.append("}");
     noiseOctavesCode.append("return (result + 1.0) / 2.0;");
-    fragBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
+    fragBuilder->emitFunction(kHalf_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
                               noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
 
-    fragBuilder->codeAppendf("float2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
-    fragBuilder->codeAppendf("float r = %s(float3(coords, %s));", noiseOctavesFuncName.c_str(),
+    fragBuilder->codeAppendf("half2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
+    fragBuilder->codeAppendf("half r = %s(half3(coords, %s));", noiseOctavesFuncName.c_str(),
                              zUni);
-    fragBuilder->codeAppendf("float g = %s(float3(coords, %s + 0000.0));",
+    fragBuilder->codeAppendf("half g = %s(half3(coords, %s + 0000.0));",
                              noiseOctavesFuncName.c_str(), zUni);
-    fragBuilder->codeAppendf("float b = %s(float3(coords, %s + 0000.0));",
+    fragBuilder->codeAppendf("half b = %s(half3(coords, %s + 0000.0));",
                              noiseOctavesFuncName.c_str(), zUni);
-    fragBuilder->codeAppendf("float a = %s(float3(coords, %s + 0000.0));",
+    fragBuilder->codeAppendf("half a = %s(half3(coords, %s + 0000.0));",
                              noiseOctavesFuncName.c_str(), zUni);
-    fragBuilder->codeAppendf("%s = float4(r, g, b, a);", args.fOutputColor);
+    fragBuilder->codeAppendf("%s = half4(r, g, b, a);", args.fOutputColor);
 
     // Clamp values
     fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
 
     // Pre-multiply the result
-    fragBuilder->codeAppendf("\n\t\t%s = float4(%s.rgb * %s.aaa, %s.a);\n",
+    fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
                              args.fOutputColor, args.fOutputColor,
                              args.fOutputColor, args.fOutputColor);
 }
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 9d95f99..46d3ef6 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -1355,17 +1355,15 @@
                                                    const GrGradientEffect& ge) {
     if (int colorCount = color_type_to_color_count(ge.getColorType())) {
         fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
-                                                     kVec4f_GrSLType,
-                                                     kDefault_GrSLPrecision,
+                                                     kHalf4_GrSLType,
                                                      "Colors",
                                                      colorCount);
         if (kSingleHardStop_ColorType == ge.fColorType || kThree_ColorType == ge.fColorType) {
-            fExtraStopT = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType,
+            fExtraStopT = uniformHandler->addUniform(kFragment_GrShaderFlag, kHighFloat4_GrSLType,
                                                      kHigh_GrSLPrecision, "ExtraStopT");
         }
     } else {
-        fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                             kFloat_GrSLType, kDefault_GrSLPrecision,
+        fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                              "GradientYCoordFS");
     }
 }
@@ -1557,14 +1555,14 @@
     // First, apply tiling rules.
     switch (ge.fWrapMode) {
         case GrSamplerState::WrapMode::kClamp:
-            fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
+            fragBuilder->codeAppendf("half clamp_t = clamp(%s, 0.0, 1.0);", t);
             break;
         case GrSamplerState::WrapMode::kRepeat:
-            fragBuilder->codeAppendf("float clamp_t = fract(%s);", t);
+            fragBuilder->codeAppendf("half clamp_t = fract(%s);", t);
             break;
         case GrSamplerState::WrapMode::kMirrorRepeat:
-            fragBuilder->codeAppendf("float t_1 = %s - 1.0;", t);
-            fragBuilder->codeAppendf("float clamp_t = abs(t_1 - 2.0 * floor(t_1 * 0.5) - 1.0);");
+            fragBuilder->codeAppendf("half t_1 = %s - 1.0;", t);
+            fragBuilder->codeAppendf("half clamp_t = abs(t_1 - 2.0 * floor(t_1 * 0.5) - 1.0);");
             break;
     }
 
@@ -1575,8 +1573,8 @@
             // (t, 1/t, 1/(1-t), t/(1-t))
             const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
 
-            fragBuilder->codeAppend ("float4 start, end;");
-            fragBuilder->codeAppend ("float relative_t;");
+            fragBuilder->codeAppend ("half4 start, end;");
+            fragBuilder->codeAppend ("half relative_t;");
             fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT);
             fragBuilder->codeAppendf("    start = %s[0];", colors);
             fragBuilder->codeAppendf("    end   = %s[1];", colors);
@@ -1587,13 +1585,13 @@
             // Want: (t-s)/(1-s), but arrange it as: t/(1-s) - s/(1-s), for FMA form
             fragBuilder->codeAppendf("    relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT);
             fragBuilder->codeAppend ("}");
-            fragBuilder->codeAppend ("float4 colorTemp = mix(start, end, relative_t);");
+            fragBuilder->codeAppend ("half4 colorTemp = mix(start, end, relative_t);");
 
             break;
         }
 
         case kHardStopLeftEdged_ColorType: {
-            fragBuilder->codeAppendf("float4 colorTemp = mix(%s[1], %s[2], clamp_t);", colors,
+            fragBuilder->codeAppendf("half4 colorTemp = mix(%s[1], %s[2], clamp_t);", colors,
                                      colors);
             if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) {
                 fragBuilder->codeAppendf("if (%s < 0.0) {", t);
@@ -1605,7 +1603,7 @@
         }
 
         case kHardStopRightEdged_ColorType: {
-            fragBuilder->codeAppendf("float4 colorTemp = mix(%s[0], %s[1], clamp_t);", colors,
+            fragBuilder->codeAppendf("half4 colorTemp = mix(%s[0], %s[1], clamp_t);", colors,
                                      colors);
             if (GrSamplerState::WrapMode::kClamp == ge.fWrapMode) {
                 fragBuilder->codeAppendf("if (%s > 1.0) {", t);
@@ -1617,7 +1615,7 @@
         }
 
         case kTwo_ColorType: {
-            fragBuilder->codeAppendf("float4 colorTemp = mix(%s[0], %s[1], clamp_t);",
+            fragBuilder->codeAppendf("half4 colorTemp = mix(%s[0], %s[1], clamp_t);",
                                      colors, colors);
 
             break;
@@ -1627,8 +1625,8 @@
             // (t, 1/t, 1/(1-t), t/(1-t))
             const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
 
-            fragBuilder->codeAppend("float4 start, end;");
-            fragBuilder->codeAppend("float relative_t;");
+            fragBuilder->codeAppend("half4 start, end;");
+            fragBuilder->codeAppend("half relative_t;");
             fragBuilder->codeAppendf("if (clamp_t < %s.x) {", stopT);
             fragBuilder->codeAppendf("    start = %s[0];", colors);
             fragBuilder->codeAppendf("    end   = %s[1];", colors);
@@ -1639,7 +1637,7 @@
             // Want: (t-s)/(1-s), but arrange it as: t/(1-s) - s/(1-s), for FMA form
             fragBuilder->codeAppendf("    relative_t = (clamp_t * %s.z) - %s.w;", stopT, stopT);
             fragBuilder->codeAppend("}");
-            fragBuilder->codeAppend("float4 colorTemp = mix(start, end, relative_t);");
+            fragBuilder->codeAppend("half4 colorTemp = mix(start, end, relative_t);");
 
             break;
         }
@@ -1683,10 +1681,10 @@
 
     const char* fsyuni = uniformHandler->getUniformCStr(fFSYUni);
 
-    fragBuilder->codeAppendf("float2 coord = float2(%s, %s);", gradientTValue, fsyuni);
+    fragBuilder->codeAppendf("half2 coord = half2(%s, %s);", gradientTValue, fsyuni);
     fragBuilder->codeAppendf("%s = ", outputColor);
     fragBuilder->appendTextureLookupAndModulate(inputColor, texSamplers[0], "coord",
-                                                kVec2f_GrSLType, &fColorSpaceHelper);
+                                                kHighFloat2_GrSLType, &fColorSpaceHelper);
     fragBuilder->codeAppend(";");
 }
 
diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp
index 87b82fd..0e2b785a 100644
--- a/src/shaders/gradients/SkSweepGradient.cpp
+++ b/src/shaders/gradients/SkSweepGradient.cpp
@@ -198,8 +198,8 @@
     const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     this->emitUniforms(uniformHandler, ge);
-    fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
-                                                kDefault_GrSLPrecision, "SweepFSParams");
+    fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
+                                                "SweepFSParams");
     const char* tBiasScaleV = uniformHandler->getUniformCStr(fTBiasScaleUni);
 
     const SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
index b58ac2a..37e0708 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -235,8 +235,7 @@
     const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     this->emitUniforms(uniformHandler, ge);
-    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                           kVec3f_GrSLType, kDefault_GrSLPrecision,
+    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
                                            "Conical2FSParams");
 
     SkString cName("c");
@@ -255,8 +254,8 @@
     const char* coords2D;
     SkString bVar;
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-    if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
-        fragBuilder->codeAppendf("\tfloat3 interpolants = float3(%s.xy / %s.z, %s.x / %s.z);\n",
+    if (kHalf3_GrSLType == args.fTransformedCoords[0].getType()) {
+        fragBuilder->codeAppendf("\thalf3 interpolants = half3(%s.xy / %s.z, %s.x / %s.z);\n",
                                  args.fTransformedCoords[0].c_str(),
                                  args.fTransformedCoords[0].c_str(),
                                  args.fTransformedCoords[1].c_str(),
@@ -270,14 +269,14 @@
 
     // output will default to transparent black (we simply won't write anything
     // else to it if invalid, instead of discarding or returning prematurely)
-    fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
+    fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
 
     // c = (x^2)+(y^2) - params[1]
-    fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
+    fragBuilder->codeAppendf("\thalf %s = dot(%s, %s) - %s;\n",
                            cName.c_str(), coords2D, coords2D, p1.c_str());
 
     // linear case: t = -c/b
-    fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
+    fragBuilder->codeAppendf("\thalf %s = -(%s / %s);\n", tName.c_str(),
                            cName.c_str(), bVar.c_str());
 
     // if r(t) > 0, then t will be the x coordinate
@@ -525,8 +524,7 @@
     const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     this->emitUniforms(uniformHandler, ge);
-    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                           kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                            "Conical2FSParams");
     SkString tName("t");
     SkString p0; // focalX
@@ -544,19 +542,19 @@
 
     // output will default to transparent black (we simply won't write anything
     // else to it if invalid, instead of discarding or returning prematurely)
-    fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
+    fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
 
-    fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
-    fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
-    fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
+    fragBuilder->codeAppendf("\thalf xs = %s.x * %s.x;\n", coords2D, coords2D);
+    fragBuilder->codeAppendf("\thalf ys = %s.y * %s.y;\n", coords2D, coords2D);
+    fragBuilder->codeAppendf("\thalf d = xs + %s * ys;\n", p1.c_str());
 
     // Must check to see if we flipped the circle order (to make sure start radius < end radius)
     // If so we must also flip sign on sqrt
     if (!fIsFlipped) {
-        fragBuilder->codeAppendf("\tfloat %s = %s.x * %s  + sqrt(d);\n", tName.c_str(),
+        fragBuilder->codeAppendf("\thalf %s = %s.x * %s  + sqrt(d);\n", tName.c_str(),
                                  coords2D, p0.c_str());
     } else {
-        fragBuilder->codeAppendf("\tfloat %s = %s.x * %s  - sqrt(d);\n", tName.c_str(),
+        fragBuilder->codeAppendf("\thalf %s = %s.x * %s  - sqrt(d);\n", tName.c_str(),
                                  coords2D, p0.c_str());
     }
 
@@ -734,8 +732,7 @@
     const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     this->emitUniforms(uniformHandler, ge);
-    fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                           kFloat_GrSLType, kDefault_GrSLPrecision,
+    fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                            "Conical2FSParams");
     SkString tName("t");
 
@@ -749,7 +746,7 @@
     const char* coords2D = coords2DString.c_str();
 
     // t = p.x * focalX + length(p)
-    fragBuilder->codeAppendf("\tfloat %s = %s.x * %s  + length(%s);\n", tName.c_str(),
+    fragBuilder->codeAppendf("\thalf %s = %s.x * %s  + length(%s);\n", tName.c_str(),
                              coords2D, focal.c_str(), coords2D);
 
     this->emitColor(fragBuilder,
@@ -993,11 +990,9 @@
     const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     this->emitUniforms(uniformHandler, ge);
-    fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                            kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                             "Conical2FSCenter");
-    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                           kVec3f_GrSLType, kDefault_GrSLPrecision,
+    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
                                            "Conical2FSParams");
     SkString tName("t");
 
@@ -1020,10 +1015,10 @@
     // C = 1 / A
     // d = dot(e, p) + B
     // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
-    fragBuilder->codeAppendf("\tfloat pDotp = dot(%s,  %s);\n", coords2D, coords2D);
-    fragBuilder->codeAppendf("\tfloat d = dot(%s,  %s) + %s.y;\n", coords2D, center.c_str(),
+    fragBuilder->codeAppendf("\thalf pDotp = dot(%s,  %s);\n", coords2D, coords2D);
+    fragBuilder->codeAppendf("\thalf d = dot(%s,  %s) + %s.y;\n", coords2D, center.c_str(),
                              params.c_str());
-    fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
+    fragBuilder->codeAppendf("\thalf %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
                              tName.c_str(), params.c_str(), params.c_str());
 
     this->emitColor(fragBuilder,
@@ -1241,11 +1236,9 @@
     const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     this->emitUniforms(uniformHandler, ge);
-    fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                            kVec2f_GrSLType, kDefault_GrSLPrecision,
+    fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                             "Conical2FSCenter");
-    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                           kVec4f_GrSLType, kDefault_GrSLPrecision,
+    fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                            "Conical2FSParams");
     SkString tName("t");
 
@@ -1262,7 +1255,7 @@
 
     // output will default to transparent black (we simply won't write anything
     // else to it if invalid, instead of discarding or returning prematurely)
-    fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
+    fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
 
     // p = coords2D
     // e = center end
@@ -1273,18 +1266,18 @@
     // d = dot(e, p) + B
     // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
 
-    fragBuilder->codeAppendf("\tfloat pDotp = dot(%s,  %s);\n", coords2D, coords2D);
-    fragBuilder->codeAppendf("\tfloat d = dot(%s,  %s) + %s.y;\n", coords2D, center.c_str(),
+    fragBuilder->codeAppendf("\thalf pDotp = dot(%s,  %s);\n", coords2D, coords2D);
+    fragBuilder->codeAppendf("\thalf d = dot(%s,  %s) + %s.y;\n", coords2D, center.c_str(),
                              params.c_str());
-    fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
+    fragBuilder->codeAppendf("\thalf deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
                              params.c_str());
 
     // Must check to see if we flipped the circle order (to make sure start radius < end radius)
     // If so we must also flip sign on sqrt
     if (!fIsFlipped) {
-        fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
+        fragBuilder->codeAppendf("\thalf %s = d + sqrt(deter);\n", tName.c_str());
     } else {
-        fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
+        fragBuilder->codeAppendf("\thalf %s = d - sqrt(deter);\n", tName.c_str());
     }
 
     fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
diff --git a/src/sksl/SkSLCPP.h b/src/sksl/SkSLCPP.h
index 642f7c6..808e832 100644
--- a/src/sksl/SkSLCPP.h
+++ b/src/sksl/SkSLCPP.h
@@ -22,4 +22,6 @@
 
 inline SkPoint float2(float x, float y) { return SkPoint::Make(x, y); }
 
+#define half2 float2
+
 #endif
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index e84954e..9d09a87 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -51,16 +51,14 @@
 void CPPCodeGenerator::writeHeader() {
 }
 
-void CPPCodeGenerator::writePrecisionModifier() {
+bool CPPCodeGenerator::usesPrecisionModifiers() const {
+    return false;
 }
 
-void CPPCodeGenerator::writeType(const Type& type) {
-    if (type.kind() == Type::kStruct_Kind) {
-        INHERITED::writeType(type);
-    } else {
-        this->write(type.fName);
-    }
+String CPPCodeGenerator::getTypeName(const Type& type) {
+    return type.name();
 }
+
 void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
                                              Precedence parentPrecedence) {
     if (b.fOperator == Token::PERCENT) {
@@ -117,19 +115,16 @@
     INHERITED::writeIndexExpression(i);
 }
 
-static const char* default_value(const Type& type) {
-    if (type.fName == "float") {
-        return "0.0";
-    } else if (type.fName == "float2") {
-        return "float2(0.0)";
-    } else if (type.fName == "float3") {
-        return "float30.0)";
-    } else if (type.fName == "float4") {
-        return "float4(0.0)";
-    } else if (type.fName == "floatt4x4" || type.fName == "colorSpaceXform") {
+static String default_value(const Type& type) {
+    if (type.fName == "colorSpaceXform") {
         return "float4x4(1.0)";
     }
-    ABORT("unsupported default_value type\n");
+    switch (type.kind()) {
+        case Type::kScalar_Kind: return "0";
+        case Type::kVector_Kind: return type.name() + "(0)";
+        case Type::kMatrix_Kind: return type.name() + "(1)";
+        default: ABORT("unsupported default_value type\n");
+    }
 }
 
 static bool is_private(const Variable& var) {
@@ -140,7 +135,7 @@
 }
 
 void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) {
-    if (type == *fContext.fFloat_Type) {
+    if (type.isFloat()) {
         this->write("%f");
         fFormatArgs.push_back(cppCode);
     } else if (type == *fContext.fInt_Type) {
@@ -149,12 +144,12 @@
     } else if (type == *fContext.fBool_Type) {
         this->write("%s");
         fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
-    } else if (type == *fContext.fFloat2_Type) {
-        this->write("float2(%f, %f)");
+    } else if (type == *fContext.fFloat2_Type || type == *fContext.fHalf2_Type) {
+        this->write(type.name() + "(%f, %f)");
         fFormatArgs.push_back(cppCode + ".fX");
         fFormatArgs.push_back(cppCode + ".fY");
     } else {
-        this->write(type.fName);
+        this->write(type.name());
         this->write("\n");
         ABORT("unsupported runtime value type\n");
     }
@@ -189,7 +184,7 @@
     switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
         case SK_INCOLOR_BUILTIN:
             this->write("%s");
-            fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"float4(1)\""));
+            fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"half4(1)\""));
             break;
         case SK_OUTCOLOR_BUILTIN:
             this->write("%s");
@@ -211,7 +206,7 @@
                     var = String::printf("fColorSpaceHelper.isValid() ? "
                                          "args.fUniformHandler->getUniformCStr("
                                                   "fColorSpaceHelper.gamutXformUniform()) : \"%s\"",
-                           default_value(ref.fVariable.fType));
+                           default_value(ref.fVariable.fType).c_str());
                 } else {
                     var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
                                          HCodeGenerator::FieldName(name.c_str()).c_str());
@@ -221,7 +216,7 @@
                     code = String::printf("%sVar.isValid() ? %s : \"%s\"",
                                           HCodeGenerator::FieldName(name.c_str()).c_str(),
                                           var.c_str(),
-                                          default_value(ref.fVariable.fType));
+                                          default_value(ref.fVariable.fType).c_str());
                 } else {
                     code = var;
                 }
@@ -253,7 +248,7 @@
 void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
     if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") {
         String tmpVar = "_tmpVar" + to_string(++fVarCount);
-        fFunctionHeader += "float4 " + tmpVar + ";";
+        fFunctionHeader += "half4 " + tmpVar + ";";
         ASSERT(c.fArguments.size() == 2);
         this->write("%s");
         fFormatArgs.push_back("fColorSpaceHelper.isValid() ? \"(" + tmpVar + " = \" : \"\"");
@@ -262,7 +257,7 @@
         String xform("args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform())");
         this->write("%s");
         fFormatArgs.push_back("fColorSpaceHelper.isValid() ? SkStringPrintf(\", "
-                              "float4(clamp((%s * float4(" + tmpVar + ".rgb, 1.0)).rgb, 0.0, " +
+                              "half4(clamp((%s * half4(" + tmpVar + ".rgb, 1.0)).rgb, 0.0, " +
                               tmpVar + ".a), " + tmpVar + ".a))\", " + xform + ").c_str() : \"\"");
         return;
     }
@@ -349,14 +344,22 @@
     }
     const char* type;
     if (var.fType == *fContext.fFloat_Type) {
-        type = "kFloat_GrSLType";
+        type = "kHighFloat_GrSLType";
+    } else if (var.fType == *fContext.fHalf_Type) {
+        type = "kHalf_GrSLType";
     } else if (var.fType == *fContext.fFloat2_Type) {
-        type = "kVec2f_GrSLType";
+        type = "kHighFloat2_GrSLType";
+    } else if (var.fType == *fContext.fHalf2_Type) {
+        type = "kHalf2_GrSLType";
     } else if (var.fType == *fContext.fFloat4_Type) {
-        type = "kVec4f_GrSLType";
+        type = "kHighFloat4_GrSLType";
+    } else if (var.fType == *fContext.fHalf4_Type) {
+        type = "kHalf4_GrSLType";
     } else if (var.fType == *fContext.fFloat4x4_Type ||
                var.fType == *fContext.fColorSpaceXform_Type) {
-        type = "kMat44f_GrSLType";
+        type = "kHighFloat4x4_GrSLType";
+    } else if (var.fType == *fContext.fHalf4x4_Type) {
+        type = "kHalf4x4_GrSLType";
     } else {
         ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
               String(var.fName).c_str());
@@ -457,11 +460,12 @@
             }
             String nameString(u->fName);
             const char* name = nameString.c_str();
-            if (u->fType == *fContext.fFloat4_Type) {
+            if (u->fType == *fContext.fFloat4_Type || u->fType == *fContext.fHalf4_Type) {
                 this->writef("        const SkRect %sValue = _outer.%s();\n"
                              "        %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
                              name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name);
-            } else if (u->fType == *fContext.fFloat4x4_Type) {
+            } else if (u->fType == *fContext.fFloat4x4_Type ||
+                       u->fType == *fContext.fHalf4x4_Type) {
                 this->writef("        float %sValue[16];\n"
                              "        _outer.%s().asColMajorf(%sValue);\n"
                              "        %s.setMatrix4f(%sVar, %sValue);\n",
diff --git a/src/sksl/SkSLCPPCodeGenerator.h b/src/sksl/SkSLCPPCodeGenerator.h
index 27b434a..6727b9c 100644
--- a/src/sksl/SkSLCPPCodeGenerator.h
+++ b/src/sksl/SkSLCPPCodeGenerator.h
@@ -31,9 +31,9 @@
 
     void writeHeader() override;
 
-    void writePrecisionModifier() override;
+    bool usesPrecisionModifiers() const override;
 
-    void writeType(const Type& type) override;
+    String getTypeName(const Type& type) override;
 
     void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence) override;
 
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 638e4d6..5373f9d 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -196,9 +196,8 @@
                                     *fContext.fSkArgs_Type, Variable::kGlobal_Storage);
     fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
 
-    Modifiers::Flag ignored1;
-    std::vector<std::unique_ptr<ProgramElement>> ignored2;
-    fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
+    std::vector<std::unique_ptr<ProgramElement>> ignored;
+    fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored);
     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
     if (fErrorCount) {
         printf("Unexpected errors: %s\n", fErrorText.c_str());
@@ -1134,31 +1133,28 @@
     fErrorCount = 0;
     fIRGenerator->start(&settings);
     std::vector<std::unique_ptr<ProgramElement>> elements;
-    Modifiers::Flag ignored;
     switch (kind) {
         case Program::kVertex_Kind:
             fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes,
-                                         &ignored, &elements);
+                                         &elements);
             break;
         case Program::kFragment_Kind:
             fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes,
-                                         &ignored, &elements);
+                                         &elements);
             break;
         case Program::kGeometry_Kind:
             fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes,
-                                         &ignored, &elements);
+                                         &elements);
             break;
         case Program::kFragmentProcessor_Kind:
             fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes,
-                                         &ignored, &elements);
+                                         &elements);
             break;
     }
     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
-    Modifiers::Flag defaultPrecision;
     std::unique_ptr<String> textPtr(new String(std::move(text)));
     fSource = textPtr.get();
-    fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &defaultPrecision,
-                                 &elements);
+    fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &elements);
     if (!fErrorCount) {
         for (auto& element : elements) {
             if (element->fKind == ProgramElement::kFunction_Kind) {
@@ -1166,8 +1162,10 @@
             }
         }
     }
-    auto result = std::unique_ptr<Program>(new Program(kind, std::move(textPtr), settings,
-                                                       defaultPrecision, &fContext,
+    auto result = std::unique_ptr<Program>(new Program(kind,
+                                                       std::move(textPtr),
+                                                       settings,
+                                                       &fContext,
                                                        std::move(elements),
                                                        fIRGenerator->fSymbolTable,
                                                        fIRGenerator->fInputs));
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 894ac41..1c8ef4f 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -16,6 +16,7 @@
 #include "SkSLCFGGenerator.h"
 #include "SkSLContext.h"
 #include "SkSLErrorReporter.h"
+#include "SkSLLexer.h"
 
 #define SK_FRAGCOLOR_BUILTIN           10001
 #define SK_IN_BUILTIN                  10002
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index e421695..862a777 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -21,47 +21,47 @@
     Context()
     : fInvalid_Type(new Type("<INVALID>"))
     , fVoid_Type(new Type("void"))
-    , fDouble_Type(new Type("double", Type::kFloat_NumberKind))
+    , fDouble_Type(new Type("double", Type::kFloat_NumberKind, 4))
     , fDouble2_Type(new Type("double2", *fDouble_Type, 2))
     , fDouble3_Type(new Type("double3", *fDouble_Type, 3))
     , fDouble4_Type(new Type("double4", *fDouble_Type, 4))
-    , fFloat_Type(new Type("float", Type::kFloat_NumberKind))
-    , fFloat2_Type(new Type("float2", *fFloat_Type, 2))
-    , fFloat3_Type(new Type("float3", *fFloat_Type, 3))
-    , fFloat4_Type(new Type("float4", *fFloat_Type, 4))
-    , fHalf_Type(new Type("half", Type::kFloat_NumberKind))
+    , fFloat_Type(new Type("highfloat", Type::kFloat_NumberKind, 3))
+    , fFloat2_Type(new Type("highfloat2", *fFloat_Type, 2))
+    , fFloat3_Type(new Type("highfloat3", *fFloat_Type, 3))
+    , fFloat4_Type(new Type("highfloat4", *fFloat_Type, 4))
+    , fHalf_Type(new Type("half", Type::kFloat_NumberKind, 2))
     , fHalf2_Type(new Type("half2", *fHalf_Type, 2))
     , fHalf3_Type(new Type("half3", *fHalf_Type, 3))
     , fHalf4_Type(new Type("half4", *fHalf_Type, 4))
-    , fUInt_Type(new Type("uint", Type::kUnsigned_NumberKind))
+    , fUInt_Type(new Type("uint", Type::kUnsigned_NumberKind, 1))
     , fUInt2_Type(new Type("uint2", *fUInt_Type, 2))
     , fUInt3_Type(new Type("uint3", *fUInt_Type, 3))
     , fUInt4_Type(new Type("uint4", *fUInt_Type, 4))
-    , fInt_Type(new Type("int", Type::kSigned_NumberKind))
+    , fInt_Type(new Type("int", Type::kSigned_NumberKind, 1))
     , fInt2_Type(new Type("int2", *fInt_Type, 2))
     , fInt3_Type(new Type("int3", *fInt_Type, 3))
     , fInt4_Type(new Type("int4", *fInt_Type, 4))
-    , fUShort_Type(new Type("ushort", Type::kUnsigned_NumberKind))
+    , fUShort_Type(new Type("ushort", Type::kUnsigned_NumberKind, 0))
     , fUShort2_Type(new Type("ushort2", *fUShort_Type, 2))
     , fUShort3_Type(new Type("ushort3", *fUShort_Type, 3))
     , fUShort4_Type(new Type("ushort4", *fUShort_Type, 4))
-    , fShort_Type(new Type("short", Type::kSigned_NumberKind))
+    , fShort_Type(new Type("short", Type::kSigned_NumberKind, 0))
     , fShort2_Type(new Type("short2", *fShort_Type, 2))
     , fShort3_Type(new Type("short3", *fShort_Type, 3))
     , fShort4_Type(new Type("short4", *fShort_Type, 4))
-    , fBool_Type(new Type("bool", Type::kNonnumeric_NumberKind))
+    , fBool_Type(new Type("bool", Type::kNonnumeric_NumberKind, -1))
     , fBool2_Type(new Type("bool2", *fBool_Type, 2))
     , fBool3_Type(new Type("bool3", *fBool_Type, 3))
     , fBool4_Type(new Type("bool4", *fBool_Type, 4))
-    , fFloat2x2_Type(new Type("float2x2", *fFloat_Type, 2, 2))
-    , fFloat2x3_Type(new Type("float2x3", *fFloat_Type, 2, 3))
-    , fFloat2x4_Type(new Type("float2x4", *fFloat_Type, 2, 4))
-    , fFloat3x2_Type(new Type("float3x2", *fFloat_Type, 3, 2))
-    , fFloat3x3_Type(new Type("float3x3", *fFloat_Type, 3, 3))
-    , fFloat3x4_Type(new Type("float3x4", *fFloat_Type, 3, 4))
-    , fFloat4x2_Type(new Type("float4x2", *fFloat_Type, 4, 2))
-    , fFloat4x3_Type(new Type("float4x3", *fFloat_Type, 4, 3))
-    , fFloat4x4_Type(new Type("float4x4", *fFloat_Type, 4, 4))
+    , fFloat2x2_Type(new Type("highfloat2x2", *fFloat_Type, 2, 2))
+    , fFloat2x3_Type(new Type("highfloat2x3", *fFloat_Type, 2, 3))
+    , fFloat2x4_Type(new Type("highfloat2x4", *fFloat_Type, 2, 4))
+    , fFloat3x2_Type(new Type("highfloat3x2", *fFloat_Type, 3, 2))
+    , fFloat3x3_Type(new Type("highfloat3x3", *fFloat_Type, 3, 3))
+    , fFloat3x4_Type(new Type("highfloat3x4", *fFloat_Type, 3, 4))
+    , fFloat4x2_Type(new Type("highfloat4x2", *fFloat_Type, 4, 2))
+    , fFloat4x3_Type(new Type("highfloat4x3", *fFloat_Type, 4, 3))
+    , fFloat4x4_Type(new Type("highfloat4x4", *fFloat_Type, 4, 4))
     , fHalf2x2_Type(new Type("half2x2", *fHalf_Type, 2, 2))
     , fHalf2x3_Type(new Type("half2x3", *fHalf_Type, 2, 3))
     , fHalf2x4_Type(new Type("half2x4", *fHalf_Type, 2, 4))
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 52a40f8..c6b4806 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -69,6 +69,87 @@
     this->writeLine(" : enable");
 }
 
+bool GLSLCodeGenerator::usesPrecisionModifiers() const {
+    return fProgram.fSettings.fCaps->usesPrecisionModifiers();
+}
+
+String GLSLCodeGenerator::getTypeName(const Type& type) {
+    switch (type.kind()) {
+        case Type::kVector_Kind: {
+            Type component = type.componentType();
+            String result;
+            if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
+                result = "vec";
+            }
+            else if (component == *fContext.fDouble_Type) {
+                result = "dvec";
+            }
+            else if (component == *fContext.fInt_Type || component == *fContext.fShort_Type) {
+                result = "ivec";
+            }
+            else if (component == *fContext.fUInt_Type || component == *fContext.fUShort_Type) {
+                result = "uvec";
+            }
+            else if (component == *fContext.fBool_Type) {
+                result = "bvec";
+            }
+            else {
+                ABORT("unsupported vector type");
+            }
+            result += to_string(type.columns());
+            return result;
+        }
+        case Type::kMatrix_Kind: {
+            String result;
+            Type component = type.componentType();
+            if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
+                result = "mat";
+            }
+            else if (component == *fContext.fDouble_Type) {
+                result = "dmat";
+            }
+            else {
+                ABORT("unsupported matrix type");
+            }
+            result += to_string(type.columns());
+            if (type.columns() != type.rows()) {
+                result += "x";
+                result += to_string(type.rows());
+            }
+            return result;
+        }
+        case Type::kArray_Kind: {
+            String result = this->getTypeName(type.componentType()) + "[";
+            if (type.columns() != -1) {
+                result += to_string(type.columns());
+            }
+            result += "]";
+            return result;
+        }
+        case Type::kScalar_Kind: {
+            if (type == *fContext.fHalf_Type) {
+                return "float";
+            }
+            else if (type == *fContext.fShort_Type) {
+                return "int";
+            }
+            else if (type == *fContext.fUShort_Type) {
+                return "uint";
+            }
+            else if (type == *fContext.fFloat_Type) {
+                // FIXME: temporary, this goes away when highfloat is renamed back to float
+                return "float";
+            }
+            else {
+                return type.name();
+            }
+            break;
+        }
+        default:
+            return type.name();
+    }
+}
+
 void GLSLCodeGenerator::writeType(const Type& type) {
     if (type.kind() == Type::kStruct_Kind) {
         for (const Type* search : fWrittenStructs) {
@@ -95,75 +176,7 @@
         fIndentation--;
         this->write("}");
     } else {
-        switch (type.kind()) {
-            case Type::kVector_Kind: {
-                Type component = type.componentType();
-                if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
-                    this->write("vec");
-                }
-                else if (component == *fContext.fDouble_Type) {
-                    this->write("dvec");
-                }
-                else if (component == *fContext.fInt_Type || component == *fContext.fShort_Type) {
-                    this->write("ivec");
-                }
-                else if (component == *fContext.fUInt_Type || component == *fContext.fUShort_Type) {
-                    this->write("uvec");
-                }
-                else if (component == *fContext.fBool_Type) {
-                    this->write("bvec");
-                }
-                else {
-                    ABORT("unsupported vector type");
-                }
-                this->write(to_string(type.columns()));
-                break;
-            }
-            case Type::kMatrix_Kind: {
-                Type component = type.componentType();
-                if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
-                    this->write("mat");
-                }
-                else if (component == *fContext.fDouble_Type) {
-                    this->write("dmat");
-                }
-                else {
-                    ABORT("unsupported matrix type");
-                }
-                this->write(to_string(type.columns()));
-                if (type.columns() != type.rows()) {
-                    this->write("x");
-                    this->write(to_string(type.rows()));
-                }
-                break;
-            }
-            case Type::kArray_Kind: {
-                this->writeType(type.componentType());
-                this->write("[");
-                if (type.columns() != -1) {
-                    this->write(to_string(type.columns()));
-                }
-                this->write("]");
-                break;
-            }
-            case Type::kScalar_Kind: {
-                if (type == *fContext.fHalf_Type) {
-                    this->write("float");
-                }
-                else if (type == *fContext.fShort_Type) {
-                    this->write("int");
-                }
-                else if (type == *fContext.fUShort_Type) {
-                    this->write("uint");
-                }
-                else {
-                    this->write(type.fName);
-                }
-                break;
-            }
-            default:
-                this->write(type.fName);
-        }
+        this->write(this->getTypeName(type));
     }
 }
 
@@ -176,7 +189,7 @@
             this->writeBoolLiteral((BoolLiteral&) expr);
             break;
         case Expression::kConstructor_Kind:
-            this->writeConstructor((Constructor&) expr);
+            this->writeConstructor((Constructor&) expr, parentPrecedence);
             break;
         case Expression::kIntLiteral_Kind:
             this->writeIntLiteral((IntLiteral&) expr);
@@ -229,8 +242,10 @@
     ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
     String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
     String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
-    this->fFunctionHeader += String("    ") + absExpr.fType.fName + " " + tmpVar1 + ";\n";
-    this->fFunctionHeader += String("    ") + otherExpr.fType.fName + " " + tmpVar2 + ";\n";
+    this->fFunctionHeader += String("    ") + this->getTypePrecision(absExpr.fType) +
+                             this->getTypeName(absExpr.fType) + " " + tmpVar1 + ";\n";
+    this->fFunctionHeader += String("    ") + this->getTypePrecision(otherExpr.fType) +
+                             this->getTypeName(otherExpr.fType) + " " + tmpVar2 + ";\n";
     this->write("((" + tmpVar1 + " = ");
     this->writeExpression(absExpr, kTopLevel_Precedence);
     this->write(") < (" + tmpVar2 + " = ");
@@ -358,7 +373,15 @@
     this->write(")");
 }
 
-void GLSLCodeGenerator::writeConstructor(const Constructor& c) {
+void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) {
+    if (c.fArguments.size() == 1 &&
+        this->getTypeName(c.fType) == this->getTypeName(c.fArguments[0]->fType)) {
+        // in cases like half(float), they're different types as far as SkSL is concerned but the
+        // same type as far as GLSL is concerned. We avoid a redundant float(float) by just writing
+        // out the inner expression here.
+        this->writeExpression(*c.fArguments[0], parentPrecedence);
+        return;
+    }
     this->writeType(c.fType);
     this->write("(");
     const char* separator = "";
@@ -395,16 +418,14 @@
             // depending on the surrounding code, accessing .xy with a uniform involved can
             // do the same thing. Copying gl_FragCoord.xy into a temp float2beforehand
             // (and only accessing .xy) seems to "fix" things.
-            const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
-                                                                                       : "";
+            const char* precision = usesPrecisionModifiers() ? "highp " : "";
             fHeader.writeText("uniform ");
             fHeader.writeText(precision);
             fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n");
             fSetupFragPositionGlobal = true;
         }
         if (!fSetupFragPositionLocal) {
-            const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
-                                                                                       : "";
+            const char* precision = usesPrecisionModifiers() ? "highp " : "";
             fFunctionHeader += precision;
             fFunctionHeader += "    vec2 _sktmpCoord = gl_FragCoord.xy;\n";
             fFunctionHeader += precision;
@@ -591,6 +612,7 @@
 }
 
 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
+    this->writeTypePrecision(f.fDeclaration.fReturnType);
     this->writeType(f.fDeclaration.fReturnType);
     this->write(" " + f.fDeclaration.fName + "(");
     const char* separator = "";
@@ -604,6 +626,7 @@
             sizes.push_back(type->columns());
             type = &type->componentType();
         }
+        this->writeTypePrecision(*type);
         this->writeType(*type);
         this->write(" " + param->fName);
         for (int s : sizes) {
@@ -682,7 +705,7 @@
     if (modifiers.fFlags & Modifiers::kConst_Flag) {
         this->write("const ");
     }
-    if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
+    if (usesPrecisionModifiers()) {
         if (modifiers.fFlags & Modifiers::kLowp_Flag) {
             this->write("lowp ");
         }
@@ -732,23 +755,31 @@
     this->writeExpression(value, kTopLevel_Precedence);
 }
 
-void GLSLCodeGenerator::writeTypePrecision(const Type& type) {
-    if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
+const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
+    if (usesPrecisionModifiers()) {
         switch (type.kind()) {
             case Type::kScalar_Kind:
                 if (type == *fContext.fHalf_Type || type == *fContext.fShort_Type ||
                         type == *fContext.fUShort_Type) {
-                    this->write("mediump ");
+                    return fProgram.fSettings.fForceHighPrecision ? "highp " : "mediump ";
                 }
-                break;
+                if (type == *fContext.fFloat_Type || type == *fContext.fInt_Type ||
+                        type == *fContext.fUInt_Type) {
+                    return "highp ";
+                }
+                return "";
             case Type::kVector_Kind: // fall through
             case Type::kMatrix_Kind:
-                this->writeTypePrecision(type.componentType());
-                break;
+                return this->getTypePrecision(type.componentType());
             default:
                 break;
         }
     }
+    return "";
+}
+
+void GLSLCodeGenerator::writeTypePrecision(const Type& type) {
+    this->write(this->getTypePrecision(type));
 }
 
 void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
@@ -942,27 +973,6 @@
     }
 }
 
-void GLSLCodeGenerator::writePrecisionModifier() {
-    if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
-        this->write("precision ");
-        switch (fProgram.fDefaultPrecision) {
-            case Modifiers::kLowp_Flag:
-                this->write("lowp");
-                break;
-            case Modifiers::kMediump_Flag:
-                this->write("mediump");
-                break;
-            case Modifiers::kHighp_Flag:
-                this->write("highp");
-                break;
-            default:
-                ASSERT(false);
-                this->write("<error>");
-        }
-        this->writeLine(" float;");
-    }
-}
-
 void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
     switch (e.fKind) {
         case ProgramElement::kExtension_Kind:
@@ -978,7 +988,7 @@
                 } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
                            fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
                     this->write("out ");
-                    if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
+                    if (usesPrecisionModifiers()) {
                         this->write("mediump ");
                     }
                     this->writeLine("vec4 sk_FragColor;");
@@ -1009,13 +1019,15 @@
     this->writeHeader();
     StringStream body;
     fOut = &body;
-    this->writePrecisionModifier();
     for (const auto& e : fProgram.fElements) {
         this->writeProgramElement(*e);
     }
     fOut = rawOut;
 
     write_stringstream(fHeader, *rawOut);
+    if (this->usesPrecisionModifiers()) {
+        this->writeLine("precision mediump float;");
+    }
     write_stringstream(body, *rawOut);
     return true;
 }
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index 353cd66..4813d0d 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -96,9 +96,11 @@
 
     virtual void writeHeader();
 
-    virtual void writePrecisionModifier();
+    virtual bool usesPrecisionModifiers() const;
 
-    virtual void writeType(const Type& type);
+    virtual String getTypeName(const Type& type);
+
+    void writeType(const Type& type);
 
     void writeExtension(const Extension& ext);
 
@@ -118,6 +120,8 @@
 
     virtual void writeVarInitializer(const Variable& var, const Expression& value);
 
+    const char* getTypePrecision(const Type& type);
+
     void writeTypePrecision(const Type& type);
 
     void writeVarDeclarations(const VarDeclarations& decl, bool global);
@@ -134,7 +138,7 @@
 
     virtual void writeFunctionCall(const FunctionCall& c);
 
-    void writeConstructor(const Constructor& c);
+    void writeConstructor(const Constructor& c, Precedence parentPrecedence);
 
     void writeFieldAccess(const FieldAccess& f);
 
diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp
index 482020a..8203990 100644
--- a/src/sksl/SkSLHCodeGenerator.cpp
+++ b/src/sksl/SkSLHCodeGenerator.cpp
@@ -23,13 +23,15 @@
 , fSectionAndParameterHelper(*program, *errors) {}
 
 String HCodeGenerator::ParameterType(const Type& type) {
-    if (type.name() == "float2") {
+    if (type.name() == "highfloat" || type.name() == "half") {
+        return "float";
+    } else if (type.name() == "highfloat2" || type.name() == "half2") {
         return "SkPoint";
-    } else if (type.name() == "int4") {
+    } else if (type.name() == "int4" || type.name() == "short4") {
         return "SkIRect";
-    } else if (type.name() == "float4") {
+    } else if (type.name() == "highfloat4" || type.name() == "half4") {
         return "SkRect";
-    } else if (type.name() == "float4x4") {
+    } else if (type.name() == "highfloat4x4" || type.name() == "half4x4") {
         return "SkMatrix44";
     } else if (type.kind() == Type::kSampler_Kind) {
         return "sk_sp<GrTextureProxy>";
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 83ab993..2c6b9e3 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -17,7 +17,6 @@
 #include "ast/SkSLASTFloatLiteral.h"
 #include "ast/SkSLASTIndexSuffix.h"
 #include "ast/SkSLASTIntLiteral.h"
-#include "ast/SkSLASTPrecision.h"
 #include "ir/SkSLBinaryExpression.h"
 #include "ir/SkSLBoolLiteral.h"
 #include "ir/SkSLBreakStatement.h"
@@ -981,8 +980,15 @@
             *outResultType = context.fBool_Type.get();
             return left.canCoerceTo(*context.fBool_Type) &&
                    right.canCoerceTo(*context.fBool_Type);
-        case Token::STAR: // fall through
         case Token::STAREQ:
+            if (left.kind() == Type::kScalar_Kind) {
+                *outLeftType = &left;
+                *outRightType = &left;
+                *outResultType = &left;
+                return right.canCoerceTo(left);
+            }
+            // fall through
+        case Token::STAR:
             if (is_matrix_multiply(left, right)) {
                 // determine final component type
                 if (determine_binary_type(context, Token::STAR, left.componentType(),
@@ -1022,12 +1028,22 @@
             isLogical = false;
             validMatrixOrVectorOp = true;
             break;
+        case Token::PLUSEQ:
+        case Token::MINUSEQ:
+        case Token::SLASHEQ:
+        case Token::PERCENTEQ:
+        case Token::SHLEQ:
+        case Token::SHREQ:
+            if (left.kind() == Type::kScalar_Kind) {
+                *outLeftType = &left;
+                *outRightType = &left;
+                *outResultType = &left;
+                return right.canCoerceTo(left);
+            }
+            // fall through
         case Token::PLUS:    // fall through
-        case Token::PLUSEQ:  // fall through
         case Token::MINUS:   // fall through
-        case Token::MINUSEQ: // fall through
         case Token::SLASH:   // fall through
-        case Token::SLASHEQ: // fall through
             isLogical = false;
             validMatrixOrVectorOp = true;
             break;
@@ -1041,9 +1057,23 @@
             validMatrixOrVectorOp = false;
     }
     bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
-    // FIXME: incorrect for shift
-    if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind ||
-                                   (isVectorOrMatrix && validMatrixOrVectorOp))) {
+    if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
+            right.canCoerceTo(left)) {
+        if (left.priority() > right.priority()) {
+            *outLeftType = &left;
+            *outRightType = &left;
+        } else {
+            *outLeftType = &right;
+            *outRightType = &right;
+        }
+        if (isLogical) {
+            *outResultType = context.fBool_Type.get();
+        } else {
+            *outResultType = &left;
+        }
+        return true;
+    }
+    if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
         *outLeftType = &left;
         *outRightType = &left;
         if (isLogical) {
@@ -1480,18 +1510,17 @@
                               to_string((uint64_t) args.size()) + ")");
         return nullptr;
     }
-    if (type.isFloat() && args[0]->fType.isFloat()) {
+    if (type == args[0]->fType) {
         return std::move(args[0]);
     }
-    if (type.isSigned() && args[0]->fType.isSigned()) {
-        return std::move(args[0]);
-    }
-    if (type.isUnsigned() && args[0]->fType.isUnsigned()) {
-        return std::move(args[0]);
+    if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
+        double value = ((FloatLiteral&) *args[0]).fValue;
+        return std::unique_ptr<Expression>(new FloatLiteral(fContext, offset, value, &type));
     }
     if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
         int64_t value = ((IntLiteral&) *args[0]).fValue;
-        return std::unique_ptr<Expression>(new FloatLiteral(fContext, offset, (double) value));
+        return std::unique_ptr<Expression>(new FloatLiteral(fContext, offset, (double) value,
+                                                            &type));
     }
     if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
         type == *fContext.fUInt_Type)) {
@@ -1949,7 +1978,6 @@
 void IRGenerator::convertProgram(const char* text,
                                  size_t length,
                                  SymbolTable& types,
-                                 Modifiers::Flag* defaultPrecision,
                                  std::vector<std::unique_ptr<ProgramElement>>* out) {
     Parser parser(text, length, types, fErrors);
     std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
@@ -1957,7 +1985,6 @@
         printf("float type has name: '%s'\n", fContext.fFloat_Type->name().c_str());
         return;
     }
-    *defaultPrecision = Modifiers::kHighp_Flag;
     for (size_t i = 0; i < parsed.size(); i++) {
         ASTDeclaration& decl = *parsed[i];
         switch (decl.fKind) {
@@ -2004,10 +2031,6 @@
                 }
                 break;
             }
-            case ASTDeclaration::kPrecision_Kind: {
-                *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
-                break;
-            }
             default:
                 ABORT("unsupported declaration: %s\n", decl.description().c_str());
         }
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 3dda028..0a2979d 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -64,7 +64,6 @@
     void convertProgram(const char* text,
                         size_t length,
                         SymbolTable& types,
-                        Modifiers::Flag* defaultPrecision,
                         std::vector<std::unique_ptr<ProgramElement>>* result);
 
     /**
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index d8ecc61..9bfa62f 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -29,7 +29,6 @@
 #include "ast/SkSLASTIntLiteral.h"
 #include "ast/SkSLASTModifiersDeclaration.h"
 #include "ast/SkSLASTParameter.h"
-#include "ast/SkSLASTPrecision.h"
 #include "ast/SkSLASTPrefixExpression.h"
 #include "ast/SkSLASTReturnStatement.h"
 #include "ast/SkSLASTSection.h"
@@ -81,20 +80,13 @@
     fLexer.start(text, length);
 }
 
-/* (precision | directive | section | declaration)* END_OF_FILE */
+/* (directive | section | declaration)* END_OF_FILE */
 std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
     std::vector<std::unique_ptr<ASTDeclaration>> result;
     for (;;) {
         switch (this->peek().fKind) {
             case Token::END_OF_FILE:
                 return result;
-            case Token::PRECISION: {
-                std::unique_ptr<ASTDeclaration> precision = this->precision();
-                if (precision) {
-                    result.push_back(std::move(precision));
-                }
-                break;
-            }
             case Token::DIRECTIVE: {
                 std::unique_ptr<ASTDeclaration> decl = this->directive();
                 if (decl) {
@@ -196,36 +188,6 @@
     return nullptr != fTypes[name];
 }
 
-/* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */
-std::unique_ptr<ASTDeclaration> Parser::precision() {
-    if (!this->expect(Token::PRECISION, "'precision'")) {
-        return nullptr;
-    }
-    Modifiers::Flag result;
-    Token p = this->nextToken();
-    switch (p.fKind) {
-        case Token::LOWP:
-            result = Modifiers::kLowp_Flag;
-            break;
-        case Token::MEDIUMP:
-            result = Modifiers::kMediump_Flag;
-            break;
-        case Token::HIGHP:
-            result = Modifiers::kHighp_Flag;
-            break;
-        default:
-            this->error(p, "expected 'lowp', 'mediump', or 'highp', but found '" +
-                           this->text(p) + "'");
-            return nullptr;
-    }
-    // FIXME handle the type
-    if (!this->type()) {
-        return nullptr;
-    }
-    this->expect(Token::SEMICOLON, "';'");
-    return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fOffset, result));
-}
-
 /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
    DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
 std::unique_ptr<ASTDeclaration> Parser::directive() {
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index 7ae3252..ba80fb6 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -156,21 +156,22 @@
     if (type.kind() == Type::kVector_Kind) {
         return is_float(context, type.componentType());
     }
-    return type == *context.fFloat_Type || type == *context.fDouble_Type;
+    return type == *context.fFloat_Type || type == *context.fHalf_Type ||
+           type == *context.fDouble_Type;
 }
 
 static bool is_signed(const Context& context, const Type& type) {
     if (type.kind() == Type::kVector_Kind) {
         return is_signed(context, type.componentType());
     }
-    return type == *context.fInt_Type;
+    return type == *context.fInt_Type || type == *context.fShort_Type;
 }
 
 static bool is_unsigned(const Context& context, const Type& type) {
     if (type.kind() == Type::kVector_Kind) {
         return is_unsigned(context, type.componentType());
     }
-    return type == *context.fUInt_Type;
+    return type == *context.fUInt_Type || type == *context.fUShort_Type;
 }
 
 static bool is_bool(const Context& context, const Type& type) {
@@ -1036,11 +1037,36 @@
     }
 }
 
+Type SPIRVCodeGenerator::getActualType(const Type& type) {
+    if (type == *fContext.fHalf_Type) {
+        return *fContext.fFloat_Type;
+    }
+    if (type == *fContext.fShort_Type) {
+        return *fContext.fInt_Type;
+    }
+    if (type == *fContext.fUShort_Type) {
+        return *fContext.fUInt_Type;
+    }
+    if (type.kind() == Type::kMatrix_Kind || type.kind() == Type::kVector_Kind) {
+        if (type.componentType() == *fContext.fHalf_Type) {
+            return fContext.fFloat_Type->toCompound(fContext, type.columns(), type.rows());
+        }
+        if (type.componentType() == *fContext.fShort_Type) {
+            return fContext.fInt_Type->toCompound(fContext, type.columns(), type.rows());
+        }
+        if (type.componentType() == *fContext.fUShort_Type) {
+            return fContext.fUInt_Type->toCompound(fContext, type.columns(), type.rows());
+        }
+    }
+    return type;
+}
+
 SpvId SPIRVCodeGenerator::getType(const Type& type) {
     return this->getType(type, fDefaultLayout);
 }
 
-SpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout) {
+SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layout) {
+    Type type = this->getActualType(rawType);
     String key = type.name() + to_string((int) layout.fStd);
     auto entry = fTypeMap.find(key);
     if (entry == fTypeMap.end()) {
@@ -1194,8 +1220,9 @@
     return this->getPointerType(type, fDefaultLayout, storageClass);
 }
 
-SpvId SPIRVCodeGenerator::getPointerType(const Type& type, const MemoryLayout& layout,
+SpvId SPIRVCodeGenerator::getPointerType(const Type& rawType, const MemoryLayout& layout,
                                          SpvStorageClass_ storageClass) {
+    Type type = this->getActualType(rawType);
     String key = type.description() + "*" + to_string(layout.fStd) + to_string(storageClass);
     auto entry = fTypeMap.find(key);
     if (entry == fTypeMap.end()) {
@@ -1506,55 +1533,53 @@
 }
 
 SpvId SPIRVCodeGenerator::writeFloatConstructor(const Constructor& c, OutputStream& out) {
-    ASSERT(c.fType == *fContext.fFloat_Type);
+    ASSERT(c.fType.isFloat());
     ASSERT(c.fArguments.size() == 1);
     ASSERT(c.fArguments[0]->fType.isNumber());
     SpvId result = this->nextId();
     SpvId parameter = this->writeExpression(*c.fArguments[0], out);
-    if (c.fArguments[0]->fType == *fContext.fInt_Type) {
+    if (c.fArguments[0]->fType.isSigned()) {
         this->writeInstruction(SpvOpConvertSToF, this->getType(c.fType), result, parameter,
                                out);
-    } else if (c.fArguments[0]->fType == *fContext.fUInt_Type) {
+    } else {
+        ASSERT(c.fArguments[0]->fType.isUnsigned());
         this->writeInstruction(SpvOpConvertUToF, this->getType(c.fType), result, parameter,
                                out);
-    } else if (c.fArguments[0]->fType == *fContext.fFloat_Type) {
-        return parameter;
     }
     return result;
 }
 
 SpvId SPIRVCodeGenerator::writeIntConstructor(const Constructor& c, OutputStream& out) {
-    ASSERT(c.fType == *fContext.fInt_Type);
+    ASSERT(c.fType.isSigned());
     ASSERT(c.fArguments.size() == 1);
     ASSERT(c.fArguments[0]->fType.isNumber());
     SpvId result = this->nextId();
     SpvId parameter = this->writeExpression(*c.fArguments[0], out);
-    if (c.fArguments[0]->fType == *fContext.fFloat_Type) {
+    if (c.fArguments[0]->fType.isFloat()) {
         this->writeInstruction(SpvOpConvertFToS, this->getType(c.fType), result, parameter,
                                out);
-    } else if (c.fArguments[0]->fType == *fContext.fUInt_Type) {
+    }
+    else {
+        ASSERT(c.fArguments[0]->fType.isUnsigned());
         this->writeInstruction(SpvOpBitcast, this->getType(c.fType), result, parameter,
                                out);
-    } else if (c.fArguments[0]->fType == *fContext.fInt_Type) {
-        return parameter;
     }
     return result;
 }
 
 SpvId SPIRVCodeGenerator::writeUIntConstructor(const Constructor& c, OutputStream& out) {
-    ASSERT(c.fType == *fContext.fUInt_Type);
+    ASSERT(c.fType.isUnsigned());
     ASSERT(c.fArguments.size() == 1);
     ASSERT(c.fArguments[0]->fType.isNumber());
     SpvId result = this->nextId();
     SpvId parameter = this->writeExpression(*c.fArguments[0], out);
-    if (c.fArguments[0]->fType == *fContext.fFloat_Type) {
+    if (c.fArguments[0]->fType.isFloat()) {
         this->writeInstruction(SpvOpConvertFToU, this->getType(c.fType), result, parameter,
                                out);
-    } else if (c.fArguments[0]->fType == *fContext.fInt_Type) {
+    } else {
+        ASSERT(c.fArguments[0]->fType.isSigned());
         this->writeInstruction(SpvOpBitcast, this->getType(c.fType), result, parameter,
                                out);
-    } else if (c.fArguments[0]->fType == *fContext.fUInt_Type) {
-        return parameter;
     }
     return result;
 }
@@ -1789,11 +1814,15 @@
 }
 
 SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, OutputStream& out) {
-    if (c.fType == *fContext.fFloat_Type) {
+    if (c.fArguments.size() == 1 &&
+        this->getActualType(c.fType) == this->getActualType(c.fArguments[0]->fType)) {
+        return this->writeExpression(*c.fArguments[0], out);
+    }
+    if (c.fType == *fContext.fFloat_Type || c.fType == *fContext.fHalf_Type) {
         return this->writeFloatConstructor(c, out);
-    } else if (c.fType == *fContext.fInt_Type) {
+    } else if (c.fType == *fContext.fInt_Type || c.fType == *fContext.fShort_Type) {
         return this->writeIntConstructor(c, out);
-    } else if (c.fType == *fContext.fUInt_Type) {
+    } else if (c.fType == *fContext.fUInt_Type || c.fType == *fContext.fUShort_Type) {
         return this->writeUIntConstructor(c, out);
     }
     switch (c.fType.kind()) {
@@ -2258,11 +2287,12 @@
     if (b.fOperator == Token::COMMA) {
         return rhs;
     }
+    Type tmp("<invalid>");
     // component type we are operating on: float, int, uint
     const Type* operandType;
     // IR allows mismatched types in expressions (e.g. float2* float), but they need special handling
     // in SPIR-V
-    if (b.fLeft->fType != b.fRight->fType) {
+    if (this->getActualType(b.fLeft->fType) != this->getActualType(b.fRight->fType)) {
         if (b.fLeft->fType.kind() == Type::kVector_Kind &&
             b.fRight->fType.isNumber()) {
             // promote number to vector
@@ -2326,8 +2356,9 @@
             ABORT("unsupported binary expression: %s", b.description().c_str());
         }
     } else {
-        operandType = &b.fLeft->fType;
-        ASSERT(*operandType == b.fRight->fType);
+        tmp = this->getActualType(b.fLeft->fType);
+        operandType = &tmp;
+        ASSERT(*operandType == this->getActualType(b.fRight->fType));
     }
     switch (b.fOperator) {
         case Token::EQEQ: {
@@ -2706,7 +2737,7 @@
 }
 
 SpvId SPIRVCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
-    if (f.fType == *fContext.fFloat_Type) {
+    if (f.fType == *fContext.fFloat_Type || f.fType == *fContext.fHalf_Type) {
         float value = (float) f.fValue;
         auto entry = fFloatConstants.find(value);
         if (entry == fFloatConstants.end()) {
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index eb6ec40..368e6fb 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -98,6 +98,8 @@
 
     SpvId nextId();
 
+    Type getActualType(const Type& type);
+
     SpvId getType(const Type& type);
 
     SpvId getType(const Type& type, const MemoryLayout& layout);
diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h
index 32fc0fb..cea5265 100644
--- a/src/sksl/ir/SkSLConstructor.h
+++ b/src/sksl/ir/SkSLConstructor.h
@@ -32,13 +32,15 @@
     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
                                                   const DefinitionMap& definitions) override {
         if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
-            if (fType == *irGenerator.fContext.fFloat_Type) {
+            if (fType == *irGenerator.fContext.fFloat_Type ||
+                fType == *irGenerator.fContext.fHalf_Type) {
                 // promote float(1) to 1.0
                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
                 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
                                                                     fOffset,
                                                                     intValue));
-            } else if (fType == *irGenerator.fContext.fUInt_Type) {
+            } else if (fType == *irGenerator.fContext.fUInt_Type ||
+                       fType == *irGenerator.fContext.fUShort_Type) {
                 // promote uint(1) to 1u
                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h
index 5ada506..20b901d 100644
--- a/src/sksl/ir/SkSLIRNode.h
+++ b/src/sksl/ir/SkSLIRNode.h
@@ -26,7 +26,7 @@
 
     // character offset of this element within the program being compiled, for error reporting
     // purposes
-    const int fOffset;
+    int fOffset;
 };
 
 } // namespace
diff --git a/src/sksl/ir/SkSLIndexExpression.h b/src/sksl/ir/SkSLIndexExpression.h
index 2daf1b5..803d5ff 100644
--- a/src/sksl/ir/SkSLIndexExpression.h
+++ b/src/sksl/ir/SkSLIndexExpression.h
@@ -26,8 +26,15 @@
                 case 4: return *context.fFloat4_Type;
                 default: ASSERT(false);
             }
+        } else if (type.componentType() == *context.fHalf_Type) {
+            switch (type.rows()) {
+                case 2: return *context.fHalf2_Type;
+                case 3: return *context.fHalf3_Type;
+                case 4: return *context.fHalf4_Type;
+                default: ASSERT(false);
+            }
         } else {
-            ASSERT(type.componentType() == *context.fDouble_Type);
+           ASSERT(type.componentType() == *context.fDouble_Type);
             switch (type.rows()) {
                 case 2: return *context.fDouble2_Type;
                 case 3: return *context.fDouble3_Type;
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index 639e09b..3184547 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -74,6 +74,8 @@
         // if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
         // constant equivalents during compilation
         bool fReplaceSettings = true;
+        // if true, all halfs are forced to be floats
+        bool fForceHighPrecision = false;
         std::unordered_map<String, Value> fArgs;
     };
 
@@ -105,7 +107,6 @@
     Program(Kind kind,
             std::unique_ptr<String> source,
             Settings settings,
-            Modifiers::Flag defaultPrecision,
             Context* context,
             std::vector<std::unique_ptr<ProgramElement>> elements,
             std::shared_ptr<SymbolTable> symbols,
@@ -113,7 +114,6 @@
     : fKind(kind)
     , fSource(std::move(source))
     , fSettings(settings)
-    , fDefaultPrecision(defaultPrecision)
     , fContext(context)
     , fSymbols(symbols)
     , fElements(std::move(elements))
@@ -122,8 +122,6 @@
     Kind fKind;
     std::unique_ptr<String> fSource;
     Settings fSettings;
-    // FIXME handle different types; currently it assumes this is for floats
-    Modifiers::Flag fDefaultPrecision;
     Context* fContext;
     // it's important to keep fElements defined after (and thus destroyed before) fSymbols,
     // because destroying elements can modify reference counts in symbols
diff --git a/src/sksl/ir/SkSLSwizzle.h b/src/sksl/ir/SkSLSwizzle.h
index 3256ef2..5512c85 100644
--- a/src/sksl/ir/SkSLSwizzle.h
+++ b/src/sksl/ir/SkSLSwizzle.h
@@ -32,6 +32,12 @@
             case 3: return *context.fFloat3_Type;
             case 4: return *context.fFloat4_Type;
         }
+    } else if (base == *context.fHalf_Type) {
+        switch (count) {
+            case 2: return *context.fHalf2_Type;
+            case 3: return *context.fHalf3_Type;
+            case 4: return *context.fHalf4_Type;
+        }
     } else if (base == *context.fDouble_Type) {
         switch (count) {
             case 2: return *context.fDouble2_Type;
@@ -44,12 +50,24 @@
             case 3: return *context.fInt3_Type;
             case 4: return *context.fInt4_Type;
         }
+    } else if (base == *context.fShort_Type) {
+        switch (count) {
+            case 2: return *context.fShort2_Type;
+            case 3: return *context.fShort3_Type;
+            case 4: return *context.fShort4_Type;
+        }
     } else if (base == *context.fUInt_Type) {
         switch (count) {
             case 2: return *context.fUInt2_Type;
             case 3: return *context.fUInt3_Type;
             case 4: return *context.fUInt4_Type;
         }
+    } else if (base == *context.fUShort_Type) {
+        switch (count) {
+            case 2: return *context.fUShort2_Type;
+            case 3: return *context.fUShort3_Type;
+            case 4: return *context.fUShort4_Type;
+        }
     } else if (base == *context.fBool_Type) {
         switch (count) {
             case 2: return *context.fBool2_Type;
diff --git a/src/sksl/ir/SkSLSymbol.h b/src/sksl/ir/SkSLSymbol.h
index f4c6753..4ec8f15 100644
--- a/src/sksl/ir/SkSLSymbol.h
+++ b/src/sksl/ir/SkSLSymbol.h
@@ -29,7 +29,7 @@
     , fKind(kind)
     , fName(name) {}
 
-    const Kind fKind;
+    Kind fKind;
     StringFragment fName;
 
     typedef IRNode INHERITED;
diff --git a/src/sksl/ir/SkSLType.cpp b/src/sksl/ir/SkSLType.cpp
index 1fdc9bb..19bc58e 100644
--- a/src/sksl/ir/SkSLType.cpp
+++ b/src/sksl/ir/SkSLType.cpp
@@ -80,6 +80,38 @@
                 }
             default: ABORT("unsupported row count (%d)", rows);
         }
+    } else if (*this == *context.fHalf_Type) {
+        switch (rows) {
+            case 1:
+                switch (columns) {
+                    case 2: return *context.fHalf2_Type;
+                    case 3: return *context.fHalf3_Type;
+                    case 4: return *context.fHalf4_Type;
+                    default: ABORT("unsupported vector column count (%d)", columns);
+                }
+            case 2:
+                switch (columns) {
+                    case 2: return *context.fHalf2x2_Type;
+                    case 3: return *context.fHalf3x2_Type;
+                    case 4: return *context.fHalf4x2_Type;
+                    default: ABORT("unsupported matrix column count (%d)", columns);
+                }
+            case 3:
+                switch (columns) {
+                    case 2: return *context.fHalf2x3_Type;
+                    case 3: return *context.fHalf3x3_Type;
+                    case 4: return *context.fHalf4x3_Type;
+                    default: ABORT("unsupported matrix column count (%d)", columns);
+                }
+            case 4:
+                switch (columns) {
+                    case 2: return *context.fHalf2x4_Type;
+                    case 3: return *context.fHalf3x4_Type;
+                    case 4: return *context.fHalf4x4_Type;
+                    default: ABORT("unsupported matrix column count (%d)", columns);
+                }
+            default: ABORT("unsupported row count (%d)", rows);
+        }
     } else if (*this == *context.fDouble_Type) {
         switch (rows) {
             case 1:
@@ -123,6 +155,17 @@
                 }
             default: ABORT("unsupported row count (%d)", rows);
         }
+    } else if (*this == *context.fShort_Type) {
+        switch (rows) {
+            case 1:
+                switch (columns) {
+                    case 2: return *context.fShort2_Type;
+                    case 3: return *context.fShort3_Type;
+                    case 4: return *context.fShort4_Type;
+                    default: ABORT("unsupported vector column count (%d)", columns);
+                }
+            default: ABORT("unsupported row count (%d)", rows);
+        }
     } else if (*this == *context.fUInt_Type) {
         switch (rows) {
             case 1:
@@ -134,6 +177,17 @@
                 }
             default: ABORT("unsupported row count (%d)", rows);
         }
+    } else if (*this == *context.fUShort_Type) {
+        switch (rows) {
+            case 1:
+                switch (columns) {
+                    case 2: return *context.fUShort2_Type;
+                    case 3: return *context.fUShort3_Type;
+                    case 4: return *context.fUShort4_Type;
+                    default: ABORT("unsupported vector column count (%d)", columns);
+                }
+            default: ABORT("unsupported row count (%d)", rows);
+        }
     } else if (*this == *context.fBool_Type) {
         switch (rows) {
             case 1:
diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h
index b047421..ed5e076 100644
--- a/src/sksl/ir/SkSLType.h
+++ b/src/sksl/ir/SkSLType.h
@@ -93,11 +93,12 @@
     }
 
     // Create a scalar type.
-    Type(String name, NumberKind numberKind)
+    Type(String name, NumberKind numberKind, int priority)
     : INHERITED(-1, kType_Kind, StringFragment())
     , fNameString(std::move(name))
     , fTypeKind(kScalar_Kind)
     , fNumberKind(numberKind)
+    , fPriority(priority)
     , fColumns(1)
     , fRows(1) {
         fName.fChars = fNameString.c_str();
@@ -105,11 +106,12 @@
     }
 
     // Create a scalar type which can be coerced to the listed types.
-    Type(String name, NumberKind numberKind, std::vector<const Type*> coercibleTypes)
+    Type(String name, NumberKind numberKind, int priority, std::vector<const Type*> coercibleTypes)
     : INHERITED(-1, kType_Kind, StringFragment())
     , fNameString(std::move(name))
     , fTypeKind(kScalar_Kind)
     , fNumberKind(numberKind)
+    , fPriority(priority)
     , fCoercibleTypes(std::move(coercibleTypes))
     , fColumns(1)
     , fRows(1) {
@@ -224,6 +226,14 @@
     }
 
     /**
+     * Returns the "priority" of a number type, in order of double > float > half > int > short.
+     * When operating on two number types, the result is the higher-priority type.
+     */
+    int priority() const {
+        return fPriority;
+    }
+
+    /**
      * Returns true if an instance of this type can be freely coerced (implicitly converted) to
      * another type.
      */
@@ -315,20 +325,21 @@
 private:
     typedef Symbol INHERITED;
 
-    const String fNameString;
-    const Kind fTypeKind;
+    String fNameString;
+    Kind fTypeKind;
     // always kNonnumeric_NumberKind for non-scalar values
-    const NumberKind fNumberKind;
+    NumberKind fNumberKind;
+    int fPriority = -1;
     const Type* fComponentType = nullptr;
-    const std::vector<const Type*> fCoercibleTypes;
-    const int fColumns = -1;
-    const int fRows = -1;
-    const std::vector<Field> fFields;
-    const SpvDim_ fDimensions = SpvDim1D;
-    const bool fIsDepth = false;
-    const bool fIsArrayed = false;
-    const bool fIsMultisampled = false;
-    const bool fIsSampled = false;
+    std::vector<const Type*> fCoercibleTypes;
+    int fColumns = -1;
+    int fRows = -1;
+    std::vector<Field> fFields;
+    SpvDim_ fDimensions = SpvDim1D;
+    bool fIsDepth = false;
+    bool fIsArrayed = false;
+    bool fIsMultisampled = false;
+    bool fIsSampled = false;
 };
 
 } // namespace
diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include
index 7b738d5..aab9930 100644
--- a/src/sksl/sksl.include
+++ b/src/sksl/sksl.include
@@ -43,14 +43,14 @@
 //$genDType ceil($genDType x);
 $genType fract($genType x);
 //$genDType fract($genDType x);
-$genType mod($genType x, float y);
+$genType mod($genType x, highfloat y);
 $genType mod($genType x, $genType y);
 //$genDType mod($genDType x, double y);
 //$genDType mod($genDType x, $genDType y);
 $genType modf($genType x, out $genType i);
 //$genDType modf($genDType x, out $genDType i);
 $genType min($genType x, $genType y);
-$genType min($genType x, float y);
+$genType min($genType x, highfloat y);
 //$genDType min($genDType x, $genDType y);
 //$genDType min($genDType x, double y);
 $genIType min($genIType x, $genIType y);
@@ -58,7 +58,7 @@
 //$genUType min($genUType x, $genUType y);
 //$genUType min($genUType x, uint y);
 $genType max($genType x, $genType y);
-$genType max($genType x, float y);
+$genType max($genType x, highfloat y);
 //$genDType max($genDType x, $genDType y);
 //$genDType max($genDType x, double y);
 $genIType max($genIType x, $genIType y);
@@ -66,7 +66,7 @@
 //$genUType max($genUType x, $genUType y);
 //$genUType max($genUType x, uint y);
 $genType clamp($genType x, $genType minVal, $genType maxVal);
-$genType clamp($genType x, float minVal, float maxVal);
+$genType clamp($genType x, highfloat minVal, highfloat maxVal);
 //$genDType clamp($genDType x, $genDType minVal, $genDType maxVal);
 //$genDType clamp($genDType x, double minVal, double maxVal);
 $genIType clamp($genIType x, $genIType minVal, $genIType maxVal);
@@ -74,7 +74,7 @@
 //$genUType clamp($genUType x, $genUType minVal, $genUType maxVal);
 //$genUType clamp($genUType x, uint minVal, uint maxVal);
 $genType mix($genType x, $genType y, $genType a);
-$genType mix($genType x, $genType y, float a);
+$genType mix($genType x, $genType y, highfloat a);
 //$genDType mix($genDType x, $genDType y, $genDType a);
 //$genDType mix($genDType x, $genDType y, double a);
 $genType mix($genType x, $genType y, $genBType a);
@@ -83,21 +83,21 @@
 //$genUType mix($genUType x, $genUType y, $genBType a);
 $genBType mix($genBType x, $genBType y, $genBType a);
 $genType step($genType edge, $genType x);
-$genType step(float edge, $genType x);
+$genType step(highfloat edge, $genType x);
 //$genDType step($genDType edge, $genDType x);
 //$genDType step(double edge, $genDType x);
 $genType smoothstep($genType edge0, $genType edge1, $genType x);
-$genType smoothstep(float edge0, float edge1, $genType x);
+$genType smoothstep(highfloat edge0, highfloat edge1, $genType x);
 //$genDType smoothstep($genDType edge0, $genDType edge1, $genDType x);
 //$genDType smoothstep(double edge0, double edge1, $genDType x);
 $genBType isnan($genType x);
 $genBType isnan($genDType x);
 $genBType isinf($genType x);
 $genBType isinf($genDType x);
-$genIType floatBitsToInt($genType value);
-//$genUType floatBitsToUint($genType value);
-$genType intBitsToFloat($genIType value);
-$genType uintBitsToFloat($genUType value);
+$genIType highfloatBitsToInt($genType value);
+//$genUType highfloatBitsToUint($genType value);
+$genType intBitsTohighfloat($genIType value);
+$genType uintBitsTohighfloat($genUType value);
 $genType fma($genType a, $genType b, $genType c);
 $genHType fma($genHType a, $genHType b, $genHType c);
 $genDType fma($genDType a, $genDType b, $genDType c);
@@ -106,68 +106,68 @@
 //$genDType frexp($genDType x, out $genIType exp);
 $genType ldexp($genType x, in $genIType exp);
 //$genDType ldexp($genDType x, in $genIType exp);
-uint packUnorm2x16(float2 v);
-uint packSnorm2x16(float2 v);
-uint packUnorm4x8(float4 v);
-uint packSnorm4x8(float4 v);
-float2 unpackUnorm2x16(uint p);
-float2 unpackSnorm2x16(uint p);
-float4 unpackUnorm4x8(uint p);
-float4 unpackSnorm4x8(uint p);
+uint packUnorm2x16(highfloat2 v);
+uint packSnorm2x16(highfloat2 v);
+uint packUnorm4x8(highfloat4 v);
+uint packSnorm4x8(highfloat4 v);
+highfloat2 unpackUnorm2x16(uint p);
+highfloat2 unpackSnorm2x16(uint p);
+highfloat4 unpackUnorm4x8(uint p);
+highfloat4 unpackSnorm4x8(uint p);
 //double packDouble2x32(uint2 v);
 uint2 unpackDouble2x32(double v);
-uint packHalf2x16(float2 v);
-float2 unpackHalf2x16(uint v);
-float length($genType x);
+uint packHalf2x16(highfloat2 v);
+highfloat2 unpackHalf2x16(uint v);
+highfloat length($genType x);
 half length($genHType x);
 double length($genDType x);
-float distance($genType p0, $genType p1);
+highfloat distance($genType p0, $genType p1);
 half distance($genHType p0, $genHType p1);
 double distance($genDType p0, $genDType p1);
-float dot($genType x, $genType y);
+highfloat dot($genType x, $genType y);
 half dot($genHType x, $genHType y);
 double dot($genDType x, $genDType y);
-float3 cross(float3 x, float3 y);
+highfloat3 cross(highfloat3 x, highfloat3 y);
 half3 cross(half3 x, half3 y);
 double3 cross(double3 x, double3 y);
 $genType normalize($genType x);
 $genHType normalize($genHType x);
 $genDType normalize($genDType x);
-float4 ftransform();
+highfloat4 ftransform();
 $genType faceforward($genType N, $genType I, $genType Nref);
 $genHType faceforward($genHType N, $genHType I, $genHType Nref);
 $genDType faceforward($genDType N, $genDType I, $genDType Nref);
 $genType reflect($genType I, $genType N);
 $genHType reflect($genHType I, $genHType N);
 $genDType reflect($genDType I, $genDType N);
-$genType refract($genType I, $genType N, float eta);
-$genHType refract($genHType I, $genHType N, float eta);
-$genDType refract($genDType I, $genDType N, float eta);
+$genType refract($genType I, $genType N, highfloat eta);
+$genHType refract($genHType I, $genHType N, highfloat eta);
+$genDType refract($genDType I, $genDType N, highfloat eta);
 $mat matrixCompMult($mat x, $mat y);
-float2x2 outerProduct(float2 c, float2 r);
-float3x3 outerProduct(float3 c, float3 r);
-float4x3 outerProduct(float4 c, float4 r);
-float2x3 outerProduct(float3 c, float2 r);
-float3x2 outerProduct(float2 c, float3 r);
-float2x4 outerProduct(float4 c, float2 r);
-float4x2 outerProduct(float2 c, float4 r);
-float3x4 outerProduct(float4 c, float3 r);
-float4x3 outerProduct(float3 c, float4 r);
-float2x2 transpose(float2x2 m);
-float3x3 transpose(float3x3 m);
-float4x4 transpose(float4x4 m);
-float2x3 transpose(float3x2 m);
-float3x2 transpose(float2x3 m);
-float2x4 transpose(float4x2 m);
-float4x2 transpose(float2x4 m);
-float3x4 transpose(float4x3 m);
-float4x3 transpose(float3x4 m);
-float determinant(float2x2 m);
-float determinant(float3x3 m);
-float determinant(float4x4 m);
-float2x2 inverse(float2x2 m);
-float3x3 inverse(float3x3 m);
-float4x4 inverse(float4x4 m);
+highfloat2x2 outerProduct(highfloat2 c, highfloat2 r);
+highfloat3x3 outerProduct(highfloat3 c, highfloat3 r);
+highfloat4x3 outerProduct(highfloat4 c, highfloat4 r);
+highfloat2x3 outerProduct(highfloat3 c, highfloat2 r);
+highfloat3x2 outerProduct(highfloat2 c, highfloat3 r);
+highfloat2x4 outerProduct(highfloat4 c, highfloat2 r);
+highfloat4x2 outerProduct(highfloat2 c, highfloat4 r);
+highfloat3x4 outerProduct(highfloat4 c, highfloat3 r);
+highfloat4x3 outerProduct(highfloat3 c, highfloat4 r);
+highfloat2x2 transpose(highfloat2x2 m);
+highfloat3x3 transpose(highfloat3x3 m);
+highfloat4x4 transpose(highfloat4x4 m);
+highfloat2x3 transpose(highfloat3x2 m);
+highfloat3x2 transpose(highfloat2x3 m);
+highfloat2x4 transpose(highfloat4x2 m);
+highfloat4x2 transpose(highfloat2x4 m);
+highfloat3x4 transpose(highfloat4x3 m);
+highfloat4x3 transpose(highfloat3x4 m);
+highfloat determinant(highfloat2x2 m);
+highfloat determinant(highfloat3x3 m);
+highfloat determinant(highfloat4x4 m);
+highfloat2x2 inverse(highfloat2x2 m);
+highfloat3x3 inverse(highfloat3x3 m);
+highfloat4x4 inverse(highfloat4x4 m);
 $bvec lessThan($vec x, $vec y);
 $bvec lessThan($hvec x, $hvec y);
 $bvec lessThan($dvec x, $dvec y);
@@ -254,19 +254,19 @@
 int textureSize($gsamplerBuffer sampler);
 int2 textureSize($gsampler2DMS sampler);
 int3 textureSize($gsampler2DMSArray sampler);
-float2 textureQueryLod($gsampler1D sampler, float P);
-float2 textureQueryLod($gsampler2D sampler, float2 P);
-float2 textureQueryLod($gsampler3D sampler, float3 P);
-float2 textureQueryLod($gsamplerCube sampler, float3 P);
-float2 textureQueryLod($gsampler1DArray sampler, float P);
-float2 textureQueryLod($gsampler2DArray sampler, float2 P);
-float2 textureQueryLod($gsamplerCubeArray sampler, float3 P);
-float2 textureQueryLod(sampler1DShadow sampler, float P);
-float2 textureQueryLod(sampler2DShadow sampler, float2 P);
-float2 textureQueryLod(samplerCubeShadow sampler, float3 P);
-float2 textureQueryLod(sampler1DArrayShadow sampler, float P);
-float2 textureQueryLod(sampler2DArrayShadow sampler, float2 P);
-float2 textureQueryLod(samplerCubeArrayShadow sampler, float3 P);
+highfloat2 textureQueryLod($gsampler1D sampler, highfloat P);
+highfloat2 textureQueryLod($gsampler2D sampler, highfloat2 P);
+highfloat2 textureQueryLod($gsampler3D sampler, highfloat3 P);
+highfloat2 textureQueryLod($gsamplerCube sampler, highfloat3 P);
+highfloat2 textureQueryLod($gsampler1DArray sampler, highfloat P);
+highfloat2 textureQueryLod($gsampler2DArray sampler, highfloat2 P);
+highfloat2 textureQueryLod($gsamplerCubeArray sampler, highfloat3 P);
+highfloat2 textureQueryLod(sampler1DShadow sampler, highfloat P);
+highfloat2 textureQueryLod(sampler2DShadow sampler, highfloat2 P);
+highfloat2 textureQueryLod(samplerCubeShadow sampler, highfloat3 P);
+highfloat2 textureQueryLod(sampler1DArrayShadow sampler, highfloat P);
+highfloat2 textureQueryLod(sampler2DArrayShadow sampler, highfloat2 P);
+highfloat2 textureQueryLod(samplerCubeArrayShadow sampler, highfloat3 P);
 int textureQueryLevels($gsampler1D sampler);
 int textureQueryLevels($gsampler2D sampler);
 int textureQueryLevels($gsampler3D sampler);
@@ -282,50 +282,50 @@
 int textureQueryLevels(samplerCubeArrayShadow sampler);
 */
 
-$gfloat4 texture($gsampler1D sampler, float P);
-$gfloat4 texture($gsampler1D sampler, float P, float bias);
-$gfloat4 texture($gsampler2D sampler, float2 P);
+half4 texture($gsampler1D sampler, highfloat P);
+half4 texture($gsampler1D sampler, highfloat P, highfloat bias);
+half4 texture($gsampler2D sampler, highfloat2 P);
 // The above currently only expand to handle the float/fixed case. So we also declare this integer
 // version of texture().
-int4 texture(isampler2D sampler, float2 P);
-float4 texture(samplerExternalOES sampler, float2 P, float bias);
-float4 texture(samplerExternalOES sampler, float2 P);
+int4 texture(isampler2D sampler, highfloat2 P);
+half4 texture(samplerExternalOES sampler, highfloat2 P, highfloat bias);
+half4 texture(samplerExternalOES sampler, highfloat2 P);
 
 /*
-$gfloat4 texture($gsampler2D sampler, float2 P, float bias);
-$gfloat4 texture($gsampler3D sampler, float3 P);
-$gfloat4 texture($gsampler3D sampler, float3 P, float bias);
-$gfloat4 texture($gsamplerCube sampler, float3 P);
-$gfloat4 texture($gsamplerCube sampler, float3 P, float bias);
-float texture(sampler1DShadow sampler, float3 P);
-float texture(sampler1DShadow sampler, float3 P, float bias);
-float texture(sampler2DShadow sampler, float3 P);
-float texture(sampler2DShadow sampler, float3 P, float bias);
-float texture(samplerCubeShadow sampler, float4 P);
-float texture(samplerCubeShadow sampler, float4 P, float bias);
-$gfloat4 texture($gsampler1DArray sampler, float2 P);
-$gfloat4 texture($gsampler1DArray sampler, float2 P, float bias);
-$gfloat4 texture($gsampler2DArray sampler, float3 P);
-$gfloat4 texture($gsampler2DArray sampler, float3 P, float bias);
-$gfloat4 texture($gsamplerCubeArray sampler, float4 P);
-$gfloat4 texture($gsamplerCubeArray sampler, float4 P, float bias);
-float texture(sampler1DArrayShadow sampler, float3 P);
-float texture(sampler1DArrayShadow sampler, float3 P, float bias);
-float texture(sampler2DArrayShadow sampler, float4 P);
+$gfloat4 texture($gsampler2D sampler, highfloat2 P, highfloat bias);
+$gfloat4 texture($gsampler3D sampler, highfloat3 P);
+$gfloat4 texture($gsampler3D sampler, highfloat3 P, highfloat bias);
+$gfloat4 texture($gsamplerCube sampler, highfloat3 P);
+$gfloat4 texture($gsamplerCube sampler, highfloat3 P, highfloat bias);
+highfloat texture(sampler1DShadow sampler, highfloat3 P);
+highfloat texture(sampler1DShadow sampler, highfloat3 P, highfloat bias);
+highfloat texture(sampler2DShadow sampler, highfloat3 P);
+highfloat texture(sampler2DShadow sampler, highfloat3 P, highfloat bias);
+highfloat texture(samplerCubeShadow sampler, highfloat4 P);
+highfloat texture(samplerCubeShadow sampler, highfloat4 P, highfloat bias);
+$gfloat4 texture($gsampler1DArray sampler, highfloat2 P);
+$gfloat4 texture($gsampler1DArray sampler, highfloat2 P, highfloat bias);
+$gfloat4 texture($gsampler2DArray sampler, highfloat3 P);
+$gfloat4 texture($gsampler2DArray sampler, highfloat3 P, highfloat bias);
+$gfloat4 texture($gsamplerCubeArray sampler, highfloat4 P);
+$gfloat4 texture($gsamplerCubeArray sampler, highfloat4 P, highfloat bias);
+highfloat texture(sampler1DArrayShadow sampler, highfloat3 P);
+highfloat texture(sampler1DArrayShadow sampler, highfloat3 P, highfloat bias);
+highfloat texture(sampler2DArrayShadow sampler, highfloat4 P);
 */
 
-$gfloat4 texture($gsampler2DRect sampler, float2 P);
-$gfloat4 texture($gsampler2DRect sampler, float3 P);
+half4 texture($gsampler2DRect sampler, highfloat2 P);
+half4 texture($gsampler2DRect sampler, highfloat3 P);
 
 /*
-float texture(sampler2DRectShadow sampler, float3 P);
-float texture($gsamplerCubeArrayShadow sampler, float4 P, float compare);
+highfloat texture(sampler2DRectShadow sampler, highfloat3 P);
+highfloat texture($gsamplerCubeArrayShadow sampler, highfloat4 P, highfloat compare);
 */
 
 // Currently we do not support the generic types of loading subpassInput so we have some explicit
 // versions that we currently use
-float4 subpassLoad(subpassInput subpass);
-float4 subpassLoad(subpassInputMS subpass, int sample);
+highfloat4 subpassLoad(subpassInput subpass);
+highfloat4 subpassLoad(subpassInputMS subpass, int sample);
 /*
 $gfloat4subpassLoad(gsubpassInput subpass);
 $gfloat4subpassLoad(gsubpassInputMS subpass, int sample);
@@ -336,50 +336,50 @@
 
 STRINGIFY(
 
-$gfloat4 texture($gsampler1D sampler, float2 P);
-$gfloat4 texture($gsampler1D sampler, float2 P, float bias);
-$gfloat4 texture($gsampler2D sampler, float3 P);
-$gfloat4 texture($gsampler2D sampler, float3 P, float bias);
+half4 texture($gsampler1D sampler, highfloat2 P);
+half4 texture($gsampler1D sampler, highfloat2 P, highfloat bias);
+half4 texture($gsampler2D sampler, highfloat3 P);
+half4 texture($gsampler2D sampler, highfloat3 P, highfloat bias);
 /*
-$gfloat4 textureProj($gsampler3D sampler, float4 P);
-$gfloat4 textureProj($gsampler3D sampler, float4 P, float bias);
-float textureProj(sampler1DShadow sampler, float4 P);
-float textureProj(sampler1DShadow sampler, float4 P, float bias);
-float textureProj(sampler2DShadow sampler, float4 P);
-float textureProj(sampler2DShadow sampler, float4 P, float bias);
-$gfloat4 textureProj($gsampler2DRect sampler, float4 P);
-float textureProj(sampler2DRectShadow sampler, float4 P);
-$gfloat4 textureLod($gsampler1D sampler, float P, float lod);
-$gfloat4 textureLod($gsampler2D sampler, float2 P, float lod);
-$gfloat4 textureLod($gsampler3D sampler, float3 P, float lod);
-$gfloat4 textureLod($gsamplerCube sampler, float3 P, float lod);
-float textureLod(sampler1DShadow sampler, float3 P, float lod);
-float textureLod(sampler2DShadow sampler, float3 P, float lod);
-$gfloat4 textureLod($gsampler1DArray sampler, float2 P, float lod);
-$gfloat4 textureLod($gsampler2DArray sampler, float3 P, float lod);
-float textureLod(sampler1DArrayShadow sampler, float3 P, float lod);
-$gfloat4 textureLod($gsamplerCubeArray sampler, float4 P, float lod);
-$gfloat4 textureOffset($gsampler1D sampler, float P, int offset);
-$gfloat4 textureOffset($gsampler1D sampler, float P, int offset, float bias);
-$gfloat4 textureOffset($gsampler2D sampler, float2 P, int2 offset);
-$gfloat4 textureOffset($gsampler2D sampler, float2 P, int2 offset, float bias);
-$gfloat4 textureOffset($gsampler3D sampler, float3 P, int3 offset);
-$gfloat4 textureOffset($gsampler3D sampler, float3 P, int3 offset, float bias);
-$gfloat4 textureOffset($gsampler2DRect sampler, float2 P, int2 offset);
-float textureOffset(sampler2DRectShadow sampler, float3 P, int2 offset);
-float textureOffset(sampler1DShadow sampler, float3 P, int offset);
-float textureOffset(sampler1DShadow sampler, float3 P, int offset, float bias);
-float textureOffset(sampler2DShadow sampler, float3 P, int2 offset);
-float textureOffset(sampler2DShadow sampler, float3 P, int2 offset, float bias);
-$gfloat4 textureOffset($gsampler1DArray sampler, float2 P, int offset);
-$gfloat4 textureOffset($gsampler1DArray sampler, float2 P, int offset, float bias);
-$gfloat4 textureOffset($gsampler2DArray sampler, float3 P, int2 offset);
-$gfloat4 textureOffset($gsampler2DArray sampler, float3 P, int2 offset, float bias);
-float textureOffset(sampler1DArrayShadow sampler, float3 P, int offset);
-float textureOffset(sampler1DArrayShadow sampler, float3 P, int offset, float bias);
-float textureOffset(sampler2DArrayShadow sampler, float4 P, int2 offset);
+$gfloat4 textureProj($gsampler3D sampler, highfloat4 P);
+$gfloat4 textureProj($gsampler3D sampler, highfloat4 P, highfloat bias);
+highfloat textureProj(sampler1DShadow sampler, highfloat4 P);
+highfloat textureProj(sampler1DShadow sampler, highfloat4 P, highfloat bias);
+highfloat textureProj(sampler2DShadow sampler, highfloat4 P);
+highfloat textureProj(sampler2DShadow sampler, highfloat4 P, highfloat bias);
+$gfloat4 textureProj($gsampler2DRect sampler, highfloat4 P);
+highfloat textureProj(sampler2DRectShadow sampler, highfloat4 P);
+$gfloat4 textureLod($gsampler1D sampler, highfloat P, highfloat lod);
+$gfloat4 textureLod($gsampler2D sampler, highfloat2 P, highfloat lod);
+$gfloat4 textureLod($gsampler3D sampler, highfloat3 P, highfloat lod);
+$gfloat4 textureLod($gsamplerCube sampler, highfloat3 P, highfloat lod);
+highfloat textureLod(sampler1DShadow sampler, highfloat3 P, highfloat lod);
+highfloat textureLod(sampler2DShadow sampler, highfloat3 P, highfloat lod);
+$gfloat4 textureLod($gsampler1DArray sampler, highfloat2 P, highfloat lod);
+$gfloat4 textureLod($gsampler2DArray sampler, highfloat3 P, highfloat lod);
+highfloat textureLod(sampler1DArrayShadow sampler, highfloat3 P, highfloat lod);
+$gfloat4 textureLod($gsamplerCubeArray sampler, highfloat4 P, highfloat lod);
+$gfloat4 textureOffset($gsampler1D sampler, highfloat P, int offset);
+$gfloat4 textureOffset($gsampler1D sampler, highfloat P, int offset, highfloat bias);
+$gfloat4 textureOffset($gsampler2D sampler, highfloat2 P, int2 offset);
+$gfloat4 textureOffset($gsampler2D sampler, highfloat2 P, int2 offset, highfloat bias);
+$gfloat4 textureOffset($gsampler3D sampler, highfloat3 P, int3 offset);
+$gfloat4 textureOffset($gsampler3D sampler, highfloat3 P, int3 offset, highfloat bias);
+$gfloat4 textureOffset($gsampler2DRect sampler, highfloat2 P, int2 offset);
+highfloat textureOffset(sampler2DRectShadow sampler, highfloat3 P, int2 offset);
+highfloat textureOffset(sampler1DShadow sampler, highfloat3 P, int offset);
+highfloat textureOffset(sampler1DShadow sampler, highfloat3 P, int offset, highfloat bias);
+highfloat textureOffset(sampler2DShadow sampler, highfloat3 P, int2 offset);
+highfloat textureOffset(sampler2DShadow sampler, highfloat3 P, int2 offset, highfloat bias);
+$gfloat4 textureOffset($gsampler1DArray sampler, highfloat2 P, int offset);
+$gfloat4 textureOffset($gsampler1DArray sampler, highfloat2 P, int offset, highfloat bias);
+$gfloat4 textureOffset($gsampler2DArray sampler, highfloat3 P, int2 offset);
+$gfloat4 textureOffset($gsampler2DArray sampler, highfloat3 P, int2 offset, highfloat bias);
+highfloat textureOffset(sampler1DArrayShadow sampler, highfloat3 P, int offset);
+highfloat textureOffset(sampler1DArrayShadow sampler, highfloat3 P, int offset, highfloat bias);
+highfloat textureOffset(sampler2DArrayShadow sampler, highfloat4 P, int2 offset);
 */
-float4 texelFetch(samplerBuffer sampler, int P);
+highfloat4 texelFetch(samplerBuffer sampler, int P);
 
 $gfloat4 texelFetch($gsampler1D sampler, int P, int lod);
 $gfloat4 texelFetch($gsampler2D sampler, int2 P, int lod);
@@ -396,123 +396,123 @@
 $gfloat4 texelFetchOffset($gsampler2DRect sampler, int2 P, int2 offset);
 $gfloat4 texelFetchOffset($gsampler1DArray sampler, int2 P, int lod, int offset);
 $gfloat4 texelFetchOffset($gsampler2DArray sampler, int3 P, int lod, int2 offset);
-$gfloat4 textureProjOffset($gsampler1D sampler, float2 P, int offset);
-$gfloat4 textureProjOffset($gsampler1D sampler, float2 P, int offset, float bias);
-$gfloat4 textureProjOffset($gsampler1D sampler, float4 P, int offset);
-$gfloat4 textureProjOffset($gsampler1D sampler, float4 P, int offset, float bias);
-$gfloat4 textureProjOffset($gsampler2D sampler, float3 P, int2 offset);
-$gfloat4 textureProjOffset($gsampler2D sampler, float3 P, int2 offset, float bias);
-$gfloat4 textureProjOffset($gsampler2D sampler, float4 P, int2 offset);
-$gfloat4 textureProjOffset($gsampler2D sampler, float4 P, int2 offset, float bias);
-$gfloat4 textureProjOffset($gsampler3D sampler, float4 P, int3 offset);
-$gfloat4 textureProjOffset($gsampler3D sampler, float4 P, int3 offset, float bias);
-$gfloat4 textureProjOffset($gsampler2DRect sampler, float3 P, int2 offset);
-$gfloat4 textureProjOffset($gsampler2DRect sampler, float4 P, int2 offset);
-float textureProjOffset(sampler2DRectShadow sampler, float4 P, int2 offset);
-float textureProjOffset(sampler1DShadow sampler, float4 P, int offset);
-float textureProjOffset(sampler1DShadow sampler, float4 P, int offset, float bias);
-float textureProjOffset(sampler2DShadow sampler, float4 P, int2 offset);
-float textureProjOffset(sampler2DShadow sampler, float4 P, int2 offset, float bias);
-$gfloat4 textureLodOffset($gsampler1D sampler, float P, float lod, int offset);
-$gfloat4 textureLodOffset($gsampler2D sampler, float2 P, float lod, int2 offset);
-$gfloat4 textureLodOffset($gsampler3D sampler, float3 P, float lod, int3 offset);
-float textureLodOffset(sampler1DShadow sampler, float3 P, float lod, int offset);
-float textureLodOffset(sampler2DShadow sampler, float3 P, float lod, int2 offset);
-$gfloat4 textureLodOffset($gsampler1DArray sampler, float2 P, float lod, int offset);
-$gfloat4 textureLodOffset($gsampler2DArray sampler, float3 P, float lod, int2 offset);
-float textureLodOffset(sampler1DArrayShadow sampler, float3 P, float lod, int offset);
-$gfloat4 textureProjLod($gsampler1D sampler, float2 P, float lod);
-$gfloat4 textureProjLod($gsampler1D sampler, float4 P, float lod);
-$gfloat4 textureProjLod($gsampler2D sampler, float3 P, float lod);
-$gfloat4 textureProjLod($gsampler2D sampler, float4 P, float lod);
-$gfloat4 textureProjLod($gsampler3D sampler, float4 P, float lod);
-float textureProjLod(sampler1DShadow sampler, float4 P, float lod);
-float textureProjLod(sampler2DShadow sampler, float4 P, float lod);
-$gfloat4 textureProjLodOffset($gsampler1D sampler, float2 P, float lod, int offset);
-$gfloat4 textureProjLodOffset($gsampler1D sampler, float4 P, float lod, int offset);
-$gfloat4 textureProjLodOffset($gsampler2D sampler, float3 P, float lod, int2 offset);
-$gfloat4 textureProjLodOffset($gsampler2D sampler, float4 P, float lod, int2 offset);
-$gfloat4 textureProjLodOffset($gsampler3D sampler, float4 P, float lod, int3 offset);
-float textureProjLodOffset(sampler1DShadow sampler, float4 P, float lod, int offset);
-float textureProjLodOffset(sampler2DShadow sampler, float4 P, float lod, int2 offset);
-$gfloat4 textureGrad($gsampler1D sampler, float P, float dPdx, float dPdy);
-$gfloat4 textureGrad($gsampler2D sampler, float2 P, float2 dPdx, float2 dPdy);
-$gfloat4 textureGrad($gsampler3D sampler, float3 P, float3 dPdx, float3 dPdy);
-$gfloat4 textureGrad($gsamplerCube sampler, float3 P, float3 dPdx, float3 dPdy);
-$gfloat4 textureGrad($gsampler2DRect sampler, float2 P, float2 dPdx, float2 dPdy);
-float textureGrad(sampler2DRectShadow sampler, float3 P, float2 dPdx, float2 dPdy);
-float textureGrad(sampler1DShadow sampler, float3 P, float dPdx, float dPdy);
-float textureGrad(sampler2DShadow sampler, float3 P, float2 dPdx, float2 dPdy);
-float textureGrad(samplerCubeShadow sampler, float4 P, float3 dPdx, float3 dPdy);
-$gfloat4 textureGrad($gsampler1DArray sampler, float2 P, float dPdx, float dPdy);
-$gfloat4 textureGrad($gsampler2DArray sampler, float3 P, float2 dPdx, float2 dPdy);
-float textureGrad(sampler1DArrayShadow sampler, float3 P, float dPdx, float dPdy);
-float textureGrad(sampler2DArrayShadow sampler, float4 P, float2 dPdx, float2 dPdy);
-$gfloat4 textureGrad($gsamplerCubeArray sampler, float4 P, float3 dPdx, float3 dPdy);
-$gfloat4 textureGradOffset($gsampler1D sampler, float P, float dPdx, float dPdy, int offset);
-$gfloat4 textureGradOffset($gsampler2D sampler, float2 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureGradOffset($gsampler3D sampler, float3 P, float3 dPdx, float3 dPdy, int3 offset);
-$gfloat4 textureGradOffset($gsampler2DRect sampler, float2 P, float2 dPdx, float2 dPdy, int2 offset);
-float textureGradOffset(sampler2DRectShadow sampler, float3 P, float2 dPdx, float2 dPdy, int2 offset);
-float textureGradOffset(sampler1DShadow sampler, float3 P, float dPdx, float dPdy, int offset );
-float textureGradOffset(sampler2DShadow sampler, float3 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureGradOffset($gsampler1DArray sampler, float2 P, float dPdx, float dPdy, int offset);
-$gfloat4 textureGradOffset($gsampler2DArray sampler, float3 P, float2 dPdx, float2 dPdy, int2 offset);
-float textureGradOffset(sampler1DArrayShadow sampler, float3 P, float dPdx, float dPdy, int offset);
-float textureGradOffset(sampler2DArrayShadow sampler, float4 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureProjGrad($gsampler1D sampler, float2 P, float dPdx, float dPdy);
-$gfloat4 textureProjGrad($gsampler1D sampler, float4 P, float dPdx, float dPdy);
-$gfloat4 textureProjGrad($gsampler2D sampler, float3 P, float2 dPdx, float2 dPdy);
-$gfloat4 textureProjGrad($gsampler2D sampler, float4 P, float2 dPdx, float2 dPdy);
-$gfloat4 textureProjGrad($gsampler3D sampler, float4 P, float3 dPdx, float3 dPdy);
-$gfloat4 textureProjGrad($gsampler2DRect sampler, float3 P, float2 dPdx, float2 dPdy);
-$gfloat4 textureProjGrad($gsampler2DRect sampler, float4 P, float2 dPdx, float2 dPdy);
-float textureProjGrad(sampler2DRectShadow sampler, float4 P, float2 dPdx, float2 dPdy);
-float textureProjGrad(sampler1DShadow sampler, float4 P, float dPdx, float dPdy);
-float textureProjGrad(sampler2DShadow sampler, float4 P, float2 dPdx, float2 dPdy);
-$gfloat4 textureProjGradOffset($gsampler1D sampler, float2 P, float dPdx, float dPdy, int offset);
-$gfloat4 textureProjGradOffset($gsampler1D sampler, float4 P, float dPdx, float dPdy, int offset);
-$gfloat4 textureProjGradOffset($gsampler2D sampler, float3 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureProjGradOffset($gsampler2D sampler, float4 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureProjGradOffset($gsampler2DRect sampler, float3 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureProjGradOffset($gsampler2DRect sampler, float4 P, float2 dPdx, float2 dPdy, int2 offset);
-float textureProjGradOffset(sampler2DRectShadow sampler, float4 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureProjGradOffset($gsampler3D sampler, float4 P, float3 dPdx, float3 dPdy, int3 offset);
-float textureProjGradOffset(sampler1DShadow sampler, float4 P, float dPdx, float dPdy, int offset);
-float textureProjGradOffset(sampler2DShadow sampler, float4 P, float2 dPdx, float2 dPdy, int2 offset);
-$gfloat4 textureGather($gsampler2D sampler, float2 P);
-$gfloat4 textureGather($gsampler2D sampler, float2 P, int comp);
-$gfloat4 textureGather($gsampler2DArray sampler, float3 P);
-$gfloat4 textureGather($gsampler2DArray sampler, float3 P, int comp);
-$gfloat4 textureGather($gsamplerCube sampler, float3 P);
-$gfloat4 textureGather($gsamplerCube sampler, float3 P, int comp);
-$gfloat4 textureGather($gsamplerCubeArray sampler, float4 P);
-$gfloat4 textureGather($gsamplerCubeArray sampler, float4 P, int comp);
-$gfloat4 textureGather($gsampler2DRect sampler, float2 P);
-$gfloat4 textureGather($gsampler2DRect sampler, float2 P, int comp);
-float4 textureGather(sampler2DShadow sampler, float2 P, float refZ);
-float4 textureGather(sampler2DArrayShadow sampler, float3 P, float refZ);
-float4 textureGather(samplerCubeShadow sampler, float3 P, float refZ);
-float4 textureGather(samplerCubeArrayShadow sampler, float4 P, float refZ);
-float4 textureGather(sampler2DRectShadow sampler, float2 P, float refZ);
-$gfloat4 textureGatherOffset($gsampler2D sampler, float2 P, int2 offset);
-$gfloat4 textureGatherOffset($gsampler2D sampler, float2 P, int2 offset, int comp);
-$gfloat4 textureGatherOffset($gsampler2DArray sampler, float3 P, int2 offset);
-$gfloat4 textureGatherOffset($gsampler2DArray sampler, float3 P, int2 offset, int comp);
-$gfloat4 textureGatherOffset($gsampler2DRect sampler, float2 P, int2 offset);
-$gfloat4 textureGatherOffset($gsampler2DRect sampler, float2 P, int2 offset, int comp);
-float4 textureGatherOffset(sampler2DShadow sampler, float2 P, float refZ, int2 offset);
-float4 textureGatherOffset(sampler2DArrayShadow sampler, float3 P, float refZ, int2 offset);
-float4 textureGatherOffset(sampler2DRectShadow sampler, float2 P, float refZ, int2 offset);
-$gfloat4 textureGatherOffsets($gsampler2D sampler, float2 P, int2 offsets[4]);
-$gfloat4 textureGatherOffsets($gsampler2D sampler, float2 P, int2 offsets[4], int comp);
-$gfloat4 textureGatherOffsets($gsampler2DArray sampler, float3 P, int2 offsets[4]);
-$gfloat4 textureGatherOffsets($gsampler2DArray sampler, float3 P, int2 offsets[4], int comp);
-$gfloat4 textureGatherOffsets($gsampler2DRect sampler, float2 P, int2 offsets[4]);
-$gfloat4 textureGatherOffsets($gsampler2DRect sampler, float2 P, int2 offsets[4], int comp);
-float4 textureGatherOffsets(sampler2DShadow sampler, float2 P, float refZ, int2 offsets[4]);
-float4 textureGatherOffsets(sampler2DArrayShadow sampler, float3 P, float refZ, int2 offsets[4]);
-float4 textureGatherOffsets(sampler2DRectShadow sampler, float2 P, float refZ, int2 offsets[4]);
+$gfloat4 textureProjOffset($gsampler1D sampler, highfloat2 P, int offset);
+$gfloat4 textureProjOffset($gsampler1D sampler, highfloat2 P, int offset, highfloat bias);
+$gfloat4 textureProjOffset($gsampler1D sampler, highfloat4 P, int offset);
+$gfloat4 textureProjOffset($gsampler1D sampler, highfloat4 P, int offset, highfloat bias);
+$gfloat4 textureProjOffset($gsampler2D sampler, highfloat3 P, int2 offset);
+$gfloat4 textureProjOffset($gsampler2D sampler, highfloat3 P, int2 offset, highfloat bias);
+$gfloat4 textureProjOffset($gsampler2D sampler, highfloat4 P, int2 offset);
+$gfloat4 textureProjOffset($gsampler2D sampler, highfloat4 P, int2 offset, highfloat bias);
+$gfloat4 textureProjOffset($gsampler3D sampler, highfloat4 P, int3 offset);
+$gfloat4 textureProjOffset($gsampler3D sampler, highfloat4 P, int3 offset, highfloat bias);
+$gfloat4 textureProjOffset($gsampler2DRect sampler, highfloat3 P, int2 offset);
+$gfloat4 textureProjOffset($gsampler2DRect sampler, highfloat4 P, int2 offset);
+highfloat textureProjOffset(sampler2DRectShadow sampler, highfloat4 P, int2 offset);
+highfloat textureProjOffset(sampler1DShadow sampler, highfloat4 P, int offset);
+highfloat textureProjOffset(sampler1DShadow sampler, highfloat4 P, int offset, highfloat bias);
+highfloat textureProjOffset(sampler2DShadow sampler, highfloat4 P, int2 offset);
+highfloat textureProjOffset(sampler2DShadow sampler, highfloat4 P, int2 offset, highfloat bias);
+$gfloat4 textureLodOffset($gsampler1D sampler, highfloat P, highfloat lod, int offset);
+$gfloat4 textureLodOffset($gsampler2D sampler, highfloat2 P, highfloat lod, int2 offset);
+$gfloat4 textureLodOffset($gsampler3D sampler, highfloat3 P, highfloat lod, int3 offset);
+highfloat textureLodOffset(sampler1DShadow sampler, highfloat3 P, highfloat lod, int offset);
+highfloat textureLodOffset(sampler2DShadow sampler, highfloat3 P, highfloat lod, int2 offset);
+$gfloat4 textureLodOffset($gsampler1DArray sampler, highfloat2 P, highfloat lod, int offset);
+$gfloat4 textureLodOffset($gsampler2DArray sampler, highfloat3 P, highfloat lod, int2 offset);
+highfloat textureLodOffset(sampler1DArrayShadow sampler, highfloat3 P, highfloat lod, int offset);
+$gfloat4 textureProjLod($gsampler1D sampler, highfloat2 P, highfloat lod);
+$gfloat4 textureProjLod($gsampler1D sampler, highfloat4 P, highfloat lod);
+$gfloat4 textureProjLod($gsampler2D sampler, highfloat3 P, highfloat lod);
+$gfloat4 textureProjLod($gsampler2D sampler, highfloat4 P, highfloat lod);
+$gfloat4 textureProjLod($gsampler3D sampler, highfloat4 P, highfloat lod);
+highfloat textureProjLod(sampler1DShadow sampler, highfloat4 P, highfloat lod);
+highfloat textureProjLod(sampler2DShadow sampler, highfloat4 P, highfloat lod);
+$gfloat4 textureProjLodOffset($gsampler1D sampler, highfloat2 P, highfloat lod, int offset);
+$gfloat4 textureProjLodOffset($gsampler1D sampler, highfloat4 P, highfloat lod, int offset);
+$gfloat4 textureProjLodOffset($gsampler2D sampler, highfloat3 P, highfloat lod, int2 offset);
+$gfloat4 textureProjLodOffset($gsampler2D sampler, highfloat4 P, highfloat lod, int2 offset);
+$gfloat4 textureProjLodOffset($gsampler3D sampler, highfloat4 P, highfloat lod, int3 offset);
+highfloat textureProjLodOffset(sampler1DShadow sampler, highfloat4 P, highfloat lod, int offset);
+highfloat textureProjLodOffset(sampler2DShadow sampler, highfloat4 P, highfloat lod, int2 offset);
+$gfloat4 textureGrad($gsampler1D sampler, highfloat P, highfloat dPdx, highfloat dPdy);
+$gfloat4 textureGrad($gsampler2D sampler, highfloat2 P, highfloat2 dPdx, highfloat2 dPdy);
+$gfloat4 textureGrad($gsampler3D sampler, highfloat3 P, highfloat3 dPdx, highfloat3 dPdy);
+$gfloat4 textureGrad($gsamplerCube sampler, highfloat3 P, highfloat3 dPdx, highfloat3 dPdy);
+$gfloat4 textureGrad($gsampler2DRect sampler, highfloat2 P, highfloat2 dPdx, highfloat2 dPdy);
+highfloat textureGrad(sampler2DRectShadow sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy);
+highfloat textureGrad(sampler1DShadow sampler, highfloat3 P, highfloat dPdx, highfloat dPdy);
+highfloat textureGrad(sampler2DShadow sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy);
+highfloat textureGrad(samplerCubeShadow sampler, highfloat4 P, highfloat3 dPdx, highfloat3 dPdy);
+$gfloat4 textureGrad($gsampler1DArray sampler, highfloat2 P, highfloat dPdx, highfloat dPdy);
+$gfloat4 textureGrad($gsampler2DArray sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy);
+highfloat textureGrad(sampler1DArrayShadow sampler, highfloat3 P, highfloat dPdx, highfloat dPdy);
+highfloat textureGrad(sampler2DArrayShadow sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy);
+$gfloat4 textureGrad($gsamplerCubeArray sampler, highfloat4 P, highfloat3 dPdx, highfloat3 dPdy);
+$gfloat4 textureGradOffset($gsampler1D sampler, highfloat P, highfloat dPdx, highfloat dPdy, int offset);
+$gfloat4 textureGradOffset($gsampler2D sampler, highfloat2 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureGradOffset($gsampler3D sampler, highfloat3 P, highfloat3 dPdx, highfloat3 dPdy, int3 offset);
+$gfloat4 textureGradOffset($gsampler2DRect sampler, highfloat2 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+highfloat textureGradOffset(sampler2DRectShadow sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+highfloat textureGradOffset(sampler1DShadow sampler, highfloat3 P, highfloat dPdx, highfloat dPdy, int offset );
+highfloat textureGradOffset(sampler2DShadow sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureGradOffset($gsampler1DArray sampler, highfloat2 P, highfloat dPdx, highfloat dPdy, int offset);
+$gfloat4 textureGradOffset($gsampler2DArray sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+highfloat textureGradOffset(sampler1DArrayShadow sampler, highfloat3 P, highfloat dPdx, highfloat dPdy, int offset);
+highfloat textureGradOffset(sampler2DArrayShadow sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureProjGrad($gsampler1D sampler, highfloat2 P, highfloat dPdx, highfloat dPdy);
+$gfloat4 textureProjGrad($gsampler1D sampler, highfloat4 P, highfloat dPdx, highfloat dPdy);
+$gfloat4 textureProjGrad($gsampler2D sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy);
+$gfloat4 textureProjGrad($gsampler2D sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy);
+$gfloat4 textureProjGrad($gsampler3D sampler, highfloat4 P, highfloat3 dPdx, highfloat3 dPdy);
+$gfloat4 textureProjGrad($gsampler2DRect sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy);
+$gfloat4 textureProjGrad($gsampler2DRect sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy);
+highfloat textureProjGrad(sampler2DRectShadow sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy);
+highfloat textureProjGrad(sampler1DShadow sampler, highfloat4 P, highfloat dPdx, highfloat dPdy);
+highfloat textureProjGrad(sampler2DShadow sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy);
+$gfloat4 textureProjGradOffset($gsampler1D sampler, highfloat2 P, highfloat dPdx, highfloat dPdy, int offset);
+$gfloat4 textureProjGradOffset($gsampler1D sampler, highfloat4 P, highfloat dPdx, highfloat dPdy, int offset);
+$gfloat4 textureProjGradOffset($gsampler2D sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureProjGradOffset($gsampler2D sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureProjGradOffset($gsampler2DRect sampler, highfloat3 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureProjGradOffset($gsampler2DRect sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+highfloat textureProjGradOffset(sampler2DRectShadow sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureProjGradOffset($gsampler3D sampler, highfloat4 P, highfloat3 dPdx, highfloat3 dPdy, int3 offset);
+highfloat textureProjGradOffset(sampler1DShadow sampler, highfloat4 P, highfloat dPdx, highfloat dPdy, int offset);
+highfloat textureProjGradOffset(sampler2DShadow sampler, highfloat4 P, highfloat2 dPdx, highfloat2 dPdy, int2 offset);
+$gfloat4 textureGather($gsampler2D sampler, highfloat2 P);
+$gfloat4 textureGather($gsampler2D sampler, highfloat2 P, int comp);
+$gfloat4 textureGather($gsampler2DArray sampler, highfloat3 P);
+$gfloat4 textureGather($gsampler2DArray sampler, highfloat3 P, int comp);
+$gfloat4 textureGather($gsamplerCube sampler, highfloat3 P);
+$gfloat4 textureGather($gsamplerCube sampler, highfloat3 P, int comp);
+$gfloat4 textureGather($gsamplerCubeArray sampler, highfloat4 P);
+$gfloat4 textureGather($gsamplerCubeArray sampler, highfloat4 P, int comp);
+$gfloat4 textureGather($gsampler2DRect sampler, highfloat2 P);
+$gfloat4 textureGather($gsampler2DRect sampler, highfloat2 P, int comp);
+highfloat4 textureGather(sampler2DShadow sampler, highfloat2 P, highfloat refZ);
+highfloat4 textureGather(sampler2DArrayShadow sampler, highfloat3 P, highfloat refZ);
+highfloat4 textureGather(samplerCubeShadow sampler, highfloat3 P, highfloat refZ);
+highfloat4 textureGather(samplerCubeArrayShadow sampler, highfloat4 P, highfloat refZ);
+highfloat4 textureGather(sampler2DRectShadow sampler, highfloat2 P, highfloat refZ);
+$gfloat4 textureGatherOffset($gsampler2D sampler, highfloat2 P, int2 offset);
+$gfloat4 textureGatherOffset($gsampler2D sampler, highfloat2 P, int2 offset, int comp);
+$gfloat4 textureGatherOffset($gsampler2DArray sampler, highfloat3 P, int2 offset);
+$gfloat4 textureGatherOffset($gsampler2DArray sampler, highfloat3 P, int2 offset, int comp);
+$gfloat4 textureGatherOffset($gsampler2DRect sampler, highfloat2 P, int2 offset);
+$gfloat4 textureGatherOffset($gsampler2DRect sampler, highfloat2 P, int2 offset, int comp);
+highfloat4 textureGatherOffset(sampler2DShadow sampler, highfloat2 P, highfloat refZ, int2 offset);
+highfloat4 textureGatherOffset(sampler2DArrayShadow sampler, highfloat3 P, highfloat refZ, int2 offset);
+highfloat4 textureGatherOffset(sampler2DRectShadow sampler, highfloat2 P, highfloat refZ, int2 offset);
+$gfloat4 textureGatherOffsets($gsampler2D sampler, highfloat2 P, int2 offsets[4]);
+$gfloat4 textureGatherOffsets($gsampler2D sampler, highfloat2 P, int2 offsets[4], int comp);
+$gfloat4 textureGatherOffsets($gsampler2DArray sampler, highfloat3 P, int2 offsets[4]);
+$gfloat4 textureGatherOffsets($gsampler2DArray sampler, highfloat3 P, int2 offsets[4], int comp);
+$gfloat4 textureGatherOffsets($gsampler2DRect sampler, highfloat2 P, int2 offsets[4]);
+$gfloat4 textureGatherOffsets($gsampler2DRect sampler, highfloat2 P, int2 offsets[4], int comp);
+highfloat4 textureGatherOffsets(sampler2DShadow sampler, highfloat2 P, highfloat refZ, int2 offsets[4]);
+highfloat4 textureGatherOffsets(sampler2DArrayShadow sampler, highfloat3 P, highfloat refZ, int2 offsets[4]);
+highfloat4 textureGatherOffsets(sampler2DRectShadow sampler, highfloat2 P, highfloat refZ, int2 offsets[4]);
 uint atomicCounterIncrement(atomic_uint c);
 uint atomicCounter(atomic_uint c);
 uint atomicAdd(inout uint mem, uint data);
@@ -534,18 +534,18 @@
 */
 // section 8.12 Additional Image Functions will go here if and when we add
 // support for them
-float4 imageLoad(image2D image, int2 P);
+highfloat4 imageLoad(image2D image, int2 P);
 int4 imageLoad(iimage2D image, int2 P);
 $genType dFdx($genType p);
 $genType dFdy($genType p);
-float interpolateAtSample(float interpolant, int sample);
-float2 interpolateAtSample(float2 interpolant, int sample);
-float3 interpolateAtSample(float3 interpolant, int sample);
-float4 interpolateAtSample(float4 interpolant, int sample);
-float interpolateAtOffset(float interpolant, float2 offset);
-float2 interpolateAtOffset(float2 interpolant, float2 offset);
-float3 interpolateAtOffset(float3 interpolant, float2 offset);
-float4 interpolateAtOffset(float4 interpolant, float2 offset);
+highfloat interpolateAtSample(highfloat interpolant, int sample);
+highfloat2 interpolateAtSample(highfloat2 interpolant, int sample);
+highfloat3 interpolateAtSample(highfloat3 interpolant, int sample);
+highfloat4 interpolateAtSample(highfloat4 interpolant, int sample);
+highfloat interpolateAtOffset(highfloat interpolant, highfloat2 offset);
+highfloat2 interpolateAtOffset(highfloat2 interpolant, highfloat2 offset);
+highfloat3 interpolateAtOffset(highfloat3 interpolant, highfloat2 offset);
+highfloat4 interpolateAtOffset(highfloat4 interpolant, highfloat2 offset);
 
 /*
 $genType fwidth($genType p);
diff --git a/src/sksl/sksl_fp.include b/src/sksl/sksl_fp.include
index 4d6b94d..8aed48e 100644
--- a/src/sksl/sksl_fp.include
+++ b/src/sksl/sksl_fp.include
@@ -2,24 +2,24 @@
 
 // defines built-in interfaces supported by SkiaSL fragment shaders
 
-layout(builtin=15) in float4 sk_FragCoord;
-layout(builtin=3) float sk_ClipDistance[1];
+layout(builtin=15) in highfloat4 sk_FragCoord;
+layout(builtin=3) highfloat sk_ClipDistance[1];
 
 // 9999 is a temporary value that causes us to ignore these declarations beyond
 // adding them to the symbol table. This works fine in GLSL (where they do not
 // require any further handling) but will fail in SPIR-V. We'll have a better
 // solution for this soon.
-layout(builtin=9999) float4 gl_LastFragData[1];
-layout(builtin=9999) float4 gl_LastFragColor;
-layout(builtin=9999) float4 gl_LastFragColorARM;
+layout(builtin=9999) highfloat4 gl_LastFragData[1];
+layout(builtin=9999) half4 gl_LastFragColor;
+layout(builtin=9999) half4 gl_LastFragColorARM;
 layout(builtin=9999) int gl_SampleMaskIn[1];
 layout(builtin=9999) out int gl_SampleMask[1];
-layout(builtin=9999) float4 gl_SecondaryFragColorEXT;
+layout(builtin=9999) half4 gl_SecondaryFragColorEXT;
 
-layout(builtin=10003) float4 sk_InColor;
-layout(builtin=10004) out float4 sk_OutColor;
-layout(builtin=10005) float2[] sk_TransformedCoords2D;
+layout(builtin=10003) half4 sk_InColor;
+layout(builtin=10004) out half4 sk_OutColor;
+layout(builtin=10005) highfloat2[] sk_TransformedCoords2D;
 layout(builtin=10006) sampler2D[] sk_TextureSamplers;
 
-float4 COLORSPACE(float4 color, colorSpaceXform colorSpace);
+half4 COLORSPACE(half4 color, colorSpaceXform colorSpace);
 )
diff --git a/src/sksl/sksl_frag.include b/src/sksl/sksl_frag.include
index 2cd1e52..c5f9ffe 100644
--- a/src/sksl/sksl_frag.include
+++ b/src/sksl/sksl_frag.include
@@ -2,20 +2,20 @@
 
 // defines built-in interfaces supported by SkiaSL fragment shaders
 
-layout(builtin=15) in float4 sk_FragCoord;
-layout(builtin=3) float sk_ClipDistance[1];
+layout(builtin=15) in highfloat4 sk_FragCoord;
+layout(builtin=3) highfloat sk_ClipDistance[1];
 
 // 9999 is a temporary value that causes us to ignore these declarations beyond
 // adding them to the symbol table. This works fine in GLSL (where they do not
 // require any further handling) but will fail in SPIR-V. We'll have a better
 // solution for this soon.
-layout(builtin=9999) float4 gl_LastFragData[1];
-layout(builtin=9999) float4 gl_LastFragColor;
-layout(builtin=9999) float4 gl_LastFragColorARM;
+layout(builtin=9999) highfloat4 gl_LastFragData[1];
+layout(builtin=9999) half4 gl_LastFragColor;
+layout(builtin=9999) half4 gl_LastFragColorARM;
 layout(builtin=9999) int gl_SampleMaskIn[1];
 layout(builtin=9999) out int gl_SampleMask[1];
-layout(builtin=9999) out float4 gl_SecondaryFragColorEXT;
+layout(builtin=9999) out half4 gl_SecondaryFragColorEXT;
 
-layout(location=0,index=0,builtin=10001) out float4 sk_FragColor;
+layout(location=0,index=0,builtin=10001) out half4 sk_FragColor;
 
 )
diff --git a/src/sksl/sksl_geom.include b/src/sksl/sksl_geom.include
index f1b3604..b1c05d1 100644
--- a/src/sksl/sksl_geom.include
+++ b/src/sksl/sksl_geom.include
@@ -3,15 +3,15 @@
 // defines built-in interfaces supported by SkiaSL geometry shaders
 
 layout(builtin=10002) in sk_PerVertex {
-  layout(builtin=0) float4 gl_Position;
-  layout(builtin=1) float gl_PointSize;
-  layout(builtin=3) float sk_ClipDistance[];
+  layout(builtin=0) highfloat4 gl_Position;
+  layout(builtin=1) highfloat gl_PointSize;
+  layout(builtin=3) highfloat sk_ClipDistance[];
 } sk_in[];
 
 out sk_PerVertex {
-    layout(builtin=0) float4 gl_Position;
-    layout(builtin=1) float gl_PointSize;
-    layout(builtin=3) float sk_ClipDistance[];
+    layout(builtin=0) highfloat4 gl_Position;
+    layout(builtin=1) highfloat gl_PointSize;
+    layout(builtin=3) highfloat sk_ClipDistance[];
 };
 
 layout(builtin=8) int sk_InvocationID;
diff --git a/src/sksl/sksl_vert.include b/src/sksl/sksl_vert.include
index 976877c..e7f8419 100644
--- a/src/sksl/sksl_vert.include
+++ b/src/sksl/sksl_vert.include
@@ -3,9 +3,9 @@
 // defines built-in interfaces supported by SkiaSL vertex shaders
 
 out sk_PerVertex {
-    layout(builtin=0) float4 gl_Position;
-    layout(builtin=1) float gl_PointSize;
-    layout(builtin=3) float sk_ClipDistance[1];
+    layout(builtin=0) highfloat4 gl_Position;
+    layout(builtin=1) highfloat gl_PointSize;
+    layout(builtin=3) highfloat sk_ClipDistance[1];
 };
 
 layout(builtin=5) in int sk_VertexID;
diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp
index 0f4dcb6..d174675 100644
--- a/tests/GrMeshTest.cpp
+++ b/tests/GrMeshTest.cpp
@@ -327,20 +327,20 @@
 
         GrGLSLVertexBuilder* v = args.fVertBuilder;
         if (!mp.fInstanceLocation) {
-            v->codeAppendf("float2 vertex = %s;", mp.fVertex->fName);
+            v->codeAppendf("highfloat2 vertex = %s;", mp.fVertex->fName);
         } else {
             if (mp.fVertex) {
-                v->codeAppendf("float2 offset = %s;", mp.fVertex->fName);
+                v->codeAppendf("highfloat2 offset = %s;", mp.fVertex->fName);
             } else {
-                v->codeAppend ("float2 offset = float2(sk_VertexID / 2, sk_VertexID % 2);");
+                v->codeAppend ("highfloat2 offset = highfloat2(sk_VertexID / 2, sk_VertexID % 2);");
             }
-            v->codeAppendf("float2 vertex = %s + offset * %i;",
+            v->codeAppendf("highfloat2 vertex = %s + offset * %i;",
                            mp.fInstanceLocation->fName, kBoxSize);
         }
-        gpArgs->fPositionVar.set(kVec2f_GrSLType, "vertex");
+        gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "vertex");
 
         GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
-        f->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+        f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
     }
 };
 
diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp
index 76d90dd..1f3dccd 100644
--- a/tests/GrPipelineDynamicStateTest.cpp
+++ b/tests/GrPipelineDynamicStateTest.cpp
@@ -91,11 +91,11 @@
         varyingHandler->addPassThroughAttribute(&mp.fColor, args.fOutputColor);
 
         GrGLSLVertexBuilder* v = args.fVertBuilder;
-        v->codeAppendf("float2 vertex = %s;", mp.fVertex.fName);
-        gpArgs->fPositionVar.set(kVec2f_GrSLType, "vertex");
+        v->codeAppendf("highfloat2 vertex = %s;", mp.fVertex.fName);
+        gpArgs->fPositionVar.set(kHighFloat2_GrSLType, "vertex");
 
         GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
-        f->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+        f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
     }
 };
 
diff --git a/tests/ImageStorageTest.cpp b/tests/ImageStorageTest.cpp
index 6d5cab0..8a6023f 100644
--- a/tests/ImageStorageTest.cpp
+++ b/tests/ImageStorageTest.cpp
@@ -58,13 +58,13 @@
                     const TestFP& tfp = args.fFp.cast<TestFP>();
                     GrGLSLFPFragmentBuilder* fb = args.fFragBuilder;
                     SkString imageLoadStr;
-                    fb->codeAppend("highp float2 coord = sk_FragCoord.xy;");
+                    fb->codeAppend("highfloat2 coord = sk_FragCoord.xy;");
                     fb->appendImageStorageLoad(&imageLoadStr, args.fImageStorages[0],
                                                "int2(coord)");
                     if (GrPixelConfigIsSint(tfp.fImageStorageAccess.peekTexture()->config())) {
                         // Map the signed bytes so that when then get read back as unorm values they
                         // will have their original bit pattern.
-                        fb->codeAppendf("highp int4 ivals = %s;", imageLoadStr.c_str());
+                        fb->codeAppendf("int4 ivals = %s;", imageLoadStr.c_str());
                         // NV gives a linker error for this:
                         // fb->codeAppend("ivals +=
                         //                "mix(int4(0), int4(256), lessThan(ivals, int4(0)));");
@@ -72,7 +72,7 @@
                         fb->codeAppend("if (ivals.g < 0) { ivals.g += 256; }");
                         fb->codeAppend("if (ivals.b < 0) { ivals.b += 256; }");
                         fb->codeAppend("if (ivals.a < 0) { ivals.a += 256; }");
-                        fb->codeAppendf("%s = float4(ivals)/255;", args.fOutputColor);
+                        fb->codeAppendf("%s = half4(ivals)/255;", args.fOutputColor);
                     } else {
                         fb->codeAppendf("%s = %s;", args.fOutputColor, imageLoadStr.c_str());
                     }
diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp
index 1e764e1..47dff33 100644
--- a/tests/PrimitiveProcessorTest.cpp
+++ b/tests/PrimitiveProcessorTest.cpp
@@ -72,8 +72,8 @@
                         args.fVaryingHandler->emitAttributes(gp);
                         this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.getAttrib(0).fName);
                         GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
-                        fragBuilder->codeAppendf("%s = float4(1);", args.fOutputColor);
-                        fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+                        fragBuilder->codeAppendf("%s = half4(1);", args.fOutputColor);
+                        fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
                     }
                     void setData(const GrGLSLProgramDataManager& pdman,
                                  const GrPrimitiveProcessor& primProc,
diff --git a/tests/SkSLErrorTest.cpp b/tests/SkSLErrorTest.cpp
index b94cc82..4943e10 100644
--- a/tests/SkSLErrorTest.cpp
+++ b/tests/SkSLErrorTest.cpp
@@ -37,39 +37,39 @@
 
 DEF_TEST(SkSLUndefinedSymbol, r) {
     test_failure(r,
-                 "void main() { x = float2(1); }",
+                 "void main() { x = highfloat2(1); }",
                  "error: 1: unknown identifier 'x'\n1 error\n");
 }
 
 DEF_TEST(SkSLUndefinedFunction, r) {
     test_failure(r,
-                 "void main() { int x = foo(1); }", 
+                 "void main() { int x = foo(1); }",
                  "error: 1: unknown identifier 'foo'\n1 error\n");
 }
 
 DEF_TEST(SkSLGenericArgumentMismatch, r) {
     test_failure(r,
-                 "void main() { float x = sin(1, 2); }", 
+                 "void main() { highfloat x = sin(1, 2); }",
                  "error: 1: call to 'sin' expected 1 argument, but found 2\n1 error\n");
     test_failure(r,
-                 "void main() { float x = sin(true); }", 
+                 "void main() { highfloat x = sin(true); }",
                  "error: 1: no match for sin(bool)\n1 error\n");
     test_success(r,
-                 "void main() { float x = sin(1); }");
+                 "void main() { highfloat x = sin(1); }");
 }
 
 DEF_TEST(SkSLArgumentCountMismatch, r) {
     test_failure(r,
-                 "float foo(float x) { return x * x; }"
-                 "void main() { float x = foo(1, 2); }", 
+                 "highfloat foo(highfloat x) { return x * x; }"
+                 "void main() { highfloat x = foo(1, 2); }",
                  "error: 1: call to 'foo' expected 1 argument, but found 2\n1 error\n");
 }
 
 DEF_TEST(SkSLArgumentMismatch, r) {
-    test_failure(r, 
-                 "float foo(float x) { return x * x; }"
-                 "void main() { float x = foo(true); }", 
-                 "error: 1: expected 'float', but found 'bool'\n1 error\n");
+    test_failure(r,
+                 "highfloat foo(highfloat x) { return x * x; }"
+                 "void main() { highfloat x = foo(true); }",
+                 "error: 1: expected 'highfloat', but found 'bool'\n1 error\n");
 }
 
 DEF_TEST(SkSLIfTypeMismatch, r) {
@@ -80,32 +80,32 @@
 
 DEF_TEST(SkSLDoTypeMismatch, r) {
     test_failure(r,
-                 "void main() { do { } while (float2(1)); }",
-                 "error: 1: expected 'bool', but found 'float2'\n1 error\n");
+                 "void main() { do { } while (highfloat2(1)); }",
+                 "error: 1: expected 'bool', but found 'highfloat2'\n1 error\n");
 }
 
 DEF_TEST(SkSLWhileTypeMismatch, r) {
     test_failure(r,
-                 "void main() { while (float3(1)) { } }",
-                 "error: 1: expected 'bool', but found 'float3'\n1 error\n");
+                 "void main() { while (highfloat3(1)) { } }",
+                 "error: 1: expected 'bool', but found 'highfloat3'\n1 error\n");
 }
 
 DEF_TEST(SkSLForTypeMismatch, r) {
     test_failure(r,
-                 "void main() { for (int x = 0; x; x++) { } }", 
+                 "void main() { for (int x = 0; x; x++) { } }",
                  "error: 1: expected 'bool', but found 'int'\n1 error\n");
 }
 
 DEF_TEST(SkSLConstructorTypeMismatch, r) {
     test_failure(r,
-                 "void main() { float2 x = float2(1.0, false); }", 
-                 "error: 1: expected 'float', but found 'bool'\n1 error\n");
+                 "void main() { highfloat2 x = highfloat2(1.0, false); }",
+                 "error: 1: expected 'highfloat', but found 'bool'\n1 error\n");
     test_failure(r,
-                 "void main() { float2 x = float2(bool2(false)); }",
-                 "error: 1: 'bool2' is not a valid parameter to 'float2' constructor\n1 error\n");
+                 "void main() { highfloat2 x = highfloat2(bool2(false)); }",
+                 "error: 1: 'bool2' is not a valid parameter to 'highfloat2' constructor\n1 error\n");
     test_failure(r,
-                 "void main() { bool2 x = bool2(float2(1)); }",
-                 "error: 1: 'float2' is not a valid parameter to 'bool2' constructor\n1 error\n");
+                 "void main() { bool2 x = bool2(highfloat2(1)); }",
+                 "error: 1: 'highfloat2' is not a valid parameter to 'bool2' constructor\n1 error\n");
     test_failure(r,
                  "void main() { bool x = bool(1.0); }",
                  "error: 1: cannot construct 'bool'\n1 error\n");
@@ -113,69 +113,69 @@
                  "struct foo { int x; }; void main() { foo x = foo(5); }",
                  "error: 1: cannot construct 'foo'\n1 error\n");
     test_failure(r,
-                 "struct foo { int x; } foo; void main() { float x = float(foo); }",
-                 "error: 1: invalid argument to 'float' constructor (expected a number or bool, but found 'foo')\n1 error\n");
+                 "struct foo { int x; } foo; void main() { highfloat x = highfloat(foo); }",
+                 "error: 1: invalid argument to 'highfloat' constructor (expected a number or bool, but found 'foo')\n1 error\n");
     test_failure(r,
-                 "struct foo { int x; } foo; void main() { float2 x = float2(foo); }",
-                 "error: 1: 'foo' is not a valid parameter to 'float2' constructor\n1 error\n");
+                 "struct foo { int x; } foo; void main() { highfloat2 x = highfloat2(foo); }",
+                 "error: 1: 'foo' is not a valid parameter to 'highfloat2' constructor\n1 error\n");
     test_failure(r,
-                 "void main() { float2x2 x = float2x2(true); }",
-                 "error: 1: expected 'float', but found 'bool'\n1 error\n");
+                 "void main() { highfloat2x2 x = highfloat2x2(true); }",
+                 "error: 1: expected 'highfloat', but found 'bool'\n1 error\n");
 }
 
 DEF_TEST(SkSLConstructorArgumentCount, r) {
     test_failure(r,
-                 "void main() { float3 x = float3(1.0, 2.0); }",
-                 "error: 1: invalid arguments to 'float3' constructor (expected 3 scalars, but "
+                 "void main() { highfloat3 x = highfloat3(1.0, 2.0); }",
+                 "error: 1: invalid arguments to 'highfloat3' constructor (expected 3 scalars, but "
                  "found 2)\n1 error\n");
     test_failure(r,
-                 "void main() { float3 x = float3(1.0, 2.0, 3.0, 4.0); }",
-                 "error: 1: invalid arguments to 'float3' constructor (expected 3 scalars, but found "
+                 "void main() { highfloat3 x = highfloat3(1.0, 2.0, 3.0, 4.0); }",
+                 "error: 1: invalid arguments to 'highfloat3' constructor (expected 3 scalars, but found "
                  "4)\n1 error\n");
 }
 
 DEF_TEST(SkSLSwizzleScalar, r) {
     test_failure(r,
-                 "void main() { float x = 1; float y = x.y; }",
-                 "error: 1: cannot swizzle value of type 'float'\n1 error\n");
+                 "void main() { highfloat x = 1; highfloat y = x.y; }",
+                 "error: 1: cannot swizzle value of type 'highfloat'\n1 error\n");
 }
 
 DEF_TEST(SkSLSwizzleMatrix, r) {
     test_failure(r,
-                 "void main() { float2x2 x = float2x2(1); float y = x.y; }",
-                 "error: 1: cannot swizzle value of type 'float2x2'\n1 error\n");
+                 "void main() { highfloat2x2 x = highfloat2x2(1); highfloat y = x.y; }",
+                 "error: 1: cannot swizzle value of type 'highfloat2x2'\n1 error\n");
 }
 
 DEF_TEST(SkSLSwizzleOutOfBounds, r) {
     test_failure(r,
-                 "void main() { float3 test = float2(1).xyz; }",
+                 "void main() { highfloat3 test = highfloat2(1).xyz; }",
                  "error: 1: invalid swizzle component 'z'\n1 error\n");
 }
 
 DEF_TEST(SkSLSwizzleTooManyComponents, r) {
     test_failure(r,
-                 "void main() { float4 test = float2(1).xxxxx; }",
+                 "void main() { highfloat4 test = highfloat2(1).xxxxx; }",
                  "error: 1: too many components in swizzle mask 'xxxxx'\n1 error\n");
 }
 
 DEF_TEST(SkSLSwizzleDuplicateOutput, r) {
     test_failure(r,
-                 "void main() { float4 test = float4(1); test.xyyz = float4(1); }",
+                 "void main() { highfloat4 test = highfloat4(1); test.xyyz = highfloat4(1); }",
                  "error: 1: cannot write to the same swizzle field more than once\n1 error\n");
 }
 
 DEF_TEST(SkSLAssignmentTypeMismatch, r) {
     test_failure(r,
                  "void main() { int x = 1.0; }",
-                 "error: 1: expected 'int', but found 'float'\n1 error\n");
+                 "error: 1: expected 'int', but found 'highfloat'\n1 error\n");
     test_failure(r,
                  "void main() { int x; x = 1.0; }",
-                 "error: 1: type mismatch: '=' cannot operate on 'int', 'float'\n1 error\n");
+                 "error: 1: type mismatch: '=' cannot operate on 'int', 'highfloat'\n1 error\n");
     test_success(r,
-                 "void main() { float3 x = float3(0); x *= 1.0; }");
+                 "void main() { highfloat3 x = highfloat3(0); x *= 1.0; }");
     test_failure(r,
                  "void main() { int3 x = int3(0); x *= 1.0; }",
-                 "error: 1: type mismatch: '*=' cannot operate on 'int3', 'float'\n1 error\n");
+                 "error: 1: type mismatch: '*=' cannot operate on 'int3', 'highfloat'\n1 error\n");
 }
 
 DEF_TEST(SkSLReturnFromVoid, r) {
@@ -192,13 +192,13 @@
 
 DEF_TEST(SkSLReturnTypeMismatch, r) {
     test_failure(r,
-                 "int foo() { return 1.0; } void main() { }", 
-                 "error: 1: expected 'int', but found 'float'\n1 error\n");
+                 "int foo() { return 1.0; } void main() { }",
+                 "error: 1: expected 'int', but found 'highfloat'\n1 error\n");
 }
 
 DEF_TEST(SkSLDuplicateFunction, r) {
     test_failure(r,
-                 "void main() { } void main() { }", 
+                 "void main() { } void main() { }",
                  "error: 1: duplicate definition of void main()\n1 error\n");
     test_success(r,
                  "void main(); void main() { }");
@@ -206,29 +206,29 @@
 
 DEF_TEST(SkSLUsingInvalidValue, r) {
     test_failure(r,
-                 "void main() { int x = int; }", 
+                 "void main() { int x = int; }",
                  "error: 1: expected '(' to begin constructor invocation\n1 error\n");
     test_failure(r,
-                 "int test() { return 1; } void main() { int x = test; }", 
+                 "int test() { return 1; } void main() { int x = test; }",
                  "error: 1: expected '(' to begin function call\n1 error\n");
 }
 DEF_TEST(SkSLDifferentReturnType, r) {
     test_failure(r,
-                 "int main() { return 1; } void main() { }", 
+                 "int main() { return 1; } void main() { }",
                  "error: 1: functions 'void main()' and 'int main()' differ only in return type\n1 "
                  "error\n");
 }
 
 DEF_TEST(SkSLDifferentModifiers, r) {
     test_failure(r,
-                 "void test(int x); void test(out int x) { }", 
+                 "void test(int x); void test(out int x) { }",
                  "error: 1: modifiers on parameter 1 differ between declaration and definition\n1 "
                  "error\n");
 }
 
 DEF_TEST(SkSLDuplicateSymbol, r) {
     test_failure(r,
-                 "int main; void main() { }", 
+                 "int main; void main() { }",
                  "error: 1: symbol 'main' was already defined\n1 error\n");
 
     test_failure(r,
@@ -240,32 +240,32 @@
 
 DEF_TEST(SkSLBinaryTypeMismatch, r) {
     test_failure(r,
-                 "void main() { float x = 3 * true; }",
+                 "void main() { highfloat x = 3 * true; }",
                  "error: 1: type mismatch: '*' cannot operate on 'int', 'bool'\n1 error\n");
     test_failure(r,
                  "void main() { bool x = 1 || 2.0; }",
-                 "error: 1: type mismatch: '||' cannot operate on 'int', 'float'\n1 error\n");
+                 "error: 1: type mismatch: '||' cannot operate on 'int', 'highfloat'\n1 error\n");
 }
 
 DEF_TEST(SkSLCallNonFunction, r) {
     test_failure(r,
-                 "void main() { float x = 3; x(); }",
+                 "void main() { highfloat x = 3; x(); }",
                  "error: 1: 'x' is not a function\n1 error\n");
 }
 
 DEF_TEST(SkSLInvalidUnary, r) {
     test_failure(r,
-                 "void main() { float4x4 x = float4x4(1); ++x; }",
-                 "error: 1: '++' cannot operate on 'float4x4'\n1 error\n");
+                 "void main() { highfloat4x4 x = highfloat4x4(1); ++x; }",
+                 "error: 1: '++' cannot operate on 'highfloat4x4'\n1 error\n");
     test_failure(r,
-                 "void main() { float3 x = float3(1); --x; }",
-                 "error: 1: '--' cannot operate on 'float3'\n1 error\n");
+                 "void main() { highfloat3 x = highfloat3(1); --x; }",
+                 "error: 1: '--' cannot operate on 'highfloat3'\n1 error\n");
     test_failure(r,
-                 "void main() { float4x4 x = float4x4(1); x++; }",
-                 "error: 1: '++' cannot operate on 'float4x4'\n1 error\n");
+                 "void main() { highfloat4x4 x = highfloat4x4(1); x++; }",
+                 "error: 1: '++' cannot operate on 'highfloat4x4'\n1 error\n");
     test_failure(r,
-                 "void main() { float3 x = float3(1); x--; }",
-                 "error: 1: '--' cannot operate on 'float3'\n1 error\n");
+                 "void main() { highfloat3 x = highfloat3(1); x--; }",
+                 "error: 1: '--' cannot operate on 'highfloat3'\n1 error\n");
     test_failure(r,
                  "void main() { int x = !12; }",
                  "error: 1: '!' cannot operate on 'int'\n1 error\n");
@@ -276,7 +276,7 @@
                  "struct foo { } bar; void main() { foo x = -bar; }",
                  "error: 1: '-' cannot operate on 'foo'\n1 error\n");
     test_success(r,
-                 "void main() { float2 x = float2(1, 1); x = +x; x = -x; }");
+                 "void main() { highfloat2 x = highfloat2(1, 1); x = +x; x = -x; }");
 }
 
 DEF_TEST(SkSLInvalidAssignment, r) {
@@ -296,17 +296,17 @@
                  "void main() { int x = 2[0]; }",
                  "error: 1: expected array, but found 'int'\n1 error\n");
     test_failure(r,
-                 "void main() { float2 x = float2(0); int y = x[0][0]; }",
-                 "error: 1: expected array, but found 'float'\n1 error\n");
+                 "void main() { highfloat2 x = highfloat2(0); int y = x[0][0]; }",
+                 "error: 1: expected array, but found 'highfloat'\n1 error\n");
 }
 
 DEF_TEST(SkSLTernaryMismatch, r) {
     test_failure(r,
                  "void main() { int x = 5 > 2 ? true : 1.0; }",
-                 "error: 1: ternary operator result mismatch: 'bool', 'float'\n1 error\n");
+                 "error: 1: ternary operator result mismatch: 'bool', 'highfloat'\n1 error\n");
     test_failure(r,
-                 "void main() { int x = 5 > 2 ? float3(1) : 1.0; }",
-                 "error: 1: ternary operator result mismatch: 'float3', 'float'\n1 error\n");
+                 "void main() { int x = 5 > 2 ? highfloat3(1) : 1.0; }",
+                 "error: 1: ternary operator result mismatch: 'highfloat3', 'highfloat'\n1 error\n");
 }
 
 DEF_TEST(SkSLInterfaceBlockStorageModifiers, r) {
@@ -333,7 +333,7 @@
                  "error: 1: 'x' has not been assigned\n1 error\n");
     test_failure(r,
                  "void main() { int x; switch (3) { case 0: x = 0; case 1: x = 1; }"
-                               "sk_FragColor = float4(x); }",
+                               "sk_FragColor = highfloat4(x); }",
                  "error: 1: 'x' has not been assigned\n1 error\n");
 }
 
@@ -403,32 +403,32 @@
                  "int x = 1 / 0;",
                  "error: 1: division by zero\n1 error\n");
     test_failure(r,
-                 "float x = 1 / 0;",
+                 "highfloat x = 1 / 0;",
                  "error: 1: division by zero\n1 error\n");
     test_failure(r,
-                 "float x = 1.0 / 0.0;",
+                 "highfloat x = 1.0 / 0.0;",
                  "error: 1: division by zero\n1 error\n");
     test_failure(r,
-                 "float x = -67.0 / (3.0 - 3);",
+                 "highfloat x = -67.0 / (3.0 - 3);",
                  "error: 1: division by zero\n1 error\n");
 }
 
 DEF_TEST(SkSLUnsupportedGLSLIdentifiers, r) {
     test_failure(r,
-                 "void main() { float x = gl_FragCoord.x; };",
+                 "void main() { highfloat x = gl_FragCoord.x; };",
                  "error: 1: unknown identifier 'gl_FragCoord'\n1 error\n");
     test_failure(r,
-                 "void main() { float r = gl_FragColor.r; };",
+                 "void main() { highfloat r = gl_FragColor.r; };",
                  "error: 1: unknown identifier 'gl_FragColor'\n1 error\n");
 }
 
 DEF_TEST(SkSLWrongSwitchTypes, r) {
     test_failure(r,
-                 "void main() { switch (float2(1)) { case 1: break; } }",
-                 "error: 1: expected 'int', but found 'float2'\n1 error\n");
+                 "void main() { switch (highfloat2(1)) { case 1: break; } }",
+                 "error: 1: expected 'int', but found 'highfloat2'\n1 error\n");
     test_failure(r,
-                 "void main() { switch (1) { case float2(1): break; } }",
-                 "error: 1: expected 'int', but found 'float2'\n1 error\n");
+                 "void main() { switch (1) { case highfloat2(1): break; } }",
+                 "error: 1: expected 'int', but found 'highfloat2'\n1 error\n");
 }
 
 DEF_TEST(SkSLNonConstantCase, r) {
@@ -445,18 +445,18 @@
 
 DEF_TEST(SkSLFieldAfterRuntimeArray, r) {
     test_failure(r,
-                 "buffer broken { float x[]; float y; };",
+                 "buffer broken { highfloat x[]; highfloat y; };",
                  "error: 1: only the last entry in an interface block may be a runtime-sized "
                  "array\n1 error\n");
 }
 
 DEF_TEST(SkSLStaticIf, r) {
     test_success(r,
-                 "void main() { float x = 5; float y = 10;"
-                 "@if (x < y) { sk_FragColor = float4(1); } }");
+                 "void main() { highfloat x = 5; highfloat y = 10;"
+                 "@if (x < y) { sk_FragColor = highfloat4(1); } }");
     test_failure(r,
-                 "void main() { float x = sqrt(25); float y = 10;"
-                 "@if (x < y) { sk_FragColor = float4(1); } }",
+                 "void main() { highfloat x = sqrt(25); highfloat y = 10;"
+                 "@if (x < y) { sk_FragColor = highfloat4(1); } }",
                  "error: 1: static if has non-static test\n1 error\n");
 }
 
@@ -465,16 +465,16 @@
                  "void main() {"
                  "int x = 1;"
                  "@switch (x) {"
-                 "case 1: sk_FragColor = float4(1); break;"
-                 "default: sk_FragColor = float4(0);"
+                 "case 1: sk_FragColor = highfloat4(1); break;"
+                 "default: sk_FragColor = highfloat4(0);"
                  "}"
                  "}");
     test_failure(r,
                  "void main() {"
                  "int x = int(sqrt(1));"
                  "@switch (x) {"
-                 "case 1: sk_FragColor = float4(1); break;"
-                 "default: sk_FragColor = float4(0);"
+                 "case 1: sk_FragColor = highfloat4(1); break;"
+                 "default: sk_FragColor = highfloat4(0);"
                  "}"
                  "}",
                  "error: 1: static switch has non-static test\n1 error\n");
@@ -482,8 +482,8 @@
                  "void main() {"
                  "int x = 1;"
                  "@switch (x) {"
-                 "case 1: sk_FragColor = float4(1); if (sqrt(0) < sqrt(1)) break;"
-                 "default: sk_FragColor = float4(0);"
+                 "case 1: sk_FragColor = highfloat4(1); if (sqrt(0) < sqrt(1)) break;"
+                 "default: sk_FragColor = highfloat4(0);"
                  "}"
                  "}",
                  "error: 1: static switch contains non-static conditional break\n1 error\n");
diff --git a/tests/SkSLFPTest.cpp b/tests/SkSLFPTest.cpp
index c3f9468..266169f 100644
--- a/tests/SkSLFPTest.cpp
+++ b/tests/SkSLFPTest.cpp
@@ -62,7 +62,7 @@
 DEF_TEST(SkSLFPHelloWorld, r) {
     test(r,
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -132,7 +132,7 @@
              "        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
              "        const GrTest& _outer = args.fFp.cast<GrTest>();\n"
              "        (void) _outer;\n"
-             "        fragBuilder->codeAppendf(\"%s = float4(1.0);\\n\", args.fOutputColor);\n"
+             "        fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
              "    }\n"
              "private:\n"
              "    void onSetData(const GrGLSLProgramDataManager& pdman, "
@@ -163,9 +163,9 @@
 
 DEF_TEST(SkSLFPInput, r) {
     test(r,
-         "in float2 point;"
+         "in half2 point;"
          "void main() {"
-         "sk_OutColor = float4(point, point);"
+         "sk_OutColor = half4(point, point);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -176,7 +176,7 @@
              ", fPoint(point)"
          },
          {
-             "fragBuilder->codeAppendf(\"%s = float4(float2(%f, %f), float2(%f, %f));\\n\", "
+             "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
                                       "args.fOutputColor, _outer.point().fX, _outer.point().fY, "
                                       "_outer.point().fX, _outer.point().fY);",
              "if (fPoint != that.fPoint) return false;"
@@ -185,7 +185,7 @@
 
 DEF_TEST(SkSLFPUniform, r) {
     test(r,
-         "uniform float4 color;"
+         "uniform half4 color;"
          "void main() {"
          "sk_OutColor = color;"
          "}",
@@ -194,14 +194,14 @@
              "static std::unique_ptr<GrFragmentProcessor> Make()"
          },
          {
-            "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, "
+            "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
                                                          "kDefault_GrSLPrecision, \"color\");",
          });
 }
 
 DEF_TEST(SkSLFPInUniform, r) {
     test(r,
-         "in uniform float4 color;"
+         "in uniform half4 color;"
          "void main() {"
          "sk_OutColor = color;"
          "}",
@@ -210,7 +210,7 @@
              "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
          },
          {
-            "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, "
+            "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
                                                          "kDefault_GrSLPrecision, \"color\");",
             "const SkRect colorValue = _outer.color();",
             "pdman.set4fv(fColorVar, 1, (float*) &colorValue);"
@@ -221,7 +221,7 @@
     test(r,
          "@header { header section }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -231,7 +231,7 @@
     test(r,
          "@class { class section }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -243,16 +243,16 @@
     test(r,
          "@cpp { cpp section }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {},
          {"cpp section"});
     test(r,
          "@constructorParams { int x, float y, std::vector<float> z }"
-         "in float w;"
+         "in highfloat w;"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = highfloat4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -265,7 +265,7 @@
     test(r,
          "@constructor { constructor section }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -275,7 +275,7 @@
     test(r,
          "@initializers { initializers section }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -283,22 +283,22 @@
          },
          {});
     test(r,
-         "float x = 10;"
-         "@emitCode { fragBuilder->codeAppendf(\"float y = %d\\n\", x * 2); }"
+         "half x = 10;"
+         "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {},
          {
             "x = 10.0;\n"
-            " fragBuilder->codeAppendf(\"float y = %d\\n\", x * 2);"
+            " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
          });
     test(r,
          "@fields { fields section }"
          "@clone { }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -309,7 +309,7 @@
     test(r,
          "@make { make section }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -318,11 +318,11 @@
          },
          {});
     test(r,
-         "uniform float calculated;"
-         "in float provided;"
+         "uniform half calculated;"
+         "in half provided;"
          "@setData(varName) { varName.set1f(calculated, provided * 2); }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {},
@@ -336,7 +336,7 @@
     test(r,
          "@test(testDataName) { testDataName section }"
          "void main() {"
-         "sk_OutColor = float4(1);"
+         "sk_OutColor = half4(1);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {},
@@ -353,7 +353,7 @@
          "in uniform sampler2D image;"
          "in uniform colorSpaceXform colorXform;"
          "void main() {"
-         "sk_OutColor = sk_InColor * texture(image, float2(0, 0), colorXform);"
+         "sk_OutColor = sk_InColor * texture(image, highfloat2(0, 0), colorXform);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {
@@ -363,12 +363,12 @@
              "sk_sp<GrColorSpaceXform> fColorXform;"
          },
          {
-             "fragBuilder->codeAppendf(\"float4 _tmpVar1;%s = %s * %stexture(%s, "
-             "float2(0.0, 0.0)).%s%s;\\n\", args.fOutputColor, args.fInputColor ? args.fInputColor : "
-             "\"float4(1)\", fColorSpaceHelper.isValid() ? \"(_tmpVar1 = \" : \"\", "
+             "fragBuilder->codeAppendf(\"half4 _tmpVar1;%s = %s * %stexture(%s, "
+             "highfloat2(0.0, 0.0)).%s%s;\\n\", args.fOutputColor, args.fInputColor ? args.fInputColor : "
+             "\"half4(1)\", fColorSpaceHelper.isValid() ? \"(_tmpVar1 = \" : \"\", "
              "fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), "
              "fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), "
-             "fColorSpaceHelper.isValid() ? SkStringPrintf(\", float4(clamp((%s * float4(_tmpVar1.rgb, "
+             "fColorSpaceHelper.isValid() ? SkStringPrintf(\", half4(clamp((%s * half4(_tmpVar1.rgb, "
              "1.0)).rgb, 0.0, _tmpVar1.a), _tmpVar1.a))\", args.fUniformHandler->getUniformCStr("
              "fColorSpaceHelper.gamutXformUniform())).c_str() : \"\");"
          });
@@ -377,14 +377,14 @@
 DEF_TEST(SkSLFPTransformedCoords, r) {
     test(r,
          "void main() {"
-         "sk_OutColor = float4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
+         "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          {},
          {
             "SkString sk_TransformedCoords2D_0 = "
                                          "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
-            "fragBuilder->codeAppendf(\"%s = float4(%s, %s);\\n\", args.fOutputColor, "
+            "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
                               "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
          });
 
@@ -392,7 +392,7 @@
 
 DEF_TEST(SkSLFPLayoutWhen, r) {
     test(r,
-         "layout(when=someExpression(someOtherExpression())) uniform float sometimes;"
+         "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
          "void main() {"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index a7f6740..bfcedac 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -51,7 +51,7 @@
 
 DEF_TEST(SkSLHelloWorld, r) {
     test(r,
-         "void main() { sk_FragColor = float4(0.75); }",
+         "void main() { sk_FragColor = highfloat4(0.75); }",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -63,7 +63,7 @@
 DEF_TEST(SkSLControl, r) {
     test(r,
          "void main() {"
-         "if (sqrt(2) > 5) { sk_FragColor = float4(0.75); } else { discard; }"
+         "if (sqrt(2) > 5) { sk_FragColor = highfloat4(0.75); } else { discard; }"
          "int i = 0;"
          "while (i < 10) { sk_FragColor *= 0.5; i++; }"
          "do { sk_FragColor += 0.01; } while (sk_FragColor.x < 0.75);"
@@ -98,9 +98,9 @@
 
 DEF_TEST(SkSLFunctions, r) {
     test(r,
-         "float foo(float v[2]) { return v[0] * v[1]; }"
-         "void bar(inout float x) { float y[2], z; y[0] = x; y[1] = x * 2; z = foo(y); x = z; }"
-         "void main() { float x = 10; bar(x); sk_FragColor = float4(x); }",
+         "highfloat foo(highfloat v[2]) { return v[0] * v[1]; }"
+         "void bar(inout highfloat x) { highfloat y[2], z; y[0] = x; y[1] = x * 2; z = foo(y); x = z; }"
+         "void main() { highfloat x = 10; bar(x); sk_FragColor = highfloat4(x); }",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -124,7 +124,7 @@
 DEF_TEST(SkSLOperators, r) {
     test(r,
          "void main() {"
-         "float x = 1, y = 2;"
+         "highfloat x = 1, y = 2;"
          "int z = 3;"
          "x = x - x + y * z * x * (y - z);"
          "y = x / y / z;"
@@ -142,8 +142,8 @@
          "z >>= 2;"
          "z <<= 4;"
          "z %= 5;"
-         "x = (float2(sqrt(1)) , 6);"
-         "z = (float2(sqrt(1)) , 6);"
+         "x = (highfloat2(sqrt(1)) , 6);"
+         "z = (highfloat2(sqrt(1)) , 6);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -175,12 +175,12 @@
 DEF_TEST(SkSLMatrices, r) {
     test(r,
          "void main() {"
-         "float2x4 x = float2x4(1);"
-         "float3x2 y = float3x2(1, 0, 0, 1, float2(2, 2));"
-         "float3x4 z = x * y;"
-         "float3 v1 = float3x3(1) * float3(2);"
-         "float3 v2 = float3(2) * float3x3(1);"
-         "sk_FragColor = float4(z[0].x, v1 + v2);"
+         "highfloat2x4 x = highfloat2x4(1);"
+         "highfloat3x2 y = highfloat3x2(1, 0, 0, 1, highfloat2(2, 2));"
+         "highfloat3x4 z = x * y;"
+         "highfloat3 v1 = highfloat3x3(1) * highfloat3(2);"
+         "highfloat3 v2 = highfloat3(2) * highfloat3x3(1);"
+         "sk_FragColor = highfloat4(z[0].x, v1 + v2);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -196,13 +196,13 @@
 DEF_TEST(SkSLInterfaceBlock, r) {
     test(r,
          "uniform testBlock {"
-         "float x;"
-         "float y[2];"
-         "layout(binding=12) float3x2 z;"
+         "half x;"
+         "half y[2];"
+         "layout(binding=12) half3x2 z;"
          "bool w;"
          "};"
          "void main() {"
-         "    sk_FragColor = float4(x, y[0], y[1], 0);"
+         "    sk_FragColor = half4(x, y[0], y[1], 0);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -218,10 +218,10 @@
          "}\n");
     test(r,
          "uniform testBlock {"
-         "float x;"
+         "highfloat x;"
          "} test;"
          "void main() {"
-         "    sk_FragColor = float4(test.x);"
+         "    sk_FragColor = half4(test.x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -234,10 +234,10 @@
          "}\n");
     test(r,
          "uniform testBlock {"
-         "float x;"
+         "highfloat x;"
          "} test[2];"
          "void main() {"
-         "    sk_FragColor = float4(test[1].x);"
+         "    sk_FragColor = half4(test[1].x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -258,8 +258,8 @@
          "} a1, a2;"
          "A a3;"
          "struct B {"
-         "float x;"
-         "float y[2];"
+         "highfloat x;"
+         "highfloat y[2];"
          "layout(binding=1) A z;"
          "};"
          "B b1, b2, b3;"
@@ -284,7 +284,7 @@
 
 DEF_TEST(SkSLVersion, r) {
     test(r,
-         "in float test; void main() { sk_FragColor = float4(0.75); }",
+         "in highfloat test; void main() { sk_FragColor = highfloat4(0.75); }",
          *SkSL::ShaderCapsFactory::Version450Core(),
          "#version 450 core\n"
          "out vec4 sk_FragColor;\n"
@@ -293,7 +293,7 @@
          "    sk_FragColor = vec4(0.75);\n"
          "}\n");
     test(r,
-         "in float test; void main() { sk_FragColor = float4(0.75); }",
+         "in highfloat test; void main() { sk_FragColor = highfloat4(0.75); }",
          *SkSL::ShaderCapsFactory::Version110(),
          "#version 110\n"
          "varying float test;\n"
@@ -304,8 +304,8 @@
 
 DEF_TEST(SkSLUsesPrecisionModifiers, r) {
     test(r,
-         "void main() { float x = 0.75; highp float y = 1; x++; y++;"
-         "sk_FragColor.rg = float2(x, y); }",
+         "void main() { half x = 0.75; highfloat y = 1; x++; y++;"
+         "sk_FragColor.rg = half2(x, y); }",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -317,15 +317,15 @@
          "    sk_FragColor.xy = vec2(x, y);\n"
          "}\n");
     test(r,
-         "void main() { float x = 0.75; half y = 1; x++; y++;"
-         "sk_FragColor.rg = float2(x, y); }",
+         "void main() { half x = 0.75; highfloat y = 1; x++; y++;"
+         "sk_FragColor.rg = half2(x, y); }",
          *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
          "#version 400\n"
-         "precision highp float;\n"
+         "precision mediump float;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
-         "    float x = 0.75;\n"
-         "    mediump float y = 1.0;\n"
+         "    mediump float x = 0.75;\n"
+         "    highp float y = 1.0;\n"
          "    x++;\n"
          "    y++;\n"
          "    sk_FragColor.xy = vec2(x, y);\n"
@@ -335,7 +335,7 @@
 DEF_TEST(SkSLMinAbs, r) {
     test(r,
          "void main() {"
-         "float x = -5;"
+         "highfloat x = -5;"
          "sk_FragColor.r = min(abs(x), 6);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
@@ -347,7 +347,7 @@
 
     test(r,
          "void main() {"
-         "float x = -5.0;"
+         "highfloat x = -5.0;"
          "sk_FragColor.r = min(abs(x), 6.0);"
          "}",
          *SkSL::ShaderCapsFactory::CannotUseMinAndAbsTogether(),
@@ -364,7 +364,7 @@
 DEF_TEST(SkSLFractNegative, r) {
     static constexpr char input[] =
         "void main() {"
-        "float x = -42.0;"
+        "highfloat x = -42.0;"
         "sk_FragColor.r = fract(x);"
         "}";
     static constexpr char output_default[] =
@@ -386,7 +386,7 @@
 
 DEF_TEST(SkSLNegatedAtan, r) {
     test(r,
-         "void main() { float2 x = float2(sqrt(2)); sk_FragColor.r = atan(x.x, -x.y); }",
+         "void main() { highfloat2 x = highfloat2(sqrt(2)); sk_FragColor.r = atan(x.x, -x.y); }",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -395,7 +395,7 @@
          "    sk_FragColor.x = atan(x.x, -x.y);\n"
          "}\n");
     test(r,
-         "void main() { float2 x = float2(sqrt(2)); sk_FragColor.r = atan(x.x, -x.y); }",
+         "void main() { highfloat2 x = highfloat2(sqrt(2)); sk_FragColor.r = atan(x.x, -x.y); }",
          *SkSL::ShaderCapsFactory::MustForceNegatedAtanParamToFloat(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -466,13 +466,13 @@
 
 DEF_TEST(SkSLVectorConstructors, r) {
     test(r,
-         "float2 v1 = float2(1);"
-         "float2 v2 = float2(1, 2);"
-         "float2 v3 = float2(float2(1));"
-         "float3 v4 = float3(float2(1), 1.0);"
+         "highfloat2 v1 = highfloat2(1);"
+         "highfloat2 v2 = highfloat2(1, 2);"
+         "highfloat2 v3 = highfloat2(highfloat2(1));"
+         "highfloat3 v4 = highfloat3(highfloat2(1), 1.0);"
          "int2 v5 = int2(1);"
-         "int2 v6 = int2(float2(1, 2));"
-         "float2 v7 = float2(int2(1, 2));",
+         "int2 v6 = int2(highfloat2(1, 2));"
+         "highfloat2 v7 = highfloat2(int2(1, 2));",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -487,9 +487,9 @@
 
 DEF_TEST(SkSLArrayConstructors, r) {
     test(r,
-         "float test1[] = float[](1, 2, 3, 4);"
-         "float2 test2[] = float2[](float2(1, 2), float2(3, 4));"
-         "float4x4 test3[] = float4x4[]();",
+         "highfloat test1[] = highfloat[](1, 2, 3, 4);"
+         "highfloat2 test2[] = highfloat2[](highfloat2(1, 2), highfloat2(3, 4));"
+         "highfloat4x4 test3[] = highfloat4x4[]();",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -511,7 +511,7 @@
          "void main() { sk_FragColor.r = 1; }",
          *SkSL::ShaderCapsFactory::ShaderDerivativeExtensionString(),
          "#version 400\n"
-         "precision highp float;\n"
+         "precision mediump float;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
          "    sk_FragColor.x = 1.0;\n"
@@ -521,7 +521,7 @@
          *SkSL::ShaderCapsFactory::ShaderDerivativeExtensionString(),
          "#version 400\n"
          "#extension GL_OES_standard_derivatives : require\n"
-         "precision highp float;\n"
+         "precision mediump float;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
          "    sk_FragColor.x = dFdx(1.0);\n"
@@ -717,55 +717,55 @@
 DEF_TEST(SkSLVecFolding, r) {
     test(r,
          "void main() {"
-         "sk_FragColor.r = float4(0.5, 1, 1, 1).x;"
-         "sk_FragColor = float4(float2(1), float2(2, 3)) + float4(5, 6, 7, 8);"
-         "sk_FragColor = float4(8, float3(10)) - float4(1);"
-         "sk_FragColor = float4(2) * float4(1, 2, 3, 4);"
-         "sk_FragColor = float4(12) / float4(1, 2, 3, 4);"
-         "sk_FragColor.r = (float4(12) / float4(1, 2, 3, 4)).y;"
-         "sk_FragColor.x = float4(1) == float4(1) ? 1.0 : -1.0;"
-         "sk_FragColor.x = float4(1) == float4(2) ? 2.0 : -2.0;"
-         "sk_FragColor.x = float2(1) == float2(1, 1) ? 3.0 : -3.0;"
-         "sk_FragColor.x = float2(1, 1) == float2(1, 1) ? 4.0 : -4.0;"
-         "sk_FragColor.x = float2(1) == float2(1, 0) ? 5.0 : -5.0;"
-         "sk_FragColor.x = float4(1) == float4(float2(1), float2(1)) ? 6.0 : -6.0;"
-         "sk_FragColor.x = float4(float3(1), 1) == float4(float2(1), float2(1)) ? 7.0 : -7.0;"
-         "sk_FragColor.x = float4(float3(1), 1) == float4(float2(1), 1, 0) ? 8.0 : -8.0;"
-         "sk_FragColor.x = float2(1) != float2(1, 0) ? 9.0 : -9.0;"
-         "sk_FragColor.x = float4(1) != float4(float2(1), float2(1)) ? 10.0 : -10.0;"
-         "sk_FragColor = float4(sqrt(1)) * float4(1);"
-         "sk_FragColor = float4(1) * float4(sqrt(2));"
-         "sk_FragColor = float4(0) * float4(sqrt(3));"
-         "sk_FragColor = float4(sqrt(4)) * float4(0);"
-         "sk_FragColor = float4(0) / float4(sqrt(5));"
-         "sk_FragColor = float4(0) + float4(sqrt(6));"
-         "sk_FragColor = float4(sqrt(7)) + float4(0);"
-         "sk_FragColor = float4(sqrt(8)) - float4(0);"
-         "sk_FragColor = float4(0) + sqrt(9);"
-         "sk_FragColor = float4(0) * sqrt(10);"
-         "sk_FragColor = float4(0) / sqrt(11);"
-         "sk_FragColor = float4(1) * sqrt(12);"
-         "sk_FragColor = 0 + float4(sqrt(13));"
-         "sk_FragColor = 0 * float4(sqrt(14));"
-         "sk_FragColor = 0 / float4(sqrt(15));"
-         "sk_FragColor = 1 * float4(sqrt(16));"
-         "sk_FragColor = float4(sqrt(17)) + 0;"
-         "sk_FragColor = float4(sqrt(18)) * 0;"
-         "sk_FragColor = float4(sqrt(19)) * 1;"
-         "sk_FragColor = float4(sqrt(19.5)) - 0;"
-         "sk_FragColor = sqrt(20) * float4(1);"
-         "sk_FragColor = sqrt(21) + float4(0);"
-         "sk_FragColor = sqrt(22) - float4(0);"
-         "sk_FragColor = sqrt(23) / float4(1);"
-         "sk_FragColor = float4(sqrt(24)) / 1;"
-         "sk_FragColor += float4(1);"
-         "sk_FragColor += float4(0);"
-         "sk_FragColor -= float4(1);"
-         "sk_FragColor -= float4(0);"
-         "sk_FragColor *= float4(1);"
-         "sk_FragColor *= float4(2);"
-         "sk_FragColor /= float4(1);"
-         "sk_FragColor /= float4(2);"
+         "sk_FragColor.r = highfloat4(0.5, 1, 1, 1).x;"
+         "sk_FragColor = highfloat4(highfloat2(1), highfloat2(2, 3)) + highfloat4(5, 6, 7, 8);"
+         "sk_FragColor = highfloat4(8, highfloat3(10)) - highfloat4(1);"
+         "sk_FragColor = highfloat4(2) * highfloat4(1, 2, 3, 4);"
+         "sk_FragColor = highfloat4(12) / highfloat4(1, 2, 3, 4);"
+         "sk_FragColor.r = (highfloat4(12) / highfloat4(1, 2, 3, 4)).y;"
+         "sk_FragColor.x = highfloat4(1) == highfloat4(1) ? 1.0 : -1.0;"
+         "sk_FragColor.x = highfloat4(1) == highfloat4(2) ? 2.0 : -2.0;"
+         "sk_FragColor.x = highfloat2(1) == highfloat2(1, 1) ? 3.0 : -3.0;"
+         "sk_FragColor.x = highfloat2(1, 1) == highfloat2(1, 1) ? 4.0 : -4.0;"
+         "sk_FragColor.x = highfloat2(1) == highfloat2(1, 0) ? 5.0 : -5.0;"
+         "sk_FragColor.x = highfloat4(1) == highfloat4(highfloat2(1), highfloat2(1)) ? 6.0 : -6.0;"
+         "sk_FragColor.x = highfloat4(highfloat3(1), 1) == highfloat4(highfloat2(1), highfloat2(1)) ? 7.0 : -7.0;"
+         "sk_FragColor.x = highfloat4(highfloat3(1), 1) == highfloat4(highfloat2(1), 1, 0) ? 8.0 : -8.0;"
+         "sk_FragColor.x = highfloat2(1) != highfloat2(1, 0) ? 9.0 : -9.0;"
+         "sk_FragColor.x = highfloat4(1) != highfloat4(highfloat2(1), highfloat2(1)) ? 10.0 : -10.0;"
+         "sk_FragColor = highfloat4(sqrt(1)) * highfloat4(1);"
+         "sk_FragColor = highfloat4(1) * highfloat4(sqrt(2));"
+         "sk_FragColor = highfloat4(0) * highfloat4(sqrt(3));"
+         "sk_FragColor = highfloat4(sqrt(4)) * highfloat4(0);"
+         "sk_FragColor = highfloat4(0) / highfloat4(sqrt(5));"
+         "sk_FragColor = highfloat4(0) + highfloat4(sqrt(6));"
+         "sk_FragColor = highfloat4(sqrt(7)) + highfloat4(0);"
+         "sk_FragColor = highfloat4(sqrt(8)) - highfloat4(0);"
+         "sk_FragColor = highfloat4(0) + sqrt(9);"
+         "sk_FragColor = highfloat4(0) * sqrt(10);"
+         "sk_FragColor = highfloat4(0) / sqrt(11);"
+         "sk_FragColor = highfloat4(1) * sqrt(12);"
+         "sk_FragColor = 0 + highfloat4(sqrt(13));"
+         "sk_FragColor = 0 * highfloat4(sqrt(14));"
+         "sk_FragColor = 0 / highfloat4(sqrt(15));"
+         "sk_FragColor = 1 * highfloat4(sqrt(16));"
+         "sk_FragColor = highfloat4(sqrt(17)) + 0;"
+         "sk_FragColor = highfloat4(sqrt(18)) * 0;"
+         "sk_FragColor = highfloat4(sqrt(19)) * 1;"
+         "sk_FragColor = highfloat4(sqrt(19.5)) - 0;"
+         "sk_FragColor = sqrt(20) * highfloat4(1);"
+         "sk_FragColor = sqrt(21) + highfloat4(0);"
+         "sk_FragColor = sqrt(22) - highfloat4(0);"
+         "sk_FragColor = sqrt(23) / highfloat4(1);"
+         "sk_FragColor = highfloat4(sqrt(24)) / 1;"
+         "sk_FragColor += highfloat4(1);"
+         "sk_FragColor += highfloat4(0);"
+         "sk_FragColor -= highfloat4(1);"
+         "sk_FragColor -= highfloat4(0);"
+         "sk_FragColor *= highfloat4(1);"
+         "sk_FragColor *= highfloat4(2);"
+         "sk_FragColor /= highfloat4(1);"
+         "sk_FragColor /= highfloat4(2);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -822,24 +822,24 @@
 DEF_TEST(SkSLMatFolding, r) {
     test(r,
          "void main() {"
-         "sk_FragColor.x = float2x2(float2(1.0, 0.0), float2(0.0, 1.0)) == "
-                          "float2x2(float2(1.0, 0.0), float2(0.0, 1.0)) ? 1 : -1;"
-         "sk_FragColor.x = float2x2(float2(1.0, 0.0), float2(1.0, 1.0)) == "
-                          "float2x2(float2(1.0, 0.0), float2(0.0, 1.0)) ? 2 : -2;"
-         "sk_FragColor.x = float2x2(1) == float2x2(1) ? 3 : -3;"
-         "sk_FragColor.x = float2x2(1) == float2x2(0) ? 4 : -4;"
-         "sk_FragColor.x = float2x2(1) == float2x2(float2(1.0, 0.0), float2(0.0, 1.0)) ? 5 : -5;"
-         "sk_FragColor.x = float2x2(2) == float2x2(float2(1.0, 0.0), float2(0.0, 1.0)) ? 6 : -6;"
-         "sk_FragColor.x = float3x2(2) == float3x2(float2(2.0, 0.0), float2(0.0, 2.0), float2(0.0))"
+         "sk_FragColor.x = highfloat2x2(highfloat2(1.0, 0.0), highfloat2(0.0, 1.0)) == "
+                          "highfloat2x2(highfloat2(1.0, 0.0), highfloat2(0.0, 1.0)) ? 1 : -1;"
+         "sk_FragColor.x = highfloat2x2(highfloat2(1.0, 0.0), highfloat2(1.0, 1.0)) == "
+                          "highfloat2x2(highfloat2(1.0, 0.0), highfloat2(0.0, 1.0)) ? 2 : -2;"
+         "sk_FragColor.x = highfloat2x2(1) == highfloat2x2(1) ? 3 : -3;"
+         "sk_FragColor.x = highfloat2x2(1) == highfloat2x2(0) ? 4 : -4;"
+         "sk_FragColor.x = highfloat2x2(1) == highfloat2x2(highfloat2(1.0, 0.0), highfloat2(0.0, 1.0)) ? 5 : -5;"
+         "sk_FragColor.x = highfloat2x2(2) == highfloat2x2(highfloat2(1.0, 0.0), highfloat2(0.0, 1.0)) ? 6 : -6;"
+         "sk_FragColor.x = highfloat3x2(2) == highfloat3x2(highfloat2(2.0, 0.0), highfloat2(0.0, 2.0), highfloat2(0.0))"
                            "? 7 : -7;"
-         "sk_FragColor.x = float2x2(1) != float2x2(1) ? 8 : -8;"
-         "sk_FragColor.x = float2x2(1) != float2x2(0) ? 9 : -9;"
-         "sk_FragColor.x = float3x3(float3(1.0, 0.0, 0.0), float3(0.0, 1.0, 0.0), "
-                          "float3(0.0, 0.0, 0.0)) == float3x3(float2x2(1.0)) ? 10 : -10;"
-         "sk_FragColor.x = float2x2(float3x3(1.0)) == float2x2(1.0) ? 11 : -11;"
-         "sk_FragColor.x = float2x2(float4(1.0, 0.0, 0.0, 1.0)) == float2x2(1.0) ? 12 : -12;"
-         "sk_FragColor.x = float2x2(1.0, 0.0, float2(0.0, 1.0)) == float2x2(1.0) ? 13 : -13;"
-         "sk_FragColor.x = float2x2(float2(1.0, 0.0), 0.0, 1.0) == float2x2(1.0) ? 14 : -14;"
+         "sk_FragColor.x = highfloat2x2(1) != highfloat2x2(1) ? 8 : -8;"
+         "sk_FragColor.x = highfloat2x2(1) != highfloat2x2(0) ? 9 : -9;"
+         "sk_FragColor.x = highfloat3x3(highfloat3(1.0, 0.0, 0.0), highfloat3(0.0, 1.0, 0.0), "
+                          "highfloat3(0.0, 0.0, 0.0)) == highfloat3x3(highfloat2x2(1.0)) ? 10 : -10;"
+         "sk_FragColor.x = highfloat2x2(highfloat3x3(1.0)) == highfloat2x2(1.0) ? 11 : -11;"
+         "sk_FragColor.x = highfloat2x2(highfloat4(1.0, 0.0, 0.0, 1.0)) == highfloat2x2(1.0) ? 12 : -12;"
+         "sk_FragColor.x = highfloat2x2(1.0, 0.0, highfloat2(0.0, 1.0)) == highfloat2x2(1.0) ? 13 : -13;"
+         "sk_FragColor.x = highfloat2x2(highfloat2(1.0, 0.0), 0.0, 1.0) == highfloat2x2(1.0) ? 14 : -14;"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -891,7 +891,7 @@
          "if (sk_Caps.fbFetchSupport) y = 1;"
          "if (sk_Caps.dropsTileOnZeroDivide && sk_Caps.texelFetchSupport) z = 1;"
          "if (sk_Caps.dropsTileOnZeroDivide && sk_Caps.canUseAnyFunctionInShader) w = 1;"
-         "sk_FragColor = float4(x, y, z, w);"
+         "sk_FragColor = half4(x, y, z, w);"
          "}",
          *SkSL::ShaderCapsFactory::VariousCaps(),
          "#version 400\n"
@@ -906,11 +906,11 @@
          "uniform sampler1D one;"
          "uniform sampler2D two;"
          "void main() {"
-         "float4 a = texture(one, 0);"
-         "float4 b = texture(two, float2(0));"
-         "float4 c = texture(one, float2(0));"
-         "float4 d = texture(two, float3(0));"
-         "sk_FragColor = float4(a.x, b.x, c.x, d.x);"
+         "highfloat4 a = texture(one, 0);"
+         "highfloat4 b = texture(two, highfloat2(0));"
+         "highfloat4 c = texture(one, highfloat2(0));"
+         "highfloat4 d = texture(two, highfloat3(0));"
+         "sk_FragColor = half4(a.x, b.x, c.x, d.x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -928,11 +928,11 @@
          "uniform sampler1D one;"
          "uniform sampler2D two;"
          "void main() {"
-         "float4 a = texture(one, 0);"
-         "float4 b = texture(two, float2(0));"
-         "float4 c = texture(one, float2(0));"
-         "float4 d = texture(two, float3(0));"
-         "sk_FragColor = float4(a.x, b.x, c.x, d.x);"
+         "highfloat4 a = texture(one, 0);"
+         "highfloat4 b = texture(two, highfloat2(0));"
+         "highfloat4 c = texture(one, highfloat2(0));"
+         "highfloat4 d = texture(two, highfloat3(0));"
+         "sk_FragColor = half4(a.x, b.x, c.x, d.x);"
          "}",
          *SkSL::ShaderCapsFactory::Version110(),
          "#version 110\n"
@@ -1047,7 +1047,7 @@
          "}\n",
          SkSL::Program::kVertex_Kind);
     test(r,
-         "void main() { sk_FragColor = float4(sk_ClipDistance[0]); }",
+         "void main() { sk_FragColor = half4(sk_ClipDistance[0]); }",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -1058,9 +1058,9 @@
 
 DEF_TEST(SkSLArrayTypes, r) {
     test(r,
-         "void main() { float2 x[2] = float2[2](float2(1), float2(2));"
-         "float2[2] y = float2[2](float2(3), float2(4));"
-         "sk_FragColor = float4(x[0], y[1]); }",
+         "void main() { highfloat2 x[2] = highfloat2[2](highfloat2(1), highfloat2(2));"
+         "highfloat2[2] y = highfloat2[2](highfloat2(3), highfloat2(4));"
+         "sk_FragColor = highfloat4(x[0], y[1]); }",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -1076,9 +1076,9 @@
          "layout(invocations = 2) in;"
          "layout(line_strip, max_vertices = 2) out;"
          "void main() {"
-         "gl_Position = sk_in[0].gl_Position + float4(-0.5, 0, 0, sk_InvocationID);"
+         "gl_Position = sk_in[0].gl_Position + highfloat4(-0.5, 0, 0, sk_InvocationID);"
          "EmitVertex();"
-         "gl_Position = sk_in[0].gl_Position + float4(0.5, 0, 0, sk_InvocationID);"
+         "gl_Position = sk_in[0].gl_Position + highfloat4(0.5, 0, 0, sk_InvocationID);"
          "EmitVertex();"
          "EndPrimitive();"
          "}",
@@ -1101,7 +1101,7 @@
     // basic "does a switch even work" test
     test(r,
          "void main() {"
-         "    float x;"
+         "    highfloat x;"
          "    switch (int(sqrt(1))) {"
          "        case 0:"
          "            x = 0.0;"
@@ -1112,7 +1112,7 @@
          "        default:"
          "            x = 2.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = highfloat4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1134,7 +1134,7 @@
     // dead code inside of switch
     test(r,
          "void main() {"
-         "    float x;"
+         "    highfloat x;"
          "    switch (int(sqrt(2))) {"
          "        case 0:"
          "            x = 0.0;"
@@ -1143,7 +1143,7 @@
          "        default:"
          "            x = 2.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = half4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1162,14 +1162,14 @@
     // non-static test w/ fallthrough
     test(r,
          "void main() {"
-         "    float x = 0.0;"
+         "    highfloat x = 0.0;"
          "    switch (int(sqrt(3))) {"
          "        case 0:"
          "            x = 0.0;"
          "        case 1:"
          "            x = 1.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = half4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1187,14 +1187,14 @@
     // static test w/ fallthrough
     test(r,
          "void main() {"
-         "    float x = 0.0;"
+         "    highfloat x = 0.0;"
          "    switch (0) {"
          "        case 0:"
          "            x = 0.0;"
          "        case 1:"
          "            x = 1.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = half4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1205,14 +1205,14 @@
     // static test w/ fallthrough, different entry point
     test(r,
          "void main() {"
-         "    float x = 0.0;"
+         "    highfloat x = 0.0;"
          "    switch (1) {"
          "        case 0:"
          "            x = 0.0;"
          "        case 1:"
          "            x = 1.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = half4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1223,7 +1223,7 @@
     // static test w/ break
     test(r,
          "void main() {"
-         "    float x = 0.0;"
+         "    highfloat x = 0.0;"
          "    switch (0) {"
          "        case 0:"
          "            x = 0.0;"
@@ -1231,7 +1231,7 @@
          "        case 1:"
          "            x = 1.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = half4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1242,7 +1242,7 @@
     // static test w/ static conditional break
     test(r,
          "void main() {"
-         "    float x = 0.0;"
+         "    highfloat x = 0.0;"
          "    switch (0) {"
          "        case 0:"
          "            x = 0.0;"
@@ -1250,7 +1250,7 @@
          "        case 1:"
          "            x = 1.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = half4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1261,7 +1261,7 @@
     // static test w/ non-static conditional break
     test(r,
          "void main() {"
-         "    float x = 0.0;"
+         "    highfloat x = 0.0;"
          "    switch (0) {"
          "        case 0:"
          "            x = 0.0;"
@@ -1269,7 +1269,7 @@
          "        case 1:"
          "            x = 1.0;"
          "    }"
-         "    sk_FragColor = float4(x);"
+         "    sk_FragColor = half4(x);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1291,7 +1291,7 @@
     test(r,
          "uniform sampler2D test;"
          "void main() {"
-         "    sk_FragColor = texture(test, float2(0.5));"
+         "    sk_FragColor = texture(test, highfloat2(0.5));"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1303,7 +1303,7 @@
     test(r,
          "uniform sampler2DRect test;"
          "void main() {"
-         "    sk_FragColor = texture(test, float2(0.5));"
+         "    sk_FragColor = texture(test, highfloat2(0.5));"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1315,7 +1315,7 @@
     test(r,
          "uniform sampler2DRect test;"
          "void main() {"
-         "    sk_FragColor = texture(test, float3(0.5));"
+         "    sk_FragColor = texture(test, highfloat3(0.5));"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1329,12 +1329,12 @@
 DEF_TEST(SkSLUnusedVars, r) {
     test(r,
          "void main() {"
-         "float a = 1, b = 2, c = 3;"
-         "float d = c;"
-         "float e = d;"
+         "highfloat a = 1, b = 2, c = 3;"
+         "highfloat d = c;"
+         "highfloat e = d;"
          "b++;"
          "d++;"
-         "sk_FragColor = float4(b, b, d, d);"
+         "sk_FragColor = highfloat4(b, b, d, d);"
          "}",
         *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1351,11 +1351,11 @@
 DEF_TEST(SkSLMultipleAssignments, r) {
     test(r,
          "void main() {"
-         "float x;"
-         "float y;"
+         "highfloat x;"
+         "highfloat y;"
          "int z;"
          "x = y = z = 1;"
-         "sk_FragColor = float4(z);"
+         "sk_FragColor = highfloat4(z);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1367,13 +1367,13 @@
 
 DEF_TEST(SkSLComplexDelete, r) {
     test(r,
-         "uniform float4x4 colorXform;"
+         "uniform highfloat4x4 colorXform;"
          "uniform sampler2D sampler;"
          "void main() {"
-         "float4 tmpColor;"
-         "sk_FragColor = float4(1.0) * (tmpColor = texture(sampler, float2(1)) , "
-         "colorXform != float4x4(1.0) ? float4(clamp((float4x4(colorXform) * "
-                                                     "float4(tmpColor.xyz, 1.0)).xyz, "
+         "highfloat4 tmpColor;"
+         "sk_FragColor = highfloat4(1.0) * (tmpColor = texture(sampler, highfloat2(1)) , "
+         "colorXform != highfloat4x4(1.0) ? highfloat4(clamp((highfloat4x4(colorXform) * "
+                                                     "highfloat4(tmpColor.xyz, 1.0)).xyz, "
                                                      "0.0, tmpColor.w), tmpColor.w) : tmpColor);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
@@ -1392,8 +1392,8 @@
 DEF_TEST(SkSLDependentInitializers, r) {
     test(r,
          "void main() {"
-         "float x = 0.5, y = x * 2;"
-         "sk_FragColor = float4(y);"
+         "highfloat x = 0.5, y = x * 2;"
+         "sk_FragColor = highfloat4(y);"
          "}",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
@@ -1427,11 +1427,11 @@
          "layout(invocations = 2) in;"
          "layout(line_strip, max_vertices = 2) out;"
          "void test() {"
-         "gl_Position = sk_in[0].gl_Position + float4(0.5, 0, 0, sk_InvocationID);"
+         "gl_Position = sk_in[0].gl_Position + highfloat4(0.5, 0, 0, sk_InvocationID);"
          "EmitVertex();"
          "}"
          "void main() {"
-         "gl_Position = sk_in[0].gl_Position + float4(-0.5, 0, 0, sk_InvocationID);"
+         "gl_Position = sk_in[0].gl_Position + highfloat4(-0.5, 0, 0, sk_InvocationID);"
          "EmitVertex();"
          "}",
          *SkSL::ShaderCapsFactory::MustImplementGSInvocationsWithLoop(),
@@ -1458,13 +1458,13 @@
 
 DEF_TEST(SkSLTypePrecision, r) {
     test(r,
-         "float f = 1;"
+         "highfloat f = 1;"
          "half h = 2;"
          "double d = 3;"
-         "float2 f2 = float2(1, 2);"
+         "highfloat2 f2 = highfloat2(1, 2);"
          "half3 h3 = half3(1, 2, 3);"
          "double4 d4 = double4(1, 2, 3, 4);"
-         "float2x2 f22 = float2x2(1, 2, 3, 4);"
+         "highfloat2x2 f22 = highfloat2x2(1, 2, 3, 4);"
          "half2x4 h24 = half2x4(1, 2, 3, 4, 5, 6, 7, 8);"
          "double4x2 d42 = double4x2(1, 2, 3, 4, 5, 6, 7, 8);",
          *SkSL::ShaderCapsFactory::Default(),
@@ -1480,21 +1480,21 @@
          "mat2x4 h24 = mat2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);\n"
          "dmat4x2 d42 = dmat4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);\n");
     test(r,
-         "float f = 1;"
+         "highfloat f = 1;"
          "half h = 2;"
-         "float2 f2 = float2(1, 2);"
+         "highfloat2 f2 = highfloat2(1, 2);"
          "half3 h3 = half3(1, 2, 3);"
-         "float2x2 f22 = float2x2(1, 2, 3, 4);"
+         "highfloat2x2 f22 = highfloat2x2(1, 2, 3, 4);"
          "half2x4 h24 = half2x4(1, 2, 3, 4, 5, 6, 7, 8);",
          *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
          "#version 400\n"
-         "precision highp float;\n"
+         "precision mediump float;\n"
          "out mediump vec4 sk_FragColor;\n"
-         "float f = 1.0;\n"
+         "highp float f = 1.0;\n"
          "mediump float h = 2.0;\n"
-         "vec2 f2 = vec2(1.0, 2.0);\n"
+         "highp vec2 f2 = vec2(1.0, 2.0);\n"
          "mediump vec3 h3 = vec3(1.0, 2.0, 3.0);\n"
-         "mat2 f22 = mat2(1.0, 2.0, 3.0, 4.0);\n"
+         "highp mat2 f22 = mat2(1.0, 2.0, 3.0, 4.0);\n"
          "mediump mat2x4 h24 = mat2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);\n");
 }
 
@@ -1505,50 +1505,37 @@
          "ushort us = ushort(sqrt(1));"
          "uint ui = uint(sqrt(1));"
          "half h = sqrt(1);"
-         "float f = sqrt(1);"
-         "double d = sqrt(1);"
+         "highfloat f = sqrt(1);"
          "short s2s = s;"
          "short i2s = i;"
          "short us2s = short(us);"
          "short ui2s = short(ui);"
          "short h2s = short(h);"
          "short f2s = short(f);"
-         "short d2fs = short(d);"
          "int s2i = s;"
          "int i2i = i;"
          "int us2i = int(us);"
          "int ui2i = int(ui);"
          "int h2i = int(h);"
          "int f2i = int(f);"
-         "int d2fi = int(d);"
          "ushort s2us = ushort(s);"
          "ushort i2us = ushort(i);"
          "ushort us2us = us;"
          "ushort ui2us = ui;"
          "ushort h2us = ushort(h);"
          "ushort f2us = ushort(f);"
-         "ushort d2fus = ushort(d);"
          "uint s2ui = uint(s);"
          "uint i2ui = uint(i);"
          "uint us2ui = us;"
          "uint ui2ui = ui;"
          "uint h2ui = uint(h);"
          "uint f2ui = uint(f);"
-         "uint d2fui = uint(d);"
-         "float s2f = s;"
-         "float i2f = i;"
-         "float us2f = us;"
-         "float ui2f = ui;"
-         "float h2f = h;"
-         "float f2f = f;"
-         "float d2f = d;"
-         "double s2d = s;"
-         "double i2d = i;"
-         "double us2d = us;"
-         "double ui2d = ui;"
-         "double h2d = h;"
-         "double f2d = f;"
-         "double d2d = d;",
+         "highfloat s2f = s;"
+         "highfloat i2f = i;"
+         "highfloat us2f = us;"
+         "highfloat ui2f = ui;"
+         "highfloat h2f = h;"
+         "highfloat f2f = f;",
          *SkSL::ShaderCapsFactory::Default(),
          "#version 400\n"
          "out vec4 sk_FragColor;\n"
@@ -1558,49 +1545,67 @@
          "uint ui = uint(sqrt(1.0));\n"
          "float h = sqrt(1.0);\n"
          "float f = sqrt(1.0);\n"
-         "double d = sqrt(1.0);\n"
          "int s2s = s;\n"
          "int i2s = i;\n"
          "int us2s = int(us);\n"
          "int ui2s = int(ui);\n"
          "int h2s = int(h);\n"
          "int f2s = int(f);\n"
-         "int d2fs = int(d);\n"
          "int s2i = s;\n"
          "int i2i = i;\n"
          "int us2i = int(us);\n"
          "int ui2i = int(ui);\n"
          "int h2i = int(h);\n"
          "int f2i = int(f);\n"
-         "int d2fi = int(d);\n"
          "uint s2us = uint(s);\n"
          "uint i2us = uint(i);\n"
          "uint us2us = us;\n"
          "uint ui2us = ui;\n"
          "uint h2us = uint(h);\n"
          "uint f2us = uint(f);\n"
-         "uint d2fus = uint(d);\n"
          "uint s2ui = uint(s);\n"
          "uint i2ui = uint(i);\n"
          "uint us2ui = us;\n"
          "uint ui2ui = ui;\n"
          "uint h2ui = uint(h);\n"
          "uint f2ui = uint(f);\n"
-         "uint d2fui = uint(d);\n"
          "float s2f = float(s);\n"
          "float i2f = float(i);\n"
          "float us2f = float(us);\n"
          "float ui2f = float(ui);\n"
          "float h2f = h;\n"
-         "float f2f = f;\n"
-         "float d2f = d;\n"
-         "double s2d = double(s);\n"
-         "double i2d = double(i);\n"
-         "double us2d = double(us);\n"
-         "double ui2d = double(ui);\n"
-         "double h2d = h;\n"
-         "double f2d = f;\n"
-         "double d2d = d;\n");
+         "float f2f = f;\n");
+}
+
+DEF_TEST(SkSLForceHighPrecision, r) {
+    test(r,
+         "void main() { half x = sqrt(1); half4 y = half4(x); sk_FragColor = y; }",
+         *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
+         "#version 400\n"
+         "precision mediump float;\n"
+         "out mediump vec4 sk_FragColor;\n"
+         "void main() {\n"
+         "    mediump float x = sqrt(1.0);\n"
+         "    mediump vec4 y = vec4(x);\n"
+         "    sk_FragColor = y;\n"
+         "}\n");
+    SkSL::Program::Settings settings;
+    settings.fForceHighPrecision = true;
+    sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::UsesPrecisionModifiers();
+    settings.fCaps = caps.get();
+    SkSL::Program::Inputs inputs;
+    test(r,
+         "void main() { half x = sqrt(1); half4 y = half4(x); sk_FragColor = y; }",
+         settings,
+         "#version 400\n"
+         "precision mediump float;\n"
+         "out mediump vec4 sk_FragColor;\n"
+         "void main() {\n"
+         "    highp float x = sqrt(1.0);\n"
+         "    highp vec4 y = vec4(x);\n"
+         "    sk_FragColor = y;\n"
+         "}\n",
+         &inputs);
 }
 
 #endif