Vulkan: Fold glClear into draw call when command graph is disabled

This sets ContextVk::mRenderPassCommandBuffer properly when glClear get
called so that it wonr end up start anotyer render pass during setupDraw
call.

Bug: angleproject:4395
Change-Id: Id2110719ad4d70b4c410062466d32381fb5e1f88
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2050966
Commit-Queue: Charlie Lao <cclao@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Charlie Lao 2020-02-11 18:19:16 -08:00 коммит произвёл Commit Bot
Родитель 94c191427a
Коммит ef599fb0f4
3 изменённых файлов: 111 добавлений и 3 удалений

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

@ -46,6 +46,10 @@ namespace rx
namespace
{
// The value to assign an alpha channel that's emulated. The type is unsigned int, though it will
// automatically convert to the actual data type.
constexpr unsigned int kEmulatedAlphaValue = 1;
// For shader uniforms such as gl_DepthRange and the viewport size.
struct GraphicsDriverUniforms
{
@ -2188,6 +2192,93 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
return angle::Result::Continue;
}
angle::Result ContextVk::clearWithRenderPassOp(
const gl::Rectangle &clearArea,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue)
{
ASSERT(!commandGraphEnabled());
// Start a new render pass if:
//
// - no render pass has started,
// - there is a render pass started but it contains commands; we cannot modify its ops, so new
// render pass is needed,
// - the current render area doesn't match the clear area. We need the render area to be
// exactly as specified by the scissor for the loadOp to clear only that area. See
// ContextVk::updateScissor for more information.
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
if (!framebuffer->valid() || !framebuffer->renderPassStartedButEmpty() ||
framebuffer->getRenderPassRenderArea() != clearArea)
{
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, clearArea, &mRenderPassCommandBuffer));
}
else
{
mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands);
}
size_t attachmentIndexVk = 0;
// Go through clearColorBuffers and set the appropriate loadOp and clear values.
for (size_t colorIndexGL : mDrawFramebuffer->getState().getEnabledDrawBuffers())
{
if (clearColorBuffers.test(colorIndexGL))
{
RenderTargetVk *renderTarget = mDrawFramebuffer->getColorDrawRenderTarget(colorIndexGL);
// If the render target doesn't have alpha, but its emulated format has it, clear the
// alpha to 1.
VkClearColorValue value = clearColorValue;
if (mDrawFramebuffer->getEmulatedAlphaAttachmentMask()[colorIndexGL])
{
const vk::Format &format = renderTarget->getImageFormat();
if (format.vkFormatIsInt)
{
if (format.vkFormatIsUnsigned)
{
value.uint32[3] = kEmulatedAlphaValue;
}
else
{
value.int32[3] = kEmulatedAlphaValue;
}
}
else
{
value.float32[3] = kEmulatedAlphaValue;
}
}
mRenderPassCommands.clearRenderPassColorAttachment(attachmentIndexVk, value);
}
++attachmentIndexVk;
}
// Set the appropriate loadOp and clear values for depth and stencil.
RenderTargetVk *depthStencilRenderTarget = mDrawFramebuffer->getDepthStencilRenderTarget();
if (depthStencilRenderTarget)
{
if (clearDepth)
{
getRenderPassCommandBuffer().clearRenderPassDepthAttachment(
attachmentIndexVk, clearDepthStencilValue.depth);
}
if (clearStencil)
{
getRenderPassCommandBuffer().clearRenderPassStencilAttachment(
attachmentIndexVk, clearDepthStencilValue.stencil);
}
}
return angle::Result::Continue;
}
gl::GraphicsResetStatus ContextVk::getResetStatus()
{
if (mRenderer->isDeviceLost())

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

@ -314,6 +314,12 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
gl::PrimitiveMode mode,
gl::DrawElementsType type,
const void *indirect) override;
angle::Result clearWithRenderPassOp(const gl::Rectangle &clearArea,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
// Device loss
gl::GraphicsResetStatus getResetStatus() override;

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

@ -292,9 +292,19 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
{
clearBuffersWithRenderPassLoadOp = clearColorBuffers;
}
ANGLE_TRY(clearWithRenderPassOp(
contextVk, scissoredRenderArea, clearBuffersWithRenderPassLoadOp, clearDepth,
clearStencilWithRenderPassLoadOp, clearColorValue, modifiedDepthStencilValue));
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(clearWithRenderPassOp(
contextVk, scissoredRenderArea, clearBuffersWithRenderPassLoadOp, clearDepth,
clearStencilWithRenderPassLoadOp, clearColorValue, modifiedDepthStencilValue));
}
else
{
ANGLE_TRY(contextVk->clearWithRenderPassOp(
scissoredRenderArea, clearBuffersWithRenderPassLoadOp, clearDepth,
clearStencilWithRenderPassLoadOp, clearColorValue, modifiedDepthStencilValue));
}
// Fallback to other methods for whatever isn't cleared here.
clearDepth = false;
@ -1246,6 +1256,7 @@ angle::Result FramebufferVk::clearWithRenderPassOp(
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue)
{
ASSERT(contextVk->commandGraphEnabled());
// Start a new render pass if:
//
// - no render pass has started,