Vulkan: Don't break the RP on masked/scissored clears

Bug: b/166809097
Change-Id: Iedd10a6528808e859c5693a2d30c98aca1a1159c
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2390862
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Charlie Lao <cclao@google.com>
Reviewed-by: Tim Van Patten <timvp@google.com>
This commit is contained in:
Shahbaz Youssefi 2020-09-02 11:10:00 -04:00 коммит произвёл Commit Bot
Родитель d0d523f4b5
Коммит b2944fcfe0
3 изменённых файлов: 56 добавлений и 2 удалений

Просмотреть файл

@ -1999,6 +1999,10 @@ angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
// Scissored-only clears are handled in clearImmediatelyWithRenderPassOp.
ASSERT(clearColorBuffers.any() || clearStencil);
// Force start a new render pass for the depth clear to take effect.
// UtilsVk::clearFramebuffer may not start a new render pass if there's one already started.
ANGLE_TRY(flushDeferredClears(contextVk, clearArea));
}
UtilsVk::ClearFramebufferParameters params = {};

Просмотреть файл

@ -1142,9 +1142,19 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
const gl::Rectangle &scissoredRenderArea = params.clearArea;
vk::Framebuffer *currentFramebuffer = nullptr;
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer));
// Start a new render pass if not already started
ANGLE_TRY(framebuffer->getFramebuffer(contextVk, &currentFramebuffer, nullptr));
if (contextVk->hasStartedRenderPassWithFramebuffer(currentFramebuffer))
{
commandBuffer = &contextVk->getStartedRenderPassCommands().getCommandBuffer();
}
else
{
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer));
}
ImageClearShaderParams shaderParams;
shaderParams.clearValue = params.colorClearValue;

Просмотреть файл

@ -499,6 +499,46 @@ TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthAfterClear)
EXPECT_EQ(expectedDepthClears, actualDepthClears);
}
// Tests that masked color clears don't break the RP.
TEST_P(VulkanPerformanceCounterTest, MaskedClearDoesNotBreakRenderPass)
{
const rx::vk::PerfCounters &counters = hackANGLE();
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
ASSERT_GL_NO_ERROR();
uint32_t expectedRenderPassCount = counters.renderPasses + 1;
// Mask color channels and clear the framebuffer multiple times.
glClearColor(0.25f, 0.25f, 0.25f, 0.25f);
glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.75f, 0.75f, 0.75f, 0.75f);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT);
uint32_t actualRenderPassCount = counters.renderPasses;
EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 191, 1);
}
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_ES31, ES31_VULKAN());