Remove support for image load/store

This isn't used and has become a maintenance burden.

Change-Id: I5f3af8f91e5c4f073fe4ea30e0a7f1f61efeea47
Reviewed-on: https://skia-review.googlesource.com/70640
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/gn/tests.gni b/gn/tests.gni
index 3f8283d..02cc45f 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -113,7 +113,6 @@
   "$_tests/ImageGeneratorTest.cpp",
   "$_tests/ImageIsOpaqueTest.cpp",
   "$_tests/ImageNewShaderTest.cpp",
-  "$_tests/ImageStorageTest.cpp",
   "$_tests/ImageTest.cpp",
   "$_tests/IndexedPngOverflowTest.cpp",
   "$_tests/InfRectTest.cpp",
diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h
index 0b4c2e7..4da73c9 100644
--- a/include/gpu/GrCaps.h
+++ b/include/gpu/GrCaps.h
@@ -147,7 +147,6 @@
     virtual bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const = 0;
     // Returns whether a texture of the given config can be copied to a texture of the same config.
     virtual bool isConfigCopyable(GrPixelConfig config) const = 0;
-    virtual bool canConfigBeImageStorage(GrPixelConfig config) const = 0;
 
     bool suppressPrints() const { return fSuppressPrints; }
 
diff --git a/include/gpu/GrShaderCaps.h b/include/gpu/GrShaderCaps.h
index 9779a4a..5ecd58c 100644
--- a/include/gpu/GrShaderCaps.h
+++ b/include/gpu/GrShaderCaps.h
@@ -244,14 +244,6 @@
 
     int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
 
-    int maxVertexImageStorages() const { return fMaxVertexImageStorages; }
-
-    int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; }
-
-    int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; }
-
-    int maxCombinedImageStorages() const { return fMaxCombinedImageStorages; }
-
     bool disableImageMultitexturingSupport() const { return fDisableImageMultitexturing; }
 
     /**
@@ -342,11 +334,6 @@
     int fMaxFragmentSamplers;
     int fMaxCombinedSamplers;
 
-    int fMaxVertexImageStorages;
-    int fMaxGeometryImageStorages;
-    int fMaxFragmentImageStorages;
-    int fMaxCombinedImageStorages;
-
     AdvBlendEqInteraction fAdvBlendEqInteraction;
 
     GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
diff --git a/include/private/GrTextureProxy.h b/include/private/GrTextureProxy.h
index a761dca..cc1148a 100644
--- a/include/private/GrTextureProxy.h
+++ b/include/private/GrTextureProxy.h
@@ -29,14 +29,6 @@
 
     GrSamplerState::Filter highestFilterMode() const;
 
-    GrSLType imageStorageType() const {
-        if (GrPixelConfigIsSint(this->config())) {
-            return kIImageStorage2D_GrSLType;
-        } else {
-            return kImageStorage2D_GrSLType;
-        }
-    }
-
     GrMipMapped mipMapped() const { return fMipMapped; }
 
     /**
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 9f379f6..75ca0ac 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -140,8 +140,6 @@
     kBufferSampler_GrSLType,
     kTexture2D_GrSLType,
     kSampler_GrSLType,
-    kImageStorage2D_GrSLType,
-    kIImageStorage2D_GrSLType,
 };
 
 enum GrShaderType {
@@ -225,8 +223,6 @@
         case kUint2_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
             return false;
     }
     SK_ABORT("Unexpected type");
@@ -274,8 +270,6 @@
         case kUShort4_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
             return false;
     }
     SK_ABORT("Unexpected type");
@@ -323,57 +317,6 @@
         case kUShort4_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
-            return false;
-    }
-    SK_ABORT("Unexpected type");
-    return false;
-}
-
-static inline bool GrSLTypeIsImageStorage(GrSLType type) {
-    switch (type) {
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
-            return true;
-
-        case kVoid_GrSLType:
-        case kFloat_GrSLType:
-        case kFloat2_GrSLType:
-        case kFloat3_GrSLType:
-        case kFloat4_GrSLType:
-        case kFloat2x2_GrSLType:
-        case kFloat3x3_GrSLType:
-        case kFloat4x4_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 kShort2_GrSLType:
-        case kShort3_GrSLType:
-        case kShort4_GrSLType:
-        case kUShort_GrSLType:
-        case kUShort2_GrSLType:
-        case kUShort3_GrSLType:
-        case kUShort4_GrSLType:
-        case kTexture2D_GrSLType:
-        case kSampler_GrSLType:
-        case kTexture2DSampler_GrSLType:
-        case kITexture2DSampler_GrSLType:
-        case kTextureExternalSampler_GrSLType:
-        case kTexture2DRectSampler_GrSLType:
-        case kBufferSampler_GrSLType:
             return false;
     }
     SK_ABORT("Unexpected type");
@@ -389,8 +332,6 @@
         case kBufferSampler_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
             return true;
 
         case kVoid_GrSLType:
@@ -462,8 +403,6 @@
         case kBufferSampler_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
             return true;
 
         case kVoid_GrSLType:
@@ -605,40 +544,6 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-enum class GrImageStorageFormat {
-    kRGBA8,
-    kRGBA8i,
-    kRGBA16f,
-    kRGBA32f,
-};
-
-/**
- * Describes types of caching and compiler optimizations allowed for certain variable types
- * (currently only image storages).
- **/
-enum class GrSLMemoryModel {
-    /** No special restrctions on memory accesses or compiler optimizations */
-    kNone,
-    /** Cache coherent across shader invocations */
-    kCoherent,
-    /**
-     * Disallows compiler from eliding loads or stores that appear redundant in a single
-     * invocation. Implies coherent.
-     */
-    kVolatile
-};
-
-/**
- * If kYes then the memory backing the varialble is only accessed via the variable. This is
- * currently only used with image storages.
- */
-enum class GrSLRestrict {
-    kYes,
-    kNo,
-};
-
-//////////////////////////////////////////////////////////////////////////////
-
 static const int kGrClipEdgeTypeCnt = (int) GrClipEdgeType::kLast + 1;
 
 static inline bool GrProcessorEdgeTypeIsFill(const GrClipEdgeType edgeType) {
diff --git a/infra/bots/recipes/test.expected/Test-Ubuntu16-Clang-NUCDE3815TYKHE-GPU-IntelBayTrail-x86_64-Debug-All.json b/infra/bots/recipes/test.expected/Test-Ubuntu16-Clang-NUCDE3815TYKHE-GPU-IntelBayTrail-x86_64-Debug-All.json
index db2b7bd..0731896 100644
--- a/infra/bots/recipes/test.expected/Test-Ubuntu16-Clang-NUCDE3815TYKHE-GPU-IntelBayTrail-x86_64-Debug-All.json
+++ b/infra/bots/recipes/test.expected/Test-Ubuntu16-Clang-NUCDE3815TYKHE-GPU-IntelBayTrail-x86_64-Debug-All.json
@@ -376,8 +376,6 @@
       "image",
       "_",
       ".SRW",
-      "--match",
-      "~ImageStorageLoad",
       "--nonativeFonts",
       "--verbose"
     ],
diff --git a/infra/bots/recipes/test.py b/infra/bots/recipes/test.py
index e52e85a..055db23 100644
--- a/infra/bots/recipes/test.py
+++ b/infra/bots/recipes/test.py
@@ -687,9 +687,6 @@
     # skia:6857
     blacklist(['angle_d3d9_es2', 'gm', '_', 'lighting'])
 
-  if 'IntelBayTrail' in bot and api.vars.is_linux:
-    match.append('~ImageStorageLoad') # skia:6358
-
   if 'PowerVRGX6250' in bot:
     match.append('~gradients_view_perspective_nodither') #skia:6972
 
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 89a3171..4294c9f 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -133,10 +133,6 @@
     fBufferAccesses.push_back(access);
 }
 
-void GrResourceIOProcessor::addImageStorageAccess(const ImageStorageAccess* access) {
-    fImageStorageAccesses.push_back(access);
-}
-
 void GrResourceIOProcessor::addPendingIOs() const {
     for (const auto& sampler : fTextureSamplers) {
         sampler->programProxy()->markPendingIO();
@@ -144,9 +140,6 @@
     for (const auto& buffer : fBufferAccesses) {
         buffer->programBuffer()->markPendingIO();
     }
-    for (const auto& imageStorage : fImageStorageAccesses) {
-        imageStorage->programProxy()->markPendingIO();
-    }
 }
 
 void GrResourceIOProcessor::removeRefs() const {
@@ -156,9 +149,6 @@
     for (const auto& buffer : fBufferAccesses) {
         buffer->programBuffer()->removeRef();
     }
-    for (const auto& imageStorage : fImageStorageAccesses) {
-        imageStorage->programProxy()->removeRef();
-    }
 }
 
 void GrResourceIOProcessor::pendingIOComplete() const {
@@ -168,9 +158,6 @@
     for (const auto& buffer : fBufferAccesses) {
         buffer->programBuffer()->pendingIOComplete();
     }
-    for (const auto& imageStorage : fImageStorageAccesses) {
-        imageStorage->programProxy()->pendingIOComplete();
-    }
 }
 
 bool GrResourceIOProcessor::instantiate(GrResourceProvider* resourceProvider) const {
@@ -182,19 +169,12 @@
 
     // MDB TODO: instantiate 'fBufferAccesses' here as well
 
-    for (const auto& imageStorage : fImageStorageAccesses) {
-        if (!imageStorage->instantiate(resourceProvider)) {
-            return false;
-        }
-    }
-
     return true;
 }
 
 bool GrResourceIOProcessor::hasSameSamplersAndAccesses(const GrResourceIOProcessor& that) const {
     if (this->numTextureSamplers() != that.numTextureSamplers() ||
-        this->numBuffers() != that.numBuffers() ||
-        this->numImageStorages() != that.numImageStorages()) {
+        this->numBuffers() != that.numBuffers()) {
         return false;
     }
     for (int i = 0; i < this->numTextureSamplers(); ++i) {
@@ -207,11 +187,6 @@
             return false;
         }
     }
-    for (int i = 0; i < this->numImageStorages(); ++i) {
-        if (this->imageStorageAccess(i) != that.imageStorageAccess(i)) {
-            return false;
-        }
-    }
     return true;
 }
 
