diff --git a/src/video/SDL_vulkan_internal.h b/src/video/SDL_vulkan_internal.h index 1ec1ab473306d..ae9b962209f19 100644 --- a/src/video/SDL_vulkan_internal.h +++ b/src/video/SDL_vulkan_internal.h @@ -34,12 +34,14 @@ #define VK_USE_PLATFORM_ANDROID_KHR #endif #if SDL_VIDEO_DRIVER_COCOA +#define VK_USE_PLATFORM_METAL_EXT #define VK_USE_PLATFORM_MACOS_MVK #endif #if SDL_VIDEO_DRIVER_DIRECTFB #define VK_USE_PLATFORM_DIRECTFB_EXT #endif #if SDL_VIDEO_DRIVER_UIKIT +#define VK_USE_PLATFORM_METAL_EXT #define VK_USE_PLATFORM_IOS_MVK #endif #if SDL_VIDEO_DRIVER_WAYLAND diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m index 20c83d47d78d6..f91924cd0ca41 100644 --- a/src/video/cocoa/SDL_cocoavulkan.m +++ b/src/video/cocoa/SDL_cocoavulkan.m @@ -53,6 +53,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path) VkExtensionProperties *extensions = NULL; Uint32 extensionCount = 0; SDL_bool hasSurfaceExtension = SDL_FALSE; + SDL_bool hasMetalSurfaceExtension = SDL_FALSE; SDL_bool hasMacOSSurfaceExtension = SDL_FALSE; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; @@ -130,6 +131,8 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path) for (Uint32 i = 0; i < extensionCount; i++) { if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { 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) { 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 " VK_KHR_SURFACE_EXTENSION_NAME " extension"); goto fail; - } else if (!hasMacOSSurfaceExtension) { + } else if (!hasMetalSurfaceExtension && !hasMacOSSurfaceExtension) { 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; } return 0; @@ -186,11 +190,14 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS, { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; + PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT = + (PFN_vkCreateMetalSurfaceEXT)vkGetInstanceProcAddr( + (VkInstance)instance, + "vkCreateMetalSurfaceEXT"); PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr( (VkInstance)instance, "vkCreateMacOSSurfaceMVK"); - VkMacOSSurfaceCreateInfoMVK createInfo = {}; VkResult result; SDL_MetalView metalview; @@ -199,9 +206,10 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS, return SDL_FALSE; } - if (!vkCreateMacOSSurfaceMVK) { - SDL_SetError(VK_MVK_MACOS_SURFACE_EXTENSION_NAME - " extension is not enabled in the Vulkan instance."); + if (!vkCreateMetalSurfaceEXT && !vkCreateMacOSSurfaceMVK) { + SDL_SetError(VK_EXT_METAL_SURFACE_EXTENSION_NAME " or " + VK_MVK_MACOS_SURFACE_EXTENSION_NAME + " extensions are not enabled in the Vulkan instance."); return SDL_FALSE; } @@ -210,17 +218,34 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS, return SDL_FALSE; } - 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; + if (vkCreateMetalSurfaceEXT) { + VkMetalSurfaceCreateInfoEXT createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.pLayer = (__bridge const CAMetalLayer *) + Cocoa_Metal_GetLayer(_this, metalview); + result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface); + if (result != VK_SUCCESS) { + Cocoa_Metal_DestroyView(_this, metalview); + 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 diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m index f0f2d2b04a3e3..891f5bb09a414 100644 --- a/src/video/uikit/SDL_uikitvulkan.m +++ b/src/video/uikit/SDL_uikitvulkan.m @@ -51,6 +51,7 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path) VkExtensionProperties *extensions = NULL; Uint32 extensionCount = 0; SDL_bool hasSurfaceExtension = SDL_FALSE; + SDL_bool hasMetalSurfaceExtension = SDL_FALSE; SDL_bool hasIOSSurfaceExtension = SDL_FALSE; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; @@ -134,6 +135,8 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path) for (Uint32 i = 0; i < extensionCount; i++) { if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { 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) { hasIOSSurfaceExtension = SDL_TRUE; } @@ -145,9 +148,10 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path) SDL_SetError("Installed Vulkan Portability doesn't implement the " VK_KHR_SURFACE_EXTENSION_NAME " extension"); goto fail; - } else if (!hasIOSSurfaceExtension) { + } else if (!hasMetalSurfaceExtension && !hasIOSSurfaceExtension) { 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; } @@ -193,11 +197,14 @@ SDL_bool UIKit_Vulkan_CreateSurface(_THIS, { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; + PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT = + (PFN_vkCreateMetalSurfaceEXT)vkGetInstanceProcAddr( + (VkInstance)instance, + "vkCreateMetalSurfaceEXT"); PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK = (PFN_vkCreateIOSSurfaceMVK)vkGetInstanceProcAddr( (VkInstance)instance, "vkCreateIOSSurfaceMVK"); - VkIOSSurfaceCreateInfoMVK createInfo = {}; VkResult result; SDL_MetalView metalview; @@ -206,9 +213,10 @@ SDL_bool UIKit_Vulkan_CreateSurface(_THIS, return SDL_FALSE; } - if (!vkCreateIOSSurfaceMVK) { - SDL_SetError(VK_MVK_IOS_SURFACE_EXTENSION_NAME - " extension is not enabled in the Vulkan instance."); + if (!vkCreateMetalSurfaceEXT && !vkCreateIOSSurfaceMVK) { + SDL_SetError(VK_EXT_METAL_SURFACE_EXTENSION_NAME " or " + VK_MVK_IOS_SURFACE_EXTENSION_NAME + " extensions are not enabled in the Vulkan instance."); return SDL_FALSE; } @@ -217,17 +225,34 @@ SDL_bool UIKit_Vulkan_CreateSurface(_THIS, return SDL_FALSE; } - 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; + if (vkCreateMetalSurfaceEXT) { + VkMetalSurfaceCreateInfoEXT createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.pLayer = (__bridge const CAMetalLayer *) + UIKit_Metal_GetLayer(_this, metalview); + result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface); + if (result != VK_SUCCESS) { + UIKit_Metal_DestroyView(_this, metalview); + 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