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/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;