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());