Commit 9bc9a321 by Martin Radev Committed by Commit Bot

Integrate multiview state in FBO completeness check

The patch extends the FBO completeness validation to include the multiview state members according to the ANGLE_multiview specification. It also changes the numViews in FramebufferAttachment to be consistently of type GLsizei instead of GLint. BUG=angleproject:2062 TEST=angle_end2end_tests Change-Id: Ibe550ba03204d808d96a4edf4807c68421aa1158 Reviewed-on: https://chromium-review.googlesource.com/581193 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 7c5f5268
......@@ -39,6 +39,32 @@ void BindResourceChannel(OnAttachmentDirtyBinding *binding, FramebufferAttachmen
binding->bind(resource ? resource->getDirtyChannel() : nullptr);
}
bool CheckMultiviewStateMatchesForCompleteness(const FramebufferAttachment *firstAttachment,
const FramebufferAttachment *secondAttachment)
{
ASSERT(firstAttachment && secondAttachment);
ASSERT(firstAttachment->isAttached() && secondAttachment->isAttached());
if (firstAttachment->getNumViews() != secondAttachment->getNumViews())
{
return false;
}
if (firstAttachment->getBaseViewIndex() != secondAttachment->getBaseViewIndex())
{
return false;
}
if (firstAttachment->getMultiviewLayout() != secondAttachment->getMultiviewLayout())
{
return false;
}
if (firstAttachment->getMultiviewViewportOffsets() !=
secondAttachment->getMultiviewViewportOffsets())
{
return false;
}
return true;
}
bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
{
ASSERT(attachment.isAttached());
......@@ -797,6 +823,8 @@ GLenum Framebuffer::checkStatusImpl(const Context *context)
Optional<GLboolean> fixedSampleLocations;
bool hasRenderbuffer = false;
const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
{
if (colorAttachment.isAttached())
......@@ -835,6 +863,11 @@ GLenum Framebuffer::checkStatusImpl(const Context *context)
}
}
if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
{
return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
hasAttachments = true;
}
......@@ -860,6 +893,11 @@ GLenum Framebuffer::checkStatusImpl(const Context *context)
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
}
if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
{
return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
hasAttachments = true;
}
......@@ -884,6 +922,11 @@ GLenum Framebuffer::checkStatusImpl(const Context *context)
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
}
if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
{
return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
hasAttachments = true;
}
......@@ -910,6 +953,12 @@ GLenum Framebuffer::checkStatusImpl(const Context *context)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
&mState.mWebGLDepthStencilAttachment))
{
return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
}
else if (mState.mStencilAttachment.isAttached() &&
mState.mStencilAttachment.getDepthSize() > 0)
......
......@@ -23,7 +23,7 @@ namespace gl
////// FramebufferAttachment::Target Implementation //////
const GLint FramebufferAttachment::kDefaultNumViews = 1;
const GLsizei FramebufferAttachment::kDefaultNumViews = 1;
const GLenum FramebufferAttachment::kDefaultMultiviewLayout = GL_NONE;
const GLint FramebufferAttachment::kDefaultBaseViewIndex = 0;
const GLint FramebufferAttachment::kDefaultViewportOffsets[2] = {0};
......@@ -231,7 +231,7 @@ GLint FramebufferAttachment::layer() const
return 0;
}
GLint FramebufferAttachment::getNumViews() const
GLsizei FramebufferAttachment::getNumViews() const
{
return mNumViews;
}
......
......@@ -97,7 +97,7 @@ class FramebufferAttachment final
GLenum cubeMapFace() const;
GLint mipLevel() const;
GLint layer() const;
GLint getNumViews() const;
GLsizei getNumViews() const;
GLenum getMultiviewLayout() const;
GLint getBaseViewIndex() const;
const std::vector<Offset> &getMultiviewViewportOffsets() const;
......@@ -129,7 +129,7 @@ class FramebufferAttachment final
bool operator==(const FramebufferAttachment &other) const;
bool operator!=(const FramebufferAttachment &other) const;
static const GLint kDefaultNumViews;
static const GLsizei kDefaultNumViews;
static const GLenum kDefaultMultiviewLayout;
static const GLint kDefaultBaseViewIndex;
static const GLint kDefaultViewportOffsets[2];
......@@ -163,7 +163,7 @@ class FramebufferAttachment final
GLenum mType;
Target mTarget;
FramebufferAttachmentObject *mResource;
GLint mNumViews;
GLsizei mNumViews;
GLenum mMultiviewLayout;
GLint mBaseViewIndex;
std::vector<Offset> mViewportOffsets;
......
......@@ -11,6 +11,20 @@
using namespace angle;
namespace
{
GLuint CreateTexture2D(GLenum internalFormat, GLenum format, GLenum type)
{
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, nullptr);
return tex;
}
} // namespace
class FramebufferMultiviewTest : public ANGLETest
{
protected:
......@@ -55,14 +69,6 @@ class FramebufferMultiviewTest : public ANGLETest
ANGLETest::TearDown();
}
void createTexture2D()
{
glGenTextures(1, &mTexture2D);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, 1, 1);
ASSERT_GL_NO_ERROR();
}
void createTexture2DArray()
{
glGenTextures(1, &mTexture2DArray);
......@@ -102,7 +108,8 @@ TEST_P(FramebufferMultiviewTest, DefaultState)
return;
}
createTexture2D();
mTexture2D = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
GLint numViews = -1;
......@@ -139,7 +146,8 @@ TEST_P(FramebufferMultiviewTest, DefaultState)
// the ANGLE_multiview tokens results in an INVALID_ENUM error.
TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
{
createTexture2D();
mTexture2D = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
GLint numViews = -1;
......@@ -176,7 +184,8 @@ TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
return;
}
createTexture2D();
mTexture2D = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_GL_NO_ERROR();
// Negative offsets.
int viewportOffsets[2] = {-1};
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture2D,
......@@ -219,7 +228,8 @@ TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
// available.
TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
{
createTexture2D();
mTexture2D = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_GL_NO_ERROR();
int viewportOffsets[2] = {0};
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture2D,
0, 1, &viewportOffsets[0]);
......@@ -235,7 +245,8 @@ TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
}
const GLint viewportOffsets[4] = {0, 0, 1, 2};
createTexture2D();
mTexture2D = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_GL_NO_ERROR();
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture2D,
0, 2, &viewportOffsets[0]);
ASSERT_GL_NO_ERROR();
......@@ -272,4 +283,100 @@ TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
}
}
// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
// attachments.
TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
{
if (!requestMultiviewExtension())
{
return;
}
mTexture2D = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_GL_NO_ERROR();
GLuint otherTexture = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_GL_NO_ERROR();
GLuint depthTexture = CreateTexture2D(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT);
ASSERT_GL_NO_ERROR();
const GLint viewportOffsets[4] = {0, 0, 2, 0};
const GLint otherViewportOffsets[4] = {2, 0, 4, 0};
// Set the 0th attachment and keep it as it is till the end of the test. The 1st or depth
// attachment will me modified to change the framebuffer's status.
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture2D,
0, 2, &viewportOffsets[0]);
ASSERT_GL_NO_ERROR();
// Color attachment 1.
{
// Test framebuffer completeness when the number of views differ.
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
otherTexture, 0, 1, &viewportOffsets[0]);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
glCheckFramebufferStatus(GL_FRAMEBUFFER));
// Test framebuffer completeness when the viewport offsets differ.
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
otherTexture, 0, 2, &otherViewportOffsets[0]);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
glCheckFramebufferStatus(GL_FRAMEBUFFER));
// Test framebuffer completeness when attachment layouts differ.
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTexture,
0);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
glCheckFramebufferStatus(GL_FRAMEBUFFER));
// Test that framebuffer is complete when the number of views, viewport offsets and layouts
// are the same.
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
otherTexture, 0, 2, &viewportOffsets[0]);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
// Reset attachment 1
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
&viewportOffsets[0]);
}
// Depth attachment.
{
// Test framebuffer completeness when the number of views differ.
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
depthTexture, 0, 1, &viewportOffsets[0]);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
glCheckFramebufferStatus(GL_FRAMEBUFFER));
// Test framebuffer completeness when the viewport offsets differ.
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
depthTexture, 0, 2, &otherViewportOffsets[0]);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
glCheckFramebufferStatus(GL_FRAMEBUFFER));
// Test framebuffer completeness when attachment layouts differ.
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
glCheckFramebufferStatus(GL_FRAMEBUFFER));
// Test that framebuffer is complete when the number of views, viewport offsets and layouts
// are the same.
glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
depthTexture, 0, 2, &viewportOffsets[0]);
ASSERT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
glDeleteTextures(1, &depthTexture);
glDeleteTextures(1, &otherTexture);
}
ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL());
\ No newline at end of file
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