Commit 42e10d3e by Shahbaz Youssefi Committed by Commit Bot

Noop empty-scissor clears

Bug: angleproject:4988 Change-Id: I64909292927e20c65141302c9bf5e7ef09af84b7 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2511370 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 807e6b33
......@@ -259,9 +259,21 @@ enum SubjectIndexes : angle::SubjectIndex
kDrawFramebufferSubjectIndex
};
bool IsClearBufferEnabled(const FramebufferState &mState, GLenum buffer, GLint drawbuffer)
bool IsClearBufferEnabled(const FramebufferState &fbState, GLenum buffer, GLint drawbuffer)
{
return buffer != GL_COLOR || mState.getEnabledDrawBuffers()[drawbuffer];
return buffer != GL_COLOR || fbState.getEnabledDrawBuffers()[drawbuffer];
}
bool IsEmptyScissor(const State &glState)
{
if (!glState.isScissorTestEnabled())
{
return false;
}
const Extents &dimensions = glState.getDrawFramebuffer()->getExtents();
Rectangle framebufferArea(0, 0, dimensions.width, dimensions.height);
return !ClipRectangle(framebufferArea, glState.getScissor(), nullptr);
}
bool IsColorMaskedOut(const BlendStateExt &blendStateExt, const GLint drawbuffer)
......@@ -3799,6 +3811,12 @@ void Context::clear(GLbitfield mask)
return;
}
// Noop empty scissors.
if (IsEmptyScissor(mState))
{
return;
}
// Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
// color/depth/stencil masks make the clear ineffective we skip it altogether.
......@@ -3855,7 +3873,8 @@ bool Context::noopClearBuffer(GLenum buffer, GLint drawbuffer) const
Framebuffer *framebufferObject = mState.getDrawFramebuffer();
return !IsClearBufferEnabled(framebufferObject->getState(), buffer, drawbuffer) ||
mState.isRasterizerDiscardEnabled() || isClearBufferMaskedOut(buffer, drawbuffer);
mState.isRasterizerDiscardEnabled() || isClearBufferMaskedOut(buffer, drawbuffer) ||
IsEmptyScissor(mState);
}
void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
......
......@@ -628,14 +628,20 @@ bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *in
{
return false;
}
int x = std::max(minSourceX, minClipX);
int y = std::max(minSourceY, minClipY);
int width = std::min(maxSourceX, maxClipX) - x;
int height = std::min(maxSourceY, maxClipY) - y;
if (intersection)
{
intersection->x = std::max(minSourceX, minClipX);
intersection->y = std::max(minSourceY, minClipY);
intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX);
intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY);
intersection->x = x;
intersection->y = y;
intersection->width = width;
intersection->height = height;
}
return true;
return width != 0 && height != 0;
}
bool Box::operator==(const Box &other) const
......
......@@ -227,4 +227,64 @@ TEST(BlendStateExt, BlendFactors)
ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), static_cast<GLenum>(GL_ONE));
}
// Test clip rectangle
TEST(Rectangle, Clip)
{
const gl::Rectangle source(0, 0, 100, 200);
const gl::Rectangle clip1(0, 0, 50, 100);
gl::Rectangle result;
ASSERT_TRUE(gl::ClipRectangle(source, clip1, &result));
ASSERT_EQ(result.x, 0);
ASSERT_EQ(result.y, 0);
ASSERT_EQ(result.width, 50);
ASSERT_EQ(result.height, 100);
gl::Rectangle clip2(10, 20, 30, 40);
ASSERT_TRUE(gl::ClipRectangle(source, clip2, &result));
ASSERT_EQ(result.x, 10);
ASSERT_EQ(result.y, 20);
ASSERT_EQ(result.width, 30);
ASSERT_EQ(result.height, 40);
gl::Rectangle clip3(-20, -30, 10000, 400000);
ASSERT_TRUE(gl::ClipRectangle(source, clip3, &result));
ASSERT_EQ(result.x, 0);
ASSERT_EQ(result.y, 0);
ASSERT_EQ(result.width, 100);
ASSERT_EQ(result.height, 200);
gl::Rectangle clip4(50, 100, -20, -30);
ASSERT_TRUE(gl::ClipRectangle(source, clip4, &result));
ASSERT_EQ(result.x, 30);
ASSERT_EQ(result.y, 70);
ASSERT_EQ(result.width, 20);
ASSERT_EQ(result.height, 30);
// Non-overlapping rectangles
gl::Rectangle clip5(-100, 0, 99, 200);
ASSERT_FALSE(gl::ClipRectangle(source, clip5, nullptr));
gl::Rectangle clip6(0, -100, 100, 99);
ASSERT_FALSE(gl::ClipRectangle(source, clip6, nullptr));
gl::Rectangle clip7(101, 0, 99, 200);
ASSERT_FALSE(gl::ClipRectangle(source, clip7, nullptr));
gl::Rectangle clip8(0, 201, 100, 99);
ASSERT_FALSE(gl::ClipRectangle(source, clip8, nullptr));
// Zero-width/height rectangles
gl::Rectangle clip9(50, 0, 0, 200);
ASSERT_FALSE(gl::ClipRectangle(source, clip9, nullptr));
ASSERT_FALSE(gl::ClipRectangle(clip9, source, nullptr));
gl::Rectangle clip10(0, 100, 100, 0);
ASSERT_FALSE(gl::ClipRectangle(source, clip10, nullptr));
ASSERT_FALSE(gl::ClipRectangle(clip10, source, nullptr));
}
} // namespace angle
......@@ -429,13 +429,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
ContextVk *contextVk = vk::GetImpl(context);
const gl::Rectangle scissoredRenderArea = getRotatedScissoredRenderArea(contextVk);
// Discard clear altogether if scissor has 0 width or height.
if (scissoredRenderArea.width == 0 || scissoredRenderArea.height == 0)
{
ASSERT(mDeferredClears.empty());
return angle::Result::Continue;
}
ASSERT(scissoredRenderArea.width != 0 && scissoredRenderArea.height != 0);
// This function assumes that only enabled attachments are asked to be cleared.
ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
......
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