@@ -249,37 +224,3 @@
     fSamplerState = GrSamplerState(wrapXAndY, filterMode);
     fVisibility = visibility;
 }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-GrResourceIOProcessor::ImageStorageAccess::ImageStorageAccess(sk_sp<GrTextureProxy> proxy,
-                                                              GrIOType ioType,
-                                                              GrSLMemoryModel memoryModel,
-                                                              GrSLRestrict restrict,
-                                                              GrShaderFlags visibility)
-        : fProxyRef(std::move(proxy), ioType) {
-    SkASSERT(fProxyRef.get());
-
-    fMemoryModel = memoryModel;
-    fRestrict = restrict;
-    fVisibility = visibility;
-    // We currently infer this from the config. However, we could allow the client to specify
-    // a format that is different but compatible with the config.
-    switch (fProxyRef.get()->config()) {
-        case kRGBA_8888_GrPixelConfig:
-            fFormat = GrImageStorageFormat::kRGBA8;
-            break;
-        case kRGBA_8888_sint_GrPixelConfig:
-            fFormat = GrImageStorageFormat::kRGBA8i;
-            break;
-        case kRGBA_half_GrPixelConfig:
-            fFormat = GrImageStorageFormat::kRGBA16f;
-            break;
-        case kRGBA_float_GrPixelConfig:
-            fFormat = GrImageStorageFormat::kRGBA32f;
-            break;
-        default:
-            SK_ABORT("Config is not (yet) supported as image storage.");
-            break;
-    }
-}
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index cd11ac4..cafc713 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -227,7 +227,6 @@
 public:
     class TextureSampler;
     class BufferAccess;
-    class ImageStorageAccess;
 
     int numTextureSamplers() const { return fTextureSamplers.count(); }
 
@@ -241,14 +240,6 @@
         numBuffers(). */
     const BufferAccess& bufferAccess(int index) const { return *fBufferAccesses[index]; }
 
-    int numImageStorages() const { return fImageStorageAccesses.count(); }
-
-    /** Returns the access object for the image at index. index must be valid according to
-        numImages(). */
-    const ImageStorageAccess& imageStorageAccess(int index) const {
-        return *fImageStorageAccesses[index];
-    }
-
     bool instantiate(GrResourceProvider* resourceProvider) const;
 
 protected:
@@ -256,14 +247,13 @@
     : INHERITED(classID) {}
 
     /**
-     * Subclasses call these from their constructor to register sampler/image sources. The processor
+     * Subclasses call these from their constructor to register sampler sources. The processor
      * subclass manages the lifetime of the objects (these functions only store pointers). The
      * TextureSampler and/or BufferAccess instances are typically member fields of the GrProcessor
      * subclass. These must only be called from the constructor because GrProcessors are immutable.
      */
     void addTextureSampler(const TextureSampler*);
     void addBufferAccess(const BufferAccess*);
-    void addImageStorageAccess(const ImageStorageAccess*);
 
     bool hasSameSamplersAndAccesses(const GrResourceIOProcessor&) const;
 
@@ -275,7 +265,6 @@
 private:
     SkSTArray<4, const TextureSampler*, true> fTextureSamplers;
     SkSTArray<1, const BufferAccess*, true> fBufferAccesses;
-    SkSTArray<1, const ImageStorageAccess*, true> fImageStorageAccesses;
 
     typedef GrProcessor INHERITED;
 };
@@ -408,65 +397,4 @@
     typedef SkNoncopyable INHERITED;
 };
 
-/**
- * This is used by a GrProcessor to access a texture using image load/store in its shader code.
- * ImageStorageAccesses don't perform any coord manipulation to account for texture origin.
- * Currently the format of the load/store data in the shader is inferred from the texture config,
- * though it could be made explicit.
- */
-class GrResourceIOProcessor::ImageStorageAccess {
-public:
-    ImageStorageAccess(sk_sp<GrTextureProxy>, GrIOType, GrSLMemoryModel, GrSLRestrict,
-                       GrShaderFlags visibility = kFragment_GrShaderFlag);
-    /**
-     * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy
-     * always takes a new ref on the surface proxy as the new fragment processor will not yet be
-     * in pending execution state.
-     */
-    explicit ImageStorageAccess(const ImageStorageAccess& that)
-            : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType())
-            , fVisibility(that.fVisibility)
-            , fFormat(that.fFormat)
-            , fMemoryModel(that.fMemoryModel)
-            , fRestrict(that.fRestrict) {}
-
-    ImageStorageAccess& operator=(const ImageStorageAccess&) = delete;
-
-    bool operator==(const ImageStorageAccess& that) const {
-        return this->proxy() == that.proxy() && fVisibility == that.fVisibility;
-    }
-
-    bool operator!=(const ImageStorageAccess& that) const { return !(*this == that); }
-
-    GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); }
-    GrShaderFlags visibility() const { return fVisibility; }
-    GrIOType ioType() const { return fProxyRef.ioType(); }
-    GrImageStorageFormat format() const { return fFormat; }
-    GrSLMemoryModel memoryModel() const { return fMemoryModel; }
-    GrSLRestrict restrict() const { return fRestrict; }
-
-    // 'instantiate' should only ever be called at flush time.
-    bool instantiate(GrResourceProvider* resourceProvider) const {
-        return SkToBool(fProxyRef.get()->instantiate(resourceProvider));
-    }
-    // 'peekTexture' should only ever be called after a successful 'instantiate' call
-    GrTexture* peekTexture() const {
-        SkASSERT(fProxyRef.get()->priv().peekTexture());
-        return fProxyRef.get()->priv().peekTexture();
-    }
-
-    /**
-     * For internal use by GrProcessor.
-     */
-    const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; }
-
-private:
-    GrSurfaceProxyRef    fProxyRef;
-    GrShaderFlags        fVisibility;
-    GrImageStorageFormat fFormat;
-    GrSLMemoryModel      fMemoryModel;
-    GrSLRestrict         fRestrict;
-    typedef SkNoncopyable INHERITED;
-};
-
 #endif
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index f40c6b6..a32e0cc 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -37,12 +37,6 @@
         case kBufferSampler_GrSLType:
             value = 4;
             break;
-        case kImageStorage2D_GrSLType:
-            value = 5;
-            break;
-        case kIImageStorage2D_GrSLType:
-            value = 6;
-            break;
 
         default:
             break;
@@ -61,18 +55,11 @@
                    (caps.samplerPrecision(config, visibility) << (8 + kSamplerOrImageTypeKeyBits)));
 }
 
-static uint16_t storage_image_key(const GrResourceIOProcessor::ImageStorageAccess& imageAccess) {
-    GrSLType type = imageAccess.proxy()->imageStorageType();
-    return image_storage_or_sampler_uniform_type_key(type) |
-           (int)imageAccess.format() << kSamplerOrImageTypeKeyBits;
-}
-
 static void add_sampler_and_image_keys(GrProcessorKeyBuilder* b, const GrResourceIOProcessor& proc,
                                        const GrShaderCaps& caps) {
     int numTextureSamplers = proc.numTextureSamplers();
     int numBuffers = proc.numBuffers();
-    int numImageStorages = proc.numImageStorages();
-    int numUniforms = numTextureSamplers + numBuffers + numImageStorages;
+    int numUniforms = numTextureSamplers + numBuffers;
     // Need two bytes per key.
     int word32Count = (numUniforms + 1) / 2;
     if (0 == word32Count) {
@@ -92,9 +79,6 @@
         k16[j] = sampler_key(kBufferSampler_GrSLType, access.texelConfig(), access.visibility(),
                              caps);
     }
-    for (int i = 0; i < numImageStorages; ++i, ++j) {
-        k16[j] = storage_image_key(proc.imageStorageAccess(i));
-    }
     // zero the last 16 bits if the number of uniforms for samplers and image storages is odd.
     if (numUniforms & 0x1) {
         k16[numUniforms] = 0;
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index 0a612db..d4f4475 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -91,10 +91,6 @@
     fMaxGeometrySamplers = 0;
     fMaxFragmentSamplers = 0;
     fMaxCombinedSamplers = 0;
-    fMaxVertexImageStorages = 0;
-    fMaxGeometryImageStorages = 0;
-    fMaxFragmentImageStorages = 0;
-    fMaxCombinedImageStorages   = 0;
     fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
 
 #if GR_TEST_UTILS
@@ -175,10 +171,6 @@
     writer->appendS32("Max GS Samplers", fMaxGeometrySamplers);
     writer->appendS32("Max FS Samplers", fMaxFragmentSamplers);
     writer->appendS32("Max Combined Samplers", fMaxFragmentSamplers);
-    writer->appendS32("Max VS Image Storages", fMaxVertexImageStorages);
-    writer->appendS32("Max GS Image Storages", fMaxGeometryImageStorages);
-    writer->appendS32("Max FS Image Storages", fMaxFragmentImageStorages);
-    writer->appendS32("Max Combined Image Storages", fMaxFragmentImageStorages);
     writer->appendString("Advanced blend equation interaction",
                          kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]);
     writer->appendBool("Disable image multitexturing", fDisableImageMultitexturing);
diff --git a/src/gpu/GrShaderVar.cpp b/src/gpu/GrShaderVar.cpp
index fcc05c0..4d6c658 100644
--- a/src/gpu/GrShaderVar.cpp
+++ b/src/gpu/GrShaderVar.cpp
@@ -21,51 +21,6 @@
     return "";
 }
 
-void GrShaderVar::setImageStorageFormat(GrImageStorageFormat format) {
-    const char* formatStr = nullptr;
-    switch (format) {
-        case GrImageStorageFormat::kRGBA8:
-            formatStr = "rgba8";
-            break;
-        case GrImageStorageFormat::kRGBA8i:
-            formatStr = "rgba8i";
-            break;
-        case GrImageStorageFormat::kRGBA16f:
-            formatStr = "rgba16f";
-            break;
-        case GrImageStorageFormat::kRGBA32f:
-            formatStr = "rgba32f";
-            break;
-    }
-    this->addLayoutQualifier(formatStr);
-    SkASSERT(formatStr);
-}
-
-void GrShaderVar::setMemoryModel(GrSLMemoryModel model) {
-    switch (model) {
-        case GrSLMemoryModel::kNone:
-            return;
-        case GrSLMemoryModel::kCoherent:
-            this->addModifier("coherent");
-            return;
-        case GrSLMemoryModel::kVolatile:
-            this->addModifier("volatile");
-            return;
-    }
-    SK_ABORT("Unknown memory model.");
-}
-
-void GrShaderVar::setRestrict(GrSLRestrict restrict) {
-    switch (restrict) {
-        case GrSLRestrict::kNo:
-            return;
-        case GrSLRestrict::kYes:
-            this->addModifier("restrict");
-            return;
-    }
-    SK_ABORT("Unknown restrict.");
-}
-
 void GrShaderVar::setIOType(GrIOType ioType) {
     switch (ioType) {
         case kRW_GrIOType:
diff --git a/src/gpu/GrShaderVar.h b/src/gpu/GrShaderVar.h
index 29e056c..0f22085 100644
--- a/src/gpu/GrShaderVar.h
+++ b/src/gpu/GrShaderVar.h
@@ -283,12 +283,6 @@
         }
     }
 
-    void setImageStorageFormat(GrImageStorageFormat format);
-
-    void setMemoryModel(GrSLMemoryModel);
-
-    void setRestrict(GrSLRestrict);
-
     void setIOType(GrIOType);
 
     void addModifier(const char* modifier) {
diff --git a/src/gpu/GrTexturePriv.h b/src/gpu/GrTexturePriv.h
index fc474ed..ad69d31 100644
--- a/src/gpu/GrTexturePriv.h
+++ b/src/gpu/GrTexturePriv.h
@@ -44,14 +44,6 @@
         return fTexture->fMaxMipMapLevel;
     }
 
-    GrSLType imageStorageType() const {
-        if (GrPixelConfigIsSint(fTexture->config())) {
-            return kIImageStorage2D_GrSLType;
-        } else {
-            return kImageStorage2D_GrSLType;
-        }
-    }
-
     GrSLType samplerType() const { return fTexture->fSamplerType; }
 
     /** The filter used is clamped to this value in GrProcessor::TextureSampler. */
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index f245d0f..14ede4f 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -358,42 +358,6 @@
     GR_GL_GetIntegerv(gli, GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxSamplers);
     shaderCaps->fMaxCombinedSamplers = SkTMin<GrGLint>(kMaxSaneSamplers, maxSamplers);
 
-    if (kGL_GrGLStandard == standard) {
-        shaderCaps->fImageLoadStoreSupport = ctxInfo.version() >= GR_GL_VER(4, 2);
-        if (!shaderCaps->fImageLoadStoreSupport &&
-            ctxInfo.hasExtension("GL_ARB_shader_image_load_store")) {
-            shaderCaps->fImageLoadStoreSupport = true;
-            shaderCaps->fImageLoadStoreExtensionString = "GL_ARB_shader_image_load_store";
-        }
-    } else {
-        shaderCaps->fImageLoadStoreSupport = ctxInfo.version() >= GR_GL_VER(3, 1);
-    }
-    if (shaderCaps->fImageLoadStoreSupport) {
-        // Protect ourselves against tracking huge amounts of image state.
-        static constexpr int kMaxSaneImages = 4;
-        GrGLint maxUnits;
-        GR_GL_GetIntegerv(gli, GR_GL_MAX_IMAGE_UNITS, &maxUnits);
-        GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_IMAGE_UNIFORMS,
-                          &shaderCaps->fMaxVertexImageStorages);
-        if (shaderCaps->fGeometryShaderSupport) {
-            GR_GL_GetIntegerv(gli, GR_GL_MAX_GEOMETRY_IMAGE_UNIFORMS,
-                              &shaderCaps->fMaxGeometryImageStorages);
-        }
-        GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
-                          &shaderCaps->fMaxFragmentImageStorages);
-        GR_GL_GetIntegerv(gli, GR_GL_MAX_COMBINED_IMAGE_UNIFORMS,
-                          &shaderCaps->fMaxCombinedImageStorages);
-        // We use one unit for every image uniform
-        shaderCaps->fMaxCombinedImageStorages = SkTMin(SkTMin(shaderCaps->fMaxCombinedImageStorages,
-                                                              maxUnits), kMaxSaneImages);
-        shaderCaps->fMaxVertexImageStorages = SkTMin(maxUnits,
-                                                     shaderCaps->fMaxVertexImageStorages);
-        shaderCaps->fMaxGeometryImageStorages = SkTMin(maxUnits,
-                                                       shaderCaps->fMaxGeometryImageStorages);
-        shaderCaps->fMaxFragmentImageStorages =  SkTMin(maxUnits,
-                                                        shaderCaps->fMaxFragmentImageStorages);
-    }
-
     // SGX and Mali GPUs that are based on a tiled-deferred architecture that have trouble with
     // frequently changing VBOs. We've measured a performance increase using non-VBO vertex
     // data for dynamic content on these GPUs. Perhaps we should read the renderer string and
@@ -2243,24 +2207,6 @@
         }
     }
 
-    // We currently only support images on rgba textures formats. We could add additional formats
-    // if desired. The shader builder would have to be updated to add swizzles where appropriate
-    // (e.g. where we use GL_RED textures to implement alpha configs).
-    if (this->shaderCaps()->imageLoadStoreSupport()) {
-        fConfigTable[kRGBA_8888_sint_GrPixelConfig].fFlags |=
-                ConfigInfo::kCanUseAsImageStorage_Flag;
-        // In OpenGL ES a texture may only be used with BindImageTexture if it has been made
-        // immutable via TexStorage. We create non-integer textures as mutable textures using
-        // TexImage because we may lazily add MIP levels. Thus, on ES we currently disable image
-        // storage support for non-integer textures.
-        if (kGL_GrGLStandard == ctxInfo.standard()) {
-            fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseAsImageStorage_Flag;
-            fConfigTable[kRGBA_float_GrPixelConfig].fFlags |=
-                    ConfigInfo::kCanUseAsImageStorage_Flag;
-            fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseAsImageStorage_Flag;
-        }
-    }
-
     for (int i = 0; i < kGrPixelConfigCnt; ++i) {
         if (ConfigInfo::kRenderableWithMSAA_Flag & fConfigTable[i].fFlags) {
             if ((kGL_GrGLStandard == ctxInfo.standard() &&
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 2c82c4c..923b3f4 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -134,9 +134,6 @@
         return this->isConfigRenderable(config, false);
     }
 
-    bool canConfigBeImageStorage(GrPixelConfig config) const override {
-        return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseAsImageStorage_Flag);
-    }
     bool canConfigBeFBOColorAttachment(GrPixelConfig config) const {
         return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kFBOColorAttachment_Flag);
     }
@@ -568,7 +565,6 @@
             kFBOColorAttachment_Flag      = 0x10,
             kCanUseTexStorage_Flag        = 0x20,
             kCanUseWithTexelBuffer_Flag   = 0x40,
-            kCanUseAsImageStorage_Flag    = 0x80,
         };
         uint32_t fFlags;
 
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index ad13516..c69b924 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -223,7 +223,6 @@
     fCaps.reset(SkRef(ctx->caps()));
 
     fHWBoundTextureUniqueIDs.reset(this->caps()->shaderCaps()->maxCombinedSamplers());
-    fHWBoundImageStorages.reset(this->caps()->shaderCaps()->maxCombinedImageStorages());
 
     fHWBufferState[kVertex_GrBufferType].fGLTarget = GR_GL_ARRAY_BUFFER;
     fHWBufferState[kIndex_GrBufferType].fGLTarget = GR_GL_ELEMENT_ARRAY_BUFFER;
@@ -451,10 +450,6 @@
             SkASSERT(this->caps()->shaderCaps()->texelBufferSupport());
             fHWBufferTextures[b].fKnownBound = false;
         }
-        for (int i = 0; i < fHWBoundImageStorages.count(); ++i) {
-            SkASSERT(this->caps()->shaderCaps()->imageLoadStoreSupport());
-            fHWBoundImageStorages[i].fTextureUniqueID.makeInvalid();
-        }
     }
 
     if (resetBits & kBlend_GrGLBackendState) {
@@ -3182,27 +3177,6 @@
     }
 }
 
