1
2 /// Loader module for vkdgen.
3 /// Loading bindings is done in 3 steps as follow:
4 /// ---
5 /// import gfx.bindings.vulkan.loader;
6 ///
7 /// // load global commands
8 /// auto globVk = loadVulkanGlobalCmds();
9 ///
10 /// // load instance commands
11 /// VkInstance inst;
12 /// VkInstanceCreateInfo instCreateInfo = // ...
13 /// globVk.CreateInstance(&instCreateInfo, null, &inst);
14 /// auto instVk = new VkInstanceCmds(inst, globVk);
15 ///
16 /// // load device commands
17 /// VkPhysicalDevice phDev = // ...
18 /// VkDevice dev;
19 /// VkDeviceCreateInfo devCreateInfo = // ...
20 /// instVk.CreateDevice(phDev, &devCreateInfo, null, &dev);
21 /// auto vk = new VkDeviceCmds(dev, instVk);
22 ///
23 /// // vk.CreateBuffer(dev, ...);
24 /// ---
25 module gfx.bindings.vulkan.loader;
26
27 import gfx.bindings.vulkan.vk : VkGlobalCmds;
28
29 import std.exception;
30
31 /// A handle to a shared library
32 alias SharedLib = void*;
33 /// A handle to a shared library symbol
34 alias SharedSym = void*;
35
36 /// Opens a shared library.
37 /// Return null in case of failure.
38 SharedLib openSharedLib(string name);
39
40 /// Load a symbol from a shared library.
41 /// Return null in case of failure.
42 SharedSym loadSharedSym(SharedLib lib, string name);
43
44 /// Close a shared library
45 void closeSharedLib(SharedLib lib);
46
47
48 /// Generic Dynamic lib symbol loader.
49 /// Symbols loaded with such loader must be cast to the appropriate function type.
50 alias SymbolLoader = SharedSym delegate (in string name);
51
52
53 version(Posix)
54 {
55 import std..string : toStringz;
56 import core.sys.posix.dlfcn;
57
58 SharedLib openSharedLib(string name)
59 {
60 return dlopen(toStringz(name), RTLD_LAZY);
61 }
62
63 SharedSym loadSharedSym(SharedLib lib, string name)
64 {
65 return dlsym(lib, toStringz(name));
66 }
67
68 void closeSharedLib(SharedLib lib)
69 {
70 dlclose(lib);
71 }
72 }
73 version(Windows)
74 {
75 import std..string : toStringz;
76 import core.sys.windows.winbase;
77
78 SharedLib openSharedLib(string name)
79 {
80 return LoadLibraryA(toStringz(name));
81 }
82
83 SharedSym loadSharedSym(SharedLib lib, string name)
84 {
85 return GetProcAddress(lib, toStringz(name));
86 }
87
88 void closeSharedLib(SharedLib lib)
89 {
90 FreeLibrary(lib);
91 }
92 }
93
94 /// Load global commands from Vulkan DLL/Shared object.
95 /// Returns: a VkGlobalCmds object
96 VkGlobalCmds loadVulkanGlobalCmds()
97 {
98 import gfx.bindings.vulkan.vk : PFN_vkGetInstanceProcAddr;
99
100 version( Windows )
101 enum libName = "vulkan-1.dll";
102 else version ( OSX )
103 enum libName = "libMoltenVK.dylib";
104 else version( Posix )
105 enum libName = "libvulkan.so.1";
106 else
107 static assert (false, "Vulkan bindings not supported on this OS");
108
109 auto lib = enforce(openSharedLib(libName), "Cannot open "~libName);
110
111 auto getInstanceProcAddr = enforce(
112 cast(PFN_vkGetInstanceProcAddr)loadSharedSym(lib, "vkGetInstanceProcAddr"),
113 "Could not load vkGetInstanceProcAddr from "~libName
114 );
115
116 return new VkGlobalCmds(getInstanceProcAddr);
117 }