MetalSurface: correctly handle the window resizing.

In metal the size of the drawable (the texture use to render to the
window) is decoupled from the window's size:

 - When the first drawable is created, its size is given by
   layer.bounds.size * layer.contentsScale.
 - Once set the drawableSize never changes without the user setting the
   layer.drawableSize explicitly.

This means that the code checking for OUT_OF_DATE_KHR needs to be
updated to check the texture size against the drawable's size (and not
the current scaled window size).

Also Swiftshader needs to set the drawableSize to the correct value when
the window is resized. The best moment to do this is when querying the
capabilities as that's done when a new swapchain is created (which
happens when the application is handling the window's resize).

Bug: dawn:269
Change-Id: Icf1c3df63d42e0fa9211893f6b89d8709dfd942e
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/49328
Tested-by: Corentin Wallez <cwallez@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/WSI/MetalSurface.mm b/src/WSI/MetalSurface.mm
index af5a4ae..d4a4448 100644
--- a/src/WSI/MetalSurface.mm
+++ b/src/WSI/MetalSurface.mm
@@ -78,7 +78,9 @@
         }
     }
 
-    VkExtent2D getExtent() const API_AVAILABLE(macosx(10.11))
+    // Synchronizes the drawableSize to layer.bounds.size * layer.contentsScale and returns the new value of
+    // drawableSize.
+    VkExtent2D syncExtent() const API_AVAILABLE(macosx(10.11))
     {
         if(layer)
         {
@@ -86,6 +88,9 @@
             CGFloat scaleFactor = layer.contentsScale;
             drawSize.width = trunc(drawSize.width * scaleFactor);
             drawSize.height = trunc(drawSize.height * scaleFactor);
+
+            [layer setDrawableSize: drawSize];
+
             return { static_cast<uint32_t>(drawSize.width), static_cast<uint32_t>(drawSize.height) };
         }
         else
@@ -104,6 +109,16 @@
         return nil;
     }
 
+    VkExtent2D getDrawableSize() const API_AVAILABLE(macosx(10.11)) {
+        if (layer) {
+            return {
+                static_cast<uint32_t>([layer drawableSize].width),
+                static_cast<uint32_t>([layer drawableSize].height),
+            };
+        }
+        return {0, 0};
+    }
+
 private:
     NSView* view;
     CAMetalLayer* layer API_AVAILABLE(macosx(10.11));
@@ -133,7 +148,11 @@
 {
     SurfaceKHR::getSurfaceCapabilities(pSurfaceCapabilities);
 
-    VkExtent2D extent = metalLayer->getExtent();
+    // The value of drawableSize in CAMetalLayer is set the first time a drawable is queried but after that it is the
+    // (Metal) application's responsibility to resize the drawable when the window is resized. The best time for Swiftshader
+    // to resize the drawable is when querying the capabilities of the swapchain as that's done when the Vulkan application
+    // is trying to handle a window resize.
+    VkExtent2D extent = metalLayer->syncExtent();
     pSurfaceCapabilities->currentExtent = extent;
     pSurfaceCapabilities->minImageExtent = extent;
     pSurfaceCapabilities->maxImageExtent = extent;
@@ -146,10 +165,10 @@
         auto drawable = metalLayer->getNextDrawable();
         if(drawable)
         {
-            VkExtent2D windowExtent = metalLayer->getExtent();
             const VkExtent3D &extent = image->getImage()->getExtent();
+            VkExtent2D drawableExtent = metalLayer->getDrawableSize();
 
-            if(windowExtent.width != extent.width || windowExtent.height != extent.height)
+            if(drawableExtent.width != extent.width || drawableExtent.height != extent.height)
             {
                 return VK_ERROR_OUT_OF_DATE_KHR;
             }