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 ...@@ -259,9 +259,21 @@ enum SubjectIndexes : angle::SubjectIndex
kDrawFramebufferSubjectIndex 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) bool IsColorMaskedOut(const BlendStateExt &blendStateExt, const GLint drawbuffer)
...@@ -3799,6 +3811,12 @@ void Context::clear(GLbitfield mask) ...@@ -3799,6 +3811,12 @@ void Context::clear(GLbitfield mask)
return; return;
} }
// Noop empty scissors.
if (IsEmptyScissor(mState))
{
return;
}
// Remove clear bits that are ineffective. An effective clear changes at least one fragment. If // 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. // color/depth/stencil masks make the clear ineffective we skip it altogether.
...@@ -3855,7 +3873,8 @@ bool Context::noopClearBuffer(GLenum buffer, GLint drawbuffer) const ...@@ -3855,7 +3873,8 @@ bool Context::noopClearBuffer(GLenum buffer, GLint drawbuffer) const
Framebuffer *framebufferObject = mState.getDrawFramebuffer(); Framebuffer *framebufferObject = mState.getDrawFramebuffer();
return !IsClearBufferEnabled(framebufferObject->getState(), buffer, drawbuffer) || 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) void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
......
...@@ -628,14 +628,20 @@ bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *in ...@@ -628,14 +628,20 @@ bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *in
{ {
return false; 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) if (intersection)
{ {
intersection->x = std::max(minSourceX, minClipX); intersection->x = x;
intersection->y = std::max(minSourceY, minClipY); intersection->y = y;
intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX); intersection->width = width;
intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY); intersection->height = height;
} }
return true; return width != 0 && height != 0;
} }
bool Box::operator==(const Box &other) const bool Box::operator==(const Box &other) const
......
...@@ -227,4 +227,64 @@ TEST(BlendStateExt, BlendFactors) ...@@ -227,4 +227,64 @@ TEST(BlendStateExt, BlendFactors)
ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), static_cast<GLenum>(GL_ONE)); 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 } // namespace angle
...@@ -429,13 +429,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context, ...@@ -429,13 +429,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
const gl::Rectangle scissoredRenderArea = getRotatedScissoredRenderArea(contextVk); const gl::Rectangle scissoredRenderArea = getRotatedScissoredRenderArea(contextVk);
ASSERT(scissoredRenderArea.width != 0 && scissoredRenderArea.height != 0);
// Discard clear altogether if scissor has 0 width or height.
if (scissoredRenderArea.width == 0 || scissoredRenderArea.height == 0)
{
ASSERT(mDeferredClears.empty());
return angle::Result::Continue;
}
// This function assumes that only enabled attachments are asked to be cleared. // This function assumes that only enabled attachments are asked to be cleared.
ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers); 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