SkSL GLSL generator writes default precision for sampler2D/samplerExternalOS/sampler2DRect

This is a stop gap. We should probably base the precision decision on the texture format.

Also removes all code used to add sampler precision to program keys. The precision that
was added to the key did not affect the generated GLSL.

Bug: skia:8863
Bug: skia:6718
Change-Id: Ibdb702e1aca5d48d83e2f24cb24010a0b7270871
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/234322
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 7ec48bc..cfc2549 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -408,28 +408,6 @@
 };
 GR_MAKE_BITFIELD_OPS(GrShaderFlags)
 
-/**
- * Precisions of shader language variables. Not all shading languages support precisions or actually
- * vary the internal precision based on the qualifiers. These currently only apply to float types (
- * including float vectors and matrices).
- */
-enum GrSLPrecision : int {
-    kLow_GrSLPrecision,
-    kMedium_GrSLPrecision,
-    kHigh_GrSLPrecision,
-
-    // Default precision is a special tag that means "whatever the default for the program/type
-    // combination is". In other words, it maps to the empty string in shader code. There are some
-    // scenarios where kDefault is not allowed (as the default precision for a program, or for
-    // varyings, for example).
-    kDefault_GrSLPrecision,
-
-    // We only consider the "real" precisions here
-    kLast_GrSLPrecision = kHigh_GrSLPrecision,
-};
-
-static const int kGrSLPrecisionCount = kLast_GrSLPrecision + 1;
-
 /** Is the shading language type float (including vectors/matrices)? */
 static constexpr bool GrSLTypeIsFloatType(GrSLType type) {
     switch (type) {
@@ -1081,46 +1059,6 @@
 }
 
 /**
- * Precision qualifier that should be used with a sampler.
- */
-static constexpr GrSLPrecision GrSLSamplerPrecision(GrPixelConfig config) {
-    switch (config) {
-        case kUnknown_GrPixelConfig:
-        case kAlpha_8_GrPixelConfig:
-        case kAlpha_8_as_Alpha_GrPixelConfig:
-        case kAlpha_8_as_Red_GrPixelConfig:
-        case kGray_8_GrPixelConfig:
-        case kGray_8_as_Lum_GrPixelConfig:
-        case kGray_8_as_Red_GrPixelConfig:
-        case kRGB_565_GrPixelConfig:
-        case kRGBA_4444_GrPixelConfig:
-        case kRGBA_8888_GrPixelConfig:
-        case kRGB_888_GrPixelConfig:
-        case kRGB_888X_GrPixelConfig:
-        case kRG_88_GrPixelConfig:
-        case kBGRA_8888_GrPixelConfig:
-        case kSRGBA_8888_GrPixelConfig:
-        case kRGB_ETC1_GrPixelConfig:
-            return kLow_GrSLPrecision;
-        case kRGBA_float_GrPixelConfig:
-            return kHigh_GrSLPrecision;
-        case kAlpha_half_GrPixelConfig:
-        case kAlpha_half_as_Lum_GrPixelConfig:
-        case kAlpha_half_as_Red_GrPixelConfig:
-        case kRGBA_half_GrPixelConfig:
-        case kRGBA_half_Clamped_GrPixelConfig:
-        case kRGBA_1010102_GrPixelConfig:
-        case kR_16_GrPixelConfig:
-        case kRG_1616_GrPixelConfig:
-        // Experimental (for Y416 and mutant P016/P010)
-        case kRGBA_16161616_GrPixelConfig:
-        case kRG_half_GrPixelConfig:
-            return kMedium_GrSLPrecision;
-    }
-    SkUNREACHABLE;
-}
-
-/**
  * Like SkColorType this describes a layout of pixel data in CPU memory. It specifies the channels,
  * their type, and width. This exists so that the GPU backend can have private types that have no
  * analog in the public facing SkColorType enum and omit types not implemented in the GPU backend.
diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp
index becab18..1ce6ca2 100644
--- a/src/gpu/GrPrimitiveProcessor.cpp
+++ b/src/gpu/GrPrimitiveProcessor.cpp
@@ -54,44 +54,38 @@
 }
 
 GrPrimitiveProcessor::TextureSampler::TextureSampler(GrTextureType textureType,
-                                                     GrPixelConfig config,
                                                      const GrSamplerState& samplerState,
                                                      const GrSwizzle& swizzle,
                                                      uint32_t extraSamplerKey) {
-    this->reset(textureType, config, samplerState, swizzle, extraSamplerKey);
+    this->reset(textureType, samplerState, swizzle, extraSamplerKey);
 }
 
 GrPrimitiveProcessor::TextureSampler::TextureSampler(GrTextureType textureType,
-                                                     GrPixelConfig config,
                                                      GrSamplerState::Filter filterMode,
                                                      GrSamplerState::WrapMode wrapXAndY,
                                                      const GrSwizzle& swizzle) {
-    this->reset(textureType, config, filterMode, wrapXAndY, swizzle);
+    this->reset(textureType, filterMode, wrapXAndY, swizzle);
 }
 
 void GrPrimitiveProcessor::TextureSampler::reset(GrTextureType textureType,
-                                                 GrPixelConfig config,
                                                  const GrSamplerState& samplerState,
                                                  const GrSwizzle& swizzle,
                                                  uint32_t extraSamplerKey) {
-    SkASSERT(kUnknown_GrPixelConfig != config);
     fSamplerState = samplerState;
     fSamplerState.setFilterMode(clamp_filter(textureType, samplerState.filter()));
     fSwizzle = swizzle;
     fTextureType = textureType;
-    fConfig = config;
     fExtraSamplerKey = extraSamplerKey;
+    fIsInitialized = true;
 }
 
 void GrPrimitiveProcessor::TextureSampler::reset(GrTextureType textureType,
-                                                 GrPixelConfig config,
                                                  GrSamplerState::Filter filterMode,
                                                  GrSamplerState::WrapMode wrapXAndY,
                                                  const GrSwizzle& swizzle) {
-    SkASSERT(kUnknown_GrPixelConfig != config);
     filterMode = clamp_filter(textureType, filterMode);
     fSamplerState = GrSamplerState(wrapXAndY, filterMode);
     fSwizzle = swizzle;
     fTextureType = textureType;
-    fConfig = config;
+    fIsInitialized = true;
 }
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index 83b161f..ca79985 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -254,38 +254,37 @@
 public:
     TextureSampler() = default;
 
-    TextureSampler(GrTextureType, GrPixelConfig, const GrSamplerState&, const GrSwizzle&,
+    TextureSampler(GrTextureType, const GrSamplerState&, const GrSwizzle&,
                    uint32_t extraSamplerKey);
 
-    explicit TextureSampler(GrTextureType, GrPixelConfig, GrSamplerState::Filter,
+    explicit TextureSampler(GrTextureType, GrSamplerState::Filter,
                             GrSamplerState::WrapMode wrapXAndY, const GrSwizzle&);
 
     TextureSampler(const TextureSampler&) = delete;
     TextureSampler& operator=(const TextureSampler&) = delete;
 
-    void reset(GrTextureType, GrPixelConfig, const GrSamplerState&, const GrSwizzle&,
+    void reset(GrTextureType, const GrSamplerState&, const GrSwizzle&,
                uint32_t extraSamplerKey = 0);
-    void reset(GrTextureType, GrPixelConfig,
+    void reset(GrTextureType,
                GrSamplerState::Filter,
                GrSamplerState::WrapMode wrapXAndY,
                const GrSwizzle& swizzle);
 
     GrTextureType textureType() const { return fTextureType; }
-    GrPixelConfig config() const { return fConfig; }
 
     const GrSamplerState& samplerState() const { return fSamplerState; }
     const GrSwizzle& swizzle() const { return fSwizzle; }
 
     uint32_t extraSamplerKey() const { return fExtraSamplerKey; }
 
-    bool isInitialized() const { return fConfig != kUnknown_GrPixelConfig; }
+    bool isInitialized() const { return fIsInitialized; }
 
 private:
     GrSamplerState fSamplerState;
     GrSwizzle fSwizzle;
     GrTextureType fTextureType = GrTextureType::k2D;
-    GrPixelConfig fConfig = kUnknown_GrPixelConfig;
     uint32_t fExtraSamplerKey = 0;
+    bool fIsInitialized = false;
 };
 
 const GrPrimitiveProcessor::TextureSampler& GrPrimitiveProcessor::IthTextureSampler(int i) {
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index d20d6e1..10a593b 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -44,7 +44,7 @@
 }
 
 static uint32_t sampler_key(GrTextureType textureType, const GrSwizzle& swizzle,
-                            GrPixelConfig config, const GrShaderCaps& caps) {
+                            const GrShaderCaps& caps) {
     int samplerTypeKey = texture_type_key(textureType);
 
     GR_STATIC_ASSERT(2 == sizeof(swizzle.asKey()));
@@ -52,9 +52,7 @@
     if (caps.textureSwizzleAppliedInShader()) {
         swizzleKey = swizzle.asKey();
     }
-    return SkToU32(samplerTypeKey |
-                   swizzleKey << kSamplerOrImageTypeKeyBits |
-                   (GrSLSamplerPrecision(config) << (16 + kSamplerOrImageTypeKeyBits)));
+    return SkToU32(samplerTypeKey | swizzleKey << kSamplerOrImageTypeKeyBits);
 }
 
 static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrFragmentProcessor& fp,
@@ -67,7 +65,7 @@
         const GrFragmentProcessor::TextureSampler& sampler = fp.textureSampler(i);
         const GrTexture* tex = sampler.peekTexture();
         uint32_t samplerKey = sampler_key(
-                tex->texturePriv().textureType(), sampler.swizzle(), tex->config(), caps);
+                tex->texturePriv().textureType(), sampler.swizzle(), caps);
         uint32_t extraSamplerKey = gpu->getExtraSamplerKeyForProgram(
                 sampler.samplerState(), sampler.proxy()->backendFormat());
         if (extraSamplerKey) {
@@ -91,7 +89,7 @@
     for (int i = 0; i < numTextureSamplers; ++i) {
         const GrPrimitiveProcessor::TextureSampler& sampler = pp.textureSampler(i);
         uint32_t samplerKey = sampler_key(
-                sampler.textureType(), sampler.swizzle(), sampler.config(), caps);
+                sampler.textureType(), sampler.swizzle(), caps);
         uint32_t extraSamplerKey = sampler.extraSamplerKey();
         if (extraSamplerKey) {
             // We first mark the normal sampler key with last bit to flag that it has an extra
diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp
index 8b8af8a..3a88698 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPathProcessor.cpp
@@ -84,8 +84,8 @@
                                      const SkMatrix& viewMatrixIfUsingLocalCoords)
         : INHERITED(kGrCCPathProcessor_ClassID)
         , fCoverageMode(coverageMode)
-        , fAtlasAccess(atlasTexture->texturePriv().textureType(), atlasTexture->config(),
-                       GrSamplerState::Filter::kNearest, GrSamplerState::WrapMode::kClamp, swizzle)
+        , fAtlasAccess(atlasTexture->texturePriv().textureType(), GrSamplerState::Filter::kNearest,
+                       GrSamplerState::WrapMode::kClamp, swizzle)
         , fAtlasSize(SkISize::Make(atlasTexture->width(), atlasTexture->height()))
         , fAtlasOrigin(atlasOrigin) {
     // TODO: Can we just assert that atlas has GrCCAtlas::kTextureOrigin and remove fAtlasOrigin?
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 5ae4dfd..4a8c25d 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -154,8 +154,7 @@
     for (int i = 0; i < numActiveProxies; ++i) {
         SkASSERT(proxies[i]);
         SkASSERT(proxies[i]->isize() == fAtlasSize);
-        fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
-                                  proxies[i]->textureSwizzle());
+        fTextureSamplers[i].reset(proxies[i]->textureType(), params, proxies[i]->textureSwizzle());
     }
     this->setTextureSamplerCnt(numActiveProxies);
 }
@@ -174,7 +173,7 @@
         SkASSERT(proxies[i]->isize() == fAtlasSize);
 
         if (!fTextureSamplers[i].isInitialized()) {
-            fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
+            fTextureSamplers[i].reset(proxies[i]->textureType(), params,
                                       proxies[i]->textureSwizzle());
         }
     }
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 92d404a..08c36dc 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -241,8 +241,7 @@
     for (int i = 0; i < numProxies; ++i) {
         SkASSERT(proxies[i]);
         SkASSERT(proxies[i]->isize() == fAtlasSize);
-        fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
-                                  proxies[i]->textureSwizzle());
+        fTextureSamplers[i].reset(proxies[i]->textureType(), params, proxies[i]->textureSwizzle());
     }
     this->setTextureSamplerCnt(numProxies);
 }
@@ -260,7 +259,7 @@
         SkASSERT(proxies[i]);
         SkASSERT(proxies[i]->isize() == fAtlasSize);
         if (!fTextureSamplers[i].isInitialized()) {
-            fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
+            fTextureSamplers[i].reset(proxies[i]->textureType(), params,
                                       proxies[i]->textureSwizzle());
         }
     }
@@ -537,8 +536,7 @@
     for (int i = 0; i < numProxies; ++i) {
         SkASSERT(proxies[i]);
         SkASSERT(proxies[i]->isize() == fAtlasSize);
-        fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
-                                  proxies[i]->textureSwizzle());
+        fTextureSamplers[i].reset(proxies[i]->textureType(), params, proxies[i]->textureSwizzle());
     }
     this->setTextureSamplerCnt(numProxies);
 }
@@ -557,7 +555,7 @@
         SkASSERT(proxies[i]->isize() == fAtlasSize);
 
         if (!fTextureSamplers[i].isInitialized()) {
-            fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
+            fTextureSamplers[i].reset(proxies[i]->textureType(), params,
                                       proxies[i]->textureSwizzle());
         }
     }
@@ -861,8 +859,7 @@
     for (int i = 0; i < numProxies; ++i) {
         SkASSERT(proxies[i]);
         SkASSERT(proxies[i]->isize() == fAtlasSize);
-        fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
-                                  proxies[i]->textureSwizzle());
+        fTextureSamplers[i].reset(proxies[i]->textureType(), params, proxies[i]->textureSwizzle());
     }
     this->setTextureSamplerCnt(numProxies);
 }
@@ -881,7 +878,7 @@
         SkASSERT(proxies[i]->isize() == fAtlasSize);
 
         if (!fTextureSamplers[i].isInitialized()) {
-            fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params,
+            fTextureSamplers[i].reset(proxies[i]->textureType(), params,
                                       proxies[i]->textureSwizzle());
         }
     }
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 3376268..2c41312 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -106,7 +106,6 @@
         const auto& sampler = proc.textureSampler(i);
         const GrTexture* texture = primProcProxies[i]->peekTexture();
         SkASSERT(sampler.textureType() == texture->texturePriv().textureType());
-        SkASSERT(sampler.config() == texture->config());
         texSamplers[i] = this->emitSampler(texture,
                                            sampler.samplerState(),
                                            sampler.swizzle(),
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 4b9a09a..b3af37a 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -101,7 +101,7 @@
         uint32_t extraSamplerKey = gpu->getExtraSamplerKeyForProgram(samplerState,
                                                                      proxy->backendFormat());
 
-        fSampler.reset(proxy->textureType(), proxy->config(), samplerState, proxy->textureSwizzle(),
+        fSampler.reset(proxy->textureType(), samplerState, proxy->textureSwizzle(),
                        extraSamplerKey);
         this->setTextureSamplerCnt(1);
         fInPosition = {"position", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index 5b22fc2..6c4211c 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -856,13 +856,13 @@
     }
 
     static sk_sp<GrGeometryProcessor> Make(const VertexSpec& vertexSpec, const GrShaderCaps& caps,
-                                           GrTextureType textureType, GrPixelConfig textureConfig,
+                                           GrTextureType textureType,
                                            const GrSamplerState& samplerState,
                                            const GrSwizzle& swizzle, uint32_t extraSamplerKey,
                                            sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
         return sk_sp<QuadPerEdgeAAGeometryProcessor>(new QuadPerEdgeAAGeometryProcessor(
-                vertexSpec, caps, textureType, textureConfig, samplerState, swizzle,
-                extraSamplerKey, std::move(textureColorSpaceXform)));
+                vertexSpec, caps, textureType, samplerState, swizzle, extraSamplerKey,
+                std::move(textureColorSpaceXform)));
     }
 
     const char* name() const override { return "QuadPerEdgeAAGeometryProcessor"; }
@@ -1050,15 +1050,16 @@
         this->setTextureSamplerCnt(0);
     }
 
-    QuadPerEdgeAAGeometryProcessor(const VertexSpec& spec, const GrShaderCaps& caps,
-                                   GrTextureType textureType, GrPixelConfig textureConfig,
+    QuadPerEdgeAAGeometryProcessor(const VertexSpec& spec,
+                                   const GrShaderCaps& caps,
+                                   GrTextureType textureType,
                                    const GrSamplerState& samplerState,
                                    const GrSwizzle& swizzle,
                                    uint32_t extraSamplerKey,
                                    sk_sp<GrColorSpaceXform> textureColorSpaceXform)
             : INHERITED(kQuadPerEdgeAAGeometryProcessor_ClassID)
             , fTextureColorSpaceXform(std::move(textureColorSpaceXform))
-            , fSampler(textureType, textureConfig, samplerState, swizzle, extraSamplerKey) {
+            , fSampler(textureType, samplerState, swizzle, extraSamplerKey) {
         SkASSERT(spec.hasLocalCoords());
         this->initializeAttrs(spec);
         this->setTextureSamplerCnt(1);
@@ -1136,12 +1137,12 @@
 }
 
 sk_sp<GrGeometryProcessor> MakeTexturedProcessor(const VertexSpec& spec, const GrShaderCaps& caps,
-        GrTextureType textureType, GrPixelConfig textureConfig,
-        const GrSamplerState& samplerState, const GrSwizzle& swizzle, uint32_t extraSamplerKey,
-        sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
-    return QuadPerEdgeAAGeometryProcessor::Make(spec, caps, textureType, textureConfig,
-                                                samplerState, swizzle, extraSamplerKey,
-                                                std::move(textureColorSpaceXform));
+                                                 GrTextureType textureType,
+                                                 const GrSamplerState& samplerState,
+                                                 const GrSwizzle& swizzle, uint32_t extraSamplerKey,
+                                                 sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
+    return QuadPerEdgeAAGeometryProcessor::Make(spec, caps, textureType, samplerState, swizzle,
+                                                extraSamplerKey, std::move(textureColorSpaceXform));
 }
 
 } // namespace GrQuadPerEdgeAA
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.h b/src/gpu/ops/GrQuadPerEdgeAA.h
index ba74aab..5c1a429 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.h
+++ b/src/gpu/ops/GrQuadPerEdgeAA.h
@@ -81,8 +81,8 @@
 
     sk_sp<GrGeometryProcessor> MakeProcessor(const VertexSpec& spec);
 
-    sk_sp<GrGeometryProcessor> MakeTexturedProcessor(const VertexSpec& spec,
-            const GrShaderCaps& caps, GrTextureType textureType, GrPixelConfig textureConfig,
+    sk_sp<GrGeometryProcessor> MakeTexturedProcessor(
+            const VertexSpec& spec, const GrShaderCaps& caps, GrTextureType textureType,
             const GrSamplerState& samplerState, const GrSwizzle& swizzle, uint32_t extraSamplerKey,
             sk_sp<GrColorSpaceXform> textureColorSpaceXform);
 
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index e7bf602..4c04ce0 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -416,7 +416,6 @@
         int numProxies = 0;
         int numTotalQuads = 0;
         auto textureType = fProxies[0].fProxy->textureType();
-        auto config = fProxies[0].fProxy->config();
         const GrSwizzle& swizzle = fProxies[0].fProxy->textureSwizzle();
         GrAAType aaType = this->aaType();
         for (const auto& op : ChainRange<TextureOp>(this)) {
@@ -437,7 +436,6 @@
                 if (!proxy->isInstantiated()) {
                     return;
                 }
-                SkASSERT(proxy->config() == config);
                 SkASSERT(proxy->textureType() == textureType);
                 SkASSERT(proxy->textureSwizzle() == swizzle);
             }
@@ -457,9 +455,8 @@
                 samplerState, fProxies[0].fProxy->backendFormat());
 
         sk_sp<GrGeometryProcessor> gp = GrQuadPerEdgeAA::MakeTexturedProcessor(
-                vertexSpec, *target->caps().shaderCaps(),
-                textureType, config, samplerState, swizzle, extraSamplerKey,
-                std::move(fTextureColorSpaceXform));
+                vertexSpec, *target->caps().shaderCaps(), textureType, samplerState, swizzle,
+                extraSamplerKey, std::move(fTextureColorSpaceXform));
 
         // We'll use a dynamic state array for the GP textures when there are multiple ops.
         // Otherwise, we use fixed dynamic state to specify the single op's proxy.
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 61a7c11..2d29823 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -1277,6 +1277,9 @@
             }
             fFoundExternalSamplerDecl = true;
         }
+        if (!fFoundRectSamplerDecl && var.fVar->fType == *fContext.fSampler2DRect_Type) {
+            fFoundRectSamplerDecl = true;
+        }
     }
     if (wroteType) {
         this->write(";");
@@ -1601,6 +1604,13 @@
 
     if (this->usesPrecisionModifiers()) {
         this->writeLine("precision mediump float;");
+        this->writeLine("precision mediump sampler2D;");
+        if (fFoundExternalSamplerDecl) {
+            this->writeLine("precision mediump samplerExternalOES;");
+        }
+        if (fFoundRectSamplerDecl) {
+            this->writeLine("precision mediump sampler2DRect;");
+        }
     }
     write_stringstream(fExtraFunctions, *rawOut);
     write_stringstream(body, *rawOut);
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index f75f633..87fff42 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -215,6 +215,7 @@
     // true if we have run into usages of dFdx / dFdy
     bool fFoundDerivatives = false;
     bool fFoundExternalSamplerDecl = false;
+    bool fFoundRectSamplerDecl = false;
     bool fFoundGSInvocations = false;
     bool fSetupFragPositionGlobal = false;
     bool fSetupFragPositionLocal = false;
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 246ae0b..1f76e39 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -326,6 +326,7 @@
          *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
          "#version 400\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
          "    mediump float x = 0.75;\n"
@@ -578,6 +579,7 @@
          *SkSL::ShaderCapsFactory::ShaderDerivativeExtensionString(),
          "#version 400\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
          "    sk_FragColor.x = 1.0;\n"
@@ -588,6 +590,7 @@
          "#version 400\n"
          "#extension GL_OES_standard_derivatives : require\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
          "    sk_FragColor.x = dFdx(1.0);\n"
@@ -1857,6 +1860,7 @@
          *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
          "#version 400\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "highp float f = 1.0;\n"
          "mediump float h = 2.0;\n"
@@ -1970,6 +1974,7 @@
          *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
          "#version 400\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
          "    mediump float x = sqrt(1.0);\n"
@@ -1986,6 +1991,7 @@
          settings,
          "#version 400\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "void main() {\n"
          "    highp float x = sqrt(1.0);\n"
@@ -2095,6 +2101,7 @@
          *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
          "#version 400\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "uniform sampler2D tex;\n"
          "in highp vec2 texcoord;\n"
@@ -2115,6 +2122,7 @@
          *SkSL::ShaderCapsFactory::IncompleteShortIntPrecision(),
          "#version 310es\n"
          "precision mediump float;\n"
+         "precision mediump sampler2D;\n"
          "out mediump vec4 sk_FragColor;\n"
          "uniform sampler2D tex;\n"
          "in highp vec2 texcoord;\n"