Commit 61e710b6 by Martin Radev Committed by Commit Bot

GL: Optimize multi-view layered Clear* commands

Until this patch multi-view layered framebuffers used to be cleared by attaching a single layer of each attachment to a framebuffer and calling the Clear* command for that internal framebuffer. According to the GL 4.1+ specifications, Clear* commands clear all of the layers of an attached 2D texture array. If all of the layers are active for a multi-view layered framebuffer, then we can directly call the corresponding Clear* command instead of iterating over each layer and clearing it. BUG=angleproject:2062 TEST=angle_end2end_tests Change-Id: Ie4dfd9fff47715b502f358272bfc47c0373c4e91 Reviewed-on: https://chromium-review.googlesource.com/649209 Commit-Queue: Martin Radev <mradev@nvidia.com> Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent c1d4e550
...@@ -104,8 +104,61 @@ void BindFramebufferAttachment(const FunctionsGL *functions, ...@@ -104,8 +104,61 @@ void BindFramebufferAttachment(const FunctionsGL *functions,
} }
} }
bool RequiresMultiviewClear(const FramebufferAttachment *attachment, bool scissorTestEnabled) bool AreAllLayersActive(const FramebufferAttachment &attachment)
{ {
int baseViewIndex = attachment.getBaseViewIndex();
if (baseViewIndex != 0)
{
return false;
}
const ImageIndex &imageIndex = attachment.getTextureImageIndex();
int numLayers =
static_cast<int>(attachment.getTexture()->getDepth(imageIndex.type, imageIndex.mipIndex));
return (attachment.getNumViews() == numLayers);
}
bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabled)
{
// Get one attachment and check whether all layers are attached.
const FramebufferAttachment *attachment = nullptr;
bool allTextureArraysAreFullyAttached = true;
for (const FramebufferAttachment &colorAttachment : state.getColorAttachments())
{
if (colorAttachment.isAttached())
{
if (colorAttachment.getMultiviewLayout() == GL_NONE)
{
return false;
}
attachment = &colorAttachment;
allTextureArraysAreFullyAttached =
allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
}
}
const FramebufferAttachment *depthAttachment = state.getDepthAttachment();
if (depthAttachment)
{
if (depthAttachment->getMultiviewLayout() == GL_NONE)
{
return false;
}
attachment = depthAttachment;
allTextureArraysAreFullyAttached =
allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
}
const FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
if (stencilAttachment)
{
if (stencilAttachment->getMultiviewLayout() == GL_NONE)
{
return false;
}
attachment = stencilAttachment;
allTextureArraysAreFullyAttached =
allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
}
if (attachment == nullptr) if (attachment == nullptr)
{ {
return false; return false;
...@@ -113,13 +166,11 @@ bool RequiresMultiviewClear(const FramebufferAttachment *attachment, bool scisso ...@@ -113,13 +166,11 @@ bool RequiresMultiviewClear(const FramebufferAttachment *attachment, bool scisso
switch (attachment->getMultiviewLayout()) switch (attachment->getMultiviewLayout())
{ {
case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE: case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
// TODO(mradev): Optimize this for layered FBOs in which all of the layers in each // If all layers of each texture array are active, then there is no need to issue a
// attachment are active. // special multiview clear.
return true; return !allTextureArraysAreFullyAttached;
case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE: case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
return (scissorTestEnabled == true); return (scissorTestEnabled == true);
case GL_NONE:
return false;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -241,8 +292,7 @@ Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask) ...@@ -241,8 +292,7 @@ Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
syncClearState(context, mask); syncClearState(context, mask);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
const auto &firstAttachment = mState.getFirstNonNullAttachment(); if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
{ {
mFunctions->clear(mask); mFunctions->clear(mask);
} }
...@@ -264,8 +314,7 @@ Error FramebufferGL::clearBufferfv(const gl::Context *context, ...@@ -264,8 +314,7 @@ Error FramebufferGL::clearBufferfv(const gl::Context *context,
syncClearBufferState(context, buffer, drawbuffer); syncClearBufferState(context, buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
const auto &firstAttachment = mState.getFirstNonNullAttachment(); if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
{ {
mFunctions->clearBufferfv(buffer, drawbuffer, values); mFunctions->clearBufferfv(buffer, drawbuffer, values);
} }
...@@ -288,8 +337,7 @@ Error FramebufferGL::clearBufferuiv(const gl::Context *context, ...@@ -288,8 +337,7 @@ Error FramebufferGL::clearBufferuiv(const gl::Context *context,
syncClearBufferState(context, buffer, drawbuffer); syncClearBufferState(context, buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
const auto &firstAttachment = mState.getFirstNonNullAttachment(); if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
{ {
mFunctions->clearBufferuiv(buffer, drawbuffer, values); mFunctions->clearBufferuiv(buffer, drawbuffer, values);
} }
...@@ -312,8 +360,7 @@ Error FramebufferGL::clearBufferiv(const gl::Context *context, ...@@ -312,8 +360,7 @@ Error FramebufferGL::clearBufferiv(const gl::Context *context,
syncClearBufferState(context, buffer, drawbuffer); syncClearBufferState(context, buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
const auto &firstAttachment = mState.getFirstNonNullAttachment(); if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
{ {
mFunctions->clearBufferiv(buffer, drawbuffer, values); mFunctions->clearBufferiv(buffer, drawbuffer, values);
} }
...@@ -337,8 +384,7 @@ Error FramebufferGL::clearBufferfi(const gl::Context *context, ...@@ -337,8 +384,7 @@ Error FramebufferGL::clearBufferfi(const gl::Context *context,
syncClearBufferState(context, buffer, drawbuffer); syncClearBufferState(context, buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
const auto &firstAttachment = mState.getFirstNonNullAttachment(); if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
{ {
mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil); mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
} }
......
...@@ -1327,6 +1327,25 @@ TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach) ...@@ -1327,6 +1327,25 @@ TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
// array are attached. The test is added because a special fast code path is used for this case.
TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
{
if (!requestMultiviewExtension())
{
return;
}
initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
}
ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest, ES3_OPENGL(), ES3_D3D11()); ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest, ES3_OPENGL(), ES3_D3D11());
ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest, ES3_OPENGL(), ES3_D3D11()); ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest, ES3_OPENGL(), ES3_D3D11());
\ 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