Commit e416c92a by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fold deferred clears into current clears

If there are clears prior to a glClear() call, those clears were flushed (starting a new render pass) and then the clear call's clears would be applied (essentially modifying the loadOps of said render pass). The main downside of the above is that the current glClear() clears don't get a chance to be deferred. This was observed in Chrome which clears an attachment with an emulated format, then switches framebuffers. Additionally, if the render pass had already been started, the deferred clears could have become inlined instead of breaking the render pass. Although, it's unlikely for there to be deferred clears when the render pass is already open. This change first identifies which clears need to go through the draw path (scissored, masked or as workaround for driver bug). It merges the rest of the clears (that don't need the draw path) with the deferred clears. It then checks deferred clears and applies them by either: - vkCmdClearAttachments if mid RP - Start a new render pass and use loadOps, if any draw-based clear needs to follow. - Modify current RP loadOps / defer the clear Afterwards, the draw-based clears are applied. Bug: angleproject:4836 Change-Id: Id4992c78983b199734508c9d4bb18ed3195c91ec Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2455167 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com>
parent 96a49a48
...@@ -4690,6 +4690,8 @@ angle::Result ContextVk::beginNewRenderPass( ...@@ -4690,6 +4690,8 @@ angle::Result ContextVk::beginNewRenderPass(
// Restart at subpass 0. // Restart at subpass 0.
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition); mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
mPerfCounters.renderPasses++;
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -4715,8 +4717,6 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea, ...@@ -4715,8 +4717,6 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
*commandBufferOut = mRenderPassCommandBuffer; *commandBufferOut = mRenderPassCommandBuffer;
} }
mPerfCounters.renderPasses++;
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -172,6 +172,11 @@ class FramebufferVk : public FramebufferImpl ...@@ -172,6 +172,11 @@ class FramebufferVk : public FramebufferImpl
const VkClearColorValue &clearColorValue, const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue); const VkClearDepthStencilValue &clearDepthStencilValue);
void mergeClearsWithDeferredClears(gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithDraw(ContextVk *contextVk, angle::Result clearWithDraw(ContextVk *contextVk,
const gl::Rectangle &clearArea, const gl::Rectangle &clearArea,
gl::DrawBufferMask clearColorBuffers, gl::DrawBufferMask clearColorBuffers,
...@@ -181,20 +186,10 @@ class FramebufferVk : public FramebufferImpl ...@@ -181,20 +186,10 @@ class FramebufferVk : public FramebufferImpl
uint8_t stencilMask, uint8_t stencilMask,
const VkClearColorValue &clearColorValue, const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue); const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithLoadOp(ContextVk *contextVk, angle::Result clearWithLoadOp(ContextVk *contextVk);
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithCommand(ContextVk *contextVk, angle::Result clearWithCommand(ContextVk *contextVk,
vk::CommandBufferHelper *renderpassCommands, vk::CommandBufferHelper *renderpassCommands,
const gl::Rectangle &scissoredRenderArea, const gl::Rectangle &scissoredRenderArea);
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a); void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc(); void updateRenderPassDesc();
angle::Result updateColorAttachment(const gl::Context *context, angle::Result updateColorAttachment(const gl::Context *context,
......
...@@ -1081,7 +1081,7 @@ class UniformsAndXfbDesc ...@@ -1081,7 +1081,7 @@ class UniformsAndXfbDesc
// In the FramebufferDesc object: // In the FramebufferDesc object:
// - Depth/stencil serial is at index 0 // - Depth/stencil serial is at index 0
// - Color serials are at indices [1:gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] // - Color serials are at indices [1, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]
// - Depth/stencil resolve attachment is at index gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+1 // - Depth/stencil resolve attachment is at index gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+1
// - Resolve attachments are at indices [gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+2, // - Resolve attachments are at indices [gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+2,
// gl::IMPLEMENTATION_MAX_DRAW_BUFFERS*2+1] // gl::IMPLEMENTATION_MAX_DRAW_BUFFERS*2+1]
......
...@@ -757,6 +757,13 @@ void ClearValuesArray::storeNoDepthStencil(uint32_t index, const VkClearValue &c ...@@ -757,6 +757,13 @@ void ClearValuesArray::storeNoDepthStencil(uint32_t index, const VkClearValue &c
mEnabled.set(index); mEnabled.set(index);
} }
gl::DrawBufferMask ClearValuesArray::getColorMask() const
{
constexpr uint32_t kColorBuffersMask =
angle::Bit<uint32_t>(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS) - 1;
return gl::DrawBufferMask(mEnabled.bits() & kColorBuffersMask);
}
// ResourceSerialFactory implementation. // ResourceSerialFactory implementation.
ResourceSerialFactory::ResourceSerialFactory() : mCurrentUniqueSerial(1) {} ResourceSerialFactory::ResourceSerialFactory() : mCurrentUniqueSerial(1) {}
......
...@@ -711,6 +711,7 @@ class ClearValuesArray final ...@@ -711,6 +711,7 @@ class ClearValuesArray final
bool test(size_t index) const { return mEnabled.test(index); } bool test(size_t index) const { return mEnabled.test(index); }
bool testDepth() const { return mEnabled.test(kUnpackedDepthIndex); } bool testDepth() const { return mEnabled.test(kUnpackedDepthIndex); }
bool testStencil() const { return mEnabled.test(kUnpackedStencilIndex); } bool testStencil() const { return mEnabled.test(kUnpackedStencilIndex); }
gl::DrawBufferMask getColorMask() const;
const VkClearValue &operator[](size_t index) const { return mValues[index]; } const VkClearValue &operator[](size_t index) const { return mValues[index]; }
......
...@@ -1897,6 +1897,81 @@ TEST_P(ClearTestES3, ClearMaxAttachmentsAfterDraw) ...@@ -1897,6 +1897,81 @@ TEST_P(ClearTestES3, ClearMaxAttachmentsAfterDraw)
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green); EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
} }
// Test that mixed masked clear works after clear.
TEST_P(ClearTestES3, ClearThenMixedMaskedClear)
{
constexpr GLsizei kSize = 16;
GLint maxDrawBuffers = 0;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
ASSERT_GE(maxDrawBuffers, 4);
// Setup framebuffer.
GLRenderbuffer color;
glBindRenderbuffer(GL_RENDERBUFFER, color);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
GLRenderbuffer depthStencil;
glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
GLFramebuffer fb;
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencil);
EXPECT_GL_NO_ERROR();
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Clear color and depth/stencil
glClearColor(0.1f, 1.0f, 0.0f, 0.7f);
glClearDepthf(0.0f);
glClearStencil(0x55);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Clear again, but with color and stencil masked
glClearColor(1.0f, 0.2f, 0.6f, 1.0f);
glClearDepthf(1.0f);
glClearStencil(0x3C);
glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
glStencilMask(0xF0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Issue a draw call to verify color, depth and stencil.
// If depth is not cleared to 1, rendering would fail.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// If stencil is not cleared to 0x35, rendering would fail.
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x35, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xFF);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
glUseProgram(drawColor);
GLint colorUniformLocation =
glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
ASSERT_NE(colorUniformLocation, -1);
// Blend half-transparent blue into the color buffer.
glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 0.5f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
ASSERT_GL_NO_ERROR();
// Verify that the color buffer is now gray
const GLColor kExpected(127, 127, 127, 191);
EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
}
#ifdef Bool #ifdef Bool
// X11 craziness. // X11 craziness.
# undef Bool # undef Bool
......
...@@ -2366,6 +2366,154 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout) ...@@ -2366,6 +2366,154 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout)
EXPECT_EQ(expectedReadOnlyDepthStencilCount, actualReadOnlyDepthStencilCount); EXPECT_EQ(expectedReadOnlyDepthStencilCount, actualReadOnlyDepthStencilCount);
} }
// Ensures repeated clears of various kind (all attachments, some attachments, scissored, masked
// etc) don't break the render pass.
TEST_P(VulkanPerformanceCounterTest, ClearAfterClearDoesNotBreakRenderPass)
{
const rx::vk::PerfCounters &counters = hackANGLE();
uint32_t expectedRenderPassCount = counters.renderPasses + 1;
GLFramebuffer FBO;
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
constexpr GLsizei kSize = 6;
// Create a framebuffer to clear with both color and depth/stencil attachments.
GLTexture color;
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GLTexture depth;
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kSize, kSize, 0, GL_DEPTH_STENCIL,
GL_UNSIGNED_INT_24_8_OES, nullptr);
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
ASSERT_GL_NO_ERROR();
// Clear color and depth, but not stencil.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepthf(0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Clear color and stencil, but not depth.
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClearStencil(0x11);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Clear depth and stencil, but not color.
glClearDepthf(0.1f);
glClearStencil(0x22);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Clear masked color, and unmasked depth.
glClearDepthf(0.2f);
glClearColor(0.1f, 1.0f, 0.0f, 1.0f);
glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Clear unmasked color, and masked stencil.
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearStencil(0x33);
glStencilMask(0xF0);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Clear unmasked depth and stencil.
glClearDepthf(0.3f);
glClearStencil(0x44);
glStencilMask(0xFF);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Clear with scissor.
glEnable(GL_SCISSOR_TEST);
glScissor(kSize / 3, kSize / 3, kSize / 3, kSize / 3);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClearDepthf(1.0f);
glClearStencil(0x55);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Verify render pass count.
EXPECT_EQ(counters.renderPasses, expectedRenderPassCount);
// Make sure the result is correct. The border of the image should be blue with depth 0.3f and
// stencil 0x44. The center is red with depth 1.0f and stencil 0x55.
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(kSize / 3, kSize / 3, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, kSize / 3, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize / 3, 2 * kSize / 3 - 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, 2 * kSize / 3 - 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::red);
glViewport(0, 0, kSize, kSize);
glDisable(GL_SCISSOR_TEST);
// Center: If depth is not cleared to 1, rendering would fail.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// Center: If stencil is not clear to 0x55, rendering would fail.
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x55, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xFF);
// Set up program
ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
glUseProgram(drawColor);
GLint colorUniformLocation =
glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
ASSERT_NE(colorUniformLocation, -1);
// Draw green
glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
ASSERT_GL_NO_ERROR();
// Verify that only the center has changed
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(kSize / 3, kSize / 3, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, kSize / 3, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize / 3, 2 * kSize / 3 - 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, 2 * kSize / 3 - 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
// Border: If depth is not cleared to 0.3f, rendering would fail.
glDepthFunc(GL_LESS);
// Center: If stencil is not clear to 0x44, rendering would fail.
glStencilFunc(GL_EQUAL, 0x44, 0xFF);
// Draw yellow
glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), -0.5f);
ASSERT_GL_NO_ERROR();
// Verify that only the border has changed
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(kSize / 3, kSize / 3, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, kSize / 3, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize / 3, 2 * kSize / 3 - 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, 2 * kSize / 3 - 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
}
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN()); ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_ES31, ES31_VULKAN()); ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_ES31, ES31_VULKAN());
......
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