Vulkan: Fix for framebuffer blit and Y flip

- The depth/stencil related tests are now disabled since I found out
that the tests are too simple to find issues if there is a flip since
they use only a single color and no gradient / checked board.
This is left to implement in the Vulkan backend later on.

Bug: angleproject:2673
Change-Id: I8f7091d4b9c8c3bec0353ebab28304b6209ea350
Reviewed-on: https://chromium-review.googlesource.com/1129629
Reviewed-by: Geoff Lang <geofflang@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 f01a1de..e7d9931 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -306,7 +306,7 @@
         return gl::NoError();
     }
     gl::Rectangle flippedArea = clippedArea;
-    if (contextVk->isViewportFlipEnabled())
+    if (contextVk->isViewportFlipEnabledForDrawFBO())
     {
         flippedArea.y = fbRect.height - flippedArea.y - flippedArea.height;
     }
@@ -317,7 +317,7 @@
     ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
 
     gl::PixelPackState packState(glState.getPackState());
-    if (contextVk->isViewportFlipEnabled())
+    if (contextVk->isViewportFlipEnabledForDrawFBO())
     {
         packState.reverseRowOrder = !packState.reverseRowOrder;
     }
@@ -448,6 +448,9 @@
     vk::CommandBuffer *commandBuffer = nullptr;
     ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
     FramebufferVk *sourceFramebufferVk = vk::GetImpl(sourceFramebuffer);
+    bool flipSource                    = contextVk->isViewportFlipEnabledForReadFBO();
+    bool flipDest                      = contextVk->isViewportFlipEnabledForDrawFBO();
+
     if (blitColorBuffer)
     {
         RenderTargetVk *readRenderTarget = sourceFramebufferVk->getColorReadRenderTarget();
@@ -458,8 +461,9 @@
             ASSERT(drawRenderTarget);
             ASSERT(HasSrcAndDstBlitProperties(renderer->getPhysicalDevice(), readRenderTarget,
                                               drawRenderTarget));
-            ANGLE_TRY(blitImpl(commandBuffer, sourceArea, destArea, readRenderTarget,
-                               drawRenderTarget, filter, scissor, true, false, false));
+            ANGLE_TRY(blitImpl(contextVk, commandBuffer, sourceArea, destArea, readRenderTarget,
+                               drawRenderTarget, filter, scissor, true, false, false, flipSource,
+                               flipDest));
         }
     }
 
@@ -473,12 +477,22 @@
         if (HasSrcAndDstBlitProperties(renderer->getPhysicalDevice(), readRenderTarget,
                                        drawRenderTarget))
         {
-            ANGLE_TRY(blitImpl(commandBuffer, sourceArea, destArea, readRenderTarget,
+            ANGLE_TRY(blitImpl(contextVk, commandBuffer, sourceArea, destArea, readRenderTarget,
                                drawRenderTarget, filter, scissor, false, blitDepthBuffer,
-                               blitStencilBuffer));
+                               blitStencilBuffer, flipSource, flipDest));
         }
         else
         {
+            if (flipSource || contextVk->isViewportFlipEnabledForReadFBO())
+            {
+                // The tests in BlitFramebufferANGLETest are passing, but they are wrong since they
+                // use a single color for the depth / stencil buffers, it looks like its working,
+                // but if it was a gradient or a checked board, you would realize the flip isn't
+                // happening with this copy.
+                UNIMPLEMENTED();
+                return gl::InternalError();
+            }
+
             ASSERT(filter == GL_NEAREST);
             ANGLE_TRY(blitUsingCopy(renderer, commandBuffer, sourceArea, destArea, readRenderTarget,
                                     drawRenderTarget, scissor, blitDepthBuffer, blitStencilBuffer));
@@ -488,7 +502,8 @@
     return gl::NoError();
 }
 
