Add top-level state sync for Samplers.

This also reformats the Sampler class to use a shared state struct
with the implementation. It removes the call to sync the sampler
state from the StateManagerGL::setGenericShaderState method, since
it should all be handled at the front-end now.

Also rename 'syncImplState' to 'syncState' methods.

BUG=angleproject:1387

Change-Id: I5f0219b719aee99aaaa486ec188b2af0c9128e6a
Reviewed-on: https://chromium-review.googlesource.com/648054
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 3d87d08..53b6d32 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -2356,6 +2356,7 @@
     Sampler *samplerObject =
         mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
     SetSamplerParameteri(samplerObject, pname, param);
+    mGLState.setObjectDirty(GL_SAMPLER);
 }
 
 void Context::samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
@@ -2363,6 +2364,7 @@
     Sampler *samplerObject =
         mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
     SetSamplerParameteriv(samplerObject, pname, param);
+    mGLState.setObjectDirty(GL_SAMPLER);
 }
 
 void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
@@ -2370,6 +2372,7 @@
     Sampler *samplerObject =
         mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
     SetSamplerParameterf(samplerObject, pname, param);
+    mGLState.setObjectDirty(GL_SAMPLER);
 }
 
 void Context::samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
@@ -2377,6 +2380,7 @@
     Sampler *samplerObject =
         mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
     SetSamplerParameterfv(samplerObject, pname, param);
+    mGLState.setObjectDirty(GL_SAMPLER);
 }
 
 void Context::getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
@@ -2384,6 +2388,7 @@
     const Sampler *samplerObject =
         mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
     QuerySamplerParameteriv(samplerObject, pname, params);
+    mGLState.setObjectDirty(GL_SAMPLER);
 }
 
 void Context::getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
@@ -2391,6 +2396,7 @@
     const Sampler *samplerObject =
         mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
     QuerySamplerParameterfv(samplerObject, pname, params);
+    mGLState.setObjectDirty(GL_SAMPLER);
 }
 
 void Context::programParameteri(GLuint program, GLenum pname, GLint value)
