Vulkan: Fix how the viewport is calculated with Y flip

- This fixes all ViewportTest.* and MipmapTest.*
- Tests left to fix in end2end:
	- BlitFramebuffer*
	- MaxTextureSizeTest.*
	- PointSpritesTest.*

Every other test in angle_end2end_tests are working.

Bug: angleproject:2673
Change-Id: I162083bc847c15fa5490ab524ad4c22747d232ea
Reviewed-on: https://chromium-review.googlesource.com/1126333
Commit-Queue: Luc Ferron <lucferron@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index f8fecf4..7f6fe31 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -435,9 +435,13 @@
                 updateScissor(glState);
                 break;
             case gl::State::DIRTY_BIT_VIEWPORT:
-                mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
-                                              glState.getFarPlane(), isViewportFlipEnabled());
+            {
+                FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
+                mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(),
+                                              glState.getNearPlane(), glState.getFarPlane(),
+                                              isViewportFlipEnabled());
                 break;
+            }
             case gl::State::DIRTY_BIT_DEPTH_RANGE:
                 mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
                 break;
@@ -566,13 +570,17 @@
                 WARN() << "DIRTY_BIT_READ_FRAMEBUFFER_BINDING unimplemented";
                 break;
             case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
-                mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
-                                              glState.getFarPlane(), isViewportFlipEnabled());
+            {
+                FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
+                mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(),
+                                              glState.getNearPlane(), glState.getFarPlane(),
+                                              isViewportFlipEnabled());
                 updateColorMask(glState.getBlendState());
                 mPipelineDesc->updateCullMode(glState.getRasterizerState(),
                                               isViewportFlipEnabled());
                 updateScissor(glState);
                 break;
+            }
             case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
                 WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented";
                 break;
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 1bd9774..0ffe5b4 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -782,8 +782,15 @@
         // There is nothing to clear since the scissor is outside of the render area.
         return gl::NoError();
     }
+
     clearRect.rect = gl_vk::GetRect(intersection);
 
+    if (contextVk->isViewportFlipEnabled())
+    {
+        clearRect.rect.offset.y = getRenderPassRenderArea().height - clearRect.rect.offset.y -
+                                  clearRect.rect.extent.height;
+    }
+
     gl::AttachmentArray<VkClearAttachment> clearAttachments;
     int clearAttachmentIndex = 0;
 
@@ -889,7 +896,7 @@
     pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
     pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
     pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial());
-    pipelineDesc.updateViewport(renderArea, 0.0f, 1.0f, contextVk->isViewportFlipEnabled());
+    pipelineDesc.updateViewport(this, renderArea, 0.0f, 1.0f, contextVk->isViewportFlipEnabled());
 
     const gl::State &glState = contextVk->getGLState();
     if (glState.isScissorTestEnabled())
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
index 8812a87..41b3301 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
@@ -13,6 +13,7 @@
 #include "common/aligned_memory.h"
 #include "libANGLE/SizedMRUCache.h"
 #include "libANGLE/VertexAttribute.h"
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
 #include "libANGLE/renderer/vulkan/ProgramVk.h"
 #include "libANGLE/renderer/vulkan/RendererVk.h"
 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
@@ -637,7 +638,8 @@
         static_cast<uint32_t>(fragmentSerial.getValue());
 }
 
-void PipelineDesc::updateViewport(const gl::Rectangle &viewport,
+void PipelineDesc::updateViewport(FramebufferVk *framebufferVk,
+                                  const gl::Rectangle &viewport,
                                   float nearPlane,
                                   float farPlane,
                                   bool invertViewport)
@@ -649,7 +651,9 @@
 
     if (invertViewport)
     {
-        mViewport.y += viewport.height;
+        gl::Box dimensions       = framebufferVk->getState().getDimensions();
+        gl::Rectangle renderArea = gl::Rectangle(0, 0, dimensions.width, dimensions.height);
+        mViewport.y              = static_cast<float>(renderArea.height - viewport.y);
         mViewport.height = -mViewport.height;
     }
     updateDepthRange(nearPlane, farPlane);
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.h b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
index 3fe5613..196ed5c 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
@@ -350,7 +350,8 @@
                              const ShaderModule &fragmentModule,
                              Pipeline *pipelineOut) const;
 
-    void updateViewport(const gl::Rectangle &viewport,
+    void updateViewport(FramebufferVk *framebufferVk,
+                        const gl::Rectangle &viewport,
                         float nearPlane,
                         float farPlane,
                         bool invertViewport);