-void GrGLGpu::bindImageStorage(int unitIdx, GrIOType ioType, GrGLTexture *texture) {
-    SkASSERT(texture);
-    if (texture->uniqueID() != fHWBoundImageStorages[unitIdx].fTextureUniqueID ||
-        ioType != fHWBoundImageStorages[unitIdx].fIOType) {
-        GrGLenum access = GR_GL_READ_ONLY;
-        switch (ioType) {
-            case kRead_GrIOType:
-                access = GR_GL_READ_ONLY;
-                break;
-            case kWrite_GrIOType:
-                access = GR_GL_WRITE_ONLY;
-                break;
-            case kRW_GrIOType:
-                access = GR_GL_READ_WRITE;
-                break;
-        }
-        GrGLenum format = this->glCaps().getImageFormat(texture->config());
-        GL_CALL(BindImageTexture(unitIdx, texture->textureID(), 0, GR_GL_FALSE, 0, access, format));
-    }
-}
-
 void GrGLGpu::generateMipmaps(const GrSamplerState& params, bool allowSRGBInputs,
                               GrGLTexture* texture, GrSurfaceOrigin textureOrigin) {
     SkASSERT(texture);
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 227409e..4d8b056 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -64,8 +64,6 @@
 
     void bindTexelBuffer(int unitIdx, GrPixelConfig, GrGLBuffer*);
 
-    void bindImageStorage(int unitIdx, GrIOType, GrGLTexture *);
-
     void generateMipmaps(const GrSamplerState& params, bool allowSRGBInputs, GrGLTexture* texture,
                          GrSurfaceOrigin textureOrigin);
 
@@ -592,12 +590,6 @@
     TriState                                fHWSRGBFramebuffer;
     SkTArray<GrGpuResource::UniqueID, true> fHWBoundTextureUniqueIDs;
 
-    struct Image {
-        GrGpuResource::UniqueID fTextureUniqueID;
-        GrIOType                fIOType;
-    };
-    SkTArray<Image, true>                   fHWBoundImageStorages;
-
     struct BufferTexture {
         BufferTexture() : fTextureID(0), fKnownBound(false),
                           fAttachedBufferUniqueID(SK_InvalidUniqueID),
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 04b2138a..7257638 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -32,7 +32,6 @@
                          const UniformInfoArray& uniforms,
                          const UniformInfoArray& textureSamplers,
                          const UniformInfoArray& texelBuffers,
-                         const UniformInfoArray& imageStorages,
                          const VaryingInfoArray& pathProcVaryings,
                          std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
                          std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
@@ -51,7 +50,6 @@
     GL_CALL(UseProgram(fProgramID));
     fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
     fProgramDataManager.setSamplerUniforms(texelBuffers, fNumTextureSamplers);
-    fProgramDataManager.setImageStorages(imageStorages);
 }
 
 GrGLProgram::~GrGLProgram() {
@@ -77,18 +75,15 @@
 
     // We must bind to texture units in the same order in which we set the uniforms in
     // GrGLProgramDataManager. That is first all texture samplers and then texel buffers.
-    // ImageStorages are bound to their own image units so they are tracked separately.
     // Within each group we will bind them in primProc, fragProcs, XP order.
     int nextTexSamplerIdx = 0;
     int nextTexelBufferIdx = fNumTextureSamplers;
-    int nextImageStorageIdx = 0;
     fGeometryProcessor->setData(fProgramDataManager, primProc,
                                 GrFragmentProcessor::CoordTransformIter(pipeline));
     this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextTexSamplerIdx,
-                       &nextTexelBufferIdx, &nextImageStorageIdx);
+                       &nextTexelBufferIdx);
 
-    this->setFragmentData(primProc, pipeline, &nextTexSamplerIdx, &nextTexelBufferIdx,
-                          &nextImageStorageIdx);
+    this->setFragmentData(primProc, pipeline, &nextTexSamplerIdx, &nextTexelBufferIdx);
 
     const GrXferProcessor& xp = pipeline.getXferProcessor();
     SkIPoint offset;
@@ -117,8 +112,7 @@
 void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
                                   const GrPipeline& pipeline,
                                   int* nextTexSamplerIdx,
-                                  int* nextTexelBufferIdx,
-                                  int* nextImageStorageIdx) {
+                                  int* nextTexelBufferIdx) {
     GrFragmentProcessor::Iter iter(pipeline);
     GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(),
                                            fFragmentProcessors.count());
@@ -127,7 +121,7 @@
     while (fp && glslFP) {
         glslFP->setData(fProgramDataManager, *fp);
         this->bindTextures(*fp, pipeline.getAllowSRGBInputs(), nextTexSamplerIdx,
-                           nextTexelBufferIdx, nextImageStorageIdx);
+                           nextTexelBufferIdx);
         fp = iter.next();
         glslFP = glslIter.next();
     }
@@ -168,8 +162,7 @@
 void GrGLProgram::bindTextures(const GrResourceIOProcessor& processor,
                                bool allowSRGBInputs,
                                int* nextTexSamplerIdx,
-                               int* nextTexelBufferIdx,
-                               int* nextImageStorageIdx) {
+                               int* nextTexelBufferIdx) {
     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
         fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(), allowSRGBInputs,
@@ -181,11 +174,6 @@
         fGpu->bindTexelBuffer((*nextTexelBufferIdx)++, access.texelConfig(),
                               static_cast<GrGLBuffer*>(access.buffer()));
     }
-    for (int i = 0; i < processor.numImageStorages(); ++i) {
-        const GrResourceIOProcessor::ImageStorageAccess& access = processor.imageStorageAccess(i);
-        fGpu->bindImageStorage((*nextImageStorageIdx)++, access.ioType(),
-                               static_cast<GrGLTexture *>(access.peekTexture()));
-    }
 }
 
 void GrGLProgram::generateMipmaps(const GrResourceIOProcessor& processor, bool allowSRGBInputs) {
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 96ff10f..781baa4 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -113,7 +113,6 @@
                 const UniformInfoArray& uniforms,
                 const UniformInfoArray& textureSamplers,
                 const UniformInfoArray& texelBuffers,
-                const UniformInfoArray& imageStorages,
                 const VaryingInfoArray&, // used for NVPR only currently
                 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
                 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
@@ -121,14 +120,14 @@
 
     // A helper to loop over effects, set the transforms (via subclass) and bind textures
     void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&, int* nextTexSamplerIdx,
-                         int* nextTexelBufferIdx, int* nextImageStorageIdx);
+                         int* nextTexelBufferIdx);
 
     // Helper for setData() that sets the view matrix and loads the render target height uniform
     void setRenderTargetState(const GrPrimitiveProcessor&, const GrRenderTargetProxy*);
 
     // Helper for setData() that binds textures and texel buffers to the appropriate texture units
     void bindTextures(const GrResourceIOProcessor&, bool allowSRGBInputs, int* nextSamplerIdx,
-                      int* nextTexelBufferIdx, int* nextImageStorageIdx);
+                      int* nextTexelBufferIdx);
 
     // Helper for generateMipmaps() that ensures mipmaps are up to date
     void generateMipmaps(const GrResourceIOProcessor&, bool allowSRGBInputs);
@@ -149,7 +148,6 @@
 
     int fNumTextureSamplers;
     int fNumTexelBuffers;
-    int fNumImageStorages;
 
     friend class GrGLProgramBuilder;
 
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index ab8dee6..689b291 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -61,16 +61,6 @@
     }
 }
 
-void GrGLProgramDataManager::setImageStorages(const UniformInfoArray& images) const {
-    for (int i = 0; i < images.count(); ++i) {
-        const UniformInfo& image = images[i];
-        SkASSERT(image.fVisibility);
-        if (kUnusedUniform != image.fLocation) {
-            GR_GL_CALL(fGpu->glInterface(), Uniform1i(image.fLocation, i));
-        }
-    }
-}
-
 void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
     const Uniform& uni = fUniforms[u.toIndex()];
     SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
diff --git a/src/gpu/gl/GrGLProgramDataManager.h b/src/gpu/gl/GrGLProgramDataManager.h
index 6b4e4d9..f756a2a 100644
--- a/src/gpu/gl/GrGLProgramDataManager.h
+++ b/src/gpu/gl/GrGLProgramDataManager.h
@@ -46,7 +46,6 @@
                            const VaryingInfoArray&);
 
     void setSamplerUniforms(const UniformInfoArray& samplers, int startUnit) const;