diff --git a/src/libANGLE/Sampler.cpp b/src/libANGLE/Sampler.cpp
index f0c9a3e..17ad70a 100644
--- a/src/libANGLE/Sampler.cpp
+++ b/src/libANGLE/Sampler.cpp
@@ -16,7 +16,7 @@
 {
 
 Sampler::Sampler(rx::GLImplFactory *factory, GLuint id)
-    : RefCountObject(id), mImpl(factory->createSampler()), mLabel(), mSamplerState()
+    : RefCountObject(id), mState(), mImpl(factory->createSampler(mState)), mLabel()
 {
 }
 
@@ -37,117 +37,117 @@
 
 void Sampler::setMinFilter(GLenum minFilter)
 {
-    mSamplerState.minFilter = minFilter;
+    mState.minFilter = minFilter;
 }
 
 GLenum Sampler::getMinFilter() const
 {
-    return mSamplerState.minFilter;
+    return mState.minFilter;
 }
 
 void Sampler::setMagFilter(GLenum magFilter)
 {
-    mSamplerState.magFilter = magFilter;
+    mState.magFilter = magFilter;
 }
 
 GLenum Sampler::getMagFilter() const
 {
-    return mSamplerState.magFilter;
+    return mState.magFilter;
 }
 
 void Sampler::setWrapS(GLenum wrapS)
 {
-    mSamplerState.wrapS = wrapS;
+    mState.wrapS = wrapS;
 }
 
 GLenum Sampler::getWrapS() const
 {
-    return mSamplerState.wrapS;
+    return mState.wrapS;
 }
 
 void Sampler::setWrapT(GLenum wrapT)
 {
-    mSamplerState.wrapT = wrapT;
+    mState.wrapT = wrapT;
 }
 
 GLenum Sampler::getWrapT() const
 {
-    return mSamplerState.wrapT;
+    return mState.wrapT;
 }
 
 void Sampler::setWrapR(GLenum wrapR)
 {
-    mSamplerState.wrapR = wrapR;
+    mState.wrapR = wrapR;
 }
 
 GLenum Sampler::getWrapR() const
 {
-    return mSamplerState.wrapR;
+    return mState.wrapR;
 }
 
 void Sampler::setMaxAnisotropy(float maxAnisotropy)
 {
-    mSamplerState.maxAnisotropy = maxAnisotropy;
+    mState.maxAnisotropy = maxAnisotropy;
 }
 
 float Sampler::getMaxAnisotropy() const
 {
-    return mSamplerState.maxAnisotropy;
+    return mState.maxAnisotropy;
 }
 
 void Sampler::setMinLod(GLfloat minLod)
 {
-    mSamplerState.minLod = minLod;
+    mState.minLod = minLod;
 }
 
 GLfloat Sampler::getMinLod() const
 {
-    return mSamplerState.minLod;
+    return mState.minLod;
 }
 
 void Sampler::setMaxLod(GLfloat maxLod)
 {
-    mSamplerState.maxLod = maxLod;
+    mState.maxLod = maxLod;
 }
 
 GLfloat Sampler::getMaxLod() const
 {
-    return mSamplerState.maxLod;
+    return mState.maxLod;
 }
 
 void Sampler::setCompareMode(GLenum compareMode)
 {
-    mSamplerState.compareMode = compareMode;
+    mState.compareMode = compareMode;
 }
 
 GLenum Sampler::getCompareMode() const
 {
-    return mSamplerState.compareMode;
+    return mState.compareMode;
 }
 
 void Sampler::setCompareFunc(GLenum compareFunc)
 {
-    mSamplerState.compareFunc = compareFunc;
+    mState.compareFunc = compareFunc;
 }
 
 GLenum Sampler::getCompareFunc() const
 {
-    return mSamplerState.compareFunc;
+    return mState.compareFunc;
 }
 
 void Sampler::setSRGBDecode(GLenum sRGBDecode)
 {
-    mSamplerState.sRGBDecode = sRGBDecode;
+    mState.sRGBDecode = sRGBDecode;
 }
 
 GLenum Sampler::getSRGBDecode() const
 {
-    return mSamplerState.sRGBDecode;
+    return mState.sRGBDecode;
 }
 
 const SamplerState &Sampler::getSamplerState() const
 {
-    return mSamplerState;
+    return mState;
 }
 
 rx::SamplerImpl *Sampler::getImplementation() const
@@ -155,4 +155,10 @@
     return mImpl;
 }
 
+void Sampler::syncState(const Context *context)
+{
+    // TODO(jmadill): Use actual dirty bits for sampler.
+    mImpl->syncState(context);
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/Sampler.h b/src/libANGLE/Sampler.h
index 7ad0c98..3e97c9a 100644
--- a/src/libANGLE/Sampler.h
+++ b/src/libANGLE/Sampler.h
@@ -71,12 +71,13 @@
 
     rx::SamplerImpl *getImplementation() const;
 
+    void syncState(const Context *context);
+
   private:
+    SamplerState mState;
     rx::SamplerImpl *mImpl;
 
     std::string mLabel;
-
-    SamplerState mSamplerState;
 };
 
 }  // namespace gl
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index 2d4b07a..490859e 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -2177,7 +2177,7 @@
                 break;
             case DIRTY_OBJECT_VERTEX_ARRAY:
                 ASSERT(mVertexArray);
-                mVertexArray->syncImplState(context);
+                mVertexArray->syncState(context);
                 break;
             case DIRTY_OBJECT_PROGRAM_TEXTURES:
                 syncProgramTextures(context);
