1 /** 2 * Dlang vulkan lib loader retrieving vkGetInstanceProcAddr for windows and posix systems 3 * 4 * Copyright: Copyright 2015-2016 The Khronos Group Inc.; Copyright 2016 Alex Parrill, Peter Particle. 5 * License: $(https://opensource.org/licenses/MIT, MIT License). 6 * Authors: Copyright 2016 Alex Parrill, Peter Particle 7 */ 8 module erupted.vulkan_lib_loader; 9 10 import erupted.functions; 11 import core.stdc.stdio : fprintf, stderr, FILE; 12 13 nothrow @nogc: 14 15 16 /// private helper functions for windows platform 17 version( Windows ) { 18 private: 19 import core.sys.windows.windows; 20 HMODULE vulkan_lib = null; 21 auto loadLib() { return LoadLibrary( "vulkan-1.dll" ); } 22 auto freeLib() { return FreeLibrary( vulkan_lib ) != 0; } 23 auto loadSym() { return cast( PFN_vkGetInstanceProcAddr )GetProcAddress( vulkan_lib, "vkGetInstanceProcAddr" ); } 24 void logLibError( FILE* log_stream, const( char )* message ) { 25 fprintf( log_stream, "%svulkan-1.dll! Error code: 0x%x\n", message, GetLastError()); 26 } 27 } 28 29 30 /// private helper functions for posix platforms 31 else version( Android ) { 32 private: 33 import core.sys.posix.dlfcn : dlerror, dlopen, dlclose, dlsym, RTLD_NOW, RTLD_LOCAL; 34 void* vulkan_lib = null; 35 auto loadLib() { return dlopen( "libvulkan.so", RTLD_NOW | RTLD_LOCAL ); } 36 auto freeLib() { return dlclose( vulkan_lib ) == 0; } 37 auto loadSym() { return cast( PFN_vkGetInstanceProcAddr )dlsym( vulkan_lib, "vkGetInstanceProcAddr" ); } 38 void logLibError( FILE* log_stream, const( char )* message ) { 39 fprintf( log_stream, "%slibvulkan.so.1! Error: %s\n", message, dlerror ); 40 } 41 } 42 43 44 /// private helper functions for posix platforms 45 else version( Posix ) { 46 private: 47 import core.sys.posix.dlfcn : dlerror, dlopen, dlclose, dlsym, RTLD_LAZY, RTLD_LOCAL; 48 void* vulkan_lib = null; 49 auto loadLib() { return dlopen( "libvulkan.so.1", RTLD_LAZY | RTLD_LOCAL ); } 50 auto freeLib() { return dlclose( vulkan_lib ) == 0; } 51 auto loadSym() { return cast( PFN_vkGetInstanceProcAddr )dlsym( vulkan_lib, "vkGetInstanceProcAddr" ); } 52 void logLibError( FILE* log_stream, const( char )* message ) { 53 fprintf( log_stream, "%slibvulkan.so.1! Error: %s\n", message, dlerror ); 54 } 55 } 56 57 58 /// tries to load the platform vulkan dynamic link library 59 /// the library handle / pointer is stored privately in this module 60 /// errors are reported to a specifiable stream which is standard error by default 61 /// Params: 62 /// log_stream = file stream to receive error messages, default stderr 63 /// Returns: true if the vulkan lib could be loaded, false otherwise 64 bool loadVulkanLib( FILE* log_stream = stderr ) { 65 vulkan_lib = loadLib; 66 if( !vulkan_lib ) { 67 logLibError( log_stream, "Could not load " ); 68 return false; 69 } else { 70 return true; 71 } 72 } 73 74 75 /// tries to load the vkGetInstanceProcAddr function from the module private lib handle / pointer 76 /// if the lib was not loaded so far loadVulkanLib is called 77 /// errors are reported to a specifiable stream which is standard error by default 78 /// Params: 79 /// log_stream = file stream to receive error messages, default stderr 80 /// Returns: vkGetInstanceProcAddr if it could be loaded from the lib, null otherwise 81 PFN_vkGetInstanceProcAddr loadGetInstanceProcAddr( FILE* log_stream = stderr ) { 82 if( !vulkan_lib && !loadVulkanLib( log_stream )) { 83 fprintf( log_stream, "Cannot not retrieve vkGetInstanceProcAddr as vulkan lib is not loaded!" ); 84 return null; 85 } 86 auto getInstanceProcAddr = loadSym; 87 if( !getInstanceProcAddr ) 88 logLibError( log_stream, "Could not retrieve vkGetInstanceProcAddr from " ); 89 return getInstanceProcAddr; 90 } 91 92 93 /// tries to free / unload the previously loaded platform vulkan lib 94 /// errors are reported to a specifiable stream which is standard error by default 95 /// Params: 96 /// log_stream = file stream to receive error messages, default stderr 97 /// Returns: true if the vulkan lib could be freed, false otherwise 98 bool freeVulkanLib( FILE* log_stream = stderr ) { 99 if( !vulkan_lib ) { 100 fprintf( log_stream, "Cannot free vulkan lib as it is not loaded!" ); 101 return false; 102 } else if( freeLib ) { 103 logLibError( log_stream, "Could not unload " ); 104 return false; 105 } else { 106 return true; 107 } 108 } 109 110 111 /// Combines loadVulkanLib, loadGetInstanceProcAddr and loadGlobalLevelFunctions( PFN_vkGetInstanceProcAddr ) 112 /// from module erupted.functions. If this function succeeds the function vkGetInstanceProcAddr 113 /// from module erupted.functions can be used freely. Moreover the required functions to initialize a 114 /// vulkan instance a vkEnumerateInstanceExtensionProperties, vkEnumerateInstanceLayerProperties and vkCreateInstance 115 /// are available as well. To get all the other functions an vulkan instance must be created and with it 116 /// loadInstanceLevelFunctions be called from either erupted.functions or through a custom tailored module 117 /// with mixed in extensions through the erupted.platform.mixin_extensions mechanism. 118 /// Additional device based functions can then be loaded with loadDeviceLevelFunctions passing in the instance or 119 /// with creating a vulkan device beforehand and calling the same function with it. 120 /// 121 /// Note: as this function indirectly calls loadVulkanLib loading the vulkan lib, freeVulkanLib should be called 122 /// at some point in the process to cleanly free / unload the lib 123 /// all errors during vulkan lib loading and vkGetInstanceProcAddr retrieving are reported to log_stream, default stderr 124 /// log_stream = file stream to receive error messages, default stderr 125 /// Returns: true if the vulkan lib could be freed, false otherwise 126 bool loadGlobalLevelFunctions( FILE* log_stream = stderr ) { 127 auto getInstanceProcAddr = loadGetInstanceProcAddr( log_stream ); 128 if( !getInstanceProcAddr ) return false; 129 erupted.functions.loadGlobalLevelFunctions( getInstanceProcAddr ); 130 return true; 131 } 132 133