Commit da8e257c by Martin Radev Committed by Commit Bot

Number of views should match when Draw* is called

The ANGLE_multiview specification is modified so that Draw* generates an error if the number of views in the active program does not match with the number of views in the active draw framebuffer object. The tests and validation are modified accordingly. The patch also sets a contact person, updates the contributor list and sets the correct enum values in the ANGLE_multiview specification. BUG=angleproject:2062 TEST=angle_end2end_tests Change-Id: I15fee4c5e729605bb1d6292f7ad1155637578dea Reviewed-on: https://chromium-review.googlesource.com/663160 Commit-Queue: Martin Radev <mradev@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 7d4602fc
...@@ -12,10 +12,11 @@ Contributors ...@@ -12,10 +12,11 @@ Contributors
Olli Etuaho, NVIDIA Corporation Olli Etuaho, NVIDIA Corporation
Corentin Wallez, Google Corentin Wallez, Google
Geoff Lang, Google Geoff Lang, Google
Jamie Madill, Google
Contact Contact
TODO Olli Etuaho (oetuaho 'at' nvidia.com)
Status Status
...@@ -58,14 +59,14 @@ New Tokens ...@@ -58,14 +59,14 @@ New Tokens
Accepted by the <pname> parameter of GetFramebufferAttachmentParameteriv: Accepted by the <pname> parameter of GetFramebufferAttachmentParameteriv:
FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE 0x9630 FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE 0x9630
FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE 0xXXXX FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE 0x969B
FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE 0x9632 FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE 0x9632
FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE 0xXXXX FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE 0x969C
Returned in <params> by GetFramebufferAttachmentParameteriv: Returned in <params> by GetFramebufferAttachmentParameteriv:
FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE 0xXXXX FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE 0x969D
FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE 0xXXXX FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE 0x969E
Accepted by the <pname> parameter of GetIntegerv: Accepted by the <pname> parameter of GetIntegerv:
...@@ -97,8 +98,7 @@ Additions to Chapter 2 of the OpenGL ES 3.0 Specification (OpenGL ES Operation) ...@@ -97,8 +98,7 @@ Additions to Chapter 2 of the OpenGL ES 3.0 Specification (OpenGL ES Operation)
Append to the end of the section: Append to the end of the section:
" "
If any drawing command is called while the current program object If any drawing command is called the number of views specified in the
uses the multi-view extension, the number of views specified in the
program must match the number of views in the draw framebuffer. If program must match the number of views in the draw framebuffer. If
there is a mismatch, an INVALID_OPERATION error is generated. there is a mismatch, an INVALID_OPERATION error is generated.
......
...@@ -2582,9 +2582,9 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count) ...@@ -2582,9 +2582,9 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
if (extensions.multiview) if (extensions.multiview)
{ {
const int programNumViews = program->getNumViews(); const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
const int framebufferNumViews = framebuffer->getNumViews(); const int framebufferNumViews = framebuffer->getNumViews();
if (programNumViews != -1 && framebufferNumViews != programNumViews) if (framebufferNumViews != programNumViews)
{ {
context->handleError(InvalidOperation() << "The number of views in the active program " context->handleError(InvalidOperation() << "The number of views in the active program "
"and draw framebuffer does not match."); "and draw framebuffer does not match.");
......
...@@ -594,7 +594,6 @@ TEST_P(MultiviewDrawValidationTest, IndirectDraw) ...@@ -594,7 +594,6 @@ TEST_P(MultiviewDrawValidationTest, IndirectDraw)
// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and // 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and
// program differs. // program differs.
// 2) does not generate any error if the number of views is the same. // 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) TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
{ {
if (!requestMultiviewExtension()) if (!requestMultiviewExtension())
...@@ -645,30 +644,38 @@ TEST_P(MultiviewDrawValidationTest, NumViewsMismatch) ...@@ -645,30 +644,38 @@ TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
}
// Check that no errors are generated if the program does not use the multiview extension. // The test verifies that glDraw* generates an INVALID_OPERATION error if the program does not use
// the multiview extension, but the active draw framebuffer has more than one view.
TEST_P(MultiviewDrawValidationTest, NumViewsMismatchForNonMultiviewProgram)
{
if (!requestMultiviewExtension())
{ {
const std::string &vsSourceNoMultiview = return;
"#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, const std::string &vsSourceNoMultiview =
0, 2, &viewportOffsets[0]); "#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);
glDrawArrays(GL_TRIANGLES, 0, 3); const GLint viewportOffsets[4] = {0, 0, 2, 0};
EXPECT_GL_NO_ERROR(); glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d, 0, 2,
&viewportOffsets[0]);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr); glDrawArrays(GL_TRIANGLES, 0, 3);
EXPECT_GL_NO_ERROR(); EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
} }
// The test verifies that glDraw*: // The test verifies that glDraw*:
...@@ -1118,14 +1125,17 @@ TEST_P(MultiviewRenderTest, DivisorOrderOfOperation) ...@@ -1118,14 +1125,17 @@ TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
// It is necessary to call draw, so that the divisor is propagated and to guarantee that dirty // It is necessary to call draw, so that the divisor is propagated and to guarantee that dirty
// bits are cleared. // bits are cleared.
glUseProgram(dummyProgram); glUseProgram(dummyProgram);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao[0]); glBindVertexArray(vao[0]);
glVertexAttribDivisor(1, 0); glVertexAttribDivisor(1, 0);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1); glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
glUseProgram(0); glUseProgram(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
// Check that vertexAttribDivisor uses the number of views to update the divisor. // Check that vertexAttribDivisor uses the number of views to update the divisor.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program); glUseProgram(program);
glVertexAttribDivisor(1, 1); glVertexAttribDivisor(1, 1);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1); glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
...@@ -1136,13 +1146,16 @@ TEST_P(MultiviewRenderTest, DivisorOrderOfOperation) ...@@ -1136,13 +1146,16 @@ TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
// We keep the vao active and propagate the divisor to guarantee that there are no unresolved // We keep the vao active and propagate the divisor to guarantee that there are no unresolved
// dirty bits when useProgram is called. // dirty bits when useProgram is called.
glUseProgram(dummyProgram); glUseProgram(dummyProgram);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glVertexAttribDivisor(1, 1); glVertexAttribDivisor(1, 1);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1); glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
glUseProgram(0); glUseProgram(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
// Check that useProgram uses the number of views to update the divisor. // Check that useProgram uses the number of views to update the divisor.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program); glUseProgram(program);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1); glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0)); EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
...@@ -1150,25 +1163,28 @@ TEST_P(MultiviewRenderTest, DivisorOrderOfOperation) ...@@ -1150,25 +1163,28 @@ TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
// We go through similar steps as before. // We go through similar steps as before.
glUseProgram(dummyProgram); glUseProgram(dummyProgram);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glVertexAttribDivisor(1, 1); glVertexAttribDivisor(1, 1);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1); glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
glUseProgram(0); glUseProgram(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
// Check that bindVertexArray uses the number of views to update the divisor. // Check that bindVertexArray uses the number of views to update the divisor.
{ {
// Call useProgram with vao[1] being active to guarantee that useProgram will adjust the // Call useProgram with vao[1] being active to guarantee that useProgram will adjust the
// divisor for vao[1] only. // divisor for vao[1] only.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao[1]); glBindVertexArray(vao[1]);
glUseProgram(program); glUseProgram(program);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1); glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(0); glBindVertexArray(0);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
// Bind vao[0] after useProgram is called to ensure that bindVertexArray is the call which // Bind vao[0] after useProgram is called to ensure that bindVertexArray is the call which
// adjusts the divisor. // adjusts the divisor.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao[0]); glBindVertexArray(vao[0]);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1); glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0)); EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment