Fix bugs in 2D Array Texture support.
This fixes assertion failures and other errors, reproducible
by running the dEQP Texture Format tests.
BUG=angle:813
Change-Id: I3b97f89323f9656b45f617211fb4579a24013951
Reviewed-on: https://chromium-review.googlesource.com/229351
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
diff --git a/tests/angle_tests/TextureTest.cpp b/tests/angle_tests/TextureTest.cpp
index f227457..d2e08e0 100644
--- a/tests/angle_tests/TextureTest.cpp
+++ b/tests/angle_tests/TextureTest.cpp
@@ -112,6 +112,89 @@
GLint mTextureScaleUniformLocation;
};
+ANGLE_TYPED_TEST_CASE(TextureTestES3, ES3_D3D11);
+
+template<typename T>
+class TextureTestES3 : public TextureTest<T>
+{
+ protected:
+ virtual void SetUp()
+ {
+ TextureTest::SetUp();
+
+ glGenTextures(1, &mTextureArray);
+ EXPECT_GL_NO_ERROR();
+
+ ASSERT_GL_NO_ERROR();
+
+ const std::string vertexShaderSource = SHADER_SOURCE
+ (
+ #version 300 es\n
+ precision highp float;
+ in vec4 position;
+ out vec2 texcoord;
+
+ uniform vec2 textureScale;
+
+ void main()
+ {
+ gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
+ texcoord = (position.xy * 0.5) + 0.5;
+ }
+ );
+
+ const std::string fragmentShaderSourceArray = SHADER_SOURCE
+ (
+ #version 300 es\n
+ precision highp float;
+ uniform sampler2DArray tex;
+ uniform int slice;
+ in vec2 texcoord;
+ out vec4 out_FragColor;
+
+ void main()
+ {
+ out_FragColor = texture(tex, vec3(texcoord, float(slice)));
+ }
+ );
+
+ mArrayProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceArray);
+ if (mArrayProgram == 0)
+ {
+ FAIL() << "shader compilation failed.";
+ }
+
+ mTextureArrayUniformLocation = glGetUniformLocation(mArrayProgram, "tex");
+ ASSERT_NE(-1, mTextureArrayUniformLocation);
+
+ mTextureArrayScaleUniformLocation = glGetUniformLocation(mArrayProgram, "textureScale");
+ ASSERT_NE(-1, mTextureArrayScaleUniformLocation);
+
+ mTextureArraySliceUniformLocation = glGetUniformLocation(mArrayProgram, "slice");
+ ASSERT_NE(-1, mTextureArraySliceUniformLocation);
+
+ glUseProgram(mArrayProgram);
+ glUniform2f(mTextureArrayScaleUniformLocation, 1.0f, 1.0f);
+ glUseProgram(0);
+ ASSERT_GL_NO_ERROR();
+ }
+
+ virtual void TearDown()
+ {
+ glDeleteTextures(1, &mTextureArray);
+ glDeleteProgram(mArrayProgram);
+
+ TextureTest::TearDown();
+ }
+
+ GLuint mTextureArray;
+
+ GLuint mArrayProgram;
+ GLint mTextureArrayUniformLocation;
+ GLint mTextureArrayScaleUniformLocation;
+ GLint mTextureArraySliceUniformLocation;
+};
+
TYPED_TEST(TextureTest, NegativeAPISubImage)
{
glBindTexture(GL_TEXTURE_2D, mTexture2D);
@@ -224,3 +307,86 @@
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
}
+
+// Creates a mipmapped 2D array texture with three layers, and calls ANGLE's GenerateMipmap.
+// Then tests if the mipmaps are rendered correctly for all three layers.
+TYPED_TEST(TextureTestES3, MipmapsForTextureArray)
+{
+ int px = getWindowWidth() / 2;
+ int py = getWindowHeight() / 2;
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
+
+ glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
+
+ // Fill the first layer with red
+ std::vector<GLubyte> pixels(4 * 16 * 16);
+ for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
+ {
+ pixels[pixelId * 4 + 0] = 255;
+ pixels[pixelId * 4 + 1] = 0;
+ pixels[pixelId * 4 + 2] = 0;
+ pixels[pixelId * 4 + 3] = 255;
+ }
+
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+
+ // Fill the second layer with green
+ for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
+ {
+ pixels[pixelId * 4 + 0] = 0;
+ pixels[pixelId * 4 + 1] = 255;
+ pixels[pixelId * 4 + 2] = 0;
+ pixels[pixelId * 4 + 3] = 255;
+ }
+
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+
+ // Fill the third layer with blue
+ for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
+ {
+ pixels[pixelId * 4 + 0] = 0;
+ pixels[pixelId * 4 + 1] = 0;
+ pixels[pixelId * 4 + 2] = 255;
+ pixels[pixelId * 4 + 3] = 255;
+ }
+
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ EXPECT_GL_NO_ERROR();
+
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+
+ EXPECT_GL_NO_ERROR();
+
+ glUseProgram(mArrayProgram);
+ glUniform1i(mTextureArrayUniformLocation, 0);
+ glUniform2f(mTextureScaleUniformLocation, 0.0625f, 0.0625f);
+
+ EXPECT_GL_NO_ERROR();
+
+ // Draw the first slice
+ glUseProgram(mArrayProgram);
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
+
+ // Draw the second slice
+ glUseProgram(mArrayProgram);
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
+
+ // Draw the third slice
+ glUseProgram(mArrayProgram);
+ glUniform1i(mTextureArraySliceUniformLocation, 2);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(px, py, 0, 0, 255, 255);
+}