-    void setImageStorages(const UniformInfoArray& images) const;
 
     /** Functions for uploading uniform values. The varities ending in v can be used to upload to an
     *  array of uniforms. arrayCount must be <= the array count of the uniform.
diff --git a/src/gpu/gl/GrGLUniformHandler.cpp b/src/gpu/gl/GrGLUniformHandler.cpp
index 914f8bc..b3b4b9f 100644
--- a/src/gpu/gl/GrGLUniformHandler.cpp
+++ b/src/gpu/gl/GrGLUniformHandler.cpp
@@ -96,31 +96,6 @@
     return GrGLSLUniformHandler::TexelBufferHandle(fTexelBuffers.count() - 1);
 }
 
-GrGLSLUniformHandler::ImageStorageHandle GrGLUniformHandler::addImageStorage(
-        uint32_t visibility, GrSLType type, GrImageStorageFormat format, GrSLMemoryModel model,
-        GrSLRestrict restrict, GrIOType ioType, const char* name) {
-    SkASSERT(name && strlen(name));
-    SkASSERT(0 != visibility);
-    SkString mangleName;
-    char prefix = 'u';
-    fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
-
-    UniformInfo& imageStorage = fImageStorages.push_back();
-    imageStorage.fVariable.setName(mangleName);
-
-    SkASSERT(GrSLTypeIsImageStorage(type));
-    imageStorage.fVariable.setType(type);
-    imageStorage.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
-    imageStorage.fVariable.setImageStorageFormat(format);
-    imageStorage.fVariable.setMemoryModel(model);
-    imageStorage.fVariable.setRestrict(restrict);
-    imageStorage.fVariable.setIOType(ioType);
-    imageStorage.fVariable.setPrecision(kHigh_GrSLPrecision);
-    imageStorage.fLocation = -1;
-    imageStorage.fVisibility = visibility;
-    return GrGLSLUniformHandler::ImageStorageHandle(fImageStorages.count() - 1);
-}
-
 void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
     for (int i = 0; i < fUniforms.count(); ++i) {
         if (fUniforms[i].fVisibility & visibility) {
@@ -140,12 +115,6 @@
             out->append(";\n");
         }
     }
-    for (int i = 0; i < fImageStorages.count(); ++i) {
-        if (fImageStorages[i].fVisibility & visibility) {
-            fImageStorages[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
-            out->append(";");
-        }
-    }
 }
 
 void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
@@ -164,11 +133,6 @@
                                         fTexelBuffers[i].fVariable.c_str()));
             fTexelBuffers[i].fLocation = currUniform;
         }
-        for (int i = 0; i < fImageStorages.count(); ++i, ++currUniform) {
-            GL_CALL(BindUniformLocation(programID, currUniform,
-                                        fImageStorages[i].fVariable.c_str()));
-            fImageStorages[i].fLocation = currUniform;
-        }
     }
 }
 
@@ -191,12 +155,6 @@
                                                      fTexelBuffers[i].fVariable.c_str()));
             fTexelBuffers[i].fLocation = location;
         }
-        for (int i = 0; i < fImageStorages.count(); ++i) {
-            GrGLint location;
-            GL_CALL_RET(location, GetUniformLocation(programID,
-                                                     fImageStorages[i].fVariable.c_str()));
-            fImageStorages[i].fLocation = location;
-        }
     }
 }
 
diff --git a/src/gpu/gl/GrGLUniformHandler.h b/src/gpu/gl/GrGLUniformHandler.h
index d029691..74d24bb 100644
--- a/src/gpu/gl/GrGLUniformHandler.h
+++ b/src/gpu/gl/GrGLUniformHandler.h
@@ -30,8 +30,7 @@
         : INHERITED(program)
         , fUniforms(kUniformsPerBlock)
         , fSamplers(kUniformsPerBlock)
-        , fTexelBuffers(kUniformsPerBlock)
-        , fImageStorages(kUniformsPerBlock) {}
+        , fTexelBuffers(kUniformsPerBlock) {}
 
     UniformHandle internalAddUniformArray(uint32_t visibility,
                                           GrSLType type,
@@ -59,14 +58,6 @@
         return fTexelBuffers[handle.toIndex()].fVariable;
     }
 
-    ImageStorageHandle addImageStorage(uint32_t visibility, GrSLType, GrImageStorageFormat,
-                                       GrSLMemoryModel, GrSLRestrict, GrIOType,
-                                       const char* name) override;
-
-    const GrShaderVar& imageStorageVariable(ImageStorageHandle handle) const override {
-        return fImageStorages[handle.toIndex()].fVariable;
-    }
-
     void appendUniformDecls(GrShaderFlags visibility, SkString*) const override;
 
     // Manually set uniform locations for all our uniforms.
@@ -84,7 +75,6 @@
     UniformInfoArray    fSamplers;
     SkTArray<GrSwizzle> fSamplerSwizzles;
     UniformInfoArray    fTexelBuffers;
-    UniformInfoArray    fImageStorages;
 
     friend class GrGLProgramBuilder;
 
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 4bc4202..3867d1b 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -369,7 +369,6 @@
                            fUniformHandler.fUniforms,
                            fUniformHandler.fSamplers,
                            fUniformHandler.fTexelBuffers,
-                           fUniformHandler.fImageStorages,
                            fVaryingHandler.fPathProcVaryingInfos,
                            std::move(fGeometryProcessor),
                            std::move(fXferProcessor),
diff --git a/src/gpu/glsl/GrGLSL.cpp b/src/gpu/glsl/GrGLSL.cpp
index 1c13ecc..07e36db 100644
--- a/src/gpu/glsl/GrGLSL.cpp
+++ b/src/gpu/glsl/GrGLSL.cpp
@@ -109,10 +109,6 @@
             return "texture2D";
         case kSampler_GrSLType:
             return "sampler";
-        case kImageStorage2D_GrSLType:
-            return "image2D";
-        case kIImageStorage2D_GrSLType:
-            return "iimage2D";
     }
     SK_ABORT("Unknown shader var type.");
     return ""; // suppress warning
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index ac2de13..8f92002 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -49,7 +49,6 @@
     TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
     TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
     TexelBuffers texelBuffers = args.fTexelBuffers.childInputs(childIndex);
-    ImageStorages imageStorages = args.fImageStorages.childInputs(childIndex);
     EmitArgs childArgs(fragBuilder,
                        args.fUniformHandler,
                        args.fShaderCaps,
@@ -58,8 +57,7 @@
                        inputColor,
                        coordVars,
                        textureSamplers,
-                       texelBuffers,
-                       imageStorages);
+                       texelBuffers);
     this->childProcessor(childIndex)->emitCode(childArgs);
     fragBuilder->codeAppend("}\n");
 
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h
index 68bd1f2..74cfc4e 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h
@@ -31,7 +31,6 @@
     using UniformHandle      = GrGLSLUniformHandler::UniformHandle;
     using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle;
     using TexelBufferHandle  = GrGLSLUniformHandler::TexelBufferHandle;
-    using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
 
 private:
     /**
@@ -75,8 +74,6 @@
                                                  &GrResourceIOProcessor::numTextureSamplers>;
     using TexelBuffers = BuilderInputProvider<TexelBufferHandle, GrResourceIOProcessor,
                                                 &GrResourceIOProcessor::numBuffers>;
-    using ImageStorages = BuilderInputProvider<ImageStorageHandle, GrResourceIOProcessor,
-                                               &GrResourceIOProcessor::numImageStorages>;
 
     /** Called when the program stage should insert its code into the shaders. The code in each
         shader will be in its own block ({}) and so locally scoped names will not collide across
@@ -102,9 +99,6 @@
         @param bufferSamplers    Contains one entry for each BufferAccess of the GrProcessor. These
                                  can be passed to the builder to emit buffer reads in the generated
                                  code.
-        @param imageStorages     Contains one entry for each ImageStorageAccess of the GrProcessor.
-                                 These can be passed to the builder to emit image loads and stores
-                                 in the generated code.
      */
     struct EmitArgs {
         EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
@@ -115,8 +109,7 @@
                  const char* inputColor,
                  const TransformedCoordVars& transformedCoordVars,
                  const TextureSamplers& textureSamplers,
-                 const TexelBuffers& texelBuffers,
-                 const ImageStorages& imageStorages)
+                 const TexelBuffers& texelBuffers)
                 : fFragBuilder(fragBuilder)
                 , fUniformHandler(uniformHandler)
                 , fShaderCaps(caps)
@@ -125,8 +118,7 @@
                 , fInputColor(inputColor)
                 , fTransformedCoords(transformedCoordVars)
                 , fTexSamplers(textureSamplers)
-                , fTexelBuffers(texelBuffers)
-                , fImageStorages(imageStorages) {}
+                , fTexelBuffers(texelBuffers) {}
         GrGLSLFPFragmentBuilder* fFragBuilder;
         GrGLSLUniformHandler* fUniformHandler;
         const GrShaderCaps* fShaderCaps;
@@ -136,7 +128,6 @@
         const TransformedCoordVars& fTransformedCoords;
         const TextureSamplers& fTexSamplers;
         const TexelBuffers& fTexelBuffers;
-        const ImageStorages& fImageStorages;
     };
 
     virtual void emitCode(EmitArgs&) = 0;
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
index c4f3115..30ca143 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
@@ -30,7 +30,6 @@
     using UniformHandle      = GrGLSLProgramDataManager::UniformHandle;
     using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle;
     using TexelBufferHandle  = GrGLSLUniformHandler::TexelBufferHandle;