@@ -2218,16 +2218,15 @@
         for (GLuint textureUnitIndex : samplerBinding.boundTextureUnits)
         {
             Texture *texture = getSamplerTexture(textureUnitIndex, textureType);
+            Sampler *sampler = getSampler(textureUnitIndex);
 
             if (texture != nullptr)
             {
-                const Sampler *sampler = getSampler(textureUnitIndex);
-
                 // Mark the texture binding bit as dirty if the texture completeness changes.
                 // TODO(jmadill): Use specific dirty bit for completeness change.
                 if (texture->isSamplerComplete(context, sampler))
                 {
-                    texture->syncImplState();
+                    texture->syncState();
                     ASSERT(static_cast<size_t>(textureUnitIndex) < mCompleteTextureCache.size());
                     ASSERT(mCompleteTextureCache[textureUnitIndex] == nullptr ||
                            mCompleteTextureCache[textureUnitIndex] == texture);
@@ -2238,7 +2237,10 @@
                 mCompleteTextureBindings[textureUnitIndex].bind(texture->getDirtyChannel());
             }
 
-            // TODO(jmadill): Sync sampler state.
+            if (sampler != nullptr)
+            {
+                sampler->syncState(context);
+            }
         }
     }
 }
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index 6ddfeea..d8819c4 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -1109,7 +1109,7 @@
 
     if (maxLevel > baseLevel)
     {
-        syncImplState();
+        syncState();
         ANGLE_TRY(mTexture->generateMipmap(context));
 
         const ImageDesc &baseImageInfo =
@@ -1264,7 +1264,7 @@
     return id();
 }
 
-void Texture::syncImplState()
+void Texture::syncState()
 {
     mTexture->syncState(mDirtyBits);
     mDirtyBits.reset();
diff --git a/src/libANGLE/Texture.h b/src/libANGLE/Texture.h
index dc73b20..cd8a46a 100644
--- a/src/libANGLE/Texture.h
+++ b/src/libANGLE/Texture.h
@@ -387,7 +387,7 @@
     };
     using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
 
-    void syncImplState();
+    void syncState();
     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
 
   private:
diff --git a/src/libANGLE/VertexArray.cpp b/src/libANGLE/VertexArray.cpp
index 64be514..a8c2fce 100644
--- a/src/libANGLE/VertexArray.cpp
+++ b/src/libANGLE/VertexArray.cpp
@@ -255,7 +255,7 @@
     mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
 }
 
-void VertexArray::syncImplState(const Context *context)
+void VertexArray::syncState(const Context *context)
 {
     if (mDirtyBits.any())
     {
diff --git a/src/libANGLE/VertexArray.h b/src/libANGLE/VertexArray.h
index b42cd87..c749032 100644
--- a/src/libANGLE/VertexArray.h
+++ b/src/libANGLE/VertexArray.h
@@ -186,7 +186,7 @@
 
     static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit);
 
-    void syncImplState(const Context *context);
+    void syncState(const Context *context);
     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
 
   private:
diff --git a/src/libANGLE/renderer/GLImplFactory.h b/src/libANGLE/renderer/GLImplFactory.h
index 2f72425..524196e 100644
--- a/src/libANGLE/renderer/GLImplFactory.h
+++ b/src/libANGLE/renderer/GLImplFactory.h
@@ -78,7 +78,7 @@
         const gl::TransformFeedbackState &state) = 0;
 
     // Sampler object creation
-    virtual SamplerImpl *createSampler() = 0;
+    virtual SamplerImpl *createSampler(const gl::SamplerState &state) = 0;
 
     virtual std::vector<PathImpl *> createPaths(GLsizei range) = 0;
 };
diff --git a/src/libANGLE/renderer/SamplerImpl.h b/src/libANGLE/renderer/SamplerImpl.h
index 741b0da..66e1079 100644
--- a/src/libANGLE/renderer/SamplerImpl.h
+++ b/src/libANGLE/renderer/SamplerImpl.h
@@ -11,15 +11,29 @@
 
 #include "common/angleutils.h"
 
+namespace gl
+{
+class Context;
+struct SamplerState;
+}  // namespace gl
+
 namespace rx
 {
 
 class SamplerImpl : angle::NonCopyable
 {
   public:
-    SamplerImpl() {}
+    SamplerImpl(const gl::SamplerState &state) : mState(state) {}
     virtual ~SamplerImpl() {}
+
+    virtual void syncState(const gl::Context *context)
+    {
+        // Default implementation: no-op.
+    }
+
+  protected:
+    const gl::SamplerState &mState;
 };
-}
+}  // namespace rx
 
 #endif  // LIBANGLE_RENDERER_SAMPLERIMPL_H_