-gl::Error FramebufferVk::blitImpl(vk::CommandBuffer *commandBuffer,
+gl::Error FramebufferVk::blitImpl(ContextVk *contextVk,
+                                  vk::CommandBuffer *commandBuffer,
                                   const gl::Rectangle &readRectIn,
                                   const gl::Rectangle &drawRectIn,
                                   RenderTargetVk *readRenderTarget,
@@ -497,7 +512,9 @@
                                   const gl::Rectangle *scissor,
                                   bool colorBlit,
                                   bool depthBlit,
-                                  bool stencilBlit)
+                                  bool stencilBlit,
+                                  bool flipSource,
+                                  bool flipDest)
 {
     // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
     // it should never be the case that both color and depth/stencil need to be blitted at
@@ -537,9 +554,17 @@
     vk::ImageHelper *srcImage = readRenderTarget->getImageForRead(
         this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, aspectMask, commandBuffer);
 
+    if (flipSource)
+    {
+        scissoredReadRect.y =
+            sourceFrameBufferExtents.height - scissoredReadRect.y - scissoredReadRect.height;
+    }
+
     VkImageBlit blit                   = {};
-    blit.srcOffsets[0]                 = {scissoredReadRect.x0(), scissoredReadRect.y0(), 0};
-    blit.srcOffsets[1]                 = {scissoredReadRect.x1(), scissoredReadRect.y1(), 1};
+    blit.srcOffsets[0]                 = {scissoredReadRect.x0(),
+                          flipSource ? scissoredReadRect.y1() : scissoredReadRect.y0(), 0};
+    blit.srcOffsets[1]                 = {scissoredReadRect.x1(),
+                          flipSource ? scissoredReadRect.y0() : scissoredReadRect.y1(), 1};
     blit.srcSubresource.aspectMask     = aspectMask;
     blit.srcSubresource.mipLevel       = 0;
     blit.srcSubresource.baseArrayLayer = 0;
@@ -557,8 +582,16 @@
         return gl::NoError();
     }
 
-    blit.dstOffsets[0] = {scissoredDrawRect.x0(), scissoredDrawRect.y0(), 0};
-    blit.dstOffsets[1] = {scissoredDrawRect.x1(), scissoredDrawRect.y1(), 1};
+    if (flipDest)
+    {
+        scissoredDrawRect.y =
+            drawFrameBufferBounds.height - scissoredDrawRect.y - scissoredDrawRect.height;
+    }
+
+    blit.dstOffsets[0] = {scissoredDrawRect.x0(),
+                          flipDest ? scissoredDrawRect.y1() : scissoredDrawRect.y0(), 0};
+    blit.dstOffsets[1] = {scissoredDrawRect.x1(),
+                          flipDest ? scissoredDrawRect.y0() : scissoredDrawRect.y1(), 1};
 
     vk::ImageHelper *dstImage = drawRenderTarget->getImageForWrite(this);
 
@@ -785,7 +818,7 @@
 
     clearRect.rect = gl_vk::GetRect(intersection);
 
-    if (contextVk->isViewportFlipEnabled())
+    if (contextVk->isViewportFlipEnabledForDrawFBO())
     {
         clearRect.rect.offset.y = getRenderPassRenderArea().height - clearRect.rect.offset.y -
                                   clearRect.rect.extent.height;
@@ -896,7 +929,9 @@
     pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
     pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
     pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial());
-    pipelineDesc.updateViewport(this, renderArea, 0.0f, 1.0f, contextVk->isViewportFlipEnabled());
+    bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
+
+    pipelineDesc.updateViewport(this, renderArea, 0.0f, 1.0f, invertViewport);
 
     const gl::State &glState = contextVk->getGLState();
     if (glState.isScissorTestEnabled())
@@ -907,11 +942,11 @@
             return gl::NoError();
         }
 
-        pipelineDesc.updateScissor(intersection, contextVk->isViewportFlipEnabled(), renderArea);
+        pipelineDesc.updateScissor(intersection, invertViewport, renderArea);
     }
     else
     {
-        pipelineDesc.updateScissor(renderArea, contextVk->isViewportFlipEnabled(), renderArea);
+        pipelineDesc.updateScissor(renderArea, invertViewport, renderArea);
     }
 
     vk::PipelineAndSerial *pipeline = nullptr;