From a37d974815e8f4b8b6c026add42a67a6cbacdae8 Mon Sep 17 00:00:00 2001 From: Charlie Lao Date: Tue, 13 Apr 2021 14:52:31 -0700 Subject: [PATCH] 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 Reviewed-by: Jamie Madill Reviewed-by: Tim Van Patten --- src/libANGLE/Framebuffer.cpp | 33 +++++++++++++++++-- src/libANGLE/Framebuffer.h | 1 + .../renderer/vulkan/FramebufferVk.cpp | 25 ++------------ src/tests/gl_tests/FramebufferTest.cpp | 2 -- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp index 7d9856d15..8828677d9 100644 --- a/src/libANGLE/Framebuffer.cpp +++ b/src/libANGLE/Framebuffer.cpp @@ -517,6 +517,34 @@ const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const return nullptr; } +const Extents FramebufferState::getAttachmentExtentsIntersection() const +{ + int32_t width = std::numeric_limits::max(); + int32_t height = std::numeric_limits::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 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); } diff --git a/src/libANGLE/Framebuffer.h b/src/libANGLE/Framebuffer.h index 2c70023d2..71dad7796 100644 --- a/src/libANGLE/Framebuffer.h +++ b/src/libANGLE/Framebuffer.h @@ -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; diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp index 9c11d3b85..cb6fb4661 100644 --- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp +++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp @@ -2020,7 +2020,8 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, // Gather VkImageViews over all FBO attachments, also size of attached region. std::vector 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(); } diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp index a1819ebd7..15649f0be 100644 --- a/src/tests/gl_tests/FramebufferTest.cpp +++ b/src/tests/gl_tests/FramebufferTest.cpp @@ -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());