diff --git a/src/libANGLE/renderer/d3d/SamplerD3D.h b/src/libANGLE/renderer/d3d/SamplerD3D.h
index 7aabdc8..3f8f5b9 100644
--- a/src/libANGLE/renderer/d3d/SamplerD3D.h
+++ b/src/libANGLE/renderer/d3d/SamplerD3D.h
@@ -17,7 +17,7 @@
 class SamplerD3D : public SamplerImpl
 {
   public:
-    SamplerD3D() {}
+    SamplerD3D(const gl::SamplerState &state) : SamplerImpl(state) {}
     ~SamplerD3D() override {}
 };
 }
diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
index 4ea46e4..d0c4ac9 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -131,9 +131,9 @@
     return new TransformFeedback11(state, mRenderer);
 }
 
-SamplerImpl *Context11::createSampler()
+SamplerImpl *Context11::createSampler(const gl::SamplerState &state)
 {
-    return new SamplerD3D();
+    return new SamplerD3D(state);
 }
 
 std::vector<PathImpl *> Context11::createPaths(GLsizei)
diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/libANGLE/renderer/d3d/d3d11/Context11.h
index 09d5831..66697cf 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Context11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -54,7 +54,7 @@
         const gl::TransformFeedbackState &state) override;
 
     // Sampler object creation
-    SamplerImpl *createSampler() override;
+    SamplerImpl *createSampler(const gl::SamplerState &state) override;
 
     // Path object creation.
     std::vector<PathImpl *> createPaths(GLsizei) override;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
index c229d81..d39d5ee 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -115,9 +115,9 @@
     return nullptr;
 }
 
-SamplerImpl *Context9::createSampler()
+SamplerImpl *Context9::createSampler(const gl::SamplerState &state)
 {
-    return new SamplerD3D();
+    return new SamplerD3D(state);
 }
 
 std::vector<PathImpl *> Context9::createPaths(GLsizei)
diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.h b/src/libANGLE/renderer/d3d/d3d9/Context9.h
index 1dcdc68..ac918e0 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Context9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -54,7 +54,7 @@
         const gl::TransformFeedbackState &state) override;
 
     // Sampler object creation
-    SamplerImpl *createSampler() override;
+    SamplerImpl *createSampler(const gl::SamplerState &state) override;
 
     // Path object creation
     std::vector<PathImpl *> createPaths(GLsizei) override;
diff --git a/src/libANGLE/renderer/gl/ContextGL.cpp b/src/libANGLE/renderer/gl/ContextGL.cpp
index e77ebfa..1c9276e 100644
--- a/src/libANGLE/renderer/gl/ContextGL.cpp
+++ b/src/libANGLE/renderer/gl/ContextGL.cpp
@@ -117,9 +117,9 @@
     return new TransformFeedbackGL(state, getFunctions(), getStateManager());
 }
 
-SamplerImpl *ContextGL::createSampler()
+SamplerImpl *ContextGL::createSampler(const gl::SamplerState &state)
 {
-    return new SamplerGL(getFunctions(), getStateManager());
+    return new SamplerGL(state, getFunctions(), getStateManager());
 }
 
 std::vector<PathImpl *> ContextGL::createPaths(GLsizei range)
diff --git a/src/libANGLE/renderer/gl/ContextGL.h b/src/libANGLE/renderer/gl/ContextGL.h
index 3fadd28..e07b648 100644
--- a/src/libANGLE/renderer/gl/ContextGL.h
+++ b/src/libANGLE/renderer/gl/ContextGL.h
@@ -62,7 +62,7 @@
         const gl::TransformFeedbackState &state) override;
 
     // Sampler object creation
-    SamplerImpl *createSampler() override;
+    SamplerImpl *createSampler(const gl::SamplerState &state) override;
 
     // Path object creation
     std::vector<PathImpl *> createPaths(GLsizei range) override;
diff --git a/src/libANGLE/renderer/gl/SamplerGL.cpp b/src/libANGLE/renderer/gl/SamplerGL.cpp
index 2a6d815..19c7ff9 100644
--- a/src/libANGLE/renderer/gl/SamplerGL.cpp
+++ b/src/libANGLE/renderer/gl/SamplerGL.cpp
@@ -33,8 +33,10 @@
 namespace rx
 {
 
-SamplerGL::SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager)
-    : SamplerImpl(),
+SamplerGL::SamplerGL(const gl::SamplerState &state,
+                     const FunctionsGL *functions,
+                     StateManagerGL *stateManager)
+    : SamplerImpl(state),
       mFunctions(functions),
       mStateManager(stateManager),
       mAppliedSamplerState(),
@@ -49,20 +51,20 @@
     mSamplerID = 0;
 }
 
-void SamplerGL::syncState(const gl::SamplerState &samplerState) const
+void SamplerGL::syncState(const gl::Context *context)
 {
     // clang-format off
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
-    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_SRGB_DECODE_EXT, &gl::SamplerState::sRGBDecode);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
+    SyncSamplerStateMember(mFunctions, mSamplerID, mState, mAppliedSamplerState, GL_TEXTURE_SRGB_DECODE_EXT, &gl::SamplerState::sRGBDecode);
     // clang-format on
 }
 
diff --git a/src/libANGLE/renderer/gl/SamplerGL.h b/src/libANGLE/renderer/gl/SamplerGL.h
index c3fcfde..1c095cf 100644
--- a/src/libANGLE/renderer/gl/SamplerGL.h
+++ b/src/libANGLE/renderer/gl/SamplerGL.h
@@ -21,10 +21,12 @@
 class SamplerGL : public SamplerImpl
 {
   public:
-    SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager);
+    SamplerGL(const gl::SamplerState &state,
+              const FunctionsGL *functions,
+              StateManagerGL *stateManager);
     ~SamplerGL() override;
 
-    void syncState(const gl::SamplerState &samplerState) const;
+    void syncState(const gl::Context *context) override;
 
     GLuint getSamplerID() const;
 
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index 215a4e8..a8805e1 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -907,8 +907,7 @@
             const gl::Sampler *sampler = glState.getSampler(textureUnitIndex);
             if (sampler != nullptr)
             {
-                const SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
-                samplerGL->syncState(sampler->getSamplerState());
+                SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
                 bindSampler(textureUnitIndex, samplerGL->getSamplerID());
             }
             else
diff --git a/src/libANGLE/renderer/null/ContextNULL.cpp b/src/libANGLE/renderer/null/ContextNULL.cpp
index f0a1545..4d39cd9 100644
--- a/src/libANGLE/renderer/null/ContextNULL.cpp
+++ b/src/libANGLE/renderer/null/ContextNULL.cpp
@@ -357,9 +357,9 @@
     return new TransformFeedbackNULL(state);
 }
 
-SamplerImpl *ContextNULL::createSampler()
+SamplerImpl *ContextNULL::createSampler(const gl::SamplerState &state)
 {
-    return new SamplerNULL();
+    return new SamplerNULL(state);
 }
 
 std::vector<PathImpl *> ContextNULL::createPaths(GLsizei range)
diff --git a/src/libANGLE/renderer/null/ContextNULL.h b/src/libANGLE/renderer/null/ContextNULL.h
index 1c58135..d72b671 100644
--- a/src/libANGLE/renderer/null/ContextNULL.h
+++ b/src/libANGLE/renderer/null/ContextNULL.h
@@ -183,7 +183,7 @@
         const gl::TransformFeedbackState &state) override;
 
     // Sampler object creation
-    SamplerImpl *createSampler() override;
+    SamplerImpl *createSampler(const gl::SamplerState &state) override;
 
     std::vector<PathImpl *> createPaths(GLsizei range) override;
 
diff --git a/src/libANGLE/renderer/null/SamplerNULL.cpp b/src/libANGLE/renderer/null/SamplerNULL.cpp
index e1e8c7c..5387019 100644
--- a/src/libANGLE/renderer/null/SamplerNULL.cpp
+++ b/src/libANGLE/renderer/null/SamplerNULL.cpp
@@ -14,7 +14,7 @@
 namespace rx
 {
 
-SamplerNULL::SamplerNULL() : SamplerImpl()
+SamplerNULL::SamplerNULL(const gl::SamplerState &state) : SamplerImpl(state)
 {
 }
 
diff --git a/src/libANGLE/renderer/null/SamplerNULL.h b/src/libANGLE/renderer/null/SamplerNULL.h
index 031fafa..8a2808d 100644
--- a/src/libANGLE/renderer/null/SamplerNULL.h
+++ b/src/libANGLE/renderer/null/SamplerNULL.h
@@ -18,7 +18,7 @@
 class SamplerNULL : public SamplerImpl
 {
   public:
-    SamplerNULL();
+    SamplerNULL(const gl::SamplerState &state);
     ~SamplerNULL() override;
 };
 
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index f0e448a..55afc9a 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -540,9 +540,9 @@
     return new TransformFeedbackVk(state);
 }
 
-SamplerImpl *ContextVk::createSampler()
+SamplerImpl *ContextVk::createSampler(const gl::SamplerState &state)
 {
-    return new SamplerVk();
+    return new SamplerVk(state);
 }
 
 std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h
index 6961be8..0855a93 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.h
+++ b/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -126,7 +126,7 @@
         const gl::TransformFeedbackState &state) override;
 
     // Sampler object creation
-    SamplerImpl *createSampler() override;
+    SamplerImpl *createSampler(const gl::SamplerState &state) override;
 
     // Path object creation
     std::vector<PathImpl *> createPaths(GLsizei) override;
diff --git a/src/libANGLE/renderer/vulkan/SamplerVk.cpp b/src/libANGLE/renderer/vulkan/SamplerVk.cpp
index 00bb81b..00ec517 100644
--- a/src/libANGLE/renderer/vulkan/SamplerVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SamplerVk.cpp
@@ -14,7 +14,7 @@
 namespace rx
 {
 
-SamplerVk::SamplerVk() : SamplerImpl()
+SamplerVk::SamplerVk(const gl::SamplerState &state) : SamplerImpl(state)
 {
 }
 
diff --git a/src/libANGLE/renderer/vulkan/SamplerVk.h b/src/libANGLE/renderer/vulkan/SamplerVk.h
index 1111f40..1b20b5e 100644
--- a/src/libANGLE/renderer/vulkan/SamplerVk.h
+++ b/src/libANGLE/renderer/vulkan/SamplerVk.h
@@ -18,7 +18,7 @@
 class SamplerVk : public SamplerImpl
 {
   public:
-    SamplerVk();
+    SamplerVk(const gl::SamplerState &state);
     ~SamplerVk() override;
 };
 
diff --git a/src/tests/angle_unittests_utils.h b/src/tests/angle_unittests_utils.h
index 9920d39..b7c8938 100644
--- a/src/tests/angle_unittests_utils.h
+++ b/src/tests/angle_unittests_utils.h
@@ -61,7 +61,7 @@
     }
 
     // Sampler object creation
-    SamplerImpl *createSampler() override { return nullptr; }
+    SamplerImpl *createSampler(const gl::SamplerState &state) override { return nullptr; }
 
     std::vector<PathImpl *> createPaths(GLsizei range) override
     {
@@ -87,7 +87,7 @@
     MOCK_METHOD0(createSync, SyncImpl *());
     MOCK_METHOD1(createTransformFeedback,
                  TransformFeedbackImpl *(const gl::TransformFeedbackState &));
-    MOCK_METHOD0(createSampler, SamplerImpl *());
+    MOCK_METHOD1(createSampler, SamplerImpl *(const gl::SamplerState &));
     MOCK_METHOD1(createPaths, std::vector<PathImpl *>(GLsizei));
 };