Vulkan: Add support for FBO with unequal sized attachments

OpenGLES 3.0 allows FBO with unequal sized attachments. This CL removes
assertion that all attachment must have equal size from vulkan backend,
and uses common intersect area to create VkFramebuffer object.

Bug: b/181800403
Change-Id: Icbb12a26784b184ebd91740855672013f64b889d
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2824760
Commit-Queue: Charlie Lao <cclao@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Tim Van Patten <timvp@google.com>
This commit is contained in:
Charlie Lao 2021-04-13 14:52:31 -07:00 коммит произвёл Commit Bot
Родитель aa2d400a2b
Коммит a37d974815
4 изменённых файлов: 34 добавлений и 27 удалений

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

@ -517,6 +517,34 @@ const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
return nullptr;
}
const Extents FramebufferState::getAttachmentExtentsIntersection() const
{
int32_t width = std::numeric_limits<int32_t>::max();
int32_t height = std::numeric_limits<int32_t>::max();
for (const FramebufferAttachment &attachment : mColorAttachments)
{
if (attachment.isAttached())
{
width = std::min(width, attachment.getSize().width);
height = std::min(height, attachment.getSize().height);
}
}
if (mDepthAttachment.isAttached())
{
width = std::min(width, mDepthAttachment.getSize().width);
height = std::min(height, mDepthAttachment.getSize().height);
}
if (mStencilAttachment.isAttached())
{
width = std::min(width, mStencilAttachment.getSize().width);
height = std::min(height, mStencilAttachment.getSize().height);
}
return Extents(width, height, 0);
}
bool FramebufferState::attachmentsHaveSameDimensions() const
{
Optional<Extents> attachmentSize;
@ -673,11 +701,12 @@ Box FramebufferState::getDimensions() const
Extents FramebufferState::getExtents() const
{
ASSERT(attachmentsHaveSameDimensions());
// OpenGLES3.0 (https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf
// section 4.4.4.2) allows attachments have unequal size.
const FramebufferAttachment *first = getFirstNonNullAttachment();
if (first)
{
return first->getSize();
return getAttachmentExtentsIntersection();
}
return Extents(getDefaultWidth(), getDefaultHeight(), 0);
}

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

@ -81,6 +81,7 @@ class FramebufferState final : angle::NonCopyable
}
const DrawBufferMask getColorAttachmentsMask() const { return mColorAttachmentsMask; }
const Extents getAttachmentExtentsIntersection() const;
bool attachmentsHaveSameDimensions() const;
bool hasSeparateDepthAndStencilAttachments() const;
bool colorAttachmentsAreUniqueImages() const;

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

@ -2020,7 +2020,8 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
// Gather VkImageViews over all FBO attachments, also size of attached region.
std::vector<VkImageView> attachments;
gl::Extents attachmentsSize;
gl::Extents attachmentsSize = mState.getExtents();
ASSERT(attachmentsSize.width != 0 && attachmentsSize.height != 0);
// Color attachments.
const auto &colorRenderTargets = mRenderTargetCache.getColors();
@ -2034,9 +2035,6 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
contextVk, mCurrentFramebufferDesc.getWriteControlMode(), &imageView));
attachments.push_back(imageView->getHandle());
ASSERT(attachmentsSize.empty() || attachmentsSize == colorRenderTarget->getExtents());
attachmentsSize = colorRenderTarget->getExtents();
}
// Depth/stencil attachment.
@ -2047,10 +2045,6 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
ANGLE_TRY(depthStencilRenderTarget->getImageView(contextVk, &imageView));
attachments.push_back(imageView->getHandle());
ASSERT(attachmentsSize.empty() ||
attachmentsSize == depthStencilRenderTarget->getExtents());
attachmentsSize = depthStencilRenderTarget->getExtents();
}
// Color resolve attachments.
@ -2076,8 +2070,6 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
ANGLE_TRY(colorRenderTarget->getResolveImageView(contextVk, &resolveImageView));
attachments.push_back(resolveImageView->getHandle());
ASSERT(!attachmentsSize.empty());
}
}
}
@ -2089,17 +2081,8 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(contextVk, &imageView));
attachments.push_back(imageView->getHandle());
ASSERT(!attachmentsSize.empty());
}
if (attachmentsSize.empty())
{
// No attachments, so use the default values.
attachmentsSize.height = mState.getDefaultHeight();
attachmentsSize.width = mState.getDefaultWidth();
attachmentsSize.depth = 0;
}
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
@ -2708,10 +2691,6 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
gl::Extents FramebufferVk::getReadImageExtents() const
{
RenderTargetVk *readRenderTarget = mRenderTargetCache.getColorRead(mState);
ASSERT(readRenderTarget->getExtents().width == mState.getDimensions().width);
ASSERT(readRenderTarget->getExtents().height == mState.getDimensions().height);
return readRenderTarget->getExtents();
}

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

@ -3054,8 +3054,6 @@ TEST_P(FramebufferTest_ES3, ChangeAttachmentThenInvalidateAndDraw)
// outside common intersection area are undefined.
TEST_P(FramebufferTest_ES3, AttachmentsWithUnequalDimensions)
{
// TODO: https://issuetracker.google.com/181800403
ANGLE_SKIP_TEST_IF(IsVulkan());
// TODO: https://anglebug.com/5866
ANGLE_SKIP_TEST_IF(IsD3D() || IsMetal());