Generate error on program-framebuffer num views mismatch
According to the ANGLE_multiview spec Draw* commands should generate
an INVALID_OPERATION error if the program uses the multiview extension
and the number of views in the active draw framebuffer and active
program differs. The patch addresses this by extending the base draw
call validation.
BUG=angleproject:2062
TEST=angle_end2end_tests
Change-Id: I369070beb5ccb17211dbe61ebec40bfcbcf5bc4e
Reviewed-on: https://chromium-review.googlesource.com/586605
Commit-Queue: Martin Radev <mradev@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/tests/gl_tests/MultiviewDrawTest.cpp b/src/tests/gl_tests/MultiviewDrawTest.cpp
index 765c137..1f37c22 100644
--- a/src/tests/gl_tests/MultiviewDrawTest.cpp
+++ b/src/tests/gl_tests/MultiviewDrawTest.cpp
@@ -21,6 +21,7 @@
setWindowHeight(128);
setWebGLCompatibilityEnabled(true);
}
+ virtual ~MultiviewDrawTest() {}
void SetUp() override
{
@@ -49,23 +50,52 @@
PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
};
+class MultiviewDrawValidationTest : public MultiviewDrawTest
+{
+ protected:
+ MultiviewDrawValidationTest() {}
+
+ void SetUp() override
+ {
+ MultiviewDrawTest::SetUp();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+ glBindTexture(GL_TEXTURE_2D, mTex2d);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+ glBindVertexArray(mVao);
+
+ const float kVertexData[3] = {0.0f};
+ glBindBuffer(GL_ARRAY_BUFFER, mVbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3u, &kVertexData[0], GL_STATIC_DRAW);
+
+ const unsigned int kIndices[3] = {0u, 1u, 2u};
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIbo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, &kIndices[0],
+ GL_STATIC_DRAW);
+ ASSERT_GL_NO_ERROR();
+ }
+
+ GLTexture mTex2d;
+ GLVertexArray mVao;
+ GLBuffer mVbo;
+ GLBuffer mIbo;
+ GLFramebuffer mFramebuffer;
+};
+
// The test verifies that glDraw*Indirect:
// 1) generates an INVALID_OPERATION error if the number of views in the draw framebuffer is greater
// than 1.
// 2) does not generate any error if the draw framebuffer has exactly 1 view.
-TEST_P(MultiviewDrawTest, IndirectDraw)
+TEST_P(MultiviewDrawValidationTest, IndirectDraw)
{
if (!requestMultiviewExtension())
{
return;
}
- GLTexture tex2d;
- glBindTexture(GL_TEXTURE_2D, tex2d);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
-
const GLint viewportOffsets[4] = {0, 0, 2, 0};
- ASSERT_GL_NO_ERROR();
const std::string fsSource =
"#version 300 es\n"
@@ -74,31 +104,12 @@
"void main()\n"
"{}\n";
- GLVertexArray vao;
- glBindVertexArray(vao);
-
- const float kVertexData[3] = {0.0f};
- const unsigned int kIndices[3] = {0u, 1u, 2u};
-
- GLBuffer vbo;
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3u, &kVertexData[0], GL_STATIC_DRAW);
- ASSERT_GL_NO_ERROR();
-
- GLBuffer ibo;
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, &kIndices[0], GL_STATIC_DRAW);
- ASSERT_GL_NO_ERROR();
-
GLBuffer commandBuffer;
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, commandBuffer);
const GLuint commandData[] = {1u, 1u, 0u, 0u, 0u};
glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(GLuint) * 5u, &commandData[0], GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
- GLFramebuffer framebuffer;
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
-
// Check for a GL_INVALID_OPERATION error with the framebuffer having 2 views.
{
const std::string &vsSource =
@@ -110,8 +121,8 @@
ANGLE_GL_PROGRAM(program, vsSource, fsSource);
glUseProgram(program);
- glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2d, 0,
- 2, &viewportOffsets[0]);
+ glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
+ 0, 2, &viewportOffsets[0]);
glDrawArraysIndirect(GL_TRIANGLES, nullptr);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
@@ -131,8 +142,8 @@
ANGLE_GL_PROGRAM(program, vsSource, fsSource);
glUseProgram(program);
- glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2d, 0,
- 1, &viewportOffsets[0]);
+ glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
+ 0, 1, &viewportOffsets[0]);
glDrawArraysIndirect(GL_TRIANGLES, nullptr);
EXPECT_GL_NO_ERROR();
@@ -142,4 +153,85 @@
}
}
-ANGLE_INSTANTIATE_TEST(MultiviewDrawTest, ES31_OPENGL());
\ No newline at end of file
+// The test verifies that glDraw*:
+// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and
+// program differs.
+// 2) does not generate any error if the number of views is the same.
+// 3) does not generate any error if the program does not use the multiview extension.
+TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
+{
+ if (!requestMultiviewExtension())
+ {
+ return;
+ }
+
+ const GLint viewportOffsets[4] = {0, 0, 2, 0};
+
+ const std::string &vsSource =
+ "#version 300 es\n"
+ "#extension GL_OVR_multiview : require\n"
+ "layout(num_views = 2) in;\n"
+ "void main()\n"
+ "{}\n";
+ const std::string &fsSource =
+ "#version 300 es\n"
+ "#extension GL_OVR_multiview : require\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{}\n";
+ ANGLE_GL_PROGRAM(program, vsSource, fsSource);
+ glUseProgram(program);
+
+ // Check for a GL_INVALID_OPERATION error with the framebuffer and program having different
+ // number of views.
+ {
+ // The framebuffer has only 1 view.
+ glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
+ 0, 1, &viewportOffsets[0]);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+ glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ }
+
+ // Check that no errors are generated if the number of views in both program and draw
+ // framebuffer matches.
+ {
+ glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
+ 0, 2, &viewportOffsets[0]);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ EXPECT_GL_NO_ERROR();
+
+ glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
+ EXPECT_GL_NO_ERROR();
+ }
+
+ // Check that no errors are generated if the program does not use the multiview extension.
+ {
+ const std::string &vsSourceNoMultiview =
+ "#version 300 es\n"
+ "void main()\n"
+ "{}\n";
+ const std::string &fsSourceNoMultiview =
+ "#version 300 es\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{}\n";
+ ANGLE_GL_PROGRAM(programNoMultiview, vsSourceNoMultiview, fsSourceNoMultiview);
+ glUseProgram(programNoMultiview);
+
+ glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
+ 0, 2, &viewportOffsets[0]);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ EXPECT_GL_NO_ERROR();
+
+ glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
+ EXPECT_GL_NO_ERROR();
+ }
+}
+
+ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest, ES31_OPENGL());
\ No newline at end of file