cocoa/uikit: Support VK_EXT_metal_surface

Uses VK_EXT_metal_surface (vkCreateMetalSurfaceEXT)
when possible, otherwise falls back to the obsoleted
VK_MVK_macos_surface and VK_MVK_ios_surface.

Fixes #3906
This commit is contained in:
Luke Street 2022-05-19 12:57:35 -07:00 committed by Sam Lantinga
parent ad874536a4
commit 029a9b2fa1
3 changed files with 86 additions and 34 deletions

View File

@ -34,12 +34,14 @@
#define VK_USE_PLATFORM_ANDROID_KHR #define VK_USE_PLATFORM_ANDROID_KHR
#endif #endif
#if SDL_VIDEO_DRIVER_COCOA #if SDL_VIDEO_DRIVER_COCOA
#define VK_USE_PLATFORM_METAL_EXT
#define VK_USE_PLATFORM_MACOS_MVK #define VK_USE_PLATFORM_MACOS_MVK
#endif #endif
#if SDL_VIDEO_DRIVER_DIRECTFB #if SDL_VIDEO_DRIVER_DIRECTFB
#define VK_USE_PLATFORM_DIRECTFB_EXT #define VK_USE_PLATFORM_DIRECTFB_EXT
#endif #endif
#if SDL_VIDEO_DRIVER_UIKIT #if SDL_VIDEO_DRIVER_UIKIT
#define VK_USE_PLATFORM_METAL_EXT
#define VK_USE_PLATFORM_IOS_MVK #define VK_USE_PLATFORM_IOS_MVK
#endif #endif
#if SDL_VIDEO_DRIVER_WAYLAND #if SDL_VIDEO_DRIVER_WAYLAND

View File

