wrapper.cpp 29 KB

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