SDL  2.0
SDL_uikitvulkan.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_UIKIT
30 
31 #include "SDL_uikitvideo.h"
32 #include "SDL_uikitwindow.h"
33 #include "SDL_assert.h"
34 
35 #include "SDL_loadso.h"
36 #include "SDL_uikitvulkan.h"
37 #include "SDL_uikitmetalview.h"
38 #include "SDL_syswm.h"
39 
40 #include <dlfcn.h>
41 
42 #define DEFAULT_MOLTENVK "libMoltenVK.dylib"
43 /* Since libSDL is static, could use RTLD_SELF. Using RTLD_DEFAULT is future
44  * proofing. */
45 #define DEFAULT_HANDLE RTLD_DEFAULT
46 
47 int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
48 {
49  VkExtensionProperties *extensions = NULL;
50  Uint32 extensionCount = 0;
51  SDL_bool hasSurfaceExtension = SDL_FALSE;
52  SDL_bool hasIOSSurfaceExtension = SDL_FALSE;
54 
56  return SDL_SetError("MoltenVK/Vulkan already loaded");
57  }
58 
59  /* Load the Vulkan loader library */
60  if (!path) {
61  path = SDL_getenv("SDL_VULKAN_LIBRARY");
62  }
63 
64  if (!path) {
65  /* MoltenVK framework, currently, v0.17.0, has a static library and is
66  * the recommended way to use the package. There is likely no object to
67  * load. */
68  vkGetInstanceProcAddr =
69  (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
70  "vkGetInstanceProcAddr");
71  }
72 
73  if (vkGetInstanceProcAddr) {
74  _this->vulkan_config.loader_handle = DEFAULT_HANDLE;
75  } else {
76  if (!path) {
77  /* Look for the .dylib packaged with the application instead. */
78  path = DEFAULT_MOLTENVK;
79  }
80 
83  return -1;
84  }
87  vkGetInstanceProcAddr =
90  "vkGetInstanceProcAddr");
91  }
92 
93  if (!vkGetInstanceProcAddr) {
94  SDL_SetError("Failed to find %s in either executable or %s: %s",
95  "vkGetInstanceProcAddr",
96  DEFAULT_MOLTENVK,
97  (const char *) dlerror());
98  goto fail;
99  }
100 
101  _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
104  VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
105 
107  SDL_SetError("No vkEnumerateInstanceExtensionProperties found.");
108  goto fail;
109  }
110 
111  extensions = SDL_Vulkan_CreateInstanceExtensionsList(
114  &extensionCount);
115 
116  if (!extensions) {
117  goto fail;
118  }
119 
120  for (Uint32 i = 0; i < extensionCount; i++) {
121  if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
122  hasSurfaceExtension = SDL_TRUE;
123  } else if (SDL_strcmp(VK_MVK_IOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
124  hasIOSSurfaceExtension = SDL_TRUE;
125  }
126  }
127 
128  SDL_free(extensions);
129 
130  if (!hasSurfaceExtension) {
131  SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
132  VK_KHR_SURFACE_EXTENSION_NAME " extension");
133  goto fail;
134  } else if (!hasIOSSurfaceExtension) {
135  SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
136  VK_MVK_IOS_SURFACE_EXTENSION_NAME "extension");
137  goto fail;
138  }
139 
140  return 0;
141 
142 fail:
144  return -1;
145 }
146 
147 void UIKit_Vulkan_UnloadLibrary(_THIS)
148 {
150  if (_this->vulkan_config.loader_handle != DEFAULT_HANDLE) {
152  }
154  }
155 }
156 
157 SDL_bool UIKit_Vulkan_GetInstanceExtensions(_THIS,
159  unsigned *count,
160  const char **names)
161 {
162  static const char *const extensionsForUIKit[] = {
163  VK_KHR_SURFACE_EXTENSION_NAME, VK_MVK_IOS_SURFACE_EXTENSION_NAME
164  };
166  SDL_SetError("Vulkan is not loaded");
167  return SDL_FALSE;
168  }
169 
170  return SDL_Vulkan_GetInstanceExtensions_Helper(
171  count, names, SDL_arraysize(extensionsForUIKit),
172  extensionsForUIKit);
173 }
174 
175 SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
176  SDL_Window *window,
177  VkInstance instance,
178  VkSurfaceKHR *surface)
179 {
180  PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
182  PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK =
183  (PFN_vkCreateIOSSurfaceMVK)vkGetInstanceProcAddr(
184  (VkInstance)instance,
185  "vkCreateIOSSurfaceMVK");
186  VkIOSSurfaceCreateInfoMVK createInfo = {};
188 
190  SDL_SetError("Vulkan is not loaded");
191  return SDL_FALSE;
192  }
193 
194  if (!vkCreateIOSSurfaceMVK) {
195  SDL_SetError(VK_MVK_IOS_SURFACE_EXTENSION_NAME
196  " extension is not enabled in the Vulkan instance.");
197  return SDL_FALSE;
198  }
199 
201  createInfo.pNext = NULL;
202  createInfo.flags = 0;
203  createInfo.pView = (__bridge void *)UIKit_Mtl_AddMetalView(window);
204  result = vkCreateIOSSurfaceMVK(instance, &createInfo,
205  NULL, surface);
206  if (result != VK_SUCCESS) {
207  SDL_SetError("vkCreateIOSSurfaceMVK failed: %s",
208  SDL_Vulkan_GetResultString(result));
209  return SDL_FALSE;
210  }
211 
212  return SDL_TRUE;
213 }
214 
215 void UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
216 {
217  UIKit_Mtl_GetDrawableSize(window, w, h);
218 }
219 
220 #endif
221 
222 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_strlcpy
#define VK_KHR_SURFACE_EXTENSION_NAME
Definition: vulkan.h:3416
struct SDL_VideoDevice::@35 vulkan_config
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)
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define SDL_LoadObject
#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:371
#define _THIS
#define SDL_free
GLubyte GLubyte GLubyte GLubyte w
#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:139
#define SDL_SetError
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties
Definition: SDL_sysvideo.h:369
The type used to identify a window.
Definition: SDL_sysvideo.h:73
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr
Definition: SDL_sysvideo.h:368
#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)
VkResult(VKAPI_PTR * PFN_vkEnumerateInstanceExtensionProperties)(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties)
Definition: vulkan.h:2488
void * loader_handle
Definition: SDL_sysvideo.h:372