@ -53,6 +53,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
VkExtensionProperties *extensions = NULL; VkExtensionProperties *extensions = NULL;
Uint32 extensionCount = 0; Uint32 extensionCount = 0;
SDL_bool hasSurfaceExtension = SDL_FALSE; SDL_bool hasSurfaceExtension = SDL_FALSE;
SDL_bool hasMetalSurfaceExtension = SDL_FALSE;
SDL_bool hasMacOSSurfaceExtension = SDL_FALSE; SDL_bool hasMacOSSurfaceExtension = SDL_FALSE;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
@ -130,6 +131,8 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
for (Uint32 i = 0; i < extensionCount; i++) { for (Uint32 i = 0; i < extensionCount; i++) {
if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
hasSurfaceExtension = SDL_TRUE; hasSurfaceExtension = SDL_TRUE;
} else if (SDL_strcmp(VK_EXT_METAL_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
hasMetalSurfaceExtension = SDL_TRUE;
} else if (SDL_strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { } else if (SDL_strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
hasMacOSSurfaceExtension = SDL_TRUE; hasMacOSSurfaceExtension = SDL_TRUE;
} }
@ -139,9 +142,10 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
SDL_SetError("Installed Vulkan Portability library doesn't implement the " SDL_SetError("Installed Vulkan Portability library doesn't implement the "
VK_KHR_SURFACE_EXTENSION_NAME " extension"); VK_KHR_SURFACE_EXTENSION_NAME " extension");
goto fail; goto fail;
} else if (!hasMacOSSurfaceExtension) { } else if (!hasMetalSurfaceExtension && !hasMacOSSurfaceExtension) {
SDL_SetError("Installed Vulkan Portability library doesn't implement the " SDL_SetError("Installed Vulkan Portability library doesn't implement the "
VK_MVK_MACOS_SURFACE_EXTENSION_NAME "extension"); VK_EXT_METAL_SURFACE_EXTENSION_NAME " or "
VK_MVK_MACOS_SURFACE_EXTENSION_NAME " extensions");
goto fail; goto fail;
} }
return 0; return 0;
@ -186,11 +190,14 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
{ {
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT =
(PFN_vkCreateMetalSurfaceEXT)vkGetInstanceProcAddr(
(VkInstance)instance,
"vkCreateMetalSurfaceEXT");
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK = PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
(PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr( (PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr(
(VkInstance)instance, (VkInstance)instance,
"vkCreateMacOSSurfaceMVK"); "vkCreateMacOSSurfaceMVK");
VkMacOSSurfaceCreateInfoMVK createInfo = {};
VkResult result; VkResult result;
SDL_MetalView metalview; SDL_MetalView metalview;
@ -199,9 +206,10 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
return SDL_FALSE; return SDL_FALSE;
} }
if (!vkCreateMacOSSurfaceMVK) { if (!vkCreateMetalSurfaceEXT && !vkCreateMacOSSurfaceMVK) {
SDL_SetError(VK_MVK_MACOS_SURFACE_EXTENSION_NAME SDL_SetError(VK_EXT_METAL_SURFACE_EXTENSION_NAME " or "
" extension is not enabled in the Vulkan instance."); VK_MVK_MACOS_SURFACE_EXTENSION_NAME
" extensions are not enabled in the Vulkan instance.");
return SDL_FALSE; return SDL_FALSE;
} }
@ -210,17 +218,34 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
return SDL_FALSE; return SDL_FALSE;
} }
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; if (vkCreateMetalSurfaceEXT) {
createInfo.pNext = NULL; VkMetalSurfaceCreateInfoEXT createInfo = {};
createInfo.flags = 0; createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
createInfo.pView = (const void *)metalview; createInfo.pNext = NULL;
result = vkCreateMacOSSurfaceMVK(instance, &createInfo, createInfo.flags = 0;
NULL, surface); createInfo.pLayer = (__bridge const CAMetalLayer *)
if (result != VK_SUCCESS) { Cocoa_Metal_GetLayer(_this, metalview);
Cocoa_Metal_DestroyView(_this, metalview); result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface);
SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s", if (result != VK_SUCCESS) {
SDL_Vulkan_GetResultString(result)); Cocoa_Metal_DestroyView(_this, metalview);
return SDL_FALSE; SDL_SetError("vkCreateMetalSurfaceEXT failed: %s",
SDL_Vulkan_GetResultString(result));
return SDL_FALSE;
}
} else {
VkMacOSSurfaceCreateInfoMVK createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.pView = (const void *)metalview;
result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
NULL, surface);
if (result != VK_SUCCESS) {
Cocoa_Metal_DestroyView(_this, metalview);
SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
SDL_Vulkan_GetResultString(result));
return SDL_FALSE;
}
} }
/* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call /* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call

View File

@ -51,6 +51,7 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
VkExtensionProperties *extensions = NULL; VkExtensionProperties *extensions = NULL;
Uint32 extensionCount = 0; Uint32 extensionCount = 0;
SDL_bool hasSurfaceExtension = SDL_FALSE; SDL_bool hasSurfaceExtension = SDL_FALSE;
SDL_bool hasMetalSurfaceExtension = SDL_FALSE;
SDL_bool hasIOSSurfaceExtension = SDL_FALSE; SDL_bool hasIOSSurfaceExtension = SDL_FALSE;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
@ -134,6 +135,8 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
for (Uint32 i = 0; i < extensionCount; i++) { for (Uint32 i = 0; i < extensionCount; i++) {
if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
hasSurfaceExtension = SDL_TRUE; hasSurfaceExtension = SDL_TRUE;
} else if (SDL_strcmp(VK_EXT_METAL_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
hasMetalSurfaceExtension = SDL_TRUE;
} else if (SDL_strcmp(VK_MVK_IOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { } else if (SDL_strcmp(VK_MVK_IOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
hasIOSSurfaceExtension = SDL_TRUE; hasIOSSurfaceExtension = SDL_TRUE;
} }
@ -145,9 +148,10 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
SDL_SetError("Installed Vulkan Portability doesn't implement the " SDL_SetError("Installed Vulkan Portability doesn't implement the "
VK_KHR_SURFACE_EXTENSION_NAME " extension"); VK_KHR_SURFACE_EXTENSION_NAME " extension");
goto fail; goto fail;
} else if (!hasIOSSurfaceExtension) { } else if (!hasMetalSurfaceExtension && !hasIOSSurfaceExtension) {
SDL_SetError("Installed Vulkan Portability doesn't implement the " SDL_SetError("Installed Vulkan Portability doesn't implement the "
VK_MVK_IOS_SURFACE_EXTENSION_NAME "extension"); VK_EXT_METAL_SURFACE_EXTENSION_NAME " or "
VK_MVK_IOS_SURFACE_EXTENSION_NAME " extensions");
goto fail; goto fail;
} }
@ -193,11 +197,14 @@ SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
{ {
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT =
(PFN_vkCreateMetalSurfaceEXT)vkGetInstanceProcAddr(
(VkInstance)instance,
"vkCreateMetalSurfaceEXT");
PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK = PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK =
(PFN_vkCreateIOSSurfaceMVK)vkGetInstanceProcAddr( (PFN_vkCreateIOSSurfaceMVK)vkGetInstanceProcAddr(
(VkInstance)instance, (VkInstance)instance,
"vkCreateIOSSurfaceMVK"); "vkCreateIOSSurfaceMVK");
VkIOSSurfaceCreateInfoMVK createInfo = {};
VkResult result; VkResult result;
SDL_MetalView metalview; SDL_MetalView metalview;
@ -206,9 +213,10 @@ SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
return SDL_FALSE; return SDL_FALSE;
} }
if (!vkCreateIOSSurfaceMVK) { if (!vkCreateMetalSurfaceEXT && !vkCreateIOSSurfaceMVK) {
SDL_SetError(VK_MVK_IOS_SURFACE_EXTENSION_NAME SDL_SetError(VK_EXT_METAL_SURFACE_EXTENSION_NAME " or "
" extension is not enabled in the Vulkan instance."); VK_MVK_IOS_SURFACE_EXTENSION_NAME
" extensions are not enabled in the Vulkan instance.");
return SDL_FALSE; return SDL_FALSE;
} }
@ -217,17 +225,34 @@ SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
return SDL_FALSE; return SDL_FALSE;
} }
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK; if (vkCreateMetalSurfaceEXT) {
createInfo.pNext = NULL; VkMetalSurfaceCreateInfoEXT createInfo = {};
createInfo.flags = 0; createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
createInfo.pView = (const void *)metalview; createInfo.pNext = NULL;
result = vkCreateIOSSurfaceMVK(instance, &createInfo, createInfo.flags = 0;
NULL, surface); createInfo.pLayer = (__bridge const CAMetalLayer *)
if (result != VK_SUCCESS) { UIKit_Metal_GetLayer(_this, metalview);
UIKit_Metal_DestroyView(_this, metalview); result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface);
SDL_SetError("vkCreateIOSSurfaceMVK failed: %s", if (result != VK_SUCCESS) {
SDL_Vulkan_GetResultString(result)); UIKit_Metal_DestroyView(_this, metalview);
return SDL_FALSE; SDL_SetError("vkCreateMetalSurfaceEXT failed: %s",
SDL_Vulkan_GetResultString(result));
return SDL_FALSE;
}
} else {
VkIOSSurfaceCreateInfoMVK createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.pView = (const void *)metalview;
result = vkCreateIOSSurfaceMVK(instance, &createInfo,
NULL, surface);
if (result != VK_SUCCESS) {
UIKit_Metal_DestroyView(_this, metalview);
SDL_SetError("vkCreateIOSSurfaceMVK failed: %s",
SDL_Vulkan_GetResultString(result));
return SDL_FALSE;
}
} }
/* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call /* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call