-    using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
 
     /**
      * This class provides access to the GrCoordTransforms across all GrFragmentProcessors in a
@@ -78,7 +77,6 @@
                  const char* rtAdjustName,
                  const SamplerHandle* texSamplers,
                  const TexelBufferHandle* texelBuffers,
-                 const ImageStorageHandle* imageStorages,
                  FPCoordTransformHandler* transformHandler)
             : fVertBuilder(vertBuilder)
             , fGeomBuilder(geomBuilder)
@@ -92,7 +90,6 @@
             , fRTAdjustName(rtAdjustName)
             , fTexSamplers(texSamplers)
             , fTexelBuffers(texelBuffers)
-            , fImageStorages(imageStorages)
             , fFPCoordTransformHandler(transformHandler) {}
         GrGLSLVertexBuilder* fVertBuilder;
         GrGLSLGeometryBuilder* fGeomBuilder;
@@ -106,7 +103,6 @@
         const char* fRTAdjustName;
         const SamplerHandle* fTexSamplers;
         const TexelBufferHandle* fTexelBuffers;
-        const ImageStorageHandle* fImageStorages;
         FPCoordTransformHandler* fFPCoordTransformHandler;
     };
 
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 07d6d20..6f8d1be 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -32,10 +32,7 @@
     , fXferProcessor(nullptr)
     , fNumVertexSamplers(0)
     , fNumGeometrySamplers(0)
-    , fNumFragmentSamplers(0)
-    , fNumVertexImageStorages(0)
-    , fNumGeometryImageStorages(0)
-    , fNumFragmentImageStorages(0) {
+    , fNumFragmentSamplers(0) {
 }
 
 void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
@@ -65,7 +62,7 @@
     this->emitAndInstallXferProc(inputColor, inputCoverage);
     this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
 
-    return this->checkSamplerCounts() && this->checkImageStorageCounts();
+    return this->checkSamplerCounts();
 }
 
 void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc,
@@ -98,8 +95,7 @@
 
     SkSTArray<4, SamplerHandle>      texSamplers(proc.numTextureSamplers());
     SkSTArray<2, TexelBufferHandle>  texelBuffers(proc.numBuffers());
-    SkSTArray<2, ImageStorageHandle> imageStorages(proc.numImageStorages());
-    this->emitSamplersAndImageStorages(proc, &texSamplers, &texelBuffers, &imageStorages);
+    this->emitSamplers(proc, &texSamplers, &texelBuffers);
 
     GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
                                                                        &fTransformedCoordVars);
@@ -115,7 +111,6 @@
                                            rtAdjustName,
                                            texSamplers.begin(),
                                            texelBuffers.begin(),
-                                           imageStorages.begin(),
                                            &transformHandler);
     fGeometryProcessor->emitCode(args);
 
@@ -165,18 +160,15 @@
 
     SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers());
     SkSTArray<2, TexelBufferHandle> texelBufferArray(fp.numBuffers());
-    SkSTArray<2, ImageStorageHandle> imageStorageArray(fp.numImageStorages());
     GrFragmentProcessor::Iter iter(&fp);
     while (const GrFragmentProcessor* subFP = iter.next()) {
-        this->emitSamplersAndImageStorages(*subFP, &textureSamplerArray, &texelBufferArray,
-                                           &imageStorageArray);
+        this->emitSamplers(*subFP, &textureSamplerArray, &texelBufferArray);
     }
 
     const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
     GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
     GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin());
     GrGLSLFragmentProcessor::TexelBuffers texelBuffers(&fp, texelBufferArray.begin());
-    GrGLSLFragmentProcessor::ImageStorages imageStorages(&fp, imageStorageArray.begin());
     GrGLSLFragmentProcessor::EmitArgs args(&fFS,
                                            this->uniformHandler(),
                                            this->shaderCaps(),
@@ -185,8 +177,7 @@
                                            input.c_str(),
                                            coords,
                                            textureSamplers,
-                                           texelBuffers,
-                                           imageStorages);
+                                           texelBuffers);
 
     fragProc->emitCode(args);
 
@@ -252,11 +243,10 @@
     fFS.codeAppend("}");
 }
 
-void GrGLSLProgramBuilder::emitSamplersAndImageStorages(
+void GrGLSLProgramBuilder::emitSamplers(
         const GrResourceIOProcessor& processor,
         SkTArray<SamplerHandle>* outTexSamplerHandles,
-        SkTArray<TexelBufferHandle>* outTexelBufferHandles,
-        SkTArray<ImageStorageHandle>* outImageStorageHandles) {
+        SkTArray<TexelBufferHandle>* outTexelBufferHandles) {
     SkString name;
     int numTextureSamplers = processor.numTextureSamplers();
     for (int t = 0; t < numTextureSamplers; ++t) {
@@ -293,14 +283,6 @@
                              extension);
         }
     }
-    int numImageStorages = processor.numImageStorages();
-    for (int i = 0; i < numImageStorages; ++i) {
-        const GrResourceIOProcessor::ImageStorageAccess& imageStorageAccess =
-                processor.imageStorageAccess(i);
-        name.printf("Image_%d", outImageStorageHandles->count());
-        outImageStorageHandles->emplace_back(
-                this->emitImageStorage(imageStorageAccess, name.c_str()));
-    }
 }
 
 void GrGLSLProgramBuilder::updateSamplerCounts(GrShaderFlags visibility) {
@@ -333,24 +315,6 @@
     return this->uniformHandler()->addTexelBuffer(visibility, precision, name);
 }
 
-GrGLSLProgramBuilder::ImageStorageHandle GrGLSLProgramBuilder::emitImageStorage(
-        const GrResourceIOProcessor::ImageStorageAccess& access, const char* name) {
-    if (access.visibility() & kVertex_GrShaderFlag) {
-        ++fNumVertexImageStorages;
-    }
-    if (access.visibility() & kGeometry_GrShaderFlag) {
-        SkASSERT(this->primitiveProcessor().willUseGeoShader());
-        ++fNumGeometryImageStorages;
-    }
-    if (access.visibility() & kFragment_GrShaderFlag) {
-        ++fNumFragmentImageStorages;
-    }
-    GrSLType uniformType = access.proxy()->imageStorageType();
-    return this->uniformHandler()->addImageStorage(access.visibility(), uniformType,
-                                                   access.format(), access.memoryModel(),
-                                                   access.restrict(), access.ioType(), name);
-}
-
 void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
     // Swizzle the fragment shader outputs if necessary.
     GrSwizzle swizzle;
@@ -390,30 +354,6 @@
     return true;
 }
 
-bool GrGLSLProgramBuilder::checkImageStorageCounts() {
-    const GrShaderCaps& shaderCaps = *this->shaderCaps();
-    if (fNumVertexImageStorages > shaderCaps.maxVertexImageStorages()) {
-        GrCapsDebugf(this->caps(), "Program would use too many vertex images\n");
-        return false;
-    }
-    if (fNumGeometryImageStorages > shaderCaps.maxGeometryImageStorages()) {
-        GrCapsDebugf(this->caps(), "Program would use too many geometry images\n");
-        return false;
-    }
-    if (fNumFragmentImageStorages > shaderCaps.maxFragmentImageStorages()) {
-        GrCapsDebugf(this->caps(), "Program would use too many fragment images\n");
-        return false;
-    }
-    // If the same image is used in two different shaders, it counts as two combined images.
-    int numCombinedImages = fNumVertexImageStorages + fNumGeometryImageStorages +
-        fNumFragmentImageStorages;
-    if (numCombinedImages > shaderCaps.maxCombinedImageStorages()) {
-        GrCapsDebugf(this->caps(), "Program would use too many combined images\n");
-        return false;
-    }
-    return true;
-}
-
 #ifdef SK_DEBUG
 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
     SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 83a437f..ac2d496 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -31,7 +31,6 @@
     using UniformHandle      = GrGLSLUniformHandler::UniformHandle;
     using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle;
     using TexelBufferHandle  = GrGLSLUniformHandler::TexelBufferHandle;
-    using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
 
     virtual ~GrGLSLProgramBuilder() {}
 
@@ -57,10 +56,6 @@
         return this->uniformHandler()->texelBufferVariable(handle);
     }
 
-    const GrShaderVar& imageStorageVariable(ImageStorageHandle handle) const {
-        return this->uniformHandler()->imageStorageVariable(handle);
-    }
-
     // Handles for program uniforms (other than per-effect uniforms)
     struct BuiltinUniformHandles {
         UniformHandle       fRTAdjustmentUni;
@@ -156,19 +151,15 @@
                                     const SkString& input,
                                     SkString output);
     void emitAndInstallXferProc(const SkString& colorIn, const SkString& coverageIn);
-    void emitSamplersAndImageStorages(const GrResourceIOProcessor& processor,
-                                      SkTArray<SamplerHandle>* outTexSamplerHandles,
-                                      SkTArray<TexelBufferHandle>* outTexelBufferHandles,
-                                      SkTArray<ImageStorageHandle>* outImageStorageHandles);
+    void emitSamplers(const GrResourceIOProcessor& processor,
+                      SkTArray<SamplerHandle>* outTexSamplerHandles,
+                      SkTArray<TexelBufferHandle>* outTexelBufferHandles);
     SamplerHandle emitSampler(GrSLType samplerType, GrPixelConfig, const char* name,
                               GrShaderFlags visibility);
     TexelBufferHandle emitTexelBuffer(GrPixelConfig, const char* name, GrShaderFlags visibility);
-    ImageStorageHandle emitImageStorage(const GrResourceIOProcessor::ImageStorageAccess&,
-                                        const char* name);
     void emitFSOutputSwizzle(bool hasSecondaryOutput);
     void updateSamplerCounts(GrShaderFlags visibility);
     bool checkSamplerCounts();
-    bool checkImageStorageCounts();
 
 #ifdef SK_DEBUG
     void verify(const GrPrimitiveProcessor&);
@@ -181,9 +172,6 @@
     int                         fNumVertexSamplers;
     int                         fNumGeometrySamplers;
     int                         fNumFragmentSamplers;
-    int                         fNumVertexImageStorages;
-    int                         fNumGeometryImageStorages;
-    int                         fNumFragmentImageStorages;
     SkSTArray<4, GrShaderVar>   fTransformedCoordVars;
 };
 
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index 750df63..4bf6602 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -213,16 +213,6 @@
     this->appendTexelFetch(&this->code(), texelBufferHandle, coordExpr);
 }
 
-void GrGLSLShaderBuilder::appendImageStorageLoad(SkString* out, ImageStorageHandle handle,
-                                                 const char* coordExpr) {
-    const GrShaderVar& imageStorage = fProgramBuilder->imageStorageVariable(handle);
-    out->appendf("imageLoad(%s, %s)", imageStorage.c_str(), coordExpr);
-}
-
-void GrGLSLShaderBuilder::appendImageStorageLoad(ImageStorageHandle handle, const char* coordExpr) {
-    this->appendImageStorageLoad(&this->code(), handle, coordExpr);
-}
-
 bool GrGLSLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) {
     if (featureBit & fFeaturesAddedMask) {
         return false;
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index 9ac6ab7..0708625 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -27,7 +27,6 @@
 
     using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle;
     using TexelBufferHandle  = GrGLSLUniformHandler::TexelBufferHandle;
-    using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
 
     /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
         Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
@@ -74,11 +73,6 @@
     /** Version of above that appends the result to the shader code instead.*/
     void appendTexelFetch(TexelBufferHandle, const char* coordExpr);
 
