VkBootstrap.cpp 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768
  1. /*
  2. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  3. * documentation files (the “Software”), to deal in the Software without restriction, including without
  4. * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  5. * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  6. *
  7. * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  8. *
  9. * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  10. * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  11. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  12. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  13. *
  14. * Copyright © 2020 Charles Giessen ([email protected])
  15. */
  16. #include "VkBootstrap.h"
  17. #include <cstdio>
  18. #include <cstring>
  19. #if defined(_WIN32)
  20. #include <fcntl.h>
  21. #define NOMINMAX
  22. #include <windows.h>
  23. #endif // _WIN32
  24. #if defined(__linux__) || defined(__APPLE__)
  25. #include <dlfcn.h>
  26. #endif
  27. #include <mutex>
  28. namespace vkb {
  29. namespace detail {
  30. class VulkanFunctions {
  31. private:
  32. std::mutex init_mutex;
  33. struct VulkanLibrary {
  34. #if defined(__linux__) || defined(__APPLE__)
  35. void* library;
  36. #elif defined(_WIN32)
  37. HMODULE library;
  38. #endif
  39. PFN_vkGetInstanceProcAddr ptr_vkGetInstanceProcAddr = VK_NULL_HANDLE;
  40. VulkanLibrary () {
  41. #if defined(__linux__)
  42. library = dlopen ("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL);
  43. if (!library) library = dlopen ("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
  44. #elif defined(__APPLE__)
  45. library = dlopen ("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL);
  46. if (!library) library = dlopen ("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL);
  47. #elif defined(_WIN32)
  48. library = LoadLibrary (TEXT ("vulkan-1.dll"));
  49. #else
  50. assert (false && "Unsupported platform");
  51. #endif
  52. if (!library) return;
  53. load_func (ptr_vkGetInstanceProcAddr, "vkGetInstanceProcAddr");
  54. }
  55. template <typename T> void load_func (T& func_dest, const char* func_name) {
  56. #if defined(__linux__) || defined(__APPLE__)
  57. func_dest = reinterpret_cast<T> (dlsym (library, func_name));
  58. #elif defined(_WIN32)
  59. func_dest = reinterpret_cast<T> (GetProcAddress (library, func_name));
  60. #endif
  61. }
  62. void close () {
  63. #if defined(__linux__) || defined(__APPLE__)
  64. dlclose (library);
  65. #elif defined(_WIN32)
  66. FreeLibrary (library);
  67. #endif
  68. library = 0;
  69. }
  70. };
  71. VulkanLibrary& get_vulkan_library () {
  72. static VulkanLibrary lib;
  73. return lib;
  74. }
  75. bool load_vulkan (PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr) {
  76. if (fp_vkGetInstanceProcAddr != nullptr) {
  77. ptr_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr;
  78. return true;
  79. } else {
  80. auto& lib = get_vulkan_library ();
  81. ptr_vkGetInstanceProcAddr = lib.ptr_vkGetInstanceProcAddr;
  82. return lib.library != nullptr && lib.ptr_vkGetInstanceProcAddr != VK_NULL_HANDLE;
  83. }
  84. }
  85. template <typename T> void get_proc_addr (T& out_ptr, const char* func_name) {
  86. out_ptr = reinterpret_cast<T> (ptr_vkGetInstanceProcAddr (instance, func_name));
  87. }
  88. void init_pre_instance_funcs () {
  89. get_proc_addr (fp_vkEnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties");
  90. get_proc_addr (fp_vkEnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties");
  91. get_proc_addr (fp_vkEnumerateInstanceVersion, "vkEnumerateInstanceVersion");
  92. get_proc_addr (fp_vkCreateInstance, "vkCreateInstance");
  93. }
  94. public:
  95. PFN_vkGetInstanceProcAddr ptr_vkGetInstanceProcAddr = nullptr;
  96. VkInstance instance = nullptr;
  97. PFN_vkEnumerateInstanceExtensionProperties fp_vkEnumerateInstanceExtensionProperties = nullptr;
  98. PFN_vkEnumerateInstanceLayerProperties fp_vkEnumerateInstanceLayerProperties = nullptr;
  99. PFN_vkEnumerateInstanceVersion fp_vkEnumerateInstanceVersion = nullptr;
  100. PFN_vkCreateInstance fp_vkCreateInstance = nullptr;
  101. PFN_vkDestroyInstance fp_vkDestroyInstance = nullptr;
  102. PFN_vkEnumeratePhysicalDevices fp_vkEnumeratePhysicalDevices = nullptr;
  103. PFN_vkGetPhysicalDeviceFeatures fp_vkGetPhysicalDeviceFeatures = nullptr;
  104. PFN_vkGetPhysicalDeviceFeatures2 fp_vkGetPhysicalDeviceFeatures2 = nullptr;
  105. PFN_vkGetPhysicalDeviceFormatProperties fp_vkGetPhysicalDeviceFormatProperties = nullptr;
  106. PFN_vkGetPhysicalDeviceImageFormatProperties fp_vkGetPhysicalDeviceImageFormatProperties = nullptr;
  107. PFN_vkGetPhysicalDeviceProperties fp_vkGetPhysicalDeviceProperties = nullptr;
  108. PFN_vkGetPhysicalDeviceProperties2 fp_vkGetPhysicalDeviceProperties2 = nullptr;
  109. PFN_vkGetPhysicalDeviceQueueFamilyProperties fp_vkGetPhysicalDeviceQueueFamilyProperties = nullptr;
  110. PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fp_vkGetPhysicalDeviceQueueFamilyProperties2 = nullptr;
  111. PFN_vkGetPhysicalDeviceMemoryProperties fp_vkGetPhysicalDeviceMemoryProperties = nullptr;
  112. PFN_vkGetPhysicalDeviceFormatProperties2 fp_vkGetPhysicalDeviceFormatProperties2 = nullptr;
  113. PFN_vkGetPhysicalDeviceMemoryProperties2 fp_vkGetPhysicalDeviceMemoryProperties2 = nullptr;
  114. PFN_vkCreateDevice fp_vkCreateDevice = nullptr;
  115. PFN_vkDestroyDevice fp_vkDestroyDevice = nullptr;
  116. PFN_vkEnumerateDeviceExtensionProperties fp_vkEnumerateDeviceExtensionProperties = nullptr;
  117. PFN_vkGetDeviceQueue fp_vkGetDeviceQueue = nullptr;
  118. PFN_vkCreateImageView fp_vkCreateImageView = nullptr;
  119. PFN_vkDestroyImageView fp_vkDestroyImageView = nullptr;
  120. PFN_vkDestroySurfaceKHR fp_vkDestroySurfaceKHR = nullptr;
  121. PFN_vkGetPhysicalDeviceSurfaceSupportKHR fp_vkGetPhysicalDeviceSurfaceSupportKHR = nullptr;
  122. PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fp_vkGetPhysicalDeviceSurfaceFormatsKHR = nullptr;
  123. PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fp_vkGetPhysicalDeviceSurfacePresentModesKHR = nullptr;
  124. PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
  125. PFN_vkCreateSwapchainKHR fp_vkCreateSwapchainKHR = nullptr;
  126. PFN_vkDestroySwapchainKHR fp_vkDestroySwapchainKHR = nullptr;
  127. PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr;
  128. bool init_vulkan_funcs (PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) {
  129. std::lock_guard<std::mutex> lg (init_mutex);
  130. if (!load_vulkan (fp_vkGetInstanceProcAddr)) return false;
  131. init_pre_instance_funcs ();
  132. return true;
  133. }
  134. template <typename T> void get_inst_proc_addr (T& out_ptr, const char* func_name) {
  135. std::lock_guard<std::mutex> lg (init_mutex);
  136. get_proc_addr (out_ptr, func_name);
  137. }
  138. void init_instance_funcs (VkInstance inst) {
  139. std::lock_guard<std::mutex> lg (init_mutex);
  140. instance = inst;
  141. get_proc_addr (fp_vkDestroyInstance, "vkDestroyInstance");
  142. get_proc_addr (fp_vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices");
  143. get_proc_addr (fp_vkGetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures");
  144. get_proc_addr (fp_vkGetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2");
  145. get_proc_addr (fp_vkGetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties");
  146. get_proc_addr (fp_vkGetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties");
  147. get_proc_addr (fp_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties");
  148. get_proc_addr (fp_vkGetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2");
  149. get_proc_addr (fp_vkGetPhysicalDeviceQueueFamilyProperties, "vkGetPhysicalDeviceQueueFamilyProperties");
  150. get_proc_addr (fp_vkGetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2");
  151. get_proc_addr (fp_vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties");
  152. get_proc_addr (fp_vkGetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2");
  153. get_proc_addr (fp_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2");
  154. get_proc_addr (fp_vkCreateDevice, "vkCreateDevice");
  155. get_proc_addr (fp_vkDestroyDevice, "vkDestroyDevice");
  156. get_proc_addr (fp_vkEnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties");
  157. get_proc_addr (fp_vkGetDeviceQueue, "vkGetDeviceQueue");
  158. get_proc_addr (fp_vkCreateImageView, "vkCreateImageView");
  159. get_proc_addr (fp_vkDestroyImageView, "vkDestroyImageView");
  160. get_proc_addr (fp_vkDestroySurfaceKHR, "vkDestroySurfaceKHR");
  161. get_proc_addr (fp_vkGetPhysicalDeviceSurfaceSupportKHR, "vkGetPhysicalDeviceSurfaceSupportKHR");
  162. get_proc_addr (fp_vkGetPhysicalDeviceSurfaceFormatsKHR, "vkGetPhysicalDeviceSurfaceFormatsKHR");
  163. get_proc_addr (fp_vkGetPhysicalDeviceSurfacePresentModesKHR, "vkGetPhysicalDeviceSurfacePresentModesKHR");
  164. get_proc_addr (fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
  165. get_proc_addr (fp_vkCreateSwapchainKHR, "vkCreateSwapchainKHR");
  166. get_proc_addr (fp_vkDestroySwapchainKHR, "vkDestroySwapchainKHR");
  167. get_proc_addr (fp_vkGetSwapchainImagesKHR, "vkGetSwapchainImagesKHR");
  168. }
  169. };
  170. VulkanFunctions& vulkan_functions () {
  171. static VulkanFunctions v;
  172. return v;
  173. }
  174. // Helper for robustly executing the two-call pattern
  175. template <typename T, typename F, typename... Ts>
  176. auto get_vector (std::vector<T>& out, F&& f, Ts&&... ts) -> VkResult {
  177. uint32_t count = 0;
  178. VkResult err;
  179. do {
  180. err = f (ts..., &count, nullptr);
  181. if (err) {
  182. return err;
  183. };
  184. out.resize (count);
  185. err = f (ts..., &count, out.data ());
  186. out.resize (count);
  187. } while (err == VK_INCOMPLETE);
  188. return err;
  189. }
  190. template <typename T, typename F, typename... Ts>
  191. auto get_vector_noerror (F&& f, Ts&&... ts) -> std::vector<T> {
  192. uint32_t count = 0;
  193. std::vector<T> results;
  194. f (ts..., &count, nullptr);
  195. results.resize (count);
  196. f (ts..., &count, results.data ());
  197. results.resize (count);
  198. return results;
  199. }
  200. } // namespace detail
  201. const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s) {
  202. switch (s) {
  203. case VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
  204. return "VERBOSE";
  205. case VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
  206. return "ERROR";
  207. case VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
  208. return "WARNING";
  209. case VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
  210. return "INFO";
  211. default:
  212. return "UNKNOWN";
  213. }
  214. }
  215. const char* to_string_message_type (VkDebugUtilsMessageTypeFlagsEXT s) {
  216. if (s == 7) return "General | Validation | Performance";
  217. if (s == 6) return "Validation | Performance";
  218. if (s == 5) return "General | Performance";
  219. if (s == 4 /*VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT*/) return "Performance";
  220. if (s == 3) return "General | Validation";
  221. if (s == 2 /*VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT*/) return "Validation";
  222. if (s == 1 /*VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT*/) return "General";
  223. return "Unknown";
  224. }
  225. VkResult create_debug_utils_messenger (VkInstance instance,
  226. PFN_vkDebugUtilsMessengerCallbackEXT debug_callback,
  227. VkDebugUtilsMessageSeverityFlagsEXT severity,
  228. VkDebugUtilsMessageTypeFlagsEXT type,
  229. VkDebugUtilsMessengerEXT* pDebugMessenger,
  230. VkAllocationCallbacks* allocation_callbacks) {
  231. if (debug_callback == nullptr) debug_callback = default_debug_callback;
  232. VkDebugUtilsMessengerCreateInfoEXT messengerCreateInfo = {};
  233. messengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  234. messengerCreateInfo.pNext = nullptr;
  235. messengerCreateInfo.messageSeverity = severity;
  236. messengerCreateInfo.messageType = type;
  237. messengerCreateInfo.pfnUserCallback = debug_callback;
  238. PFN_vkCreateDebugUtilsMessengerEXT createMessengerFunc;
  239. detail::vulkan_functions ().get_inst_proc_addr (createMessengerFunc, "vkCreateDebugUtilsMessengerEXT");
  240. if (createMessengerFunc != nullptr) {
  241. return createMessengerFunc (instance, &messengerCreateInfo, allocation_callbacks, pDebugMessenger);
  242. } else {
  243. return VK_ERROR_EXTENSION_NOT_PRESENT;
  244. }
  245. }
  246. void destroy_debug_utils_messenger (
  247. VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, VkAllocationCallbacks* allocation_callbacks) {
  248. PFN_vkDestroyDebugUtilsMessengerEXT deleteMessengerFunc;
  249. detail::vulkan_functions ().get_inst_proc_addr (deleteMessengerFunc, "vkDestroyDebugUtilsMessengerEXT");
  250. if (deleteMessengerFunc != nullptr) {
  251. deleteMessengerFunc (instance, debugMessenger, allocation_callbacks);
  252. }
  253. }
  254. VkBool32 default_debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
  255. VkDebugUtilsMessageTypeFlagsEXT messageType,
  256. const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
  257. void*) {
  258. auto ms = to_string_message_severity (messageSeverity);
  259. auto mt = to_string_message_type (messageType);
  260. printf ("[%s: %s]\n%s\n", ms, mt, pCallbackData->pMessage);
  261. return VK_FALSE;
  262. }
  263. namespace detail {
  264. bool check_layer_supported (std::vector<VkLayerProperties> const& available_layers, const char* layer_name) {
  265. if (!layer_name) return false;
  266. for (const auto& layer_properties : available_layers) {
  267. if (strcmp (layer_name, layer_properties.layerName) == 0) {
  268. return true;
  269. }
  270. }
  271. return false;
  272. }
  273. bool check_layers_supported (std::vector<VkLayerProperties> const& available_layers,
  274. std::vector<const char*> const& layer_names) {
  275. bool all_found = true;
  276. for (const auto& layer_name : layer_names) {
  277. bool found = check_layer_supported (available_layers, layer_name);
  278. if (!found) all_found = false;
  279. }
  280. return all_found;
  281. }
  282. bool check_extension_supported (
  283. std::vector<VkExtensionProperties> const& available_extensions, const char* extension_name) {
  284. if (!extension_name) return false;
  285. for (const auto& extension_properties : available_extensions) {
  286. if (strcmp (extension_name, extension_properties.extensionName) == 0) {
  287. return true;
  288. }
  289. }
  290. return false;
  291. }
  292. bool check_extensions_supported (std::vector<VkExtensionProperties> const& available_extensions,
  293. std::vector<const char*> const& extension_names) {
  294. bool all_found = true;
  295. for (const auto& extension_name : extension_names) {
  296. bool found = check_extension_supported (available_extensions, extension_name);
  297. if (!found) all_found = false;
  298. }
  299. return all_found;
  300. }
  301. template <typename T>
  302. void setup_pNext_chain (T& structure, std::vector<VkBaseOutStructure*> const& structs) {
  303. structure.pNext = nullptr;
  304. if (structs.size () <= 0) return;
  305. for (size_t i = 0; i < structs.size () - 1; i++) {
  306. structs.at (i)->pNext = structs.at (i + 1);
  307. }
  308. structure.pNext = structs.at (0);
  309. }
  310. const char* validation_layer_name = "VK_LAYER_KHRONOS_validation";
  311. struct InstanceErrorCategory : std::error_category {
  312. const char* name () const noexcept override { return "vkb_instance"; }
  313. std::string message (int err) const override {
  314. return to_string (static_cast<InstanceError> (err));
  315. }
  316. };
  317. const InstanceErrorCategory instance_error_category;
  318. struct PhysicalDeviceErrorCategory : std::error_category {
  319. const char* name () const noexcept override { return "vkb_physical_device"; }
  320. std::string message (int err) const override {
  321. return to_string (static_cast<PhysicalDeviceError> (err));
  322. }
  323. };
  324. const PhysicalDeviceErrorCategory physical_device_error_category;
  325. struct QueueErrorCategory : std::error_category {
  326. const char* name () const noexcept override { return "vkb_queue"; }
  327. std::string message (int err) const override {
  328. return to_string (static_cast<QueueError> (err));
  329. }
  330. };
  331. const QueueErrorCategory queue_error_category;
  332. struct DeviceErrorCategory : std::error_category {
  333. const char* name () const noexcept override { return "vkb_device"; }
  334. std::string message (int err) const override {
  335. return to_string (static_cast<DeviceError> (err));
  336. }
  337. };
  338. const DeviceErrorCategory device_error_category;
  339. struct SwapchainErrorCategory : std::error_category {
  340. const char* name () const noexcept override { return "vbk_swapchain"; }
  341. std::string message (int err) const override {
  342. return to_string (static_cast<SwapchainError> (err));
  343. }
  344. };
  345. const SwapchainErrorCategory swapchain_error_category;
  346. } // namespace detail
  347. std::error_code make_error_code (InstanceError instance_error) {
  348. return { static_cast<int> (instance_error), detail::instance_error_category };
  349. }
  350. std::error_code make_error_code (PhysicalDeviceError physical_device_error) {
  351. return { static_cast<int> (physical_device_error), detail::physical_device_error_category };
  352. }
  353. std::error_code make_error_code (QueueError queue_error) {
  354. return { static_cast<int> (queue_error), detail::queue_error_category };
  355. }
  356. std::error_code make_error_code (DeviceError device_error) {
  357. return { static_cast<int> (device_error), detail::device_error_category };
  358. }
  359. std::error_code make_error_code (SwapchainError swapchain_error) {
  360. return { static_cast<int> (swapchain_error), detail::swapchain_error_category };
  361. }
  362. const char* to_string (InstanceError err) {
  363. switch (err) {
  364. case InstanceError::vulkan_unavailable:
  365. return "vulkan_unavailable";
  366. case InstanceError::vulkan_version_unavailable:
  367. return "vulkan_version_unavailable";
  368. case InstanceError::vulkan_version_1_1_unavailable:
  369. return "vulkan_version_1_1_unavailable";
  370. case InstanceError::vulkan_version_1_2_unavailable:
  371. return "vulkan_version_1_2_unavailable";
  372. case InstanceError::failed_create_debug_messenger:
  373. return "failed_create_debug_messenger";
  374. case InstanceError::failed_create_instance:
  375. return "failed_create_instance";
  376. case InstanceError::requested_layers_not_present:
  377. return "requested_layers_not_present";
  378. case InstanceError::requested_extensions_not_present:
  379. return "requested_extensions_not_present";
  380. case InstanceError::windowing_extensions_not_present:
  381. return "windowing_extensions_not_present";
  382. default:
  383. return "";
  384. }
  385. }
  386. const char* to_string (PhysicalDeviceError err) {
  387. switch (err) {
  388. case PhysicalDeviceError::no_surface_provided:
  389. return "no_surface_provided";
  390. case PhysicalDeviceError::failed_enumerate_physical_devices:
  391. return "failed_enumerate_physical_devices";
  392. case PhysicalDeviceError::no_physical_devices_found:
  393. return "no_physical_devices_found";
  394. case PhysicalDeviceError::no_suitable_device:
  395. return "no_suitable_device";
  396. default:
  397. return "";
  398. }
  399. }
  400. const char* to_string (QueueError err) {
  401. switch (err) {
  402. case QueueError::present_unavailable:
  403. return "present_unavailable";
  404. case QueueError::graphics_unavailable:
  405. return "graphics_unavailable";
  406. case QueueError::compute_unavailable:
  407. return "compute_unavailable";
  408. case QueueError::transfer_unavailable:
  409. return "transfer_unavailable";
  410. case QueueError::queue_index_out_of_range:
  411. return "queue_index_out_of_range";
  412. case QueueError::invalid_queue_family_index:
  413. return "invalid_queue_family_index";
  414. default:
  415. return "";
  416. }
  417. }
  418. const char* to_string (DeviceError err) {
  419. switch (err) {
  420. case DeviceError::failed_create_device:
  421. return "failed_create_device";
  422. default:
  423. return "";
  424. }
  425. }
  426. const char* to_string (SwapchainError err) {
  427. switch (err) {
  428. case SwapchainError::surface_handle_not_provided:
  429. return "surface_handle_not_provided";
  430. case SwapchainError::failed_query_surface_support_details:
  431. return "failed_query_surface_support_details";
  432. case SwapchainError::failed_create_swapchain:
  433. return "failed_create_swapchain";
  434. case SwapchainError::failed_get_swapchain_images:
  435. return "failed_get_swapchain_images";
  436. case SwapchainError::failed_create_swapchain_image_views:
  437. return "failed_create_swapchain_image_views";
  438. default:
  439. return "";
  440. }
  441. }
  442. detail::Result<SystemInfo> SystemInfo::get_system_info () {
  443. if (!detail::vulkan_functions ().init_vulkan_funcs (nullptr)) {
  444. return make_error_code (InstanceError::vulkan_unavailable);
  445. }
  446. return SystemInfo ();
  447. }
  448. detail::Result<SystemInfo> SystemInfo::get_system_info (PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) {
  449. // Using externally provided function pointers, assume the loader is available
  450. detail::vulkan_functions ().init_vulkan_funcs (fp_vkGetInstanceProcAddr);
  451. return SystemInfo ();
  452. }
  453. SystemInfo::SystemInfo () {
  454. auto available_layers_ret = detail::get_vector<VkLayerProperties> (
  455. this->available_layers, detail::vulkan_functions ().fp_vkEnumerateInstanceLayerProperties);
  456. if (available_layers_ret != VK_SUCCESS) {
  457. this->available_layers.clear ();
  458. }
  459. for (auto& layer : this->available_layers)
  460. if (strcmp (layer.layerName, detail::validation_layer_name) == 0)
  461. validation_layers_available = true;
  462. auto available_extensions_ret = detail::get_vector<VkExtensionProperties> (this->available_extensions,
  463. detail::vulkan_functions ().fp_vkEnumerateInstanceExtensionProperties,
  464. nullptr);
  465. if (available_extensions_ret != VK_SUCCESS) {
  466. this->available_extensions.clear ();
  467. }
  468. for (auto& ext : this->available_extensions)
  469. if (strcmp (ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0)
  470. debug_utils_available = true;
  471. for (auto& layer : this->available_layers) {
  472. std::vector<VkExtensionProperties> layer_extensions;
  473. auto layer_extensions_ret = detail::get_vector<VkExtensionProperties> (layer_extensions,
  474. detail::vulkan_functions ().fp_vkEnumerateInstanceExtensionProperties,
  475. layer.layerName);
  476. if (layer_extensions_ret != VK_SUCCESS) {
  477. for (auto& ext : layer_extensions)
  478. if (strcmp (ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0)
  479. debug_utils_available = true;
  480. }
  481. }
  482. }
  483. bool SystemInfo::is_extension_available (const char* extension_name) const {
  484. if (!extension_name) return false;
  485. return detail::check_extension_supported (available_extensions, extension_name);
  486. }
  487. bool SystemInfo::is_layer_available (const char* layer_name) const {
  488. if (!layer_name) return false;
  489. return detail::check_layer_supported (available_layers, layer_name);
  490. }
  491. void destroy_instance (Instance instance) {
  492. if (instance.instance != VK_NULL_HANDLE) {
  493. if (instance.debug_messenger != nullptr)
  494. destroy_debug_utils_messenger (instance.instance, instance.debug_messenger, instance.allocation_callbacks);
  495. detail::vulkan_functions ().fp_vkDestroyInstance (instance.instance, instance.allocation_callbacks);
  496. }
  497. }
  498. InstanceBuilder::InstanceBuilder (PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) {
  499. info.fp_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr;
  500. }
  501. InstanceBuilder::InstanceBuilder () {}
  502. detail::Result<Instance> InstanceBuilder::build () const {
  503. auto sys_info_ret = SystemInfo::get_system_info ();
  504. if (!sys_info_ret) return sys_info_ret.error ();
  505. auto system = sys_info_ret.value ();
  506. uint32_t api_version = VK_MAKE_VERSION (1, 0, 0);
  507. if (info.required_api_version > VK_MAKE_VERSION (1, 0, 0) ||
  508. info.desired_api_version > VK_MAKE_VERSION (1, 0, 0)) {
  509. PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion =
  510. detail::vulkan_functions ().fp_vkEnumerateInstanceVersion;
  511. uint32_t queried_api_version = VK_MAKE_VERSION (1, 0, 0);
  512. if (pfn_vkEnumerateInstanceVersion != nullptr) {
  513. VkResult res = pfn_vkEnumerateInstanceVersion (&queried_api_version);
  514. // Should always return VK_SUCCESS
  515. if (res != VK_SUCCESS && info.required_api_version > 0)
  516. return make_error_code (InstanceError::vulkan_version_unavailable);
  517. }
  518. if (pfn_vkEnumerateInstanceVersion == nullptr || queried_api_version < info.required_api_version) {
  519. if (VK_VERSION_MINOR (info.required_api_version) == 2)
  520. return make_error_code (InstanceError::vulkan_version_1_2_unavailable);
  521. else if (VK_VERSION_MINOR (info.required_api_version))
  522. return make_error_code (InstanceError::vulkan_version_1_1_unavailable);
  523. else
  524. return make_error_code (InstanceError::vulkan_version_unavailable);
  525. }
  526. if (info.required_api_version > VK_MAKE_VERSION (1, 0, 0)) {
  527. api_version = info.required_api_version;
  528. } else if (info.desired_api_version > VK_MAKE_VERSION (1, 0, 0)) {
  529. if (queried_api_version >= info.desired_api_version)
  530. api_version = info.desired_api_version;
  531. else
  532. api_version = queried_api_version;
  533. }
  534. }
  535. VkApplicationInfo app_info = {};
  536. app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  537. app_info.pNext = nullptr;
  538. app_info.pApplicationName = info.app_name != nullptr ? info.app_name : "";
  539. app_info.applicationVersion = info.application_version;
  540. app_info.pEngineName = info.engine_name != nullptr ? info.engine_name : "";
  541. app_info.engineVersion = info.engine_version;
  542. app_info.apiVersion = api_version;
  543. std::vector<const char*> extensions;
  544. for (auto& ext : info.extensions)
  545. extensions.push_back (ext);
  546. if (info.debug_callback != nullptr && system.debug_utils_available) {
  547. extensions.push_back (VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
  548. }
  549. if (!info.headless_context) {
  550. auto check_add_window_ext = [&] (const char* name) -> bool {
  551. if (!detail::check_extension_supported (system.available_extensions, name))
  552. return false;
  553. extensions.push_back (name);
  554. return true;
  555. };
  556. bool khr_surface_added = check_add_window_ext ("VK_KHR_surface");
  557. #if defined(_WIN32)
  558. bool added_window_exts = check_add_window_ext ("VK_KHR_win32_surface");
  559. #elif defined(__ANDROID__)
  560. bool added_window_exts = check_add_window_ext ("VK_KHR_android_surface");
  561. #elif defined(_DIRECT2DISPLAY)
  562. bool added_window_exts = check_add_window_ext ("VK_KHR_display");
  563. #elif defined(__linux__)
  564. bool added_window_exts = check_add_window_ext ("VK_KHR_xcb_surface");
  565. added_window_exts = check_add_window_ext ("VK_KHR_xlib_surface") || added_window_exts;
  566. added_window_exts = check_add_window_ext ("VK_KHR_wayland_surface") || added_window_exts;
  567. #elif defined(__APPLE__)
  568. bool added_window_exts = check_add_window_ext ("VK_KHR_metal_surface");
  569. #endif
  570. if (!khr_surface_added || !added_window_exts)
  571. return make_error_code (InstanceError::windowing_extensions_not_present);
  572. }
  573. bool all_extensions_supported = detail::check_extensions_supported (system.available_extensions, extensions);
  574. if (!all_extensions_supported) {
  575. return make_error_code (InstanceError::requested_extensions_not_present);
  576. }
  577. std::vector<const char*> layers;
  578. for (auto& layer : info.layers)
  579. layers.push_back (layer);
  580. if (info.enable_validation_layers || (info.request_validation_layers && system.validation_layers_available)) {
  581. layers.push_back (detail::validation_layer_name);
  582. }
  583. bool all_layers_supported = detail::check_layers_supported (system.available_layers, layers);
  584. if (!all_layers_supported) {
  585. return make_error_code (InstanceError::requested_layers_not_present);
  586. }
  587. std::vector<VkBaseOutStructure*> pNext_chain;
  588. VkDebugUtilsMessengerCreateInfoEXT messengerCreateInfo = {};
  589. if (info.use_debug_messenger) {
  590. messengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  591. messengerCreateInfo.pNext = nullptr;
  592. messengerCreateInfo.messageSeverity = info.debug_message_severity;
  593. messengerCreateInfo.messageType = info.debug_message_type;
  594. messengerCreateInfo.pfnUserCallback = info.debug_callback;
  595. pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (&messengerCreateInfo));
  596. }
  597. VkValidationFeaturesEXT features{};
  598. if (info.enabled_validation_features.size () != 0 || info.disabled_validation_features.size ()) {
  599. features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
  600. features.pNext = nullptr;
  601. features.enabledValidationFeatureCount =
  602. static_cast<uint32_t> (info.enabled_validation_features.size ());
  603. features.pEnabledValidationFeatures = info.enabled_validation_features.data ();
  604. features.disabledValidationFeatureCount =
  605. static_cast<uint32_t> (info.disabled_validation_features.size ());
  606. features.pDisabledValidationFeatures = info.disabled_validation_features.data ();
  607. pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (&features));
  608. }
  609. VkValidationFlagsEXT checks{};
  610. if (info.disabled_validation_checks.size () != 0) {
  611. checks.sType = VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT;
  612. checks.pNext = nullptr;
  613. checks.disabledValidationCheckCount =
  614. static_cast<uint32_t> (info.disabled_validation_checks.size ());
  615. checks.pDisabledValidationChecks = info.disabled_validation_checks.data ();
  616. pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (&checks));
  617. }
  618. VkInstanceCreateInfo instance_create_info = {};
  619. instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  620. detail::setup_pNext_chain (instance_create_info, pNext_chain);
  621. instance_create_info.flags = info.flags;
  622. instance_create_info.pApplicationInfo = &app_info;
  623. instance_create_info.enabledExtensionCount = static_cast<uint32_t> (extensions.size ());
  624. instance_create_info.ppEnabledExtensionNames = extensions.data ();
  625. instance_create_info.enabledLayerCount = static_cast<uint32_t> (layers.size ());
  626. instance_create_info.ppEnabledLayerNames = layers.data ();
  627. Instance instance;
  628. VkResult res = detail::vulkan_functions ().fp_vkCreateInstance (
  629. &instance_create_info, info.allocation_callbacks, &instance.instance);
  630. if (res != VK_SUCCESS)
  631. return detail::Result<Instance> (InstanceError::failed_create_instance, res);
  632. detail::vulkan_functions ().init_instance_funcs (instance.instance);
  633. if (info.use_debug_messenger) {
  634. res = create_debug_utils_messenger (instance.instance,
  635. info.debug_callback,
  636. info.debug_message_severity,
  637. info.debug_message_type,
  638. &instance.debug_messenger,
  639. info.allocation_callbacks);
  640. if (res != VK_SUCCESS) {
  641. return detail::Result<Instance> (InstanceError::failed_create_debug_messenger, res);
  642. }
  643. }
  644. if (info.headless_context) {
  645. instance.headless = true;
  646. }
  647. instance.allocation_callbacks = info.allocation_callbacks;
  648. instance.instance_version = api_version;
  649. instance.fp_vkGetInstanceProcAddr = detail::vulkan_functions ().ptr_vkGetInstanceProcAddr;
  650. return instance;
  651. }
  652. InstanceBuilder& InstanceBuilder::set_app_name (const char* app_name) {
  653. if (!app_name) return *this;
  654. info.app_name = app_name;
  655. return *this;
  656. }
  657. InstanceBuilder& InstanceBuilder::set_engine_name (const char* engine_name) {
  658. if (!engine_name) return *this;
  659. info.engine_name = engine_name;
  660. return *this;
  661. }
  662. InstanceBuilder& InstanceBuilder::set_app_version (uint32_t major, uint32_t minor, uint32_t patch) {
  663. info.application_version = VK_MAKE_VERSION (major, minor, patch);
  664. return *this;
  665. }
  666. InstanceBuilder& InstanceBuilder::set_engine_version (uint32_t major, uint32_t minor, uint32_t patch) {
  667. info.engine_version = VK_MAKE_VERSION (major, minor, patch);
  668. return *this;
  669. }
  670. InstanceBuilder& InstanceBuilder::require_api_version (uint32_t major, uint32_t minor, uint32_t patch) {
  671. info.required_api_version = VK_MAKE_VERSION (major, minor, patch);
  672. return *this;
  673. }
  674. InstanceBuilder& InstanceBuilder::desire_api_version (uint32_t major, uint32_t minor, uint32_t patch) {
  675. info.desired_api_version = VK_MAKE_VERSION (major, minor, patch);
  676. return *this;
  677. }
  678. InstanceBuilder& InstanceBuilder::enable_layer (const char* layer_name) {
  679. if (!layer_name) return *this;
  680. info.layers.push_back (layer_name);
  681. return *this;
  682. }
  683. InstanceBuilder& InstanceBuilder::enable_extension (const char* extension_name) {
  684. if (!extension_name) return *this;
  685. info.extensions.push_back (extension_name);
  686. return *this;
  687. }
  688. InstanceBuilder& InstanceBuilder::enable_validation_layers (bool enable_validation) {
  689. info.enable_validation_layers = enable_validation;
  690. return *this;
  691. }
  692. InstanceBuilder& InstanceBuilder::request_validation_layers (bool enable_validation) {
  693. info.request_validation_layers = enable_validation;
  694. return *this;
  695. }
  696. InstanceBuilder& InstanceBuilder::use_default_debug_messenger () {
  697. info.use_debug_messenger = true;
  698. info.debug_callback = default_debug_callback;
  699. return *this;
  700. }
  701. InstanceBuilder& InstanceBuilder::set_debug_callback (PFN_vkDebugUtilsMessengerCallbackEXT callback) {
  702. info.use_debug_messenger = true;
  703. info.debug_callback = callback;
  704. return *this;
  705. }
  706. InstanceBuilder& InstanceBuilder::set_headless (bool headless) {
  707. info.headless_context = headless;
  708. return *this;
  709. }
  710. InstanceBuilder& InstanceBuilder::set_debug_messenger_severity (VkDebugUtilsMessageSeverityFlagsEXT severity) {
  711. info.debug_message_severity = severity;
  712. return *this;
  713. }
  714. InstanceBuilder& InstanceBuilder::add_debug_messenger_severity (VkDebugUtilsMessageSeverityFlagsEXT severity) {
  715. info.debug_message_severity = info.debug_message_severity | severity;
  716. return *this;
  717. }
  718. InstanceBuilder& InstanceBuilder::set_debug_messenger_type (VkDebugUtilsMessageTypeFlagsEXT type) {
  719. info.debug_message_type = type;
  720. return *this;
  721. }
  722. InstanceBuilder& InstanceBuilder::add_debug_messenger_type (VkDebugUtilsMessageTypeFlagsEXT type) {
  723. info.debug_message_type = info.debug_message_type | type;
  724. return *this;
  725. }
  726. InstanceBuilder& InstanceBuilder::add_validation_disable (VkValidationCheckEXT check) {
  727. info.disabled_validation_checks.push_back (check);
  728. return *this;
  729. }
  730. InstanceBuilder& InstanceBuilder::add_validation_feature_enable (VkValidationFeatureEnableEXT enable) {
  731. info.enabled_validation_features.push_back (enable);
  732. return *this;
  733. }
  734. InstanceBuilder& InstanceBuilder::add_validation_feature_disable (VkValidationFeatureDisableEXT disable) {
  735. info.disabled_validation_features.push_back (disable);
  736. return *this;
  737. }
  738. InstanceBuilder& InstanceBuilder::set_allocation_callbacks (VkAllocationCallbacks* callbacks) {
  739. info.allocation_callbacks = callbacks;
  740. return *this;
  741. }
  742. // ---- Physical Device ---- //
  743. namespace detail {
  744. std::vector<const char*> check_device_extension_support (
  745. VkPhysicalDevice device, std::vector<const char*> desired_extensions) {
  746. std::vector<VkExtensionProperties> available_extensions;
  747. auto available_extensions_ret = detail::get_vector<VkExtensionProperties> (
  748. available_extensions, detail::vulkan_functions ().fp_vkEnumerateDeviceExtensionProperties, device, nullptr);
  749. if (available_extensions_ret != VK_SUCCESS) return {};
  750. std::vector<const char*> extensions_to_enable;
  751. for (const auto& extension : available_extensions) {
  752. for (auto& req_ext : desired_extensions) {
  753. if (strcmp (req_ext, extension.extensionName) == 0) {
  754. extensions_to_enable.push_back (req_ext);
  755. break;
  756. }
  757. }
  758. }
  759. return extensions_to_enable;
  760. }
  761. bool supports_features (VkPhysicalDeviceFeatures supported, VkPhysicalDeviceFeatures requested) {
  762. // clang-format off
  763. if (requested.robustBufferAccess && !supported.robustBufferAccess) return false;
  764. if (requested.fullDrawIndexUint32 && !supported.fullDrawIndexUint32) return false;
  765. if (requested.imageCubeArray && !supported.imageCubeArray) return false;
  766. if (requested.independentBlend && !supported.independentBlend) return false;
  767. if (requested.geometryShader && !supported.geometryShader) return false;
  768. if (requested.tessellationShader && !supported.tessellationShader) return false;
  769. if (requested.sampleRateShading && !supported.sampleRateShading) return false;
  770. if (requested.dualSrcBlend && !supported.dualSrcBlend) return false;
  771. if (requested.logicOp && !supported.logicOp) return false;
  772. if (requested.multiDrawIndirect && !supported.multiDrawIndirect) return false;
  773. if (requested.drawIndirectFirstInstance && !supported.drawIndirectFirstInstance) return false;
  774. if (requested.depthClamp && !supported.depthClamp) return false;
  775. if (requested.depthBiasClamp && !supported.depthBiasClamp) return false;
  776. if (requested.fillModeNonSolid && !supported.fillModeNonSolid) return false;
  777. if (requested.depthBounds && !supported.depthBounds) return false;
  778. if (requested.wideLines && !supported.wideLines) return false;
  779. if (requested.largePoints && !supported.largePoints) return false;
  780. if (requested.alphaToOne && !supported.alphaToOne) return false;
  781. if (requested.multiViewport && !supported.multiViewport) return false;
  782. if (requested.samplerAnisotropy && !supported.samplerAnisotropy) return false;
  783. if (requested.textureCompressionETC2 && !supported.textureCompressionETC2) return false;
  784. if (requested.textureCompressionASTC_LDR && !supported.textureCompressionASTC_LDR) return false;
  785. if (requested.textureCompressionBC && !supported.textureCompressionBC) return false;
  786. if (requested.occlusionQueryPrecise && !supported.occlusionQueryPrecise) return false;
  787. if (requested.pipelineStatisticsQuery && !supported.pipelineStatisticsQuery) return false;
  788. if (requested.vertexPipelineStoresAndAtomics && !supported.vertexPipelineStoresAndAtomics) return false;
  789. if (requested.fragmentStoresAndAtomics && !supported.fragmentStoresAndAtomics) return false;
  790. if (requested.shaderTessellationAndGeometryPointSize && !supported.shaderTessellationAndGeometryPointSize) return false;
  791. if (requested.shaderImageGatherExtended && !supported.shaderImageGatherExtended) return false;
  792. if (requested.shaderStorageImageExtendedFormats && !supported.shaderStorageImageExtendedFormats) return false;
  793. if (requested.shaderStorageImageMultisample && !supported.shaderStorageImageMultisample) return false;
  794. if (requested.shaderStorageImageReadWithoutFormat && !supported.shaderStorageImageReadWithoutFormat) return false;
  795. if (requested.shaderStorageImageWriteWithoutFormat && !supported.shaderStorageImageWriteWithoutFormat) return false;
  796. if (requested.shaderUniformBufferArrayDynamicIndexing && !supported.shaderUniformBufferArrayDynamicIndexing) return false;
  797. if (requested.shaderSampledImageArrayDynamicIndexing && !supported.shaderSampledImageArrayDynamicIndexing) return false;
  798. if (requested.shaderStorageBufferArrayDynamicIndexing && !supported.shaderStorageBufferArrayDynamicIndexing) return false;
  799. if (requested.shaderStorageImageArrayDynamicIndexing && !supported.shaderStorageImageArrayDynamicIndexing) return false;
  800. if (requested.shaderClipDistance && !supported.shaderClipDistance) return false;
  801. if (requested.shaderCullDistance && !supported.shaderCullDistance) return false;
  802. if (requested.shaderFloat64 && !supported.shaderFloat64) return false;
  803. if (requested.shaderInt64 && !supported.shaderInt64) return false;
  804. if (requested.shaderInt16 && !supported.shaderInt16) return false;
  805. if (requested.shaderResourceResidency && !supported.shaderResourceResidency) return false;
  806. if (requested.shaderResourceMinLod && !supported.shaderResourceMinLod) return false;
  807. if (requested.sparseBinding && !supported.sparseBinding) return false;
  808. if (requested.sparseResidencyBuffer && !supported.sparseResidencyBuffer) return false;
  809. if (requested.sparseResidencyImage2D && !supported.sparseResidencyImage2D) return false;
  810. if (requested.sparseResidencyImage3D && !supported.sparseResidencyImage3D) return false;
  811. if (requested.sparseResidency2Samples && !supported.sparseResidency2Samples) return false;
  812. if (requested.sparseResidency4Samples && !supported.sparseResidency4Samples) return false;
  813. if (requested.sparseResidency8Samples && !supported.sparseResidency8Samples) return false;
  814. if (requested.sparseResidency16Samples && !supported.sparseResidency16Samples) return false;
  815. if (requested.sparseResidencyAliased && !supported.sparseResidencyAliased) return false;
  816. if (requested.variableMultisampleRate && !supported.variableMultisampleRate) return false;
  817. if (requested.inheritedQueries && !supported.inheritedQueries) return false;
  818. // clang-format on
  819. return true;
  820. }
  821. // finds the first queue which supports graphics operations. returns -1 if none is found
  822. int get_graphics_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
  823. for (size_t i = 0; i < families.size (); i++) {
  824. if (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) return static_cast<int> (i);
  825. }
  826. return -1;
  827. }
  828. // finds a compute queue which is separate from the graphics queue and tries to find one without
  829. // transfer support returns -1 if none is found
  830. int get_separate_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
  831. int compute = -1;
  832. for (size_t i = 0; i < families.size (); i++) {
  833. if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
  834. ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
  835. if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0) {
  836. return static_cast<int> (i);
  837. } else {
  838. compute = static_cast<int> (i);
  839. }
  840. }
  841. }
  842. return compute;
  843. }
  844. // finds a transfer queue which is separate from the graphics queue and tries to find one without
  845. // compute support returns -1 if none is found
  846. int get_separate_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
  847. int transfer = -1;
  848. for (size_t i = 0; i < families.size (); i++) {
  849. if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
  850. ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
  851. if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) {
  852. return static_cast<int> (i);
  853. } else {
  854. transfer = static_cast<int> (i);
  855. }
  856. }
  857. }
  858. return transfer;
  859. }
  860. // finds the first queue which supports only compute (not graphics or transfer). returns -1 if none is found
  861. int get_dedicated_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
  862. for (size_t i = 0; i < families.size (); i++) {
  863. if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
  864. (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
  865. (families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0)
  866. return static_cast<int> (i);
  867. }
  868. return -1;
  869. }
  870. // finds the first queue which supports only transfer (not graphics or compute). returns -1 if none is found
  871. int get_dedicated_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
  872. for (size_t i = 0; i < families.size (); i++) {
  873. if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
  874. (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
  875. (families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0)
  876. return static_cast<int> (i);
  877. }
  878. return -1;
  879. }
  880. // finds the first queue which supports presenting. returns -1 if none is found
  881. int get_present_queue_index (VkPhysicalDevice const phys_device,
  882. VkSurfaceKHR const surface,
  883. std::vector<VkQueueFamilyProperties> const& families) {
  884. for (size_t i = 0; i < families.size (); i++) {
  885. VkBool32 presentSupport = false;
  886. if (surface != VK_NULL_HANDLE) {
  887. VkResult res = detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfaceSupportKHR (
  888. phys_device, static_cast<uint32_t> (i), surface, &presentSupport);
  889. if (res != VK_SUCCESS) return -1; // TODO: determine if this should fail another way
  890. }
  891. if (presentSupport == VK_TRUE) return static_cast<int> (i);
  892. }
  893. return -1;
  894. }
  895. } // namespace detail
  896. PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details (
  897. VkPhysicalDevice phys_device) const {
  898. PhysicalDeviceSelector::PhysicalDeviceDesc desc{};
  899. desc.phys_device = phys_device;
  900. auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties> (
  901. detail::vulkan_functions ().fp_vkGetPhysicalDeviceQueueFamilyProperties, phys_device);
  902. desc.queue_families = queue_families;
  903. detail::vulkan_functions ().fp_vkGetPhysicalDeviceProperties (phys_device, &desc.device_properties);
  904. detail::vulkan_functions ().fp_vkGetPhysicalDeviceFeatures (phys_device, &desc.device_features);
  905. detail::vulkan_functions ().fp_vkGetPhysicalDeviceMemoryProperties (phys_device, &desc.mem_properties);
  906. return desc;
  907. }
  908. PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (PhysicalDeviceDesc pd) const {
  909. Suitable suitable = Suitable::yes;
  910. if (criteria.required_version > pd.device_properties.apiVersion) return Suitable::no;
  911. if (criteria.desired_version > pd.device_properties.apiVersion) suitable = Suitable::partial;
  912. bool dedicated_compute = detail::get_dedicated_compute_queue_index (pd.queue_families) >= 0;
  913. bool dedicated_transfer = detail::get_dedicated_transfer_queue_index (pd.queue_families) >= 0;
  914. bool separate_compute = detail::get_separate_compute_queue_index (pd.queue_families) >= 0;
  915. bool separate_transfer = detail::get_separate_transfer_queue_index (pd.queue_families) >= 0;
  916. bool present_queue =
  917. detail::get_present_queue_index (pd.phys_device, system_info.surface, pd.queue_families) >= 0;
  918. if (criteria.require_dedicated_compute_queue && !dedicated_compute) return Suitable::no;
  919. if (criteria.require_dedicated_transfer_queue && !dedicated_transfer) return Suitable::no;
  920. if (criteria.require_separate_compute_queue && !separate_compute) return Suitable::no;
  921. if (criteria.require_separate_transfer_queue && !separate_transfer) return Suitable::no;
  922. if (criteria.require_present && !present_queue && !criteria.defer_surface_initialization)
  923. return Suitable::no;
  924. auto required_extensions_supported =
  925. detail::check_device_extension_support (pd.phys_device, criteria.required_extensions);
  926. if (required_extensions_supported.size () != criteria.required_extensions.size ())
  927. return Suitable::no;
  928. auto desired_extensions_supported =
  929. detail::check_device_extension_support (pd.phys_device, criteria.desired_extensions);
  930. if (desired_extensions_supported.size () != criteria.desired_extensions.size ())
  931. suitable = Suitable::partial;
  932. bool swapChainAdequate = false;
  933. if (criteria.defer_surface_initialization) {
  934. swapChainAdequate = true;
  935. } else if (!system_info.headless) {
  936. std::vector<VkSurfaceFormatKHR> formats;
  937. std::vector<VkPresentModeKHR> present_modes;
  938. auto formats_ret = detail::get_vector<VkSurfaceFormatKHR> (formats,
  939. detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfaceFormatsKHR,
  940. pd.phys_device,
  941. system_info.surface);
  942. auto present_modes_ret = detail::get_vector<VkPresentModeKHR> (present_modes,
  943. detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfacePresentModesKHR,
  944. pd.phys_device,
  945. system_info.surface);
  946. if (formats_ret == VK_SUCCESS && present_modes_ret == VK_SUCCESS) {
  947. swapChainAdequate = !formats.empty () && !present_modes.empty ();
  948. }
  949. }
  950. if (criteria.require_present && !swapChainAdequate) return Suitable::no;
  951. if (pd.device_properties.deviceType != static_cast<VkPhysicalDeviceType> (criteria.preferred_type)) {
  952. if (criteria.allow_any_type)
  953. suitable = Suitable::partial;
  954. else
  955. return Suitable::no;
  956. }
  957. bool required_features_supported =
  958. detail::supports_features (pd.device_features, criteria.required_features);
  959. if (!required_features_supported) return Suitable::no;
  960. bool has_required_memory = false;
  961. bool has_preferred_memory = false;
  962. for (uint32_t i = 0; i < pd.mem_properties.memoryHeapCount; i++) {
  963. if (pd.mem_properties.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
  964. if (pd.mem_properties.memoryHeaps[i].size > criteria.required_mem_size) {
  965. has_required_memory = true;
  966. }
  967. if (pd.mem_properties.memoryHeaps[i].size > criteria.desired_mem_size) {
  968. has_preferred_memory = true;
  969. }
  970. }
  971. }
  972. if (!has_required_memory) return Suitable::no;
  973. if (!has_preferred_memory) suitable = Suitable::partial;
  974. return suitable;
  975. }
  976. PhysicalDeviceSelector::PhysicalDeviceSelector (Instance const& instance) {
  977. system_info.instance = instance.instance;
  978. system_info.headless = instance.headless;
  979. criteria.require_present = !instance.headless;
  980. criteria.required_version = instance.instance_version;
  981. criteria.desired_version = instance.instance_version;
  982. }
  983. detail::Result<PhysicalDevice> PhysicalDeviceSelector::select () const {
  984. if (!system_info.headless && !criteria.defer_surface_initialization) {
  985. if (system_info.surface == nullptr)
  986. return detail::Result<PhysicalDevice>{ PhysicalDeviceError::no_surface_provided };
  987. }
  988. std::vector<VkPhysicalDevice> physical_devices;
  989. auto physical_devices_ret = detail::get_vector<VkPhysicalDevice> (
  990. physical_devices, detail::vulkan_functions ().fp_vkEnumeratePhysicalDevices, system_info.instance);
  991. if (physical_devices_ret != VK_SUCCESS) {
  992. return detail::Result<PhysicalDevice>{ PhysicalDeviceError::failed_enumerate_physical_devices,
  993. physical_devices_ret };
  994. }
  995. if (physical_devices.size () == 0) {
  996. return detail::Result<PhysicalDevice>{ PhysicalDeviceError::no_physical_devices_found };
  997. }
  998. std::vector<PhysicalDeviceDesc> phys_device_descriptions;
  999. for (auto& phys_device : physical_devices) {
  1000. phys_device_descriptions.push_back (populate_device_details (phys_device));
  1001. }
  1002. PhysicalDeviceDesc selected_device{};
  1003. if (criteria.use_first_gpu_unconditionally) {
  1004. selected_device = phys_device_descriptions.at (0);
  1005. } else {
  1006. for (const auto& device : phys_device_descriptions) {
  1007. auto suitable = is_device_suitable (device);
  1008. if (suitable == Suitable::yes) {
  1009. selected_device = device;
  1010. break;
  1011. } else if (suitable == Suitable::partial) {
  1012. selected_device = device;
  1013. }
  1014. }
  1015. }
  1016. if (selected_device.phys_device == VK_NULL_HANDLE) {
  1017. return detail::Result<PhysicalDevice>{ PhysicalDeviceError::no_suitable_device };
  1018. }
  1019. PhysicalDevice out_device{};
  1020. out_device.physical_device = selected_device.phys_device;
  1021. out_device.surface = system_info.surface;
  1022. out_device.features = criteria.required_features;
  1023. out_device.properties = selected_device.device_properties;
  1024. out_device.memory_properties = selected_device.mem_properties;
  1025. out_device.queue_families = selected_device.queue_families;
  1026. out_device.defer_surface_initialization = criteria.defer_surface_initialization;
  1027. out_device.extensions_to_enable.insert (out_device.extensions_to_enable.end (),
  1028. criteria.required_extensions.begin (),
  1029. criteria.required_extensions.end ());
  1030. auto desired_extensions_supported =
  1031. detail::check_device_extension_support (out_device.physical_device, criteria.desired_extensions);
  1032. out_device.extensions_to_enable.insert (out_device.extensions_to_enable.end (),
  1033. desired_extensions_supported.begin (),
  1034. desired_extensions_supported.end ());
  1035. return out_device;
  1036. }
  1037. PhysicalDeviceSelector& PhysicalDeviceSelector::set_surface (VkSurfaceKHR surface) {
  1038. system_info.surface = surface;
  1039. system_info.headless = false;
  1040. return *this;
  1041. }
  1042. PhysicalDeviceSelector& PhysicalDeviceSelector::prefer_gpu_device_type (PreferredDeviceType type) {
  1043. criteria.preferred_type = type;
  1044. return *this;
  1045. }
  1046. PhysicalDeviceSelector& PhysicalDeviceSelector::allow_any_gpu_device_type (bool allow_any_type) {
  1047. criteria.allow_any_type = allow_any_type;
  1048. return *this;
  1049. }
  1050. PhysicalDeviceSelector& PhysicalDeviceSelector::require_present (bool require) {
  1051. criteria.require_present = require;
  1052. return *this;
  1053. }
  1054. PhysicalDeviceSelector& PhysicalDeviceSelector::require_dedicated_transfer_queue () {
  1055. criteria.require_dedicated_transfer_queue = true;
  1056. return *this;
  1057. }
  1058. PhysicalDeviceSelector& PhysicalDeviceSelector::require_dedicated_compute_queue () {
  1059. criteria.require_dedicated_compute_queue = true;
  1060. return *this;
  1061. }
  1062. PhysicalDeviceSelector& PhysicalDeviceSelector::require_separate_transfer_queue () {
  1063. criteria.require_separate_transfer_queue = true;
  1064. return *this;
  1065. }
  1066. PhysicalDeviceSelector& PhysicalDeviceSelector::require_separate_compute_queue () {
  1067. criteria.require_separate_compute_queue = true;
  1068. return *this;
  1069. }
  1070. PhysicalDeviceSelector& PhysicalDeviceSelector::required_device_memory_size (VkDeviceSize size) {
  1071. criteria.required_mem_size = size;
  1072. return *this;
  1073. }
  1074. PhysicalDeviceSelector& PhysicalDeviceSelector::desired_device_memory_size (VkDeviceSize size) {
  1075. criteria.desired_mem_size = size;
  1076. return *this;
  1077. }
  1078. PhysicalDeviceSelector& PhysicalDeviceSelector::add_required_extension (const char* extension) {
  1079. criteria.required_extensions.push_back (extension);
  1080. return *this;
  1081. }
  1082. PhysicalDeviceSelector& PhysicalDeviceSelector::add_required_extensions (std::vector<const char*> extensions) {
  1083. criteria.required_extensions.insert (
  1084. criteria.required_extensions.end (), extensions.begin (), extensions.end ());
  1085. return *this;
  1086. }
  1087. PhysicalDeviceSelector& PhysicalDeviceSelector::add_desired_extension (const char* extension) {
  1088. criteria.desired_extensions.push_back (extension);
  1089. return *this;
  1090. }
  1091. PhysicalDeviceSelector& PhysicalDeviceSelector::add_desired_extensions (std::vector<const char*> extensions) {
  1092. criteria.desired_extensions.insert (
  1093. criteria.desired_extensions.end (), extensions.begin (), extensions.end ());
  1094. return *this;
  1095. }
  1096. PhysicalDeviceSelector& PhysicalDeviceSelector::set_minimum_version (uint32_t major, uint32_t minor) {
  1097. criteria.required_version = VK_MAKE_VERSION (major, minor, 0);
  1098. return *this;
  1099. }
  1100. PhysicalDeviceSelector& PhysicalDeviceSelector::set_desired_version (uint32_t major, uint32_t minor) {
  1101. criteria.desired_version = VK_MAKE_VERSION (major, minor, 0);
  1102. return *this;
  1103. }
  1104. PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features (VkPhysicalDeviceFeatures features) {
  1105. criteria.required_features = features;
  1106. return *this;
  1107. }
  1108. PhysicalDeviceSelector& PhysicalDeviceSelector::defer_surface_initialization () {
  1109. criteria.defer_surface_initialization = true;
  1110. return *this;
  1111. }
  1112. PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditionally (bool unconditionally) {
  1113. criteria.use_first_gpu_unconditionally = unconditionally;
  1114. return *this;
  1115. }
  1116. bool PhysicalDevice::has_dedicated_compute_queue () const {
  1117. return detail::get_dedicated_compute_queue_index (queue_families) >= 0;
  1118. }
  1119. bool PhysicalDevice::has_separate_compute_queue () const {
  1120. return detail::get_separate_compute_queue_index (queue_families) >= 0;
  1121. }
  1122. bool PhysicalDevice::has_dedicated_transfer_queue () const {
  1123. return detail::get_dedicated_transfer_queue_index (queue_families) >= 0;
  1124. }
  1125. bool PhysicalDevice::has_separate_transfer_queue () const {
  1126. return detail::get_separate_transfer_queue_index (queue_families) >= 0;
  1127. }
  1128. std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families () const {
  1129. return queue_families;
  1130. }
  1131. // ---- Queues ---- //
  1132. detail::Result<uint32_t> Device::get_queue_index (QueueType type) const {
  1133. int index = -1;
  1134. switch (type) {
  1135. case QueueType::present:
  1136. index = detail::get_present_queue_index (physical_device.physical_device, surface, queue_families);
  1137. if (index < 0) return detail::Result<uint32_t>{ QueueError::present_unavailable };
  1138. break;
  1139. case QueueType::graphics:
  1140. index = detail::get_graphics_queue_index (queue_families);
  1141. if (index < 0) return detail::Result<uint32_t>{ QueueError::graphics_unavailable };
  1142. break;
  1143. case QueueType::compute:
  1144. index = detail::get_separate_compute_queue_index (queue_families);
  1145. if (index < 0) return detail::Result<uint32_t>{ QueueError::compute_unavailable };
  1146. break;
  1147. case QueueType::transfer:
  1148. index = detail::get_separate_transfer_queue_index (queue_families);
  1149. if (index < 0) return detail::Result<uint32_t>{ QueueError::transfer_unavailable };
  1150. break;
  1151. default:
  1152. return detail::Result<uint32_t>{ QueueError::invalid_queue_family_index };
  1153. }
  1154. return static_cast<uint32_t> (index);
  1155. }
  1156. detail::Result<uint32_t> Device::get_dedicated_queue_index (QueueType type) const {
  1157. int index = -1;
  1158. switch (type) {
  1159. case QueueType::compute:
  1160. index = detail::get_dedicated_compute_queue_index (queue_families);
  1161. if (index < 0) return detail::Result<uint32_t>{ QueueError::compute_unavailable };
  1162. break;
  1163. case QueueType::transfer:
  1164. index = detail::get_dedicated_transfer_queue_index (queue_families);
  1165. if (index < 0) return detail::Result<uint32_t>{ QueueError::transfer_unavailable };
  1166. break;
  1167. default:
  1168. return detail::Result<uint32_t>{ QueueError::invalid_queue_family_index };
  1169. }
  1170. return static_cast<uint32_t> (index);
  1171. }
  1172. namespace detail {
  1173. VkQueue get_queue (VkDevice device, uint32_t family) {
  1174. VkQueue out_queue;
  1175. detail::vulkan_functions ().fp_vkGetDeviceQueue (device, family, 0, &out_queue);
  1176. return out_queue;
  1177. }
  1178. } // namespace detail
  1179. detail::Result<VkQueue> Device::get_queue (QueueType type) const {
  1180. auto index = get_queue_index (type);
  1181. if (!index.has_value ()) return { index.error () };
  1182. return detail::get_queue (device, index.value ());
  1183. }
  1184. detail::Result<VkQueue> Device::get_dedicated_queue (QueueType type) const {
  1185. auto index = get_dedicated_queue_index (type);
  1186. if (!index.has_value ()) return { index.error () };
  1187. return detail::get_queue (device, index.value ());
  1188. }
  1189. // ---- Device ---- //
  1190. CustomQueueDescription::CustomQueueDescription (uint32_t index, uint32_t count, std::vector<float> priorities)
  1191. : index (index), count (count), priorities (priorities) {
  1192. assert (count == priorities.size ());
  1193. }
  1194. void destroy_device (Device device) {
  1195. detail::vulkan_functions ().fp_vkDestroyDevice (device.device, device.allocation_callbacks);
  1196. }
  1197. DeviceBuilder::DeviceBuilder (PhysicalDevice phys_device) {
  1198. info.physical_device = phys_device;
  1199. info.surface = phys_device.surface;
  1200. info.queue_families = phys_device.queue_families;
  1201. info.features = phys_device.features;
  1202. info.extensions_to_enable = phys_device.extensions_to_enable;
  1203. info.defer_surface_initialization = phys_device.defer_surface_initialization;
  1204. }
  1205. detail::Result<Device> DeviceBuilder::build () const {
  1206. std::vector<CustomQueueDescription> queue_descriptions;
  1207. queue_descriptions.insert (
  1208. queue_descriptions.end (), info.queue_descriptions.begin (), info.queue_descriptions.end ());
  1209. if (queue_descriptions.size () == 0) {
  1210. for (uint32_t i = 0; i < info.queue_families.size (); i++) {
  1211. queue_descriptions.push_back (CustomQueueDescription{ i, 1, std::vector<float>{ 1.0f } });
  1212. }
  1213. }
  1214. std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  1215. for (auto& desc : queue_descriptions) {
  1216. VkDeviceQueueCreateInfo queue_create_info = {};
  1217. queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  1218. queue_create_info.queueFamilyIndex = desc.index;
  1219. queue_create_info.queueCount = desc.count;
  1220. queue_create_info.pQueuePriorities = desc.priorities.data ();
  1221. queueCreateInfos.push_back (queue_create_info);
  1222. }
  1223. std::vector<const char*> extensions = info.extensions_to_enable;
  1224. if (info.surface != VK_NULL_HANDLE || info.defer_surface_initialization)
  1225. extensions.push_back ({ VK_KHR_SWAPCHAIN_EXTENSION_NAME });
  1226. // VUID-VkDeviceCreateInfo-pNext-00373 - don't add pEnabledFeatures if the phys_dev_features_2 is present
  1227. bool has_phys_dev_features_2 = false;
  1228. for (auto& pNext_struct : info.pNext_chain) {
  1229. if (pNext_struct->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) {
  1230. has_phys_dev_features_2 = true;
  1231. }
  1232. }
  1233. VkDeviceCreateInfo device_create_info = {};
  1234. device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  1235. detail::setup_pNext_chain (device_create_info, info.pNext_chain);
  1236. device_create_info.flags = info.flags;
  1237. device_create_info.queueCreateInfoCount = static_cast<uint32_t> (queueCreateInfos.size ());
  1238. device_create_info.pQueueCreateInfos = queueCreateInfos.data ();
  1239. device_create_info.enabledExtensionCount = static_cast<uint32_t> (extensions.size ());
  1240. device_create_info.ppEnabledExtensionNames = extensions.data ();
  1241. if (!has_phys_dev_features_2) {
  1242. device_create_info.pEnabledFeatures = &info.features;
  1243. }
  1244. Device device;
  1245. VkResult res = detail::vulkan_functions ().fp_vkCreateDevice (info.physical_device.physical_device,
  1246. &device_create_info,
  1247. info.allocation_callbacks,
  1248. &device.device);
  1249. if (res != VK_SUCCESS) {
  1250. return { DeviceError::failed_create_device, res };
  1251. }
  1252. device.physical_device = info.physical_device;
  1253. device.surface = info.surface;
  1254. device.queue_families = info.queue_families;
  1255. device.allocation_callbacks = info.allocation_callbacks;
  1256. return device;
  1257. }
  1258. DeviceBuilder& DeviceBuilder::custom_queue_setup (std::vector<CustomQueueDescription> queue_descriptions) {
  1259. info.queue_descriptions = queue_descriptions;
  1260. return *this;
  1261. }
  1262. DeviceBuilder& DeviceBuilder::set_allocation_callbacks (VkAllocationCallbacks* callbacks) {
  1263. info.allocation_callbacks = callbacks;
  1264. return *this;
  1265. }
  1266. // ---- Swapchain ---- //
  1267. namespace detail {
  1268. struct SurfaceSupportDetails {
  1269. VkSurfaceCapabilitiesKHR capabilities;
  1270. std::vector<VkSurfaceFormatKHR> formats;
  1271. std::vector<VkPresentModeKHR> present_modes;
  1272. };
  1273. enum class SurfaceSupportError {
  1274. surface_handle_null,
  1275. failed_get_surface_capabilities,
  1276. failed_enumerate_surface_formats,
  1277. failed_enumerate_present_modes
  1278. };
  1279. struct SurfaceSupportErrorCategory : std::error_category {
  1280. const char* name () const noexcept override { return "vbk_surface_support"; }
  1281. std::string message (int err) const override {
  1282. switch (static_cast<SurfaceSupportError> (err)) {
  1283. case SurfaceSupportError::surface_handle_null:
  1284. return "surface_handle_null";
  1285. case SurfaceSupportError::failed_get_surface_capabilities:
  1286. return "failed_get_surface_capabilities";
  1287. case SurfaceSupportError::failed_enumerate_surface_formats:
  1288. return "failed_enumerate_surface_formats";
  1289. case SurfaceSupportError::failed_enumerate_present_modes:
  1290. return "failed_enumerate_present_modes";
  1291. default:
  1292. return "";
  1293. }
  1294. }
  1295. };
  1296. const SurfaceSupportErrorCategory surface_support_error_category;
  1297. std::error_code make_error_code (SurfaceSupportError surface_support_error) {
  1298. return { static_cast<int> (surface_support_error), detail::surface_support_error_category };
  1299. }
  1300. Result<SurfaceSupportDetails> query_surface_support_details (VkPhysicalDevice phys_device, VkSurfaceKHR surface) {
  1301. if (surface == VK_NULL_HANDLE)
  1302. return make_error_code (SurfaceSupportError::surface_handle_null);
  1303. VkSurfaceCapabilitiesKHR capabilities;
  1304. VkResult res = detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR (
  1305. phys_device, surface, &capabilities);
  1306. if (res != VK_SUCCESS) {
  1307. return { make_error_code (SurfaceSupportError::failed_get_surface_capabilities), res };
  1308. }
  1309. std::vector<VkSurfaceFormatKHR> formats;
  1310. std::vector<VkPresentModeKHR> present_modes;
  1311. auto formats_ret = detail::get_vector<VkSurfaceFormatKHR> (
  1312. formats, detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface);
  1313. if (formats_ret != VK_SUCCESS)
  1314. return { make_error_code (SurfaceSupportError::failed_enumerate_surface_formats), formats_ret };
  1315. auto present_modes_ret = detail::get_vector<VkPresentModeKHR> (
  1316. present_modes, detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface);
  1317. if (present_modes_ret != VK_SUCCESS)
  1318. return { make_error_code (SurfaceSupportError::failed_enumerate_present_modes), present_modes_ret };
  1319. return SurfaceSupportDetails{ capabilities, formats, present_modes };
  1320. }
  1321. VkSurfaceFormatKHR find_surface_format (std::vector<VkSurfaceFormatKHR> const& available_formats,
  1322. std::vector<VkSurfaceFormatKHR> const& desired_formats) {
  1323. for (auto const& desired_format : desired_formats) {
  1324. for (auto const& available_format : available_formats) {
  1325. // finds the first format that is desired and available
  1326. if (desired_format.format == available_format.format &&
  1327. desired_format.colorSpace == available_format.colorSpace) {
  1328. return desired_format;
  1329. }
  1330. }
  1331. }
  1332. // use the first available one if any desired formats aren't found
  1333. return available_formats[0];
  1334. }
  1335. VkPresentModeKHR find_present_mode (std::vector<VkPresentModeKHR> const& available_resent_modes,
  1336. std::vector<VkPresentModeKHR> const& desired_present_modes) {
  1337. for (auto const& desired_pm : desired_present_modes) {
  1338. for (auto const& available_pm : available_resent_modes) {
  1339. // finds the first present mode that is desired and available
  1340. if (desired_pm == available_pm) return desired_pm;
  1341. }
  1342. }
  1343. // only present mode required, use as a fallback
  1344. return VK_PRESENT_MODE_FIFO_KHR;
  1345. }
  1346. template <typename T> T minimum (T a, T b) { return a < b ? a : b; }
  1347. template <typename T> T maximum (T a, T b) { return a > b ? a : b; }
  1348. VkExtent2D find_extent (
  1349. VkSurfaceCapabilitiesKHR const& capabilities, uint32_t desired_width, uint32_t desired_height) {
  1350. if (capabilities.currentExtent.width != UINT32_MAX) {
  1351. return capabilities.currentExtent;
  1352. } else {
  1353. VkExtent2D actualExtent = { desired_width, desired_height };
  1354. actualExtent.width = maximum (capabilities.minImageExtent.width,
  1355. minimum (capabilities.maxImageExtent.width, actualExtent.width));
  1356. actualExtent.height = maximum (capabilities.minImageExtent.height,
  1357. minimum (capabilities.maxImageExtent.height, actualExtent.height));
  1358. return actualExtent;
  1359. }
  1360. }
  1361. } // namespace detail
  1362. void destroy_swapchain (Swapchain const& swapchain) {
  1363. if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE) {
  1364. detail::vulkan_functions ().fp_vkDestroySwapchainKHR (
  1365. swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks);
  1366. }
  1367. }
  1368. SwapchainBuilder::SwapchainBuilder (Device const& device) {
  1369. info.device = device.device;
  1370. info.physical_device = device.physical_device.physical_device;
  1371. info.surface = device.surface;
  1372. auto present = device.get_queue_index (QueueType::present);
  1373. auto graphics = device.get_queue_index (QueueType::graphics);
  1374. // TODO: handle error of queue's not available
  1375. info.graphics_queue_index = present.value ();
  1376. info.present_queue_index = graphics.value ();
  1377. }
  1378. SwapchainBuilder::SwapchainBuilder (Device const& device, VkSurfaceKHR const surface) {
  1379. info.device = device.device;
  1380. info.physical_device = device.physical_device.physical_device;
  1381. info.surface = surface;
  1382. Device temp_device = device;
  1383. temp_device.surface = surface;
  1384. auto present = temp_device.get_queue_index (QueueType::present);
  1385. auto graphics = temp_device.get_queue_index (QueueType::graphics);
  1386. // TODO: handle error of queue's not available
  1387. info.graphics_queue_index = present.value ();
  1388. info.present_queue_index = graphics.value ();
  1389. }
  1390. SwapchainBuilder::SwapchainBuilder (VkPhysicalDevice const physical_device, VkDevice const device, VkSurfaceKHR const surface, int32_t graphics_queue_index, int32_t present_queue_index){
  1391. info.physical_device = physical_device;
  1392. info.device = device;
  1393. info.surface = surface;
  1394. info.graphics_queue_index = static_cast<uint32_t>(graphics_queue_index);
  1395. info.present_queue_index = static_cast<uint32_t>(present_queue_index);
  1396. if (graphics_queue_index < 0 || present_queue_index < 0) {
  1397. auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties> (
  1398. detail::vulkan_functions().fp_vkGetPhysicalDeviceQueueFamilyProperties, physical_device);
  1399. if (graphics_queue_index < 0)
  1400. info.graphics_queue_index = static_cast<uint32_t>(detail::get_graphics_queue_index (queue_families));
  1401. if (present_queue_index < 0)
  1402. info.present_queue_index = static_cast<uint32_t>(detail::get_present_queue_index (physical_device, surface, queue_families));
  1403. }
  1404. }
  1405. detail::Result<Swapchain> SwapchainBuilder::build () const {
  1406. if (info.surface == VK_NULL_HANDLE) {
  1407. return detail::Error{ SwapchainError::surface_handle_not_provided };
  1408. }
  1409. auto desired_formats = info.desired_formats;
  1410. if (desired_formats.size () == 0) add_desired_formats (desired_formats);
  1411. auto desired_present_modes = info.desired_present_modes;
  1412. if (desired_present_modes.size () == 0) add_desired_present_modes (desired_present_modes);
  1413. auto surface_support_ret = detail::query_surface_support_details (info.physical_device, info.surface);
  1414. if (!surface_support_ret.has_value ())
  1415. return detail::Error{ SwapchainError::failed_query_surface_support_details,
  1416. surface_support_ret.vk_result () };
  1417. auto surface_support = surface_support_ret.value ();
  1418. uint32_t image_count = surface_support.capabilities.minImageCount + 1;
  1419. if (surface_support.capabilities.maxImageCount > 0 && image_count > surface_support.capabilities.maxImageCount) {
  1420. image_count = surface_support.capabilities.maxImageCount;
  1421. }
  1422. VkSurfaceFormatKHR surface_format = detail::find_surface_format (surface_support.formats, desired_formats);
  1423. VkExtent2D extent =
  1424. detail::find_extent (surface_support.capabilities, info.desired_width, info.desired_height);
  1425. uint32_t image_array_layers = info.array_layer_count;
  1426. if (surface_support.capabilities.maxImageArrayLayers < info.array_layer_count)
  1427. image_array_layers = surface_support.capabilities.maxImageArrayLayers;
  1428. if (info.array_layer_count == 0) image_array_layers = 1;
  1429. uint32_t queue_family_indices[] = { info.graphics_queue_index, info.present_queue_index };
  1430. VkPresentModeKHR present_mode =
  1431. detail::find_present_mode (surface_support.present_modes, desired_present_modes);
  1432. VkSurfaceTransformFlagBitsKHR pre_transform = info.pre_transform;
  1433. if (info.pre_transform == static_cast<VkSurfaceTransformFlagBitsKHR> (0))
  1434. pre_transform = surface_support.capabilities.currentTransform;
  1435. VkSwapchainCreateInfoKHR swapchain_create_info = {};
  1436. swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  1437. detail::setup_pNext_chain (swapchain_create_info, info.pNext_chain);
  1438. swapchain_create_info.flags = info.create_flags;
  1439. swapchain_create_info.surface = info.surface;
  1440. swapchain_create_info.minImageCount = image_count;
  1441. swapchain_create_info.imageFormat = surface_format.format;
  1442. swapchain_create_info.imageColorSpace = surface_format.colorSpace;
  1443. swapchain_create_info.imageExtent = extent;
  1444. swapchain_create_info.imageArrayLayers = image_array_layers;
  1445. swapchain_create_info.imageUsage = info.image_usage_flags;
  1446. if (info.graphics_queue_index != info.present_queue_index) {
  1447. swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  1448. swapchain_create_info.queueFamilyIndexCount = 2;
  1449. swapchain_create_info.pQueueFamilyIndices = queue_family_indices;
  1450. } else {
  1451. swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1452. }
  1453. swapchain_create_info.preTransform = pre_transform;
  1454. swapchain_create_info.compositeAlpha = info.composite_alpha;
  1455. swapchain_create_info.presentMode = present_mode;
  1456. swapchain_create_info.clipped = info.clipped;
  1457. swapchain_create_info.oldSwapchain = info.old_swapchain;
  1458. Swapchain swapchain{};
  1459. VkResult res = detail::vulkan_functions ().fp_vkCreateSwapchainKHR (
  1460. info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain);
  1461. if (res != VK_SUCCESS) {
  1462. return detail::Error{ SwapchainError::failed_create_swapchain, res };
  1463. }
  1464. swapchain.device = info.device;
  1465. swapchain.image_format = surface_format.format;
  1466. swapchain.extent = extent;
  1467. auto images = swapchain.get_images ();
  1468. if (!images) {
  1469. return detail::Error{ SwapchainError::failed_get_swapchain_images };
  1470. }
  1471. swapchain.image_count = static_cast<uint32_t> (images.value ().size ());
  1472. swapchain.allocation_callbacks = info.allocation_callbacks;
  1473. return swapchain;
  1474. }
  1475. detail::Result<std::vector<VkImage>> Swapchain::get_images () {
  1476. std::vector<VkImage> swapchain_images;
  1477. auto swapchain_images_ret = detail::get_vector<VkImage> (
  1478. swapchain_images, detail::vulkan_functions ().fp_vkGetSwapchainImagesKHR, device, swapchain);
  1479. if (swapchain_images_ret != VK_SUCCESS) {
  1480. return detail::Error{ SwapchainError::failed_get_swapchain_images, swapchain_images_ret };
  1481. }
  1482. return swapchain_images;
  1483. }
  1484. detail::Result<std::vector<VkImageView>> Swapchain::get_image_views () {
  1485. auto swapchain_images_ret = get_images ();
  1486. if (!swapchain_images_ret) return swapchain_images_ret.error ();
  1487. auto swapchain_images = swapchain_images_ret.value ();
  1488. std::vector<VkImageView> views{ swapchain_images.size () };
  1489. for (size_t i = 0; i < swapchain_images.size (); i++) {
  1490. VkImageViewCreateInfo createInfo = {};
  1491. createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1492. createInfo.image = swapchain_images[i];
  1493. createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1494. createInfo.format = image_format;
  1495. createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  1496. createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  1497. createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  1498. createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  1499. createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1500. createInfo.subresourceRange.baseMipLevel = 0;
  1501. createInfo.subresourceRange.levelCount = 1;
  1502. createInfo.subresourceRange.baseArrayLayer = 0;
  1503. createInfo.subresourceRange.layerCount = 1;
  1504. VkResult res = detail::vulkan_functions ().fp_vkCreateImageView (
  1505. device, &createInfo, allocation_callbacks, &views[i]);
  1506. if (res != VK_SUCCESS)
  1507. return detail::Error{ SwapchainError::failed_create_swapchain_image_views, res };
  1508. }
  1509. return views;
  1510. }
  1511. void Swapchain::destroy_image_views (std::vector<VkImageView> const& image_views) {
  1512. for (auto& image_view : image_views) {
  1513. detail::vulkan_functions ().fp_vkDestroyImageView (device, image_view, allocation_callbacks);
  1514. }
  1515. }
  1516. SwapchainBuilder& SwapchainBuilder::set_old_swapchain (VkSwapchainKHR old_swapchain) {
  1517. info.old_swapchain = old_swapchain;
  1518. return *this;
  1519. }
  1520. SwapchainBuilder& SwapchainBuilder::set_old_swapchain (Swapchain const& swapchain) {
  1521. info.old_swapchain = swapchain.swapchain;
  1522. return *this;
  1523. }
  1524. SwapchainBuilder& SwapchainBuilder::set_desired_extent (uint32_t width, uint32_t height) {
  1525. info.desired_width = width;
  1526. info.desired_height = height;
  1527. return *this;
  1528. }
  1529. SwapchainBuilder& SwapchainBuilder::set_desired_format (VkSurfaceFormatKHR format) {
  1530. info.desired_formats.insert (info.desired_formats.begin (), format);
  1531. return *this;
  1532. }
  1533. SwapchainBuilder& SwapchainBuilder::add_fallback_format (VkSurfaceFormatKHR format) {
  1534. info.desired_formats.push_back (format);
  1535. return *this;
  1536. }
  1537. SwapchainBuilder& SwapchainBuilder::use_default_format_selection () {
  1538. info.desired_formats.clear ();
  1539. add_desired_formats (info.desired_formats);
  1540. return *this;
  1541. }
  1542. SwapchainBuilder& SwapchainBuilder::set_desired_present_mode (VkPresentModeKHR present_mode) {
  1543. info.desired_present_modes.insert (info.desired_present_modes.begin (), present_mode);
  1544. return *this;
  1545. }
  1546. SwapchainBuilder& SwapchainBuilder::add_fallback_present_mode (VkPresentModeKHR present_mode) {
  1547. info.desired_present_modes.push_back (present_mode);
  1548. return *this;
  1549. }
  1550. SwapchainBuilder& SwapchainBuilder::use_default_present_mode_selection () {
  1551. info.desired_present_modes.clear ();
  1552. add_desired_present_modes (info.desired_present_modes);
  1553. return *this;
  1554. }
  1555. SwapchainBuilder& SwapchainBuilder::set_allocation_callbacks (VkAllocationCallbacks* callbacks) {
  1556. info.allocation_callbacks = callbacks;
  1557. return *this;
  1558. }
  1559. SwapchainBuilder& SwapchainBuilder::set_image_usage_flags (VkImageUsageFlags usage_flags) {
  1560. info.image_usage_flags = usage_flags;
  1561. return *this;
  1562. }
  1563. SwapchainBuilder& SwapchainBuilder::add_image_usage_flags (VkImageUsageFlags usage_flags) {
  1564. info.image_usage_flags = info.image_usage_flags | usage_flags;
  1565. return *this;
  1566. }
  1567. SwapchainBuilder& SwapchainBuilder::use_default_image_usage_flags () {
  1568. info.image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  1569. return *this;
  1570. }
  1571. SwapchainBuilder& SwapchainBuilder::set_image_array_layer_count (uint32_t array_layer_count) {
  1572. info.array_layer_count = array_layer_count;
  1573. return *this;
  1574. }
  1575. SwapchainBuilder& SwapchainBuilder::set_clipped (bool clipped) {
  1576. info.clipped = clipped;
  1577. return *this;
  1578. }
  1579. SwapchainBuilder& SwapchainBuilder::set_create_flags (VkSwapchainCreateFlagBitsKHR create_flags) {
  1580. info.create_flags = create_flags;
  1581. return *this;
  1582. }
  1583. SwapchainBuilder& SwapchainBuilder::set_pre_transform_flags (VkSurfaceTransformFlagBitsKHR pre_transform_flags) {
  1584. info.pre_transform = pre_transform_flags;
  1585. return *this;
  1586. }
  1587. SwapchainBuilder& SwapchainBuilder::set_composite_alpha_flags (VkCompositeAlphaFlagBitsKHR composite_alpha_flags) {
  1588. info.composite_alpha = composite_alpha_flags;
  1589. return *this;
  1590. }
  1591. void SwapchainBuilder::add_desired_formats (std::vector<VkSurfaceFormatKHR>& formats) const {
  1592. formats.push_back ({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
  1593. formats.push_back ({ VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
  1594. }
  1595. void SwapchainBuilder::add_desired_present_modes (std::vector<VkPresentModeKHR>& modes) const {
  1596. modes.push_back (VK_PRESENT_MODE_MAILBOX_KHR);
  1597. modes.push_back (VK_PRESENT_MODE_FIFO_KHR);
  1598. }
  1599. } // namespace vkb