diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp index d9f1d7362..ff604e450 100644 --- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp +++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp @@ -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 = {}; diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/src/libANGLE/renderer/vulkan/UtilsVk.cpp index 171f29cd3..bd5163fd3 100644 --- a/src/libANGLE/renderer/vulkan/UtilsVk.cpp +++ b/src/libANGLE/renderer/vulkan/UtilsVk.cpp @@ -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, ¤tFramebuffer, nullptr)); + if (contextVk->hasStartedRenderPassWithFramebuffer(currentFramebuffer)) + { + commandBuffer = &contextVk->getStartedRenderPassCommands().getCommandBuffer(); + } + else + { + ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer)); + } ImageClearShaderParams shaderParams; shaderParams.clearValue = params.colorClearValue; diff --git a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp index 0f62579d6..194eb30d4 100644 --- a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp +++ b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp @@ -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());