-    /** Creates a string of shader code that performs an image load. */
-    void appendImageStorageLoad(SkString* out, ImageStorageHandle, const char* coordExpr);
-    /** Version of above that appends the result to the shader code instead. */
-    void appendImageStorageLoad(ImageStorageHandle, const char* coordExpr);
-
     /**
     * Adds a constant declaration to the top of the shader.
     */
diff --git a/src/gpu/glsl/GrGLSLUniformHandler.h b/src/gpu/glsl/GrGLSLUniformHandler.h
index 84bbfa1..e1511c2 100644
--- a/src/gpu/glsl/GrGLSLUniformHandler.h
+++ b/src/gpu/glsl/GrGLSLUniformHandler.h
@@ -21,7 +21,6 @@
     using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
     GR_DEFINE_RESOURCE_HANDLE_CLASS(SamplerHandle);
     GR_DEFINE_RESOURCE_HANDLE_CLASS(TexelBufferHandle);
-    GR_DEFINE_RESOURCE_HANDLE_CLASS(ImageStorageHandle);
 
     /** Add a uniform variable to the current program, that has visibility in one or more shaders.
         visibility is a bitfield of GrShaderFlag values indicating from which shaders the uniform
@@ -90,11 +89,6 @@
     virtual TexelBufferHandle addTexelBuffer(uint32_t visibility, GrSLPrecision,
                                              const char* name) = 0;
 
-    virtual const GrShaderVar& imageStorageVariable(ImageStorageHandle) const = 0;
-    virtual ImageStorageHandle addImageStorage(uint32_t visibility, GrSLType type,
-                                               GrImageStorageFormat, GrSLMemoryModel, GrSLRestrict,
-                                               GrIOType, const char* name) = 0;
-
     virtual UniformHandle internalAddUniformArray(uint32_t visibility,
                                                   GrSLType type,
                                                   GrSLPrecision precision,
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.h b/src/gpu/glsl/GrGLSLXferProcessor.h
index 763fcfa..10658a9 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.h
+++ b/src/gpu/glsl/GrGLSLXferProcessor.h
@@ -24,7 +24,6 @@
     virtual ~GrGLSLXferProcessor() {}
 
     using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
-    using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
 
     struct EmitArgs {
         EmitArgs(GrGLSLXPFragmentBuilder* fragBuilder,
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index 9f27968..c4b9449 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -45,7 +45,6 @@
         return false;
     }
 
-    bool canConfigBeImageStorage(GrPixelConfig) const override { return false; }
     bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
                             bool* rectsMustMatch, bool* disallowSubrect) const override {
         return false;
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index 75bb2e7..3f2adf8 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -43,8 +43,6 @@
         return true;
     }
 
-    bool canConfigBeImageStorage(GrPixelConfig) const override { return false; }
-
 #if 0
     /**
      * Returns both a supported and most prefered stencil format to use in draws.
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index ad51495..1a6e1bd 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -43,8 +43,6 @@
         return true;
     }
 
-    bool canConfigBeImageStorage(GrPixelConfig) const override { return false; }
-
     bool isConfigTexturableLinearly(GrPixelConfig config) const {
         return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fLinearFlags);
     }
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 1719775..1dbc490 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -209,8 +209,6 @@
         const GrResourceIOProcessor& processor,
         SkTArray<const GrResourceIOProcessor::TextureSampler*>* textureBindings,
         SkTArray<const GrResourceIOProcessor::BufferAccess*>* bufferAccesses) {
-    // We don't support image storages in VK.
-    SkASSERT(!processor.numImageStorages());
     if (int numTextureSamplers = processor.numTextureSamplers()) {
         const GrResourceIOProcessor::TextureSampler** bindings =
                 textureBindings->push_back_n(numTextureSamplers);
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp
index d9c2519..040926e 100644
--- a/src/gpu/vk/GrVkUniformHandler.cpp
+++ b/src/gpu/vk/GrVkUniformHandler.cpp
@@ -72,8 +72,6 @@
         case kBufferSampler_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
             break;
     }
     SK_ABORT("Unexpected type");
@@ -144,8 +142,6 @@
         case kBufferSampler_GrSLType:
         case kTexture2D_GrSLType:
         case kSampler_GrSLType:
-        case kImageStorage2D_GrSLType:
-        case kIImageStorage2D_GrSLType:
             break;
     }
     SK_ABORT("Unexpected type");
diff --git a/src/gpu/vk/GrVkUniformHandler.h b/src/gpu/vk/GrVkUniformHandler.h
index f6dcbbb..ebe9041 100644
--- a/src/gpu/vk/GrVkUniformHandler.h
+++ b/src/gpu/vk/GrVkUniformHandler.h
@@ -88,19 +88,6 @@
         return fTexelBuffers[handle.toIndex()].fVisibility;
     }
 
-    ImageStorageHandle addImageStorage(uint32_t visibility, GrSLType,  GrImageStorageFormat,
-                                       GrSLMemoryModel, GrSLRestrict, GrIOType,
-                                       const char* name) override {
-        SK_ABORT("Image storages not implemented for Vulkan.");
-        return 0;
-    }
-
-    const GrShaderVar& imageStorageVariable(ImageStorageHandle handle) const override {
-        SK_ABORT("Image storages not implemented for Vulkan.");
-        static const GrShaderVar* gVar = nullptr;
-        return *gVar;
-    }
-
     void appendUniformDecls(GrShaderFlags, SkString*) const override;
 
     bool hasGeometryUniforms() const { return fCurrentGeometryUBOOffset > 0; }
diff --git a/src/gpu/vk/GrVkVaryingHandler.cpp b/src/gpu/vk/GrVkVaryingHandler.cpp
index ff56a39..307ea53 100644
--- a/src/gpu/vk/GrVkVaryingHandler.cpp
+++ b/src/gpu/vk/GrVkVaryingHandler.cpp
@@ -70,10 +70,6 @@
              return 0;
         case kSampler_GrSLType:
              return 0;
-        case kImageStorage2D_GrSLType:
-            return 0;
-        case kIImageStorage2D_GrSLType:
-            return 0;
     }
     SK_ABORT("Unexpected type");
     return -1;
diff --git a/tests/ImageStorageTest.cpp b/tests/ImageStorageTest.cpp
deleted file mode 100644
index a8704c6..0000000
--- a/tests/ImageStorageTest.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Test.h"
-
-#if SK_SUPPORT_GPU
-
-#include "GrClip.h"
-#include "GrFragmentProcessor.h"
-#include "GrRenderTargetContext.h"
-#include "GrTexture.h"
-#include "glsl/GrGLSLFragmentProcessor.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) {
-    class TestFP : public GrFragmentProcessor {
-    public:
-        static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
-                                                         GrSLMemoryModel mm,
-                                                         GrSLRestrict restrict) {
-            return std::unique_ptr<GrFragmentProcessor>(new TestFP(std::move(proxy), mm, restrict));
-        }
-
-        const char* name() const override { return "Image Load Test FP"; }
-
-        std::unique_ptr<GrFragmentProcessor> clone() const override {
-            return std::unique_ptr<GrFragmentProcessor>(new TestFP(*this));
-        }
-
-    private:
-        TestFP(sk_sp<GrTextureProxy> proxy, GrSLMemoryModel mm, GrSLRestrict restrict)
-                : INHERITED(kTestFP_ClassID, kNone_OptimizationFlags)
-                , fImageStorageAccess(std::move(proxy), kRead_GrIOType, mm, restrict) {
-            this->addImageStorageAccess(&fImageStorageAccess);
-        }
-
-        explicit TestFP(const TestFP& that)
-                : INHERITED(kTestFP_ClassID, that.optimizationFlags())
-                , fImageStorageAccess(that.fImageStorageAccess) {
-            this->addImageStorageAccess(&fImageStorageAccess);
-        }
-
-        void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
-
-        bool onIsEqual(const GrFragmentProcessor& that) const override { return true; }
-
-        GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
-            class GLSLProcessor : public GrGLSLFragmentProcessor {
-            public:
-                GLSLProcessor() = default;
-                void emitCode(EmitArgs& args) override {
-                    const TestFP& tfp = args.fFp.cast<TestFP>();
-                    GrGLSLFPFragmentBuilder* fb = args.fFragBuilder;
-                    SkString imageLoadStr;
-                    fb->codeAppend("float2 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("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)));");
-                        fb->codeAppend("if (ivals.r < 0) { ivals.r += 256; }");
-                        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 = half4(ivals)/255;", args.fOutputColor);
-                    } else {
-                        fb->codeAppendf("%s = %s;", args.fOutputColor, imageLoadStr.c_str());
-                    }
-                }
-            };
-            return new GLSLProcessor;
-        }
-
-        ImageStorageAccess fImageStorageAccess;
-        typedef GrFragmentProcessor INHERITED;
-    };
-
-    static constexpr int kS = 256;
-    GrContext* context = ctxInfo.grContext();
-    if (context->caps()->shaderCaps()->maxFragmentImageStorages() < 1) {
-        return;
-    }
-
-    std::unique_ptr<uint32_t[]> data(new uint32_t[kS * kS]);
-    for (int j = 0; j < kS; ++j) {
-        for (int i = 0; i < kS; ++i) {
-            data[i + kS * j] = GrColorPackRGBA(i, j, 0, 0);
-        }
-    }
-
-    std::unique_ptr<uint32_t[]> idata(new uint32_t[kS * kS]);
-    for (int j = 0; j < kS; ++j) {
-        for (int i = 0; i < kS; ++i) {
-            int8_t r = i - 128;
-            int8_t g = j - 128;
-            int8_t b = -128;
-            int8_t a = -128;
-            idata[i + kS * j] = ((uint8_t)a << 24) | ((uint8_t)b << 16) |
-                                ((uint8_t)g << 8)  |  (uint8_t)r;
-        }
-    }
-
-    // Currently image accesses always have "top left" semantics.
-    GrSurfaceDesc desc;
-    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
-    desc.fWidth = kS;
-    desc.fHeight = kS;
-    struct {
-        GrPixelConfig fConfig;
-        std::unique_ptr<uint32_t[]> fData;
-    } tests[] = {
-        {
-           kRGBA_8888_GrPixelConfig,
-           std::move(data)
-        },
-        {
-           kRGBA_8888_sint_GrPixelConfig,
-           std::move(idata)
-        },
-    };
-    for (const auto& test : tests) {
-        // This test should work with any memory model and with or without restrict
-        for (auto mm : {GrSLMemoryModel::kNone,
-                        GrSLMemoryModel::kCoherent,
-                        GrSLMemoryModel::kVolatile}) {
-            for (auto restrict : {GrSLRestrict::kNo, GrSLRestrict::kYes}) {
-                if (!context->caps()->canConfigBeImageStorage(test.fConfig)) {
-                    continue;
-                }
-                desc.fConfig = test.fConfig;
-                sk_sp<GrTextureProxy> imageStorageTexture =
-                    GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc,
-                                                 SkBudgeted::kYes, test.fData.get(), 0);
-
-                sk_sp<GrRenderTargetContext> rtContext =
-                    context->makeDeferredRenderTargetContext(SkBackingFit::kExact, kS, kS,
-                                                             kRGBA_8888_GrPixelConfig, nullptr);
-                // We make a clone to test that copying GrFragmentProcessor::ImageStorageAccess
-                // works.
-                std::unique_ptr<GrFragmentProcessor> fps[2];
-                fps[0] = TestFP::Make(imageStorageTexture, mm, restrict);
-                fps[1] = fps[0]->clone();
-                for (auto& fp : fps) {
-                    GrPaint paint;
-                    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-                    paint.addColorFragmentProcessor(std::move(fp));
-                    rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
-                    std::unique_ptr<uint32_t[]> readData(new uint32_t[kS * kS]);
-                    SkImageInfo info = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
-                                                         kPremul_SkAlphaType);
-                    rtContext->readPixels(info, readData.get(), 0, 0, 0);
-                    int failed = false;
-                    for (int j = 0; j < kS && !failed; ++j) {
-                        for (int i = 0; i < kS && !failed; ++i) {
-                            uint32_t d = test.fData[j * kS + i];
-                            uint32_t rd = readData[j * kS + i];
-                            if (d != rd) {
-                                failed = true;
-                                ERRORF(reporter, "Expected 0x%08x, got 0x%08x at %d, %d.",
-                                       d, rd, i, j);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-#endif
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 9acf185..177eead 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -67,18 +67,12 @@
  */
 class TestFP : public GrFragmentProcessor {
 public:
-    struct Image {
-        Image(sk_sp<GrTextureProxy> proxy, GrIOType ioType) : fProxy(proxy), fIOType(ioType) {}
-        sk_sp<GrTextureProxy> fProxy;
-        GrIOType fIOType;
-    };
     static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child) {
         return std::unique_ptr<GrFragmentProcessor>(new TestFP(std::move(child)));
     }
     static std::unique_ptr<GrFragmentProcessor> Make(const SkTArray<sk_sp<GrTextureProxy>>& proxies,
-                                                     const SkTArray<sk_sp<GrBuffer>>& buffers,
-                                                     const SkTArray<Image>& images) {
-        return std::unique_ptr<GrFragmentProcessor>(new TestFP(proxies, buffers, images));
+                                                     const SkTArray<sk_sp<GrBuffer>>& buffers) {
+        return std::unique_ptr<GrFragmentProcessor>(new TestFP(proxies, buffers));
     }
 
     const char* name() const override { return "test"; }
