wrapper.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <exception>
  6. #include <memory>
  7. #include <optional>
  8. #include <string_view>
  9. #include <utility>
  10. #include <vector>
  11. #include "common/common_types.h"
  12. #include "video_core/renderer_vulkan/wrapper.h"
  13. namespace Vulkan::vk {
  14. namespace {
  15. template <typename Func>
  16. void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld,
  17. Func&& func) {
  18. // Calling GetProperties calls Vulkan more than needed. But they are supposed to be cheap
  19. // functions.
  20. std::stable_sort(devices.begin(), devices.end(),
  21. [&dld, &func](VkPhysicalDevice lhs, VkPhysicalDevice rhs) {
  22. return func(vk::PhysicalDevice(lhs, dld).GetProperties(),
  23. vk::PhysicalDevice(rhs, dld).GetProperties());
  24. });
  25. }
  26. void SortPhysicalDevicesPerVendor(std::vector<VkPhysicalDevice>& devices,
  27. const InstanceDispatch& dld,
  28. std::initializer_list<u32> vendor_ids) {
  29. for (auto it = vendor_ids.end(); it != vendor_ids.begin();) {
  30. --it;
  31. SortPhysicalDevices(devices, dld, [id = *it](const auto& lhs, const auto& rhs) {
  32. return lhs.vendorID == id && rhs.vendorID != id;
  33. });
  34. }
  35. }
  36. void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) {
  37. // Sort by name, this will set a base and make GPUs with higher numbers appear first
  38. // (e.g. GTX 1650 will intentionally be listed before a GTX 1080).
  39. SortPhysicalDevices(devices, dld, [](const auto& lhs, const auto& rhs) {
  40. return std::string_view{lhs.deviceName} > std::string_view{rhs.deviceName};
  41. });
  42. // Prefer discrete over non-discrete
  43. SortPhysicalDevices(devices, dld, [](const auto& lhs, const auto& rhs) {
  44. return lhs.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&
  45. rhs.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
  46. });
  47. // Prefer Nvidia over AMD, AMD over Intel, Intel over the rest.
  48. SortPhysicalDevicesPerVendor(devices, dld, {0x10DE, 0x1002, 0x8086});
  49. }
  50. template <typename T>
  51. bool Proc(T& result, const InstanceDispatch& dld, const char* proc_name,
  52. VkInstance instance = nullptr) noexcept {
  53. result = reinterpret_cast<T>(dld.vkGetInstanceProcAddr(instance, proc_name));
  54. return result != nullptr;
  55. }
  56. template <typename T>
  57. void Proc(T& result, const DeviceDispatch& dld, const char* proc_name, VkDevice device) noexcept {
  58. result = reinterpret_cast<T>(dld.vkGetDeviceProcAddr(device, proc_name));
  59. }
  60. void Load(VkDevice device, DeviceDispatch& dld) noexcept {
  61. #define X(name) Proc(dld.name, dld, #name, device)
  62. X(vkAcquireNextImageKHR);
  63. X(vkAllocateCommandBuffers);
  64. X(vkAllocateDescriptorSets);
  65. X(vkAllocateMemory);
  66. X(vkBeginCommandBuffer);
  67. X(vkBindBufferMemory);
  68. X(vkBindImageMemory);
  69. X(vkCmdBeginQuery);
  70. X(vkCmdBeginRenderPass);
  71. X(vkCmdBeginTransformFeedbackEXT);
  72. X(vkCmdBindDescriptorSets);
  73. X(vkCmdBindIndexBuffer);
  74. X(vkCmdBindPipeline);
  75. X(vkCmdBindTransformFeedbackBuffersEXT);
  76. X(vkCmdBindVertexBuffers);
  77. X(vkCmdBlitImage);
  78. X(vkCmdClearAttachments);
  79. X(vkCmdCopyBuffer);
  80. X(vkCmdCopyBufferToImage);
  81. X(vkCmdCopyImage);
  82. X(vkCmdCopyImageToBuffer);
  83. X(vkCmdDispatch);
  84. X(vkCmdDraw);
  85. X(vkCmdDrawIndexed);
  86. X(vkCmdEndQuery);
  87. X(vkCmdEndRenderPass);
  88. X(vkCmdEndTransformFeedbackEXT);
  89. X(vkCmdFillBuffer);
  90. X(vkCmdPipelineBarrier);
  91. X(vkCmdPushConstants);
  92. X(vkCmdSetBlendConstants);
  93. X(vkCmdSetDepthBias);
  94. X(vkCmdSetDepthBounds);
  95. X(vkCmdSetEvent);
  96. X(vkCmdSetScissor);
  97. X(vkCmdSetStencilCompareMask);
  98. X(vkCmdSetStencilReference);
  99. X(vkCmdSetStencilWriteMask);
  100. X(vkCmdSetViewport);
  101. X(vkCmdWaitEvents);
  102. X(vkCmdBindVertexBuffers2EXT);
  103. X(vkCmdSetCullModeEXT);
  104. X(vkCmdSetDepthBoundsTestEnableEXT);
  105. X(vkCmdSetDepthCompareOpEXT);
  106. X(vkCmdSetDepthTestEnableEXT);
  107. X(vkCmdSetDepthWriteEnableEXT);
  108. X(vkCmdSetFrontFaceEXT);
  109. X(vkCmdSetPrimitiveTopologyEXT);
  110. X(vkCmdSetStencilOpEXT);
  111. X(vkCmdSetStencilTestEnableEXT);
  112. X(vkCreateBuffer);
  113. X(vkCreateBufferView);
  114. X(vkCreateCommandPool);
  115. X(vkCreateComputePipelines);
  116. X(vkCreateDescriptorPool);
  117. X(vkCreateDescriptorSetLayout);
  118. X(vkCreateDescriptorUpdateTemplateKHR);
  119. X(vkCreateEvent);
  120. X(vkCreateFence);
  121. X(vkCreateFramebuffer);
  122. X(vkCreateGraphicsPipelines);
  123. X(vkCreateImage);
  124. X(vkCreateImageView);
  125. X(vkCreatePipelineLayout);
  126. X(vkCreateQueryPool);
  127. X(vkCreateRenderPass);
  128. X(vkCreateSampler);
  129. X(vkCreateSemaphore);
  130. X(vkCreateShaderModule);
  131. X(vkCreateSwapchainKHR);
  132. X(vkDestroyBuffer);
  133. X(vkDestroyBufferView);
  134. X(vkDestroyCommandPool);
  135. X(vkDestroyDescriptorPool);
  136. X(vkDestroyDescriptorSetLayout);
  137. X(vkDestroyDescriptorUpdateTemplateKHR);
  138. X(vkDestroyEvent);
  139. X(vkDestroyFence);
  140. X(vkDestroyFramebuffer);
  141. X(vkDestroyImage);
  142. X(vkDestroyImageView);
  143. X(vkDestroyPipeline);
  144. X(vkDestroyPipelineLayout);
  145. X(vkDestroyQueryPool);
  146. X(vkDestroyRenderPass);
  147. X(vkDestroySampler);
  148. X(vkDestroySemaphore);
  149. X(vkDestroyShaderModule);
  150. X(vkDestroySwapchainKHR);
  151. X(vkDeviceWaitIdle);
  152. X(vkEndCommandBuffer);
  153. X(vkFreeCommandBuffers);
  154. X(vkFreeDescriptorSets);
  155. X(vkFreeMemory);
  156. X(vkGetBufferMemoryRequirements);
  157. X(vkGetDeviceQueue);
  158. X(vkGetEventStatus);
  159. X(vkGetFenceStatus);
  160. X(vkGetImageMemoryRequirements);
  161. X(vkGetQueryPoolResults);
  162. X(vkGetSemaphoreCounterValueKHR);
  163. X(vkMapMemory);
  164. X(vkQueueSubmit);
  165. X(vkResetFences);
  166. X(vkResetQueryPoolEXT);
  167. X(vkUnmapMemory);
  168. X(vkUpdateDescriptorSetWithTemplateKHR);
  169. X(vkUpdateDescriptorSets);
  170. X(vkWaitForFences);
  171. X(vkWaitSemaphoresKHR);
  172. #undef X
  173. }
  174. } // Anonymous namespace
  175. bool Load(InstanceDispatch& dld) noexcept {
  176. #define X(name) Proc(dld.name, dld, #name)
  177. return X(vkCreateInstance) && X(vkEnumerateInstanceExtensionProperties) &&
  178. X(vkEnumerateInstanceLayerProperties);
  179. #undef X
  180. }
  181. bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
  182. #define X(name) Proc(dld.name, dld, #name, instance)
  183. // These functions may fail to load depending on the enabled extensions.
  184. // Don't return a failure on these.
  185. X(vkCreateDebugUtilsMessengerEXT);
  186. X(vkDestroyDebugUtilsMessengerEXT);
  187. X(vkDestroySurfaceKHR);
  188. X(vkGetPhysicalDeviceFeatures2KHR);
  189. X(vkGetPhysicalDeviceProperties2KHR);
  190. X(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
  191. X(vkGetPhysicalDeviceSurfaceFormatsKHR);
  192. X(vkGetPhysicalDeviceSurfacePresentModesKHR);
  193. X(vkGetPhysicalDeviceSurfaceSupportKHR);
  194. X(vkGetSwapchainImagesKHR);
  195. X(vkQueuePresentKHR);
  196. return X(vkCreateDevice) && X(vkDestroyDevice) && X(vkDestroyDevice) &&
  197. X(vkEnumerateDeviceExtensionProperties) && X(vkEnumeratePhysicalDevices) &&
  198. X(vkGetDeviceProcAddr) && X(vkGetPhysicalDeviceFormatProperties) &&
  199. X(vkGetPhysicalDeviceMemoryProperties) && X(vkGetPhysicalDeviceProperties) &&
  200. X(vkGetPhysicalDeviceQueueFamilyProperties);
  201. #undef X
  202. }
  203. const char* Exception::what() const noexcept {
  204. return ToString(result);
  205. }
  206. const char* ToString(VkResult result) noexcept {
  207. switch (result) {
  208. case VkResult::VK_SUCCESS:
  209. return "VK_SUCCESS";
  210. case VkResult::VK_NOT_READY:
  211. return "VK_NOT_READY";
  212. case VkResult::VK_TIMEOUT:
  213. return "VK_TIMEOUT";
  214. case VkResult::VK_EVENT_SET:
  215. return "VK_EVENT_SET";
  216. case VkResult::VK_EVENT_RESET:
  217. return "VK_EVENT_RESET";
  218. case VkResult::VK_INCOMPLETE:
  219. return "VK_INCOMPLETE";
  220. case VkResult::VK_ERROR_OUT_OF_HOST_MEMORY:
  221. return "VK_ERROR_OUT_OF_HOST_MEMORY";
  222. case VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY:
  223. return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
  224. case VkResult::VK_ERROR_INITIALIZATION_FAILED:
  225. return "VK_ERROR_INITIALIZATION_FAILED";
  226. case VkResult::VK_ERROR_DEVICE_LOST:
  227. return "VK_ERROR_DEVICE_LOST";
  228. case VkResult::VK_ERROR_MEMORY_MAP_FAILED:
  229. return "VK_ERROR_MEMORY_MAP_FAILED";
  230. case VkResult::VK_ERROR_LAYER_NOT_PRESENT:
  231. return "VK_ERROR_LAYER_NOT_PRESENT";
  232. case VkResult::VK_ERROR_EXTENSION_NOT_PRESENT:
  233. return "VK_ERROR_EXTENSION_NOT_PRESENT";
  234. case VkResult::VK_ERROR_FEATURE_NOT_PRESENT:
  235. return "VK_ERROR_FEATURE_NOT_PRESENT";
  236. case VkResult::VK_ERROR_INCOMPATIBLE_DRIVER:
  237. return "VK_ERROR_INCOMPATIBLE_DRIVER";
  238. case VkResult::VK_ERROR_TOO_MANY_OBJECTS:
  239. return "VK_ERROR_TOO_MANY_OBJECTS";
  240. case VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED:
  241. return "VK_ERROR_FORMAT_NOT_SUPPORTED";
  242. case VkResult::VK_ERROR_FRAGMENTED_POOL:
  243. return "VK_ERROR_FRAGMENTED_POOL";
  244. case VkResult::VK_ERROR_OUT_OF_POOL_MEMORY:
  245. return "VK_ERROR_OUT_OF_POOL_MEMORY";
  246. case VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE:
  247. return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
  248. case VkResult::VK_ERROR_SURFACE_LOST_KHR:
  249. return "VK_ERROR_SURFACE_LOST_KHR";
  250. case VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
  251. return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
  252. case VkResult::VK_SUBOPTIMAL_KHR:
  253. return "VK_SUBOPTIMAL_KHR";
  254. case VkResult::VK_ERROR_OUT_OF_DATE_KHR:
  255. return "VK_ERROR_OUT_OF_DATE_KHR";
  256. case VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
  257. return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
  258. case VkResult::VK_ERROR_VALIDATION_FAILED_EXT:
  259. return "VK_ERROR_VALIDATION_FAILED_EXT";
  260. case VkResult::VK_ERROR_INVALID_SHADER_NV:
  261. return "VK_ERROR_INVALID_SHADER_NV";
  262. case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
  263. return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
  264. case VkResult::VK_ERROR_FRAGMENTATION_EXT:
  265. return "VK_ERROR_FRAGMENTATION_EXT";
  266. case VkResult::VK_ERROR_NOT_PERMITTED_EXT:
  267. return "VK_ERROR_NOT_PERMITTED_EXT";
  268. case VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
  269. return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT";
  270. case VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
  271. return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
  272. case VkResult::VK_ERROR_UNKNOWN:
  273. return "VK_ERROR_UNKNOWN";
  274. case VkResult::VK_ERROR_INCOMPATIBLE_VERSION_KHR:
  275. return "VK_ERROR_INCOMPATIBLE_VERSION_KHR";
  276. case VkResult::VK_THREAD_IDLE_KHR:
  277. return "VK_THREAD_IDLE_KHR";
  278. case VkResult::VK_THREAD_DONE_KHR:
  279. return "VK_THREAD_DONE_KHR";
  280. case VkResult::VK_OPERATION_DEFERRED_KHR:
  281. return "VK_OPERATION_DEFERRED_KHR";
  282. case VkResult::VK_OPERATION_NOT_DEFERRED_KHR:
  283. return "VK_OPERATION_NOT_DEFERRED_KHR";
  284. case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT:
  285. return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
  286. case VkResult::VK_RESULT_MAX_ENUM:
  287. return "VK_RESULT_MAX_ENUM";
  288. }
  289. return "Unknown";
  290. }
  291. void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept {
  292. dld.vkDestroyInstance(instance, nullptr);
  293. }
  294. void Destroy(VkDevice device, const InstanceDispatch& dld) noexcept {
  295. dld.vkDestroyDevice(device, nullptr);
  296. }
  297. void Destroy(VkDevice device, VkBuffer handle, const DeviceDispatch& dld) noexcept {
  298. dld.vkDestroyBuffer(device, handle, nullptr);
  299. }
  300. void Destroy(VkDevice device, VkBufferView handle, const DeviceDispatch& dld) noexcept {
  301. dld.vkDestroyBufferView(device, handle, nullptr);
  302. }
  303. void Destroy(VkDevice device, VkCommandPool handle, const DeviceDispatch& dld) noexcept {
  304. dld.vkDestroyCommandPool(device, handle, nullptr);
  305. }
  306. void Destroy(VkDevice device, VkDescriptorPool handle, const DeviceDispatch& dld) noexcept {
  307. dld.vkDestroyDescriptorPool(device, handle, nullptr);
  308. }
  309. void Destroy(VkDevice device, VkDescriptorSetLayout handle, const DeviceDispatch& dld) noexcept {
  310. dld.vkDestroyDescriptorSetLayout(device, handle, nullptr);
  311. }
  312. void Destroy(VkDevice device, VkDescriptorUpdateTemplateKHR handle,
  313. const DeviceDispatch& dld) noexcept {
  314. dld.vkDestroyDescriptorUpdateTemplateKHR(device, handle, nullptr);
  315. }
  316. void Destroy(VkDevice device, VkDeviceMemory handle, const DeviceDispatch& dld) noexcept {
  317. dld.vkFreeMemory(device, handle, nullptr);
  318. }
  319. void Destroy(VkDevice device, VkEvent handle, const DeviceDispatch& dld) noexcept {
  320. dld.vkDestroyEvent(device, handle, nullptr);
  321. }
  322. void Destroy(VkDevice device, VkFence handle, const DeviceDispatch& dld) noexcept {
  323. dld.vkDestroyFence(device, handle, nullptr);
  324. }
  325. void Destroy(VkDevice device, VkFramebuffer handle, const DeviceDispatch& dld) noexcept {
  326. dld.vkDestroyFramebuffer(device, handle, nullptr);
  327. }
  328. void Destroy(VkDevice device, VkImage handle, const DeviceDispatch& dld) noexcept {
  329. dld.vkDestroyImage(device, handle, nullptr);
  330. }
  331. void Destroy(VkDevice device, VkImageView handle, const DeviceDispatch& dld) noexcept {
  332. dld.vkDestroyImageView(device, handle, nullptr);
  333. }
  334. void Destroy(VkDevice device, VkPipeline handle, const DeviceDispatch& dld) noexcept {
  335. dld.vkDestroyPipeline(device, handle, nullptr);
  336. }
  337. void Destroy(VkDevice device, VkPipelineLayout handle, const DeviceDispatch& dld) noexcept {
  338. dld.vkDestroyPipelineLayout(device, handle, nullptr);
  339. }
  340. void Destroy(VkDevice device, VkQueryPool handle, const DeviceDispatch& dld) noexcept {
  341. dld.vkDestroyQueryPool(device, handle, nullptr);
  342. }
  343. void Destroy(VkDevice device, VkRenderPass handle, const DeviceDispatch& dld) noexcept {
  344. dld.vkDestroyRenderPass(device, handle, nullptr);
  345. }
  346. void Destroy(VkDevice device, VkSampler handle, const DeviceDispatch& dld) noexcept {
  347. dld.vkDestroySampler(device, handle, nullptr);
  348. }
  349. void Destroy(VkDevice device, VkSwapchainKHR handle, const DeviceDispatch& dld) noexcept {
  350. dld.vkDestroySwapchainKHR(device, handle, nullptr);
  351. }
  352. void Destroy(VkDevice device, VkSemaphore handle, const DeviceDispatch& dld) noexcept {
  353. dld.vkDestroySemaphore(device, handle, nullptr);
  354. }
  355. void Destroy(VkDevice device, VkShaderModule handle, const DeviceDispatch& dld) noexcept {
  356. dld.vkDestroyShaderModule(device, handle, nullptr);
  357. }
  358. void Destroy(VkInstance instance, VkDebugUtilsMessengerEXT handle,
  359. const InstanceDispatch& dld) noexcept {
  360. dld.vkDestroyDebugUtilsMessengerEXT(instance, handle, nullptr);
  361. }
  362. void Destroy(VkInstance instance, VkSurfaceKHR handle, const InstanceDispatch& dld) noexcept {
  363. dld.vkDestroySurfaceKHR(instance, handle, nullptr);
  364. }
  365. VkResult Free(VkDevice device, VkDescriptorPool handle, Span<VkDescriptorSet> sets,
  366. const DeviceDispatch& dld) noexcept {
  367. return dld.vkFreeDescriptorSets(device, handle, sets.size(), sets.data());
  368. }
  369. VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffers,
  370. const DeviceDispatch& dld) noexcept {
  371. dld.vkFreeCommandBuffers(device, handle, buffers.size(), buffers.data());
  372. return VK_SUCCESS;
  373. }
  374. Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions,
  375. InstanceDispatch& dld) noexcept {
  376. static constexpr VkApplicationInfo application_info{
  377. .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
  378. .pNext = nullptr,
  379. .pApplicationName = "yuzu Emulator",
  380. .applicationVersion = VK_MAKE_VERSION(0, 1, 0),
  381. .pEngineName = "yuzu Emulator",
  382. .engineVersion = VK_MAKE_VERSION(0, 1, 0),
  383. .apiVersion = VK_API_VERSION_1_1,
  384. };
  385. const VkInstanceCreateInfo ci{
  386. .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
  387. .pNext = nullptr,
  388. .flags = 0,
  389. .pApplicationInfo = &application_info,
  390. .enabledLayerCount = layers.size(),
  391. .ppEnabledLayerNames = layers.data(),
  392. .enabledExtensionCount = extensions.size(),
  393. .ppEnabledExtensionNames = extensions.data(),
  394. };
  395. VkInstance instance;
  396. if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) {
  397. // Failed to create the instance.
  398. return {};
  399. }
  400. if (!Proc(dld.vkDestroyInstance, dld, "vkDestroyInstance", instance)) {
  401. // We successfully created an instance but the destroy function couldn't be loaded.
  402. // This is a good moment to panic.
  403. return {};
  404. }
  405. return Instance(instance, dld);
  406. }
  407. std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices() {
  408. u32 num;
  409. if (dld->vkEnumeratePhysicalDevices(handle, &num, nullptr) != VK_SUCCESS) {
  410. return std::nullopt;
  411. }
  412. std::vector<VkPhysicalDevice> physical_devices(num);
  413. if (dld->vkEnumeratePhysicalDevices(handle, &num, physical_devices.data()) != VK_SUCCESS) {
  414. return std::nullopt;
  415. }
  416. SortPhysicalDevices(physical_devices, *dld);
  417. return std::make_optional(std::move(physical_devices));
  418. }
  419. DebugCallback Instance::TryCreateDebugCallback(
  420. PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept {
  421. const VkDebugUtilsMessengerCreateInfoEXT ci{
  422. .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
  423. .pNext = nullptr,
  424. .flags = 0,
  425. .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
  426. VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
  427. VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
  428. VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
  429. .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
  430. VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
  431. VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
  432. .pfnUserCallback = callback,
  433. .pUserData = nullptr,
  434. };
  435. VkDebugUtilsMessengerEXT messenger;
  436. if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) {
  437. return {};
  438. }
  439. return DebugCallback(messenger, handle, *dld);
  440. }
  441. void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const {
  442. Check(dld->vkBindBufferMemory(owner, handle, memory, offset));
  443. }
  444. void Image::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const {
  445. Check(dld->vkBindImageMemory(owner, handle, memory, offset));
  446. }
  447. DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) const {
  448. const std::size_t num = ai.descriptorSetCount;
  449. std::unique_ptr sets = std::make_unique<VkDescriptorSet[]>(num);
  450. switch (const VkResult result = dld->vkAllocateDescriptorSets(owner, &ai, sets.get())) {
  451. case VK_SUCCESS:
  452. return DescriptorSets(std::move(sets), num, owner, handle, *dld);
  453. case VK_ERROR_OUT_OF_POOL_MEMORY:
  454. return {};
  455. default:
  456. throw Exception(result);
  457. }
  458. }
  459. CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const {
  460. const VkCommandBufferAllocateInfo ai{
  461. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
  462. .pNext = nullptr,
  463. .commandPool = handle,
  464. .level = level,
  465. .commandBufferCount = static_cast<u32>(num_buffers),
  466. };
  467. std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers);
  468. switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) {
  469. case VK_SUCCESS:
  470. return CommandBuffers(std::move(buffers), num_buffers, owner, handle, *dld);
  471. case VK_ERROR_OUT_OF_POOL_MEMORY:
  472. return {};
  473. default:
  474. throw Exception(result);
  475. }
  476. }
  477. std::vector<VkImage> SwapchainKHR::GetImages() const {
  478. u32 num;
  479. Check(dld->vkGetSwapchainImagesKHR(owner, handle, &num, nullptr));
  480. std::vector<VkImage> images(num);
  481. Check(dld->vkGetSwapchainImagesKHR(owner, handle, &num, images.data()));
  482. return images;
  483. }
  484. Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
  485. Span<const char*> enabled_extensions, const void* next,
  486. DeviceDispatch& dld) noexcept {
  487. const VkDeviceCreateInfo ci{
  488. .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
  489. .pNext = next,
  490. .flags = 0,
  491. .queueCreateInfoCount = queues_ci.size(),
  492. .pQueueCreateInfos = queues_ci.data(),
  493. .enabledLayerCount = 0,
  494. .ppEnabledLayerNames = nullptr,
  495. .enabledExtensionCount = enabled_extensions.size(),
  496. .ppEnabledExtensionNames = enabled_extensions.data(),
  497. .pEnabledFeatures = nullptr,
  498. };
  499. VkDevice device;
  500. if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) {
  501. return {};
  502. }
  503. Load(device, dld);
  504. return Device(device, dld);
  505. }
  506. Queue Device::GetQueue(u32 family_index) const noexcept {
  507. VkQueue queue;
  508. dld->vkGetDeviceQueue(handle, family_index, 0, &queue);
  509. return Queue(queue, *dld);
  510. }
  511. Buffer Device::CreateBuffer(const VkBufferCreateInfo& ci) const {
  512. VkBuffer object;
  513. Check(dld->vkCreateBuffer(handle, &ci, nullptr, &object));
  514. return Buffer(object, handle, *dld);
  515. }
  516. BufferView Device::CreateBufferView(const VkBufferViewCreateInfo& ci) const {
  517. VkBufferView object;
  518. Check(dld->vkCreateBufferView(handle, &ci, nullptr, &object));
  519. return BufferView(object, handle, *dld);
  520. }
  521. Image Device::CreateImage(const VkImageCreateInfo& ci) const {
  522. VkImage object;
  523. Check(dld->vkCreateImage(handle, &ci, nullptr, &object));
  524. return Image(object, handle, *dld);
  525. }
  526. ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const {
  527. VkImageView object;
  528. Check(dld->vkCreateImageView(handle, &ci, nullptr, &object));
  529. return ImageView(object, handle, *dld);
  530. }
  531. Semaphore Device::CreateSemaphore() const {
  532. static constexpr VkSemaphoreCreateInfo ci{
  533. .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
  534. .pNext = nullptr,
  535. .flags = 0,
  536. };
  537. return CreateSemaphore(ci);
  538. }
  539. Semaphore Device::CreateSemaphore(const VkSemaphoreCreateInfo& ci) const {
  540. VkSemaphore object;
  541. Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object));
  542. return Semaphore(object, handle, *dld);
  543. }
  544. Fence Device::CreateFence(const VkFenceCreateInfo& ci) const {
  545. VkFence object;
  546. Check(dld->vkCreateFence(handle, &ci, nullptr, &object));
  547. return Fence(object, handle, *dld);
  548. }
  549. DescriptorPool Device::CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const {
  550. VkDescriptorPool object;
  551. Check(dld->vkCreateDescriptorPool(handle, &ci, nullptr, &object));
  552. return DescriptorPool(object, handle, *dld);
  553. }
  554. RenderPass Device::CreateRenderPass(const VkRenderPassCreateInfo& ci) const {
  555. VkRenderPass object;
  556. Check(dld->vkCreateRenderPass(handle, &ci, nullptr, &object));
  557. return RenderPass(object, handle, *dld);
  558. }
  559. DescriptorSetLayout Device::CreateDescriptorSetLayout(
  560. const VkDescriptorSetLayoutCreateInfo& ci) const {
  561. VkDescriptorSetLayout object;
  562. Check(dld->vkCreateDescriptorSetLayout(handle, &ci, nullptr, &object));
  563. return DescriptorSetLayout(object, handle, *dld);
  564. }
  565. PipelineLayout Device::CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const {
  566. VkPipelineLayout object;
  567. Check(dld->vkCreatePipelineLayout(handle, &ci, nullptr, &object));
  568. return PipelineLayout(object, handle, *dld);
  569. }
  570. Pipeline Device::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci) const {
  571. VkPipeline object;
  572. Check(dld->vkCreateGraphicsPipelines(handle, nullptr, 1, &ci, nullptr, &object));
  573. return Pipeline(object, handle, *dld);
  574. }
  575. Pipeline Device::CreateComputePipeline(const VkComputePipelineCreateInfo& ci) const {
  576. VkPipeline object;
  577. Check(dld->vkCreateComputePipelines(handle, nullptr, 1, &ci, nullptr, &object));
  578. return Pipeline(object, handle, *dld);
  579. }
  580. Sampler Device::CreateSampler(const VkSamplerCreateInfo& ci) const {
  581. VkSampler object;
  582. Check(dld->vkCreateSampler(handle, &ci, nullptr, &object));
  583. return Sampler(object, handle, *dld);
  584. }
  585. Framebuffer Device::CreateFramebuffer(const VkFramebufferCreateInfo& ci) const {
  586. VkFramebuffer object;
  587. Check(dld->vkCreateFramebuffer(handle, &ci, nullptr, &object));
  588. return Framebuffer(object, handle, *dld);
  589. }
  590. CommandPool Device::CreateCommandPool(const VkCommandPoolCreateInfo& ci) const {
  591. VkCommandPool object;
  592. Check(dld->vkCreateCommandPool(handle, &ci, nullptr, &object));
  593. return CommandPool(object, handle, *dld);
  594. }
  595. DescriptorUpdateTemplateKHR Device::CreateDescriptorUpdateTemplateKHR(
  596. const VkDescriptorUpdateTemplateCreateInfoKHR& ci) const {
  597. VkDescriptorUpdateTemplateKHR object;
  598. Check(dld->vkCreateDescriptorUpdateTemplateKHR(handle, &ci, nullptr, &object));
  599. return DescriptorUpdateTemplateKHR(object, handle, *dld);
  600. }
  601. QueryPool Device::CreateQueryPool(const VkQueryPoolCreateInfo& ci) const {
  602. VkQueryPool object;
  603. Check(dld->vkCreateQueryPool(handle, &ci, nullptr, &object));
  604. return QueryPool(object, handle, *dld);
  605. }
  606. ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) const {
  607. VkShaderModule object;
  608. Check(dld->vkCreateShaderModule(handle, &ci, nullptr, &object));
  609. return ShaderModule(object, handle, *dld);
  610. }
  611. Event Device::CreateEvent() const {
  612. static constexpr VkEventCreateInfo ci{
  613. .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
  614. .pNext = nullptr,
  615. .flags = 0,
  616. };
  617. VkEvent object;
  618. Check(dld->vkCreateEvent(handle, &ci, nullptr, &object));
  619. return Event(object, handle, *dld);
  620. }
  621. SwapchainKHR Device::CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const {
  622. VkSwapchainKHR object;
  623. Check(dld->vkCreateSwapchainKHR(handle, &ci, nullptr, &object));
  624. return SwapchainKHR(object, handle, *dld);
  625. }
  626. DeviceMemory Device::TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept {
  627. VkDeviceMemory memory;
  628. if (dld->vkAllocateMemory(handle, &ai, nullptr, &memory) != VK_SUCCESS) {
  629. return {};
  630. }
  631. return DeviceMemory(memory, handle, *dld);
  632. }
  633. DeviceMemory Device::AllocateMemory(const VkMemoryAllocateInfo& ai) const {
  634. VkDeviceMemory memory;
  635. Check(dld->vkAllocateMemory(handle, &ai, nullptr, &memory));
  636. return DeviceMemory(memory, handle, *dld);
  637. }
  638. VkMemoryRequirements Device::GetBufferMemoryRequirements(VkBuffer buffer) const noexcept {
  639. VkMemoryRequirements requirements;
  640. dld->vkGetBufferMemoryRequirements(handle, buffer, &requirements);
  641. return requirements;
  642. }
  643. VkMemoryRequirements Device::GetImageMemoryRequirements(VkImage image) const noexcept {
  644. VkMemoryRequirements requirements;
  645. dld->vkGetImageMemoryRequirements(handle, image, &requirements);
  646. return requirements;
  647. }
  648. void Device::UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes,
  649. Span<VkCopyDescriptorSet> copies) const noexcept {
  650. dld->vkUpdateDescriptorSets(handle, writes.size(), writes.data(), copies.size(), copies.data());
  651. }
  652. VkPhysicalDeviceProperties PhysicalDevice::GetProperties() const noexcept {
  653. VkPhysicalDeviceProperties properties;
  654. dld->vkGetPhysicalDeviceProperties(physical_device, &properties);
  655. return properties;
  656. }
  657. void PhysicalDevice::GetProperties2KHR(VkPhysicalDeviceProperties2KHR& properties) const noexcept {
  658. dld->vkGetPhysicalDeviceProperties2KHR(physical_device, &properties);
  659. }
  660. VkPhysicalDeviceFeatures PhysicalDevice::GetFeatures() const noexcept {
  661. VkPhysicalDeviceFeatures2KHR features2;
  662. features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
  663. features2.pNext = nullptr;
  664. dld->vkGetPhysicalDeviceFeatures2KHR(physical_device, &features2);
  665. return features2.features;
  666. }
  667. void PhysicalDevice::GetFeatures2KHR(VkPhysicalDeviceFeatures2KHR& features) const noexcept {
  668. dld->vkGetPhysicalDeviceFeatures2KHR(physical_device, &features);
  669. }
  670. VkFormatProperties PhysicalDevice::GetFormatProperties(VkFormat format) const noexcept {
  671. VkFormatProperties properties;
  672. dld->vkGetPhysicalDeviceFormatProperties(physical_device, format, &properties);
  673. return properties;
  674. }
  675. std::vector<VkExtensionProperties> PhysicalDevice::EnumerateDeviceExtensionProperties() const {
  676. u32 num;
  677. dld->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &num, nullptr);
  678. std::vector<VkExtensionProperties> properties(num);
  679. dld->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &num, properties.data());
  680. return properties;
  681. }
  682. std::vector<VkQueueFamilyProperties> PhysicalDevice::GetQueueFamilyProperties() const {
  683. u32 num;
  684. dld->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &num, nullptr);
  685. std::vector<VkQueueFamilyProperties> properties(num);
  686. dld->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &num, properties.data());
  687. return properties;
  688. }
  689. bool PhysicalDevice::GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR surface) const {
  690. VkBool32 supported;
  691. Check(dld->vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_index, surface,
  692. &supported));
  693. return supported == VK_TRUE;
  694. }
  695. VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const {
  696. VkSurfaceCapabilitiesKHR capabilities;
  697. Check(dld->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &capabilities));
  698. return capabilities;
  699. }
  700. std::vector<VkSurfaceFormatKHR> PhysicalDevice::GetSurfaceFormatsKHR(VkSurfaceKHR surface) const {
  701. u32 num;
  702. Check(dld->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &num, nullptr));
  703. std::vector<VkSurfaceFormatKHR> formats(num);
  704. Check(
  705. dld->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &num, formats.data()));
  706. return formats;
  707. }
  708. std::vector<VkPresentModeKHR> PhysicalDevice::GetSurfacePresentModesKHR(
  709. VkSurfaceKHR surface) const {
  710. u32 num;
  711. Check(dld->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &num, nullptr));
  712. std::vector<VkPresentModeKHR> modes(num);
  713. Check(dld->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &num,
  714. modes.data()));
  715. return modes;
  716. }
  717. VkPhysicalDeviceMemoryProperties PhysicalDevice::GetMemoryProperties() const noexcept {
  718. VkPhysicalDeviceMemoryProperties properties;
  719. dld->vkGetPhysicalDeviceMemoryProperties(physical_device, &properties);
  720. return properties;
  721. }
  722. std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
  723. const InstanceDispatch& dld) {
  724. u32 num;
  725. if (dld.vkEnumerateInstanceExtensionProperties(nullptr, &num, nullptr) != VK_SUCCESS) {
  726. return std::nullopt;
  727. }
  728. std::vector<VkExtensionProperties> properties(num);
  729. if (dld.vkEnumerateInstanceExtensionProperties(nullptr, &num, properties.data()) !=
  730. VK_SUCCESS) {
  731. return std::nullopt;
  732. }
  733. return std::move(properties);
  734. }
  735. std::optional<std::vector<VkLayerProperties>> EnumerateInstanceLayerProperties(
  736. const InstanceDispatch& dld) {
  737. u32 num;
  738. if (dld.vkEnumerateInstanceLayerProperties(&num, nullptr) != VK_SUCCESS) {
  739. return std::nullopt;
  740. }
  741. std::vector<VkLayerProperties> properties(num);
  742. if (dld.vkEnumerateInstanceLayerProperties(&num, properties.data()) != VK_SUCCESS) {
  743. return std::nullopt;
  744. }
  745. return properties;
  746. }
  747. } // namespace Vulkan::vk