MetalSurface: set layer.device to a ref of the system default device.

If layer.device is null, [layer nextDrawable] returns nil, so on surface
initialization we set layer.device to a dummy MTLDevice by getting a
reference of the system default device.

MTLCreateSystemDefaultDevice() requires linking against
Metal.framework but Chromium needs to ship on platforms that don't have
Metal. This means we can't directly link against the framework, instead
we "weakly" link against it so that if it is not present, the function
pointers are just null (instead of failing to launch).

Bug: dawn:269
Change-Id: I5984613f576849c6f219c253da7eb277fa75ef52
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43209
Kokoro-Presubmit: Corentin Wallez <cwallez@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Corentin Wallez <cwallez@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 18324e9..a0a8f37 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1092,7 +1092,8 @@
     find_library(QUARTZ_FRAMEWORK Quartz)
     find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation)
     find_library(IOSURFACE_FRAMEWORK IOSurface)
-    set(OS_LIBS "${COCOA_FRAMEWORK}" "${QUARTZ_FRAMEWORK}" "${CORE_FOUNDATION_FRAMEWORK}" "${IOSURFACE_FRAMEWORK}")
+    find_library(METAL_FRAMEWORK Metal)
+    set(OS_LIBS "${COCOA_FRAMEWORK}" "${QUARTZ_FRAMEWORK}" "${CORE_FOUNDATION_FRAMEWORK}" "${IOSURFACE_FRAMEWORK}" "${METAL_FRAMEWORK}")
 endif()
 
 ###########################################################
@@ -1632,4 +1633,4 @@
     foreach(pvr_target ${PVR_TARGET_OTHER} ${PVR_VULKAN_TARGET_OTHER} ${PVR_GLES_TARGET_OTHER})
         set_target_properties(${pvr_target} PROPERTIES FOLDER Samples/PowerVR-Build)
     endforeach()
-endif()
\ No newline at end of file
+endif()
diff --git a/src/WSI/BUILD.gn b/src/WSI/BUILD.gn
index f1feb31..6a55805 100644
--- a/src/WSI/BUILD.gn
+++ b/src/WSI/BUILD.gn
@@ -14,6 +14,15 @@
 
 import("../swiftshader.gni")
 
+config("WSI_metal_weak_framework") {
+  if (is_mac) {
+    ldflags = [
+      "-weak_framework",
+      "Metal",
+    ]
+  }
+}
+
 swiftshader_source_set("WSI") {
   sources = [
     "VkSurfaceKHR.cpp",
@@ -42,13 +51,14 @@
 
   if (is_mac) {
     sources += [
-      "MetalSurface.mm",
       "MetalSurface.h",
+      "MetalSurface.mm",
     ]
     libs = [
       "Cocoa.framework",
       "QuartzCore.framework",
     ]
+    public_configs = [ ":WSI_metal_weak_framework" ]
   }
 
   include_dirs = [
@@ -63,5 +73,5 @@
     "../Vulkan:swiftshader_libvulkan_headers",
   ]
 
-  configs = [ "../Vulkan:swiftshader_libvulkan_private_config", ]
+  configs = [ "../Vulkan:swiftshader_libvulkan_private_config" ]
 }
diff --git a/src/WSI/MetalSurface.mm b/src/WSI/MetalSurface.mm
index c31248a..f88689e 100644
--- a/src/WSI/MetalSurface.mm
+++ b/src/WSI/MetalSurface.mm
@@ -40,6 +40,7 @@
         {
             layer = (CAMetalLayer*)[obj retain];
             layer.framebufferOnly = false;
+            layer.device = MTLCreateSystemDefaultDevice();
         }
         else
         {
@@ -68,6 +69,7 @@
     {
         if(layer)
         {
+            [layer.device release];
             [layer release];
         }
         if(view)