1 /*
2     DSDL
3     Copyright (C) 2025 Inochi2D Project <luna@foxgirls.gay>
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     Simple DirectMedia Layer
24     Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
25 
26     This software is provided 'as-is', without any express or implied
27     warranty.  In no event will the authors be held liable for any damages
28     arising from the use of this software.
29 
30     Permission is granted to anyone to use this software for any purpose,
31     including commercial applications, and to alter it and redistribute it
32     freely, subject to the following restrictions:
33 
34     1. The origin of this software must not be misrepresented; you must not
35         claim that you wrote the original software. If you use this software
36         in a product, an acknowledgment in the product documentation would be
37         appreciated but is not required.
38     2. Altered source versions must be plainly marked as such, and must not be
39         misrepresented as being the original software.
40     3. This notice may not be removed or altered from any source distribution.
41 */
42 
43 /**
44     SDL Vulkan
45 
46     See_Also:
47         $(LINK2 https://wiki.libsdl.org/SDL3/CategoryVulkan, SDL3 Vulkan Documentation)
48         $(LINK2 https://docs.vulkan.org/spec/latest/index.html, Vulkan Documentation)
49     
50     Copyright: © 2025 Inochi2D Project, © 1997-2025 Sam Lantinga
51     License: Subject to the terms of the Zlib License, as written in the LICENSE file.
52     Authors: 
53         Luna Nielsen
54 */
55 module sdl.vulkan;
56 import sdl.video;
57 import sdl.stdc;
58 import sdl.d;
59 
60 extern(C) nothrow @nogc:
61 
62 /**
63     A vulkan instance handle.
64 */
65 alias VkInstance = OpaqueHandle!("VkInstance");
66 
67 /**
68     A vulkan Physical Device handle.
69 */
70 alias VkPhysicalDevice = OpaqueHandle!("VkPhysicalDevice");
71 
72 /**
73     A Vulkan Surface handle.
74 */
75 alias VkSurfaceKHR = OpaqueHandle!("VkSurfaceKHR");
76 
77 /**
78     Opaque allocation callbacks handle
79 */
80 struct VkAllocationCallbacks;
81 
82 /**
83     Dynamically load the Vulkan loader library.
84 
85     This should be called after initializing the video driver, but before
86     creating any Vulkan windows. If no Vulkan loader library is loaded, the
87     default library will be loaded upon creation of the first Vulkan window.
88 
89     SDL keeps a counter of how many times this function has been successfully
90     called, so it is safe to call this function multiple times, so long as it
91     is eventually paired with an equivalent number of calls to
92     SDL_Vulkan_UnloadLibrary. The `path` argument is ignored unless there is no
93     library currently loaded, and and the library isn't actually unloaded until
94     there have been an equivalent number of calls to SDL_Vulkan_UnloadLibrary.
95 
96     It is fairly common for Vulkan applications to link with libvulkan instead
97     of explicitly loading it at run time. This will work with SDL provided the
98     application links to a dynamic library and both it and SDL use the same
99     search path.
100 
101     If you specify a non-NULL `path`, an application should retrieve all of the
102     Vulkan functions it uses from the dynamic library using
103     SDL_Vulkan_GetVkGetInstanceProcAddr unless you can guarantee `path` points
104     to the same vulkan loader library the application linked to.
105 
106     On Apple devices, if `path` is NULL, SDL will attempt to find the
107     `vkGetInstanceProcAddr` address within all the Mach-O images of the current
108     process. This is because it is fairly common for Vulkan applications to
109     link with libvulkan (and historically MoltenVK was provided as a static
110     library). If it is not found, on macOS, SDL will attempt to load
111     `vulkan.framework/vulkan`, `libvulkan.1.dylib`,
112     `MoltenVK.framework/MoltenVK`, and `libMoltenVK.dylib`, in that order. On
113     iOS, SDL will attempt to load `libMoltenVK.dylib`. Applications using a
114     dynamic framework or .dylib must ensure it is included in its application
115     bundle.
116 
117     On non-Apple devices, application linking with a static libvulkan is not
118     supported. Either do not link to the Vulkan loader or link to a dynamic
119     library version.
120 
121     Params:
122         path = the platform dependent Vulkan loader library name or NULL.
123     
124     Returns:
125         true on success or false on failure; call SDL_GetError() for more
126         information.
127 
128     Threadsafety:
129         This function is not thread safe.
130 
131     See_Also:
132         $(D SDL_Vulkan_GetVkGetInstanceProcAddr)
133         $(D SDL_Vulkan_UnloadLibrary)
134 */
135 extern bool SDL_Vulkan_LoadLibrary(const(char)* path);
136 
137 /**
138     Get the address of the `vkGetInstanceProcAddr` function.
139 
140     This should be called after either calling SDL_Vulkan_LoadLibrary() or
141     creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag.
142 
143     The actual type of the returned function pointer is
144     PFN_vkGetInstanceProcAddr, but that isn't available because the Vulkan
145     headers are not included here. You should cast the return value of this
146     function to that type, e.g.
147 
148     `vkGetInstanceProcAddr =
149     (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();`
150 
151     Returns:
152         the function pointer for `vkGetInstanceProcAddr` or NULL on
153         failure; call SDL_GetError() for more information.
154 
155 */
156 extern SDL_FunctionPointer SDL_Vulkan_GetVkGetInstanceProcAddr();
157 
158 /**
159     Unload the Vulkan library previously loaded by SDL_Vulkan_LoadLibrary().
160 
161     SDL keeps a counter of how many times this function has been called, so it
162     is safe to call this function multiple times, so long as it is paired with
163     an equivalent number of calls to SDL_Vulkan_LoadLibrary. The library isn't
164     actually unloaded until there have been an equivalent number of calls to
165     SDL_Vulkan_UnloadLibrary.
166 
167     Once the library has actually been unloaded, if any Vulkan instances
168     remain, they will likely crash the program. Clean up any existing Vulkan
169     resources, and destroy appropriate windows, renderers and GPU devices
170     before calling this function.
171 
172     Threadsafety:
173         This function is not thread safe.
174 
175     See_Also:
176         $(D SDL_Vulkan_LoadLibrary)
177 */
178 extern void SDL_Vulkan_UnloadLibrary();
179 
180 /**
181     Get the Vulkan instance extensions needed for vkCreateInstance.
182 
183     This should be called after either calling SDL_Vulkan_LoadLibrary() or
184     creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag.
185 
186     On return, the variable pointed to by `count` will be set to the number of
187     elements returned, suitable for using with
188     VkInstanceCreateInfo::enabledExtensionCount, and the returned array can be
189     used with VkInstanceCreateInfo::ppEnabledExtensionNames, for calling
190     Vulkan's vkCreateInstance API.
191 
192     You should not free the returned array; it is owned by SDL.
193 
194     Params:
195         count = a pointer filled in with the number of extensions returned.
196     
197     Returns:
198         an array of extension name strings on success, NULL on failure;
199         call SDL_GetError() for more information.
200 
201     See_Also:
202         $(D SDL_Vulkan_CreateSurface)
203 */
204 extern const(const(char)*)*  SDL_Vulkan_GetInstanceExtensions(Uint32* count);
205 
206 /**
207     Create a Vulkan rendering surface for a window.
208 
209     The `window` must have been created with the `SDL_WINDOW_VULKAN` flag and
210     `instance` must have been created with extensions returned by
211     SDL_Vulkan_GetInstanceExtensions() enabled.
212 
213     If `allocator` is NULL, Vulkan will use the system default allocator. This
214     argument is passed directly to Vulkan and isn't used by SDL itself.
215 
216     Params:
217         window =    the window to which to attach the Vulkan surface.
218         instance =  the Vulkan instance handle.
219         allocator = a VkAllocationCallbacks struct, which lets the app set the
220                     allocator that creates the surface. Can be NULL.
221         surface =   a pointer to a VkSurfaceKHR handle to output the newly
222                     created surface.
223     
224     Returns:
225         true on success or false on failure; call SDL_GetError() for more
226         information.
227 
228     See_Also:
229         $(D SDL_Vulkan_GetInstanceExtensions)
230         $(D SDL_Vulkan_DestroySurface)
231 */
232 extern bool SDL_Vulkan_CreateSurface(SDL_Window* window,
233                                     VkInstance instance,
234                                     const(VkAllocationCallbacks)* allocator,
235                                     VkSurfaceKHR* surface);
236 
237 /**
238     Destroy the Vulkan rendering surface of a window.
239 
240     This should be called before SDL_DestroyWindow, if SDL_Vulkan_CreateSurface
241     was called after SDL_CreateWindow.
242 
243     The `instance` must have been created with extensions returned by
244     SDL_Vulkan_GetInstanceExtensions() enabled and `surface` must have been
245     created successfully by an SDL_Vulkan_CreateSurface() call.
246 
247     If `allocator` is NULL, Vulkan will use the system default allocator. This
248     argument is passed directly to Vulkan and isn't used by SDL itself.
249 
250     Params:
251         instance =  the Vulkan instance handle.
252         surface =   vkSurfaceKHR handle to destroy.
253         allocator = a VkAllocationCallbacks struct, which lets the app set the
254                     allocator that destroys the surface. Can be NULL.
255 
256     See_Also:
257         $(D SDL_Vulkan_GetInstanceExtensions)
258         $(D SDL_Vulkan_CreateSurface)
259 */
260 extern void SDL_Vulkan_DestroySurface(VkInstance instance,
261                                     VkSurfaceKHR surface,
262                                     const(VkAllocationCallbacks)* allocator);
263 
264 /**
265     Query support for presentation via a given physical device and queue
266     family.
267 
268     The `instance` must have been created with extensions returned by
269     SDL_Vulkan_GetInstanceExtensions() enabled.
270 
271     Params:
272         instance =          The Vulkan instance handle.
273         physicalDevice =    A valid Vulkan physical device handle.
274         queueFamilyIndex =  A valid queue family index for the given physical
275                             device.
276 
277     Returns:
278         true if supported, false if unsupported or an error occurred.
279 
280     See_Also:
281         $(D SDL_Vulkan_GetInstanceExtensions)
282 */
283 extern bool SDL_Vulkan_GetPresentationSupport(VkInstance instance,
284                                             VkPhysicalDevice physicalDevice,
285                                             Uint32 queueFamilyIndex);