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}" \