diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index e1cd8e19..0e2b5336 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -252,6 +252,17 @@ You can enable each of these extensions by defining the `VK_USE_PLATFORM_IOS_MVK
`VK_USE_PLATFORM_MACOS_MVK` guard macro in your compiler build settings. See the description
of the `mvk_vulkan.h` file below for a convenient way to enable these extensions automatically.
+When using the `VK_MVK_macos_surface ` extension, the `pView` member of the `VkMacOSSurfaceCreateInfoMVK`
+structure passed in the `vkCreateMacOSSurfaceMVK` function can be either an `NSView` whose layer is a
+`CAMetalLayer`, or the `CAMetalLayer` itself. Passing the `CAMetalLayer` itself is recommended when calling
+the `vkCreateMacOSSurfaceMVK` function from outside the main application thread, as `NSView` should only be
+accessed from the main application thread.
+
+When using the `VK_MVK_ios_surface ` extension, the `pView` member of the `VkIOSSurfaceCreateInfoMVK`
+structure passed in the `vkCreateIOSSurfaceMVK` function can be either a `UIView` whose layer is a
+`CAMetalLayer`, or the `CAMetalLayer` itself. Passing the `CAMetalLayer` itself is recommended when
+calling the `vkCreateIOSSurfaceMVK ` function from outside the main application thread, as `UIView`
+should only be accessed from the main application thread.
### MoltenVK Extension
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h
index b8ccd4c8..56471412 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h
@@ -28,14 +28,14 @@
# define Vk_PLATFORM_SurfaceCreateInfoMVK VkIOSSurfaceCreateInfoMVK
# define PLATFORM_VIEW_CLASS UIView
# include
-#endif // MVK_IOS
+#endif
#ifdef VK_USE_PLATFORM_MACOS_MVK
# define vkCreate_PLATFORM_SurfaceMVK vkCreateMacOSSurfaceMVK
# define Vk_PLATFORM_SurfaceCreateInfoMVK VkMacOSSurfaceCreateInfoMVK
# define PLATFORM_VIEW_CLASS NSView
# include
-#endif // MVK_MACOS
+#endif
#import
#import
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm
index 8a33789e..37024f1f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm
@@ -26,18 +26,41 @@
#pragma mark Construction
+#ifdef VK_USE_PLATFORM_IOS_MVK
+static const char* mvkSurfaceCreateFuncName = "vkCreateIOSSurfaceMVK";
+static const char* mvkSurfaceCreateStructName = "VkIOSSurfaceCreateInfoMVK";
+static const char* mvkViewClassName = "UIView";
+#endif
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+static const char* mvkSurfaceCreateFuncName = "vkCreateMacOSSurfaceMVK";
+static const char* mvkSurfaceCreateStructName = "VkMacOSSurfaceCreateInfoMVK";
+static const char* mvkViewClassName = "NSView";
+#endif
+
+// pCreateInfo->pView can be either a CAMetalLayer or a view (NSView/UIView).
MVKSurface::MVKSurface(MVKInstance* mvkInstance,
const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator) {
- __block CALayer* viewLayer = nil;
- mvkDispatchToMainAndWait(^{ viewLayer = ((PLATFORM_VIEW_CLASS*)pCreateInfo->pView).layer; });
- if ( [viewLayer isKindOfClass: [CAMetalLayer class]] ) {
- _mtlCAMetalLayer = (CAMetalLayer*)[viewLayer retain]; // retained
- } else {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "On-screen rendering requires a view that is backed by a layer of type CAMetalLayer."));
- _mtlCAMetalLayer = nil;
- }
+ // Get the platform object contained in pView
+ id obj = (id)pCreateInfo->pView;
+
+ // If it's a view (NSView/UIView), extract the layer, otherwise assume it's already a CAMetalLayer.
+ if ([obj isKindOfClass: [PLATFORM_VIEW_CLASS class]]) {
+ if ( !NSThread.isMainThread ) {
+ MVKLogInfo("%s(): You are not calling this function from the main thread. %s should only be accessed from the main thread. When using this function outside the main thread, consider passing the CAMetalLayer itself in %s::pView, instead of the %s.", mvkSurfaceCreateFuncName, mvkViewClassName, mvkSurfaceCreateStructName, mvkViewClassName);
+ }
+ obj = ((PLATFORM_VIEW_CLASS*)obj).layer;
+ }
+
+ // Confirm that we were provided with a CAMetalLayer
+ if ([obj isKindOfClass: [CAMetalLayer class]]) {
+ _mtlCAMetalLayer = (CAMetalLayer*)[obj retain]; // retained
+ } else {
+ setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "%s(): On-screen rendering requires a layer of type CAMetalLayer.", mvkSurfaceCreateFuncName));
+ _mtlCAMetalLayer = nil;
+ }
}
MVKSurface::~MVKSurface() {
diff --git a/MoltenVK/scripts/create_dylib_ios.sh b/MoltenVK/scripts/create_dylib_ios.sh
index 544ea793..f1c1fc73 100755
--- a/MoltenVK/scripts/create_dylib_ios.sh
+++ b/MoltenVK/scripts/create_dylib_ios.sh
@@ -26,7 +26,7 @@ clang \
-Wno-incompatible-sysroot \
-isysroot ${SDK_DIR} \
-iframework ${MVK_SYS_FWK_DIR} \
--framework Metal ${MVK_IOSURFACE_FWK} -framework UIKit -framework QuartzCore -framework Foundation \
+-framework Metal ${MVK_IOSURFACE_FWK} -framework UIKit -framework QuartzCore -framework UIKit -framework Foundation \
--library-directory ${MVK_USR_LIB_DIR} \
-lSystem -lc++ \
-o "${MVK_BUILT_PROD_PATH}/${MVK_DYLIB_NAME}" \
diff --git a/MoltenVK/scripts/create_dylib_macos.sh b/MoltenVK/scripts/create_dylib_macos.sh
index 3e6b33bf..be0ebfa1 100755
--- a/MoltenVK/scripts/create_dylib_macos.sh
+++ b/MoltenVK/scripts/create_dylib_macos.sh
@@ -17,7 +17,7 @@ clang \
-Wno-incompatible-sysroot \
-isysroot ${SDK_DIR} \
-iframework ${MVK_SYS_FWK_DIR} \
--framework Metal -framework IOSurface -framework IOKit -framework QuartzCore -framework Foundation \
+-framework Metal -framework IOSurface -framework IOKit -framework QuartzCore -framework AppKit -framework Foundation \
--library-directory ${MVK_USR_LIB_DIR} \
-lSystem -lc++ \
-o "${MVK_BUILT_PROD_PATH}/${MVK_DYLIB_NAME}" \