@@ -94,33 +88,23 @@
     }
 
 private:
-    TestFP(const SkTArray<sk_sp<GrTextureProxy>>& proxies,
-           const SkTArray<sk_sp<GrBuffer>>& buffers,
-           const SkTArray<Image>& images)
-            : INHERITED(kTestFP_ClassID, kNone_OptimizationFlags), fSamplers(4), fBuffers(4),
-                        fImages(4) {
+    TestFP(const SkTArray<sk_sp<GrTextureProxy>>& proxies, const SkTArray<sk_sp<GrBuffer>>& buffers)
+            : INHERITED(kTestFP_ClassID, kNone_OptimizationFlags), fSamplers(4), fBuffers(4) {
         for (const auto& proxy : proxies) {
             this->addTextureSampler(&fSamplers.emplace_back(proxy));
         }
         for (const auto& buffer : buffers) {
             this->addBufferAccess(&fBuffers.emplace_back(kRGBA_8888_GrPixelConfig, buffer.get()));
         }
-        for (const Image& image : images) {
-            fImages.emplace_back(image.fProxy, image.fIOType,
-                                 GrSLMemoryModel::kNone, GrSLRestrict::kNo);
-            this->addImageStorageAccess(&fImages.back());
-        }
     }
 
     TestFP(std::unique_ptr<GrFragmentProcessor> child)
-            : INHERITED(kTestFP_ClassID, kNone_OptimizationFlags), fSamplers(4), fBuffers(4),
-                        fImages(4) {
+            : INHERITED(kTestFP_ClassID, kNone_OptimizationFlags), fSamplers(4), fBuffers(4) {
         this->registerChildProcessor(std::move(child));
     }
 
     explicit TestFP(const TestFP& that)
-            : INHERITED(kTestFP_ClassID, that.optimizationFlags()), fSamplers(4), fBuffers(4),
-                        fImages(4) {
+            : INHERITED(kTestFP_ClassID, that.optimizationFlags()), fSamplers(4), fBuffers(4) {
         for (int i = 0; i < that.fSamplers.count(); ++i) {
             fSamplers.emplace_back(that.fSamplers[i]);
             this->addTextureSampler(&fSamplers.back());
@@ -129,10 +113,6 @@
             fBuffers.emplace_back(that.fBuffers[i]);
             this->addBufferAccess(&fBuffers.back());
         }
-        for (int i = 0; i < that.fImages.count(); ++i) {
-            fImages.emplace_back(that.fImages[i]);
-            this->addImageStorageAccess(&fImages.back());
-        }
         for (int i = 0; i < that.numChildProcessors(); ++i) {
             this->registerChildProcessor(that.childProcessor(i).clone());
         }
@@ -156,7 +136,6 @@
 
     GrTAllocator<TextureSampler> fSamplers;
     GrTAllocator<BufferAccess> fBuffers;
-    GrTAllocator<ImageStorageAccess> fImages;
     typedef GrFragmentProcessor INHERITED;
 };
 }
@@ -190,7 +169,6 @@
                                                               kRGBA_8888_GrPixelConfig, nullptr));
             {
                 bool texelBufferSupport = context->caps()->shaderCaps()->texelBufferSupport();
-                bool imageLoadStoreSupport = context->caps()->shaderCaps()->imageLoadStoreSupport();
                 sk_sp<GrTextureProxy> proxy1(
                         GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
                                                      desc, SkBackingFit::kExact,
@@ -215,18 +193,11 @@
                 {
                     SkTArray<sk_sp<GrTextureProxy>> proxies;
                     SkTArray<sk_sp<GrBuffer>> buffers;
-                    SkTArray<TestFP::Image> images;
                     proxies.push_back(proxy1);
                     if (texelBufferSupport) {
                         buffers.push_back(buffer);
                     }
-                    if (imageLoadStoreSupport) {
-                        images.emplace_back(proxy2, GrIOType::kRead_GrIOType);
-                        images.emplace_back(proxy3, GrIOType::kWrite_GrIOType);
-                        images.emplace_back(proxy4, GrIOType::kRW_GrIOType);
-                    }
-                    auto fp = TestFP::Make(std::move(proxies), std::move(buffers),
-                                           std::move(images));
+                    auto fp = TestFP::Make(std::move(proxies), std::move(buffers));
                     for (int i = 0; i < parentCnt; ++i) {
                         fp = TestFP::Make(std::move(fp));
                     }
@@ -257,23 +228,6 @@
                     REPORTER_ASSERT(reporter, ioRefMul *  0 == writeCnt);
                 }
 
-                if (imageLoadStoreSupport) {
-                    testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt);
-                    REPORTER_ASSERT(reporter, 1 == refCnt);
-                    REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt);
-                    REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
-
-                    testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt);
-                    REPORTER_ASSERT(reporter, 1 == refCnt);
-                    REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt);
-                    REPORTER_ASSERT(reporter, ioRefMul * 1 == writeCnt);
-
-                    testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt);
-                    REPORTER_ASSERT(reporter, 1 == refCnt);
-                    REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt);
-                    REPORTER_ASSERT(reporter, ioRefMul * 1 == writeCnt);
-                }
-
                 context->flush();
 
                 testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt);