Vulkan: Issue when drawing with a texture and rebinding after.

Added 2 tests in StateChangeTest.cpp to validate the behavior and
reproduce the issue I saw in dEQP.

Bug: angleproject:2479

Change-Id: I29c3da0474ec2b13a10fc266284cb19a07675da2
Reviewed-on: https://chromium-review.googlesource.com/1025951
Commit-Queue: Luc Ferron <lucferron@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 315ad32..0c941de 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -168,6 +168,11 @@
     return vk::NoError();
 }
 
+bool PixelBuffer::empty() const
+{
+    return mSubresourceUpdates.empty();
+}
+
 PixelBuffer::SubresourceUpdate::SubresourceUpdate() : bufferHandle(VK_NULL_HANDLE)
 {
 }
@@ -382,6 +387,11 @@
 
 vk::Error TextureVk::ensureImageInitialized(RendererVk *renderer)
 {
+    if (mImage.valid() && mPixelBuffer.empty())
+    {
+        return vk::NoError();
+    }
+
     VkDevice device                  = renderer->getDevice();
     vk::CommandBuffer *commandBuffer = nullptr;
 
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h
index e2fa3ae..5b1602c 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.h
+++ b/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -39,6 +39,8 @@
                                   vk::ImageHelper *image,
                                   vk::CommandBuffer *commandBuffer);
 
+    bool empty() const;
+
   private:
     struct SubresourceUpdate
     {
diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
index e5d4522..fab66f4 100644
--- a/src/tests/deqp_support/deqp_gles2_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
@@ -200,7 +200,8 @@
 2161 VULKAN : dEQP-GLES2.functional.texture.filtering.cube.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.filtering.nearest_mipmap_* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.filtering.linear_mipmap_* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.mipmap.* = SKIP
+2161 VULKAN : dEQP-GLES2.functional.texture.mipmap.2d.generate.* = SKIP
+2161 VULKAN : dEQP-GLES2.functional.texture.mipmap.cube.generate.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.specification.basic_copytex* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.completeness.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.vertex.* = SKIP
diff --git a/src/tests/gl_tests/StateChangeTest.cpp b/src/tests/gl_tests/StateChangeTest.cpp
index c46e536..aea187d 100644
--- a/src/tests/gl_tests/StateChangeTest.cpp
+++ b/src/tests/gl_tests/StateChangeTest.cpp
@@ -1325,6 +1325,98 @@
     EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::white);
 }
 
+// Tests that bind the same texture all the time between different draw calls.
+TEST_P(SimpleStateChangeTest, RebindTextureDrawAgain)
+{
+    GLuint program = get2DTexturedQuadProgram();
+    glUseProgram(program);
+
+    std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
+
+    // Setup the texture
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    // Setup the vertex array to draw a quad.
+    GLint positionLocation = glGetAttribLocation(program, "position");
+    setupQuadVertexBuffer(1.0f, 1.0f);
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(positionLocation);
+
+    // Draw quad
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Bind again
+    glBindTexture(GL_TEXTURE_2D, tex);
+    ASSERT_GL_NO_ERROR();
+
+    // Draw again, should still work.
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Validate whole surface is filled with cyan.
+    int h = getWindowHeight() - 1;
+    int w = getWindowWidth() - 1;
+
+    EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
+}
+
+// Test that we can alternate between textures between different draws.
+TEST_P(SimpleStateChangeTest, DrawTextureAThenTextureBThenTextureA)
+{
+    GLuint program = get2DTexturedQuadProgram();
+    glUseProgram(program);
+
+    std::array<GLColor, 4> colorsTex1 = {
+        {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
+
+    std::array<GLColor, 4> colorsTex2 = {
+        {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
+
+    // Setup the texture
+    GLTexture tex1;
+    glBindTexture(GL_TEXTURE_2D, tex1);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex1.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    GLTexture tex2;
+    glBindTexture(GL_TEXTURE_2D, tex2);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex2.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    // Setup the vertex array to draw a quad.
+    GLint positionLocation = glGetAttribLocation(program, "position");
+    setupQuadVertexBuffer(1.0f, 1.0f);
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(positionLocation);
+
+    // Draw quad
+    glBindTexture(GL_TEXTURE_2D, tex1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Bind again, draw again
+    glBindTexture(GL_TEXTURE_2D, tex2);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Bind again, draw again
+    glBindTexture(GL_TEXTURE_2D, tex1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+
+    // Validate whole surface is filled with cyan.
+    int h = getWindowHeight() - 1;
+    int w = getWindowWidth() - 1;
+
+    EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
+}
+
 // Tests that redefining an in-flight Texture does not affect the in-flight resource.
 TEST_P(SimpleStateChangeTest, RedefineTextureInUse)
 {
@@ -1811,5 +1903,4 @@
                        ES2_OPENGL(),
                        ES2_D3D11_FL9_3());
 ANGLE_INSTANTIATE_TEST(StateChangeTestES3, ES3_D3D11(), ES3_OPENGL());
-
 ANGLE_INSTANTIATE_TEST(SimpleStateChangeTest, ES2_VULKAN(), ES2_OPENGL());