Vulkan: Implement EXT_draw_buffers
In GLES, color attachments are referenced by their indices. These
indices match between the API and GLSL. For example, if a shader has:
layout(location=0) out color;
layout(location=3) out roughness;
Then GLES would bind and enable GL_COLOR_ATTACHMENT0 and
GL_COLOR_ATTACHMENT3.
In Vulkan, the framebuffer object and the corresponding renderpass
define the color attachments, and they don't allow gaps in color
attachments as GLES does. A render subpass creates the mapping between
the color attachments as defined in the framebuffer and the attachments
used by the shader (with possible gaps).
This change packs the enabled GL color attachments for the sake of the
framebuffer, and sets the subpass up in such a way that the shaders
continue to use the same color output indices as GLES.
In the example above, we have the attachment indices as follows:
Status | GLES | GLSL | RenderPass | Subpass
enabled 0 0 0 0
disabled 1 - VK_ATTACHMENT_UNUSED
disabled 2 - VK_ATTACHMENT_UNUSED
enabled 3 3 1 1
That is, the array of color attachments in the Vulkan
framebuffer/renderpass is:
[0] = GL color attachment 0
[1] = GL color attachment 3
And the array of color attachment references in the Vulkan render
subpass is:
[0] = 0 (index 0 of the renderpass attachment array)
[1] = VK_ATTACHMENT_UNUSED
[2] = VK_ATTACHMENT_UNUSED
[3] = 1 (index 1 of the renderpass attachment array)
Bug: angleproject:2394
Change-Id: Ib6cd2b60882643ea152986eee453270d09cd4aed
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1595442
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 898acfa..cbd13ee 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -652,9 +652,9 @@
return angle::Result::Continue;
}
- for (size_t colorAttachment : mState.getEnabledDrawBuffers())
+ for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
- RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorAttachment];
+ RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
ASSERT(drawRenderTarget);
ASSERT(HasSrcAndDstBlitProperties(renderer, readRenderTarget, drawRenderTarget));
@@ -836,30 +836,31 @@
{
ASSERT(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
- size_t colorIndex =
+ size_t colorIndexGL =
static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
- ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndex));
+ ANGLE_TRY(
+ mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndexGL));
// Update cached masks for masked clears.
- RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndex];
+ RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
if (renderTarget)
{
const angle::Format &emulatedFormat =
renderTarget->getImageFormat().imageFormat();
updateActiveColorMasks(
- colorIndex, emulatedFormat.redBits > 0, emulatedFormat.greenBits > 0,
+ colorIndexGL, emulatedFormat.redBits > 0, emulatedFormat.greenBits > 0,
emulatedFormat.blueBits > 0, emulatedFormat.alphaBits > 0);
const angle::Format &sourceFormat =
renderTarget->getImageFormat().angleFormat();
mEmulatedAlphaAttachmentMask.set(
- colorIndex, sourceFormat.alphaBits == 0 && emulatedFormat.alphaBits > 0);
+ colorIndexGL, sourceFormat.alphaBits == 0 && emulatedFormat.alphaBits > 0);
contextVk->updateColorMask(context->getState().getBlendState());
}
else
{
- updateActiveColorMasks(colorIndex, false, false, false, false);
+ updateActiveColorMasks(colorIndexGL, false, false, false, false);
}
break;
}
@@ -888,19 +889,28 @@
mRenderPassDesc = {};
mRenderPassDesc.setSamples(getSamples());
- // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
- const auto &colorRenderTargets = mRenderTargetCache.getColors();
- for (size_t colorIndex : mState.getEnabledDrawBuffers())
+ const auto &colorRenderTargets = mRenderTargetCache.getColors();
+ const gl::DrawBufferMask enabledDrawBuffers = mState.getEnabledDrawBuffers();
+ for (size_t colorIndexGL = 0; colorIndexGL < enabledDrawBuffers.size(); ++colorIndexGL)
{
- RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
- ASSERT(colorRenderTarget);
- mRenderPassDesc.packAttachment(colorRenderTarget->getImage().getFormat());
+ if (enabledDrawBuffers[colorIndexGL])
+ {
+ RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
+ ASSERT(colorRenderTarget);
+ mRenderPassDesc.packColorAttachment(
+ colorIndexGL, colorRenderTarget->getImage().getFormat().angleFormatID);
+ }
+ else
+ {
+ mRenderPassDesc.packColorAttachmentGap(colorIndexGL);
+ }
}
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
if (depthStencilRenderTarget)
{
- mRenderPassDesc.packAttachment(depthStencilRenderTarget->getImage().getFormat());
+ mRenderPassDesc.packDepthStencilAttachment(
+ depthStencilRenderTarget->getImage().getFormat().angleFormatID);
}
}
@@ -927,11 +937,10 @@
std::vector<VkImageView> attachments;
gl::Extents attachmentsSize;
- // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
const auto &colorRenderTargets = mRenderTargetCache.getColors();
- for (size_t colorIndex : mState.getEnabledDrawBuffers())
+ for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
- RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
+ RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget);
attachments.push_back(colorRenderTarget->getDrawImageView()->getHandle());
@@ -949,8 +958,6 @@
attachmentsSize = depthStencilRenderTarget->getExtents();
}
- ASSERT(!attachments.empty());
-
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
@@ -993,27 +1000,26 @@
ANGLE_TRY(startNewRenderPass(contextVk, clearArea, &commandBuffer));
}
- size_t attachmentIndex = 0;
+ size_t attachmentIndexVk = 0;
// Go through clearColorBuffers and set the appropriate loadOp and clear values.
- // TODO: Support gaps in RenderTargets. http://anglebug.com/2394
- for (size_t colorIndex : mState.getEnabledDrawBuffers())
+ for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
- if (clearColorBuffers.test(colorIndex))
+ if (clearColorBuffers.test(colorIndexGL))
{
RenderTargetVk *renderTarget = getColorReadRenderTarget();
// If the render target doesn't have alpha, but its emulated format has it, clear the
// alpha to 1.
VkClearColorValue value = clearColorValue;
- if (mEmulatedAlphaAttachmentMask[colorIndex])
+ if (mEmulatedAlphaAttachmentMask[colorIndexGL])
{
SetEmulatedAlphaValue(renderTarget->getImageFormat(), &value);
}
- mFramebuffer.clearRenderPassColorAttachment(attachmentIndex, value);
+ mFramebuffer.clearRenderPassColorAttachment(attachmentIndexVk, value);
}
- ++attachmentIndex;
+ ++attachmentIndexVk;
}
// Set the appropriate loadOp and clear values for depth and stencil.
@@ -1022,13 +1028,13 @@
{
if (clearDepth)
{
- mFramebuffer.clearRenderPassDepthAttachment(attachmentIndex,
+ mFramebuffer.clearRenderPassDepthAttachment(attachmentIndexVk,
clearDepthStencilValue.depth);
}
if (clearStencil)
{
- mFramebuffer.clearRenderPassStencilAttachment(attachmentIndex,
+ mFramebuffer.clearRenderPassStencilAttachment(attachmentIndexVk,
clearDepthStencilValue.stencil);
}
}
@@ -1059,15 +1065,15 @@
params.clearStencil = clearStencil;
const auto &colorRenderTargets = mRenderTargetCache.getColors();
- for (size_t colorIndex : clearColorBuffers)
+ for (size_t colorIndexGL : clearColorBuffers)
{
- const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
+ const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget);
- params.colorFormat = &colorRenderTarget->getImage().getFormat().imageFormat();
- params.colorAttachmentIndex = colorIndex;
- params.colorMaskFlags = colorMaskFlags;
- if (mEmulatedAlphaAttachmentMask[colorIndex])
+ params.colorFormat = &colorRenderTarget->getImage().getFormat().imageFormat();
+ params.colorAttachmentIndexGL = colorIndexGL;
+ params.colorMaskFlags = colorMaskFlags;
+ if (mEmulatedAlphaAttachmentMask[colorIndexGL])
{
params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
}
@@ -1109,18 +1115,14 @@
vk::CommandBuffer *writeCommands = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &writeCommands));
- vk::RenderPassDesc renderPassDesc;
-
// Initialize RenderPass info.
- // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
const auto &colorRenderTargets = mRenderTargetCache.getColors();
- for (size_t colorIndex : mState.getEnabledDrawBuffers())
+ for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
- RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
+ RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget);
- ANGLE_TRY(colorRenderTarget->onColorDraw(contextVk, &mFramebuffer, writeCommands,
- &renderPassDesc));
+ ANGLE_TRY(colorRenderTarget->onColorDraw(contextVk, &mFramebuffer, writeCommands));
renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@@ -1131,8 +1133,8 @@
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
if (depthStencilRenderTarget)
{
- ANGLE_TRY(depthStencilRenderTarget->onDepthStencilDraw(contextVk, &mFramebuffer,
- writeCommands, &renderPassDesc));
+ ANGLE_TRY(
+ depthStencilRenderTarget->onDepthStencilDraw(contextVk, &mFramebuffer, writeCommands));
renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
@@ -1145,12 +1147,12 @@
commandBufferOut);
}
-void FramebufferVk::updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a)
+void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
{
- mActiveColorComponentMasksForClear[0].set(colorIndex, r);
- mActiveColorComponentMasksForClear[1].set(colorIndex, g);
- mActiveColorComponentMasksForClear[2].set(colorIndex, b);
- mActiveColorComponentMasksForClear[3].set(colorIndex, a);
+ mActiveColorComponentMasksForClear[0].set(colorIndexGL, r);
+ mActiveColorComponentMasksForClear[1].set(colorIndexGL, g);
+ mActiveColorComponentMasksForClear[2].set(colorIndexGL, b);
+ mActiveColorComponentMasksForClear[3].set(colorIndexGL, a);
}
const gl::DrawBufferMask &FramebufferVk::getEmulatedAlphaAttachmentMask() const