Vulkan: Depth/stencil scissored clears
- Generalize cmdClearAttachments to be able to clear
depth/stencil/color individually.
- The clear of the stencil part is implemented, but cant be tested
until stencil state support is implemented in the next commit.
Bug: angleproject:2427
Change-Id: Ib1fc7f66b2bd232761d374e217812605d3ff9152
Reviewed-on: https://chromium-review.googlesource.com/992874
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Luc Ferron <lucferron@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 2d9fdb4..2ac151d 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -132,7 +132,18 @@
bool clearStencil = (stencilAttachment && (mask & GL_STENCIL_BUFFER_BIT) != 0);
ASSERT(!clearStencil || stencilAttachment->isAttached());
- // Depth/stencil clear.
+ bool clearColor = IsMaskFlagSet(static_cast<int>(mask), GL_COLOR_BUFFER_BIT);
+
+ if (context->getGLState().isScissorTestEnabled())
+ {
+ // With scissor test enabled, we clear very differently and we don't need to access
+ // the image inside each attachment we can just use clearCmdAttachments with our
+ // scissor region instead.
+ ANGLE_TRY(clearAttachmentsWithScissorRegion(context, clearColor, clearDepth, clearStencil));
+ return gl::NoError();
+ }
+
+ // Standard Depth/stencil clear without scissor.
if (clearDepth || clearStencil)
{
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
@@ -157,21 +168,13 @@
commandBuffer->clearSingleDepthStencilImage(renderTarget->image->getImage(), aspectFlags,
clearDepthStencilValue);
- if ((mask & GL_COLOR_BUFFER_BIT) == 0)
+ if (!clearColor)
{
return gl::NoError();
}
}
- if (context->getGLState().isScissorTestEnabled())
- {
- // With scissor test enabled, we clear very differently and we don't need to access
- // the image inside each attachment we can just use clearCmdAttachments with our
- // scissor region instead.
- ANGLE_TRY(clearColorAttachmentsWithScissorRegion(context));
- return gl::NoError();
- }
-
+ ASSERT(clearColor);
const auto *attachment = mState.getFirstNonNullAttachment();
ASSERT(attachment && attachment->isAttached());
@@ -465,7 +468,10 @@
return &mFramebuffer;
}
-gl::Error FramebufferVk::clearColorAttachmentsWithScissorRegion(const gl::Context *context)
+gl::Error FramebufferVk::clearAttachmentsWithScissorRegion(const gl::Context *context,
+ bool clearColor,
+ bool clearDepth,
+ bool clearStencil)
{
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
@@ -484,17 +490,52 @@
ANGLE_TRY(node->beginInsideRenderPassRecording(renderer, &commandBuffer));
}
- const std::vector<gl::FramebufferAttachment> &colorAttachments = mState.getColorAttachments();
gl::AttachmentArray<VkClearAttachment> clearAttachments;
int clearAttachmentIndex = 0;
- for (auto colorIndex : mState.getEnabledDrawBuffers())
+
+ if (clearColor)
{
+ // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
+ for (size_t colorIndex : mState.getEnabledDrawBuffers())
+ {
+ VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
+ clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ clearAttachment.colorAttachment = static_cast<uint32_t>(colorIndex);
+ clearAttachment.clearValue = contextVk->getClearColorValue();
+ ++clearAttachmentIndex;
+ }
+ }
+
+ if (clearDepth && clearStencil && mState.getDepthStencilAttachment() != nullptr)
+ {
+ // When we have a packed depth/stencil attachment we can do 1 clear for both when it
+ // applies.
VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
- clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- clearAttachment.colorAttachment = static_cast<uint32_t>(colorIndex);
- clearAttachment.clearValue = contextVk->getClearColorValue();
+ clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
+ clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
++clearAttachmentIndex;
}
+ else
+ {
+ if (clearDepth)
+ {
+ VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
+ clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
+ clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
+ ++clearAttachmentIndex;
+ }
+
+ if (clearStencil)
+ {
+ VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
+ clearAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
+ clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
+ clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
+ ++clearAttachmentIndex;
+ }
+ }
// We assume for now that we always need to clear only 1 layer starting at the
// baseArrayLayer 0, this might need to change depending how we'll implement
@@ -504,7 +545,7 @@
clearRect.layerCount = 1;
clearRect.rect = contextVk->getScissor();
- commandBuffer->clearAttachments(static_cast<uint32_t>(colorAttachments.size()),
+ commandBuffer->clearAttachments(static_cast<uint32_t>(clearAttachmentIndex),
clearAttachments.data(), 1, &clearRect);
return gl::NoError();
}