SDL  2.0
SDL_cocoavulkan.m
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 /*
23  * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
24  * SDL_x11vulkan.c.
25  */
26 
27 #include "../../SDL_internal.h"
28 
29 #if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_COCOA
30 
31 #include "SDL_cocoavideo.h"
32 #include "SDL_cocoawindow.h"
33 #include "SDL_assert.h"
34 
35 #include "SDL_loadso.h"
36 #include "SDL_cocoametalview.h"
37 #include "SDL_cocoavulkan.h"
38 #include "SDL_syswm.h"
39 
40 #include <dlfcn.h>
41 
42 const char* defaultPaths[] = {
43  "vulkan.framework/vulkan",
44  "libvulkan.1.dylib",
45  "MoltenVK.framework/MoltenVK",
46  "libMoltenVK.dylib"
47 };
48 
49 /* Since libSDL is most likely a .dylib, need RTLD_DEFAULT not RTLD_SELF. */
50 #define DEFAULT_HANDLE RTLD_DEFAULT
51 
52 int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
53 {
54  VkExtensionProperties *extensions = NULL;
55  Uint32 extensionCount = 0;
56  SDL_bool hasSurfaceExtension = SDL_FALSE;
57  SDL_bool hasMacOSSurfaceExtension = SDL_FALSE;
59 
61  return SDL_SetError("Vulkan/MoltenVK already loaded");
62  }
63 
64  /* Load the Vulkan loader library */
65  if (!path) {
66  path = SDL_getenv("SDL_VULKAN_LIBRARY");
67  }
68 
69  if (!path) {
70  /* MoltenVK framework, currently, v0.17.0, has a static library and is
71  * the recommended way to use the package. There is likely no object to
72  * load. */
73  vkGetInstanceProcAddr =
74  (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
75  "vkGetInstanceProcAddr");
76  }
77 
78  if (vkGetInstanceProcAddr) {
79  _this->vulkan_config.loader_handle = DEFAULT_HANDLE;
80  } else {
81  const char** paths;
82  const char *foundPath = NULL;
83  int numPaths;
84  int i;
85 
86  if (path) {
87  paths = &path;
88  numPaths = 1;
89  } else {
90  /* Look for framework or .dylib packaged with the application
91  * instead. */
92  paths = defaultPaths;
93  numPaths = SDL_arraysize(defaultPaths);
94  }
95 
96  for (i = 0; i < numPaths && _this->vulkan_config.loader_handle == NULL; i++) {
97  foundPath = paths[i];
99  }
100 
102  return SDL_SetError("Failed to load Vulkan/MoltenVK library");
103  }
104 
107  vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
108  _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
109  }
110 
111  if (!vkGetInstanceProcAddr) {
112  SDL_SetError("Failed to find %s in either executable or %s: %s",
113  "vkGetInstanceProcAddr",
115  (const char *) dlerror());
116  goto fail;
117  }
118 
119  _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
122  VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
124  goto fail;
125  }
126  extensions = SDL_Vulkan_CreateInstanceExtensionsList(
129  &extensionCount);
130  if (!extensions) {
131  goto fail;
132  }
133  for (Uint32 i = 0; i < extensionCount; i++) {
134  if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
135  hasSurfaceExtension = SDL_TRUE;
136  } else if (SDL_strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
137  hasMacOSSurfaceExtension = SDL_TRUE;
138  }
139  }
140  SDL_free(extensions);
141  if (!hasSurfaceExtension) {
142  SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
143  VK_KHR_SURFACE_EXTENSION_NAME " extension");
144  goto fail;
145  } else if (!hasMacOSSurfaceExtension) {
146  SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
147  VK_MVK_MACOS_SURFACE_EXTENSION_NAME "extension");
148  goto fail;
149  }
150  return 0;
151 
152 fail:
155  return -1;
156 }
157 
158 void Cocoa_Vulkan_UnloadLibrary(_THIS)
159 {
161  if (_this->vulkan_config.loader_handle != DEFAULT_HANDLE) {
163  }
165  }
166 }
167 
168 SDL_bool Cocoa_Vulkan_GetInstanceExtensions(_THIS,
170  unsigned *count,
171  const char **names)
172 {
173  static const char *const extensionsForCocoa[] = {
174  VK_KHR_SURFACE_EXTENSION_NAME, VK_MVK_MACOS_SURFACE_EXTENSION_NAME
175  };
177  SDL_SetError("Vulkan is not loaded");
178  return SDL_FALSE;
179  }
180  return SDL_Vulkan_GetInstanceExtensions_Helper(
181  count, names, SDL_arraysize(extensionsForCocoa),
182  extensionsForCocoa);
183 }
184 
185 SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
186  SDL_Window *window,
187  VkInstance instance,
188  VkSurfaceKHR *surface)
189 {
190  PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
192  PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
193  (PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr(
194  (VkInstance)instance,
195  "vkCreateMacOSSurfaceMVK");
196  VkMacOSSurfaceCreateInfoMVK createInfo = {};
198 
200  SDL_SetError("Vulkan is not loaded");
201  return SDL_FALSE;
202  }
203 
204  if (!vkCreateMacOSSurfaceMVK) {
205  SDL_SetError(VK_MVK_MACOS_SURFACE_EXTENSION_NAME
206  " extension is not enabled in the Vulkan instance.");
207  return SDL_FALSE;
208  }
210  createInfo.pNext = NULL;
211  createInfo.flags = 0;
212  createInfo.pView = Cocoa_Mtl_AddMetalView(window);
213  result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
214  NULL, surface);
215  if (result != VK_SUCCESS) {
216  SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
217  SDL_Vulkan_GetResultString(result));
218  return SDL_FALSE;
219  }
220  return SDL_TRUE;
221 }
222 
223 void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
224 {
225  Cocoa_Mtl_GetDrawableSize(window, w, h);
226 }
227 
228 #endif
229 
230 /* vim: set ts=4 sw=4 expandtab: */
#define SDL_strlcpy
#define VK_KHR_SURFACE_EXTENSION_NAME
Definition: vulkan.h:3416
GLuint64EXT * result
GLuint GLuint * names
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLfloat GLfloat GLfloat GLfloat h
EGLSurface surface
Definition: eglext.h:248
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName)
#define SDL_LoadObject
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_UnloadObject
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
Definition: vulkan.h:2484
#define VK_NULL_HANDLE
Definition: vulkan.h:49
VkResult
Definition: vulkan.h:122
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
char loader_path[256]
Definition: SDL_sysvideo.h:375
#define _THIS
#define SDL_free
GLubyte GLubyte GLubyte GLubyte w
PP_Instance instance
Definition: SDL_naclvideo.h:57
#define SDL_getenv
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:161
struct SDL_VideoDevice::@34 vulkan_config
#define SDL_SetError
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties
Definition: SDL_sysvideo.h:373
The type used to identify a window.
Definition: SDL_sysvideo.h:73
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr
Definition: SDL_sysvideo.h:372
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
GLsizei const GLchar *const * path
#define SDL_strcmp
void * SDL_LoadFunction(void *handle, const char *name)
GLsizei const GLuint * paths
GLsizei numPaths
VkResult(VKAPI_PTR * PFN_vkEnumerateInstanceExtensionProperties)(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties)
Definition: vulkan.h:2488
void * loader_handle
Definition: SDL_sysvideo.h:376