SDL  2.0
SDL_cocoavulkan.m
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 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 #define DEFAULT_MOLTENVK "libMoltenVK.dylib"
43 /* Since libSDL is most likely a .dylib, need RTLD_DEFAULT not RTLD_SELF. */
44 #define DEFAULT_HANDLE RTLD_DEFAULT
45 
46 int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
47 {
48  VkExtensionProperties *extensions = NULL;
49  Uint32 extensionCount = 0;
50  SDL_bool hasSurfaceExtension = SDL_FALSE;
51  SDL_bool hasMacOSSurfaceExtension = SDL_FALSE;
53 
55  SDL_SetError("MoltenVK/Vulkan already loaded");
56  return -1;
57  }
58 
59  /* Load the Vulkan loader library */
60  if (!path) {
61  path = SDL_getenv("SDL_VULKAN_LIBRARY");
62  }
63  if (!path) {
64  /* MoltenVK framework, currently, v0.17.0, has a static library and is
65  * the recommended way to use the package. There is likely no object to
66  * load. */
67  vkGetInstanceProcAddr =
68  (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
69  "vkGetInstanceProcAddr");
70  }
71 
72  if (vkGetInstanceProcAddr) {
73  _this->vulkan_config.loader_handle = DEFAULT_HANDLE;
74  } else {
75  if (!path) {
76  /* Look for the .dylib packaged with the application instead. */
77  path = DEFAULT_MOLTENVK;
78  }
79 
82  return -1;
83  }
86  vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
87  _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
88  }
89 
90  if (!vkGetInstanceProcAddr) {
91  SDL_SetError("Failed to find %s in either executable or %s: %s",
92  "vkGetInstanceProcAddr",
93  DEFAULT_MOLTENVK,
94  (const char *) dlerror());
95  goto fail;
96  }
97 
98  _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
101  VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
103  goto fail;
104  }
105  extensions = SDL_Vulkan_CreateInstanceExtensionsList(
108  &extensionCount);
109  if (!extensions) {
110  goto fail;
111  }
112  for (Uint32 i = 0; i < extensionCount; i++) {
113  if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
114  hasSurfaceExtension = SDL_TRUE;
115  } else if (SDL_strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
116  hasMacOSSurfaceExtension = SDL_TRUE;
117  }
118  }
119  SDL_free(extensions);
120  if (!hasSurfaceExtension) {
121  SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
122  VK_KHR_SURFACE_EXTENSION_NAME " extension");
123  goto fail;
124  } else if (!hasMacOSSurfaceExtension) {
125  SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
126  VK_MVK_MACOS_SURFACE_EXTENSION_NAME "extension");
127  goto fail;
128  }
129  return 0;
130 
131 fail:
134  return -1;
135 }
136 
137 void Cocoa_Vulkan_UnloadLibrary(_THIS)
138 {
140  if (_this->vulkan_config.loader_handle != DEFAULT_HANDLE) {
142  }
144  }
145 }
146 
147 SDL_bool Cocoa_Vulkan_GetInstanceExtensions(_THIS,
149  unsigned *count,
150  const char **names)
151 {
152  static const char *const extensionsForCocoa[] = {
153  VK_KHR_SURFACE_EXTENSION_NAME, VK_MVK_MACOS_SURFACE_EXTENSION_NAME
154  };
156  SDL_SetError("Vulkan is not loaded");
157  return SDL_FALSE;
158  }
159  return SDL_Vulkan_GetInstanceExtensions_Helper(
160  count, names, SDL_arraysize(extensionsForCocoa),
161  extensionsForCocoa);
162 }
163 
164 SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
165  SDL_Window *window,
166  VkInstance instance,
167  VkSurfaceKHR *surface)
168 {
169  PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
171  PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
172  (PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr(
173  (VkInstance)instance,
174  "vkCreateMacOSSurfaceMVK");
175  VkMacOSSurfaceCreateInfoMVK createInfo = {};
177 
179  SDL_SetError("Vulkan is not loaded");
180  return SDL_FALSE;
181  }
182 
183  if (!vkCreateMacOSSurfaceMVK) {
184  SDL_SetError(VK_MVK_MACOS_SURFACE_EXTENSION_NAME
185  " extension is not enabled in the Vulkan instance.");
186  return SDL_FALSE;
187  }
189  createInfo.pNext = NULL;
190  createInfo.flags = 0;
191  createInfo.pView = Cocoa_Mtl_AddMetalView(window);
192  result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
193  NULL, surface);
194  if (result != VK_SUCCESS) {
195  SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
196  SDL_Vulkan_GetResultString(result));
197  return SDL_FALSE;
198  }
199  return SDL_TRUE;
200 }
201 
202 void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
203 {
204  Cocoa_Mtl_GetDrawableSize(window, w, h);
205 }
206 
207 #endif
208 
209 /* vim: set ts=4 sw=4 expandtab: */
#define SDL_strlcpy
#define VK_KHR_SURFACE_EXTENSION_NAME
Definition: vulkan.h:3416
GLuint64EXT * result
VkResult(VKAPI_PTR * PFN_vkEnumerateInstanceExtensionProperties)(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties)
Definition: vulkan.h:2488
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)
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define SDL_LoadObject
#define SDL_UnloadObject
struct SDL_VideoDevice::@32 vulkan_config
#define VK_NULL_HANDLE
Definition: vulkan.h:49
VkResult
Definition: vulkan.h:122
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
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
char loader_path[256]
Definition: SDL_sysvideo.h:371
void * vkGetInstanceProcAddr
Definition: SDL_sysvideo.h:368
#define _THIS
void SDL_free(void *mem)
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
Definition: vulkan.h:2484
GLubyte GLubyte GLubyte GLubyte w
PP_Instance instance
Definition: SDL_naclvideo.h:57
#define SDL_getenv
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:139
#define SDL_SetError
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
The type used to identify a window.
Definition: SDL_sysvideo.h:73
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
GLsizei const GLchar *const * path
#define SDL_strcmp
void * SDL_LoadFunction(void *handle, const char *name)
void * vkEnumerateInstanceExtensionProperties
Definition: SDL_sysvideo.h:369
void * loader_handle
Definition: SDL_sysvideo.h:372