vulkan_wrapper.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <memory>
  5. #include <optional>
  6. #include <utility>
  7. #include <vector>
  8. #include "common/common_types.h"
  9. #include "common/logging/log.h"
  10. #include "video_core/vulkan_common/vulkan_wrapper.h"
  11. namespace Vulkan::vk {
  12. namespace {
  13. template <typename Func>
  14. void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld,
  15. Func&& func) {
  16. // Calling GetProperties calls Vulkan more than needed. But they are supposed to be cheap
  17. // functions.
  18. std::stable_sort(devices.begin(), devices.end(),
  19. [&dld, &func](VkPhysicalDevice lhs, VkPhysicalDevice rhs) {
  20. return func(vk::PhysicalDevice(lhs, dld).GetProperties(),
  21. vk::PhysicalDevice(rhs, dld).GetProperties());
  22. });
  23. }
  24. void SortPhysicalDevicesPerVendor(std::vector<VkPhysicalDevice>& devices,
  25. const InstanceDispatch& dld,
  26. std::initializer_list<u32> vendor_ids) {
  27. for (auto it = vendor_ids.end(); it != vendor_ids.begin();) {
  28. --it;
  29. SortPhysicalDevices(devices, dld, [id = *it](const auto& lhs, const auto& rhs) {
  30. return lhs.vendorID == id && rhs.vendorID != id;
  31. });
  32. }
  33. }
  34. void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) {
  35. // Sort by name, this will set a base and make GPUs with higher numbers appear first
  36. // (e.g. GTX 1650 will intentionally be listed before a GTX 1080).
  37. SortPhysicalDevices(devices, dld, [](const auto& lhs, const auto& rhs) {
  38. return std::string_view{lhs.deviceName} > std::string_view{rhs.deviceName};
  39. });
  40. // Prefer discrete over non-discrete
  41. SortPhysicalDevices(devices, dld, [](const auto& lhs, const auto& rhs) {
  42. return lhs.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&
  43. rhs.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
  44. });
  45. // Prefer Nvidia over AMD, AMD over Intel, Intel over the rest.
  46. SortPhysicalDevicesPerVendor(devices, dld, {0x10DE, 0x1002, 0x8086});
  47. }
  48. template <typename T>
  49. bool Proc(T& result, const InstanceDispatch& dld, const char* proc_name,
  50. VkInstance instance = nullptr) noexcept {
  51. result = reinterpret_cast<T>(dld.vkGetInstanceProcAddr(instance, proc_name));
  52. return result != nullptr;
  53. }
  54. template <typename T>
  55. void Proc(T& result, const DeviceDispatch& dld, const char* proc_name, VkDevice device) noexcept {
  56. result = reinterpret_cast<T>(dld.vkGetDeviceProcAddr(device, proc_name));
  57. }
  58. void Load(VkDevice device, DeviceDispatch& dld) noexcept {
  59. #define X(name) Proc(dld.name, dld, #name, device)
  60. X(vkAcquireNextImageKHR);
  61. X(vkAllocateCommandBuffers);
  62. X(vkAllocateDescriptorSets);
  63. X(vkAllocateMemory);
  64. X(vkBeginCommandBuffer);
  65. X(vkBindBufferMemory);
  66. X(vkBindImageMemory);
  67. X(vkCmdBeginQuery);
  68. X(vkCmdBeginRenderPass);
  69. X(vkCmdBeginTransformFeedbackEXT);
  70. X(vkCmdBeginDebugUtilsLabelEXT);
  71. X(vkCmdBindDescriptorSets);
  72. X(vkCmdBindIndexBuffer);
  73. X(vkCmdBindPipeline);
  74. X(vkCmdBindTransformFeedbackBuffersEXT);
  75. X(vkCmdBindVertexBuffers);
  76. X(vkCmdBlitImage);
  77. X(vkCmdClearAttachments);
  78. X(vkCmdClearColorImage);
  79. X(vkCmdCopyBuffer);
  80. X(vkCmdCopyBufferToImage);
  81. X(vkCmdCopyImage);
  82. X(vkCmdCopyImageToBuffer);
  83. X(vkCmdDispatch);
  84. X(vkCmdDraw);
  85. X(vkCmdDrawIndexed);
  86. X(vkCmdDrawIndirect);
  87. X(vkCmdDrawIndexedIndirect);
  88. X(vkCmdDrawIndirectCount);
  89. X(vkCmdDrawIndexedIndirectCount);
  90. X(vkCmdEndQuery);
  91. X(vkCmdEndRenderPass);
  92. X(vkCmdEndTransformFeedbackEXT);
  93. X(vkCmdEndDebugUtilsLabelEXT);
  94. X(vkCmdFillBuffer);
  95. X(vkCmdPipelineBarrier);
  96. X(vkCmdPushConstants);
  97. X(vkCmdPushDescriptorSetWithTemplateKHR);
  98. X(vkCmdSetBlendConstants);
  99. X(vkCmdSetDepthBias);
  100. X(vkCmdSetDepthBounds);
  101. X(vkCmdSetEvent);
  102. X(vkCmdSetScissor);
  103. X(vkCmdSetStencilCompareMask);
  104. X(vkCmdSetStencilReference);
  105. X(vkCmdSetStencilWriteMask);
  106. X(vkCmdSetViewport);
  107. X(vkCmdWaitEvents);
  108. X(vkCmdBindVertexBuffers2EXT);
  109. X(vkCmdSetCullModeEXT);
  110. X(vkCmdSetDepthBoundsTestEnableEXT);
  111. X(vkCmdSetDepthCompareOpEXT);
  112. X(vkCmdSetDepthTestEnableEXT);
  113. X(vkCmdSetDepthWriteEnableEXT);
  114. X(vkCmdSetPrimitiveRestartEnableEXT);
  115. X(vkCmdSetRasterizerDiscardEnableEXT);
  116. X(vkCmdSetDepthBiasEnableEXT);
  117. X(vkCmdSetLogicOpEnableEXT);
  118. X(vkCmdSetDepthClampEnableEXT);
  119. X(vkCmdSetFrontFaceEXT);
  120. X(vkCmdSetLogicOpEXT);
  121. X(vkCmdSetPatchControlPointsEXT);
  122. X(vkCmdSetLineWidth);
  123. X(vkCmdSetPrimitiveTopologyEXT);
  124. X(vkCmdSetStencilOpEXT);
  125. X(vkCmdSetStencilTestEnableEXT);
  126. X(vkCmdSetVertexInputEXT);
  127. X(vkCmdSetColorWriteMaskEXT);
  128. X(vkCmdSetColorBlendEnableEXT);
  129. X(vkCmdSetColorBlendEquationEXT);
  130. X(vkCmdResolveImage);
  131. X(vkCreateBuffer);
  132. X(vkCreateBufferView);
  133. X(vkCreateCommandPool);
  134. X(vkCreateComputePipelines);
  135. X(vkCreateDescriptorPool);
  136. X(vkCreateDescriptorSetLayout);
  137. X(vkCreateDescriptorUpdateTemplate);
  138. X(vkCreateEvent);
  139. X(vkCreateFence);
  140. X(vkCreateFramebuffer);
  141. X(vkCreateGraphicsPipelines);
  142. X(vkCreateImage);
  143. X(vkCreateImageView);
  144. X(vkCreatePipelineCache);
  145. X(vkCreatePipelineLayout);
  146. X(vkCreateQueryPool);
  147. X(vkCreateRenderPass);
  148. X(vkCreateSampler);
  149. X(vkCreateSemaphore);
  150. X(vkCreateShaderModule);
  151. X(vkCreateSwapchainKHR);
  152. X(vkDestroyBuffer);
  153. X(vkDestroyBufferView);
  154. X(vkDestroyCommandPool);
  155. X(vkDestroyDescriptorPool);
  156. X(vkDestroyDescriptorSetLayout);
  157. X(vkDestroyDescriptorUpdateTemplate);
  158. X(vkDestroyEvent);
  159. X(vkDestroyFence);
  160. X(vkDestroyFramebuffer);
  161. X(vkDestroyImage);
  162. X(vkDestroyImageView);
  163. X(vkDestroyPipeline);
  164. X(vkDestroyPipelineCache);
  165. X(vkDestroyPipelineLayout);
  166. X(vkDestroyQueryPool);
  167. X(vkDestroyRenderPass);
  168. X(vkDestroySampler);
  169. X(vkDestroySemaphore);
  170. X(vkDestroyShaderModule);
  171. X(vkDestroySwapchainKHR);
  172. X(vkDeviceWaitIdle);
  173. X(vkEndCommandBuffer);
  174. X(vkFreeCommandBuffers);
  175. X(vkFreeDescriptorSets);
  176. X(vkFreeMemory);
  177. X(vkGetBufferMemoryRequirements2);
  178. X(vkGetDeviceQueue);
  179. X(vkGetEventStatus);
  180. X(vkGetFenceStatus);
  181. X(vkGetImageMemoryRequirements);
  182. X(vkGetPipelineCacheData);
  183. X(vkGetMemoryFdKHR);
  184. #ifdef _WIN32
  185. X(vkGetMemoryWin32HandleKHR);
  186. #endif
  187. X(vkGetQueryPoolResults);
  188. X(vkGetPipelineExecutablePropertiesKHR);
  189. X(vkGetPipelineExecutableStatisticsKHR);
  190. X(vkGetSemaphoreCounterValue);
  191. X(vkMapMemory);
  192. X(vkQueueSubmit);
  193. X(vkResetFences);
  194. X(vkResetQueryPool);
  195. X(vkSetDebugUtilsObjectNameEXT);
  196. X(vkSetDebugUtilsObjectTagEXT);
  197. X(vkUnmapMemory);
  198. X(vkUpdateDescriptorSetWithTemplate);
  199. X(vkUpdateDescriptorSets);
  200. X(vkWaitForFences);
  201. X(vkWaitSemaphores);
  202. // Support for timeline semaphores is mandatory in Vulkan 1.2
  203. if (!dld.vkGetSemaphoreCounterValue) {
  204. Proc(dld.vkGetSemaphoreCounterValue, dld, "vkGetSemaphoreCounterValueKHR", device);
  205. Proc(dld.vkWaitSemaphores, dld, "vkWaitSemaphoresKHR", device);
  206. }
  207. // Support for host query reset is mandatory in Vulkan 1.2
  208. if (!dld.vkResetQueryPool) {
  209. Proc(dld.vkResetQueryPool, dld, "vkResetQueryPoolEXT", device);
  210. }
  211. // Support for draw indirect with count is optional in Vulkan 1.2
  212. if (!dld.vkCmdDrawIndirectCount) {
  213. Proc(dld.vkCmdDrawIndirectCount, dld, "vkCmdDrawIndirectCountKHR", device);
  214. Proc(dld.vkCmdDrawIndexedIndirectCount, dld, "vkCmdDrawIndexedIndirectCountKHR", device);
  215. }
  216. #undef X
  217. }
  218. template <typename T>
  219. void SetObjectName(const DeviceDispatch* dld, VkDevice device, T handle, VkObjectType type,
  220. const char* name) {
  221. const VkDebugUtilsObjectNameInfoEXT name_info{
  222. .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
  223. .pNext = nullptr,
  224. .objectType = type,
  225. .objectHandle = reinterpret_cast<u64>(handle),
  226. .pObjectName = name,
  227. };
  228. Check(dld->vkSetDebugUtilsObjectNameEXT(device, &name_info));
  229. }
  230. } // Anonymous namespace
  231. bool Load(InstanceDispatch& dld) noexcept {
  232. #define X(name) Proc(dld.name, dld, #name)
  233. return X(vkCreateInstance) && X(vkEnumerateInstanceExtensionProperties) &&
  234. X(vkEnumerateInstanceLayerProperties);
  235. #undef X
  236. }
  237. bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
  238. #define X(name) Proc(dld.name, dld, #name, instance)
  239. // These functions may fail to load depending on the enabled extensions.
  240. // Don't return a failure on these.
  241. X(vkCreateDebugUtilsMessengerEXT);
  242. X(vkDestroyDebugUtilsMessengerEXT);
  243. X(vkDestroySurfaceKHR);
  244. X(vkGetPhysicalDeviceFeatures2);
  245. X(vkGetPhysicalDeviceProperties2);
  246. X(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
  247. X(vkGetPhysicalDeviceSurfaceFormatsKHR);
  248. X(vkGetPhysicalDeviceSurfacePresentModesKHR);
  249. X(vkGetPhysicalDeviceSurfaceSupportKHR);
  250. X(vkGetPhysicalDeviceToolProperties);
  251. X(vkGetSwapchainImagesKHR);
  252. X(vkQueuePresentKHR);
  253. return X(vkCreateDevice) && X(vkDestroyDevice) && X(vkDestroyDevice) &&
  254. X(vkEnumerateDeviceExtensionProperties) && X(vkEnumeratePhysicalDevices) &&
  255. X(vkGetDeviceProcAddr) && X(vkGetPhysicalDeviceFormatProperties) &&
  256. X(vkGetPhysicalDeviceMemoryProperties) && X(vkGetPhysicalDeviceMemoryProperties2) &&
  257. X(vkGetPhysicalDeviceProperties) && X(vkGetPhysicalDeviceQueueFamilyProperties);
  258. #undef X
  259. }
  260. const char* Exception::what() const noexcept {
  261. return ToString(result);
  262. }
  263. const char* ToString(VkResult result) noexcept {
  264. switch (result) {
  265. case VkResult::VK_SUCCESS:
  266. return "VK_SUCCESS";
  267. case VkResult::VK_NOT_READY:
  268. return "VK_NOT_READY";
  269. case VkResult::VK_TIMEOUT:
  270. return "VK_TIMEOUT";
  271. case VkResult::VK_EVENT_SET:
  272. return "VK_EVENT_SET";
  273. case VkResult::VK_EVENT_RESET:
  274. return "VK_EVENT_RESET";
  275. case VkResult::VK_INCOMPLETE:
  276. return "VK_INCOMPLETE";
  277. case VkResult::VK_ERROR_OUT_OF_HOST_MEMORY:
  278. return "VK_ERROR_OUT_OF_HOST_MEMORY";
  279. case VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY:
  280. return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
  281. case VkResult::VK_ERROR_INITIALIZATION_FAILED:
  282. return "VK_ERROR_INITIALIZATION_FAILED";
  283. case VkResult::VK_ERROR_DEVICE_LOST:
  284. return "VK_ERROR_DEVICE_LOST";
  285. case VkResult::VK_ERROR_MEMORY_MAP_FAILED:
  286. return "VK_ERROR_MEMORY_MAP_FAILED";
  287. case VkResult::VK_ERROR_LAYER_NOT_PRESENT:
  288. return "VK_ERROR_LAYER_NOT_PRESENT";
  289. case VkResult::VK_ERROR_EXTENSION_NOT_PRESENT:
  290. return "VK_ERROR_EXTENSION_NOT_PRESENT";
  291. case VkResult::VK_ERROR_FEATURE_NOT_PRESENT:
  292. return "VK_ERROR_FEATURE_NOT_PRESENT";
  293. case VkResult::VK_ERROR_INCOMPATIBLE_DRIVER:
  294. return "VK_ERROR_INCOMPATIBLE_DRIVER";
  295. case VkResult::VK_ERROR_TOO_MANY_OBJECTS:
  296. return "VK_ERROR_TOO_MANY_OBJECTS";
  297. case VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED:
  298. return "VK_ERROR_FORMAT_NOT_SUPPORTED";
  299. case VkResult::VK_ERROR_FRAGMENTED_POOL:
  300. return "VK_ERROR_FRAGMENTED_POOL";
  301. case VkResult::VK_ERROR_OUT_OF_POOL_MEMORY:
  302. return "VK_ERROR_OUT_OF_POOL_MEMORY";
  303. case VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE:
  304. return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
  305. case VkResult::VK_ERROR_SURFACE_LOST_KHR:
  306. return "VK_ERROR_SURFACE_LOST_KHR";
  307. case VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
  308. return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
  309. case VkResult::VK_SUBOPTIMAL_KHR:
  310. return "VK_SUBOPTIMAL_KHR";
  311. case VkResult::VK_ERROR_OUT_OF_DATE_KHR:
  312. return "VK_ERROR_OUT_OF_DATE_KHR";
  313. case VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
  314. return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
  315. case VkResult::VK_ERROR_VALIDATION_FAILED_EXT:
  316. return "VK_ERROR_VALIDATION_FAILED_EXT";
  317. case VkResult::VK_ERROR_INVALID_SHADER_NV:
  318. return "VK_ERROR_INVALID_SHADER_NV";
  319. case VkResult::VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR:
  320. return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR";
  321. case VkResult::VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR:
  322. return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR";
  323. case VkResult::VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR:
  324. return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR";
  325. case VkResult::VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR:
  326. return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR";
  327. case VkResult::VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR:
  328. return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR";
  329. case VkResult::VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR:
  330. return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR";
  331. case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
  332. return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
  333. case VkResult::VK_ERROR_FRAGMENTATION_EXT:
  334. return "VK_ERROR_FRAGMENTATION_EXT";
  335. case VkResult::VK_ERROR_NOT_PERMITTED_EXT:
  336. return "VK_ERROR_NOT_PERMITTED_EXT";
  337. case VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
  338. return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT";
  339. case VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
  340. return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
  341. case VkResult::VK_ERROR_UNKNOWN:
  342. return "VK_ERROR_UNKNOWN";
  343. case VkResult::VK_THREAD_IDLE_KHR:
  344. return "VK_THREAD_IDLE_KHR";
  345. case VkResult::VK_THREAD_DONE_KHR:
  346. return "VK_THREAD_DONE_KHR";
  347. case VkResult::VK_OPERATION_DEFERRED_KHR:
  348. return "VK_OPERATION_DEFERRED_KHR";
  349. case VkResult::VK_OPERATION_NOT_DEFERRED_KHR:
  350. return "VK_OPERATION_NOT_DEFERRED_KHR";
  351. case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT:
  352. return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
  353. case VkResult::VK_RESULT_MAX_ENUM:
  354. return "VK_RESULT_MAX_ENUM";
  355. case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT:
  356. return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
  357. }
  358. return "Unknown";
  359. }
  360. void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept {
  361. dld.vkDestroyInstance(instance, nullptr);
  362. }
  363. void Destroy(VkDevice device, const InstanceDispatch& dld) noexcept {
  364. dld.vkDestroyDevice(device, nullptr);
  365. }
  366. void Destroy(VkDevice device, VkBuffer handle, const DeviceDispatch& dld) noexcept {
  367. dld.vkDestroyBuffer(device, handle, nullptr);
  368. }
  369. void Destroy(VkDevice device, VkBufferView handle, const DeviceDispatch& dld) noexcept {
  370. dld.vkDestroyBufferView(device, handle, nullptr);
  371. }
  372. void Destroy(VkDevice device, VkCommandPool handle, const DeviceDispatch& dld) noexcept {
  373. dld.vkDestroyCommandPool(device, handle, nullptr);
  374. }
  375. void Destroy(VkDevice device, VkDescriptorPool handle, const DeviceDispatch& dld) noexcept {
  376. dld.vkDestroyDescriptorPool(device, handle, nullptr);
  377. }
  378. void Destroy(VkDevice device, VkDescriptorSetLayout handle, const DeviceDispatch& dld) noexcept {
  379. dld.vkDestroyDescriptorSetLayout(device, handle, nullptr);
  380. }
  381. void Destroy(VkDevice device, VkDescriptorUpdateTemplate handle,
  382. const DeviceDispatch& dld) noexcept {
  383. dld.vkDestroyDescriptorUpdateTemplate(device, handle, nullptr);
  384. }
  385. void Destroy(VkDevice device, VkDeviceMemory handle, const DeviceDispatch& dld) noexcept {
  386. dld.vkFreeMemory(device, handle, nullptr);
  387. }
  388. void Destroy(VkDevice device, VkEvent handle, const DeviceDispatch& dld) noexcept {
  389. dld.vkDestroyEvent(device, handle, nullptr);
  390. }
  391. void Destroy(VkDevice device, VkFence handle, const DeviceDispatch& dld) noexcept {
  392. dld.vkDestroyFence(device, handle, nullptr);
  393. }
  394. void Destroy(VkDevice device, VkFramebuffer handle, const DeviceDispatch& dld) noexcept {
  395. dld.vkDestroyFramebuffer(device, handle, nullptr);
  396. }
  397. void Destroy(VkDevice device, VkImage handle, const DeviceDispatch& dld) noexcept {
  398. dld.vkDestroyImage(device, handle, nullptr);
  399. }
  400. void Destroy(VkDevice device, VkImageView handle, const DeviceDispatch& dld) noexcept {
  401. dld.vkDestroyImageView(device, handle, nullptr);
  402. }
  403. void Destroy(VkDevice device, VkPipeline handle, const DeviceDispatch& dld) noexcept {
  404. dld.vkDestroyPipeline(device, handle, nullptr);
  405. }
  406. void Destroy(VkDevice device, VkPipelineCache handle, const DeviceDispatch& dld) noexcept {
  407. dld.vkDestroyPipelineCache(device, handle, nullptr);
  408. }
  409. void Destroy(VkDevice device, VkPipelineLayout handle, const DeviceDispatch& dld) noexcept {
  410. dld.vkDestroyPipelineLayout(device, handle, nullptr);
  411. }
  412. void Destroy(VkDevice device, VkQueryPool handle, const DeviceDispatch& dld) noexcept {
  413. dld.vkDestroyQueryPool(device, handle, nullptr);
  414. }
  415. void Destroy(VkDevice device, VkRenderPass handle, const DeviceDispatch& dld) noexcept {
  416. dld.vkDestroyRenderPass(device, handle, nullptr);
  417. }
  418. void Destroy(VkDevice device, VkSampler handle, const DeviceDispatch& dld) noexcept {
  419. dld.vkDestroySampler(device, handle, nullptr);
  420. }
  421. void Destroy(VkDevice device, VkSwapchainKHR handle, const DeviceDispatch& dld) noexcept {
  422. dld.vkDestroySwapchainKHR(device, handle, nullptr);
  423. }
  424. void Destroy(VkDevice device, VkSemaphore handle, const DeviceDispatch& dld) noexcept {
  425. dld.vkDestroySemaphore(device, handle, nullptr);
  426. }
  427. void Destroy(VkDevice device, VkShaderModule handle, const DeviceDispatch& dld) noexcept {
  428. dld.vkDestroyShaderModule(device, handle, nullptr);
  429. }
  430. void Destroy(VkInstance instance, VkDebugUtilsMessengerEXT handle,
  431. const InstanceDispatch& dld) noexcept {
  432. dld.vkDestroyDebugUtilsMessengerEXT(instance, handle, nullptr);
  433. }
  434. void Destroy(VkInstance instance, VkSurfaceKHR handle, const InstanceDispatch& dld) noexcept {
  435. dld.vkDestroySurfaceKHR(instance, handle, nullptr);
  436. }
  437. VkResult Free(VkDevice device, VkDescriptorPool handle, Span<VkDescriptorSet> sets,
  438. const DeviceDispatch& dld) noexcept {
  439. return dld.vkFreeDescriptorSets(device, handle, sets.size(), sets.data());
  440. }
  441. VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffers,
  442. const DeviceDispatch& dld) noexcept {
  443. dld.vkFreeCommandBuffers(device, handle, buffers.size(), buffers.data());
  444. return VK_SUCCESS;
  445. }
  446. Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
  447. InstanceDispatch& dispatch) {
  448. #ifdef __APPLE__
  449. constexpr VkFlags ci_flags{VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR};
  450. #else
  451. constexpr VkFlags ci_flags{};
  452. #endif
  453. const VkApplicationInfo application_info{
  454. .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
  455. .pNext = nullptr,
  456. .pApplicationName = "yuzu Emulator",
  457. .applicationVersion = VK_MAKE_VERSION(0, 1, 0),
  458. .pEngineName = "yuzu Emulator",
  459. .engineVersion = VK_MAKE_VERSION(0, 1, 0),
  460. .apiVersion = version,
  461. };
  462. const VkInstanceCreateInfo ci{
  463. .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
  464. .pNext = nullptr,
  465. .flags = ci_flags,
  466. .pApplicationInfo = &application_info,
  467. .enabledLayerCount = layers.size(),
  468. .ppEnabledLayerNames = layers.data(),
  469. .enabledExtensionCount = extensions.size(),
  470. .ppEnabledExtensionNames = extensions.data(),
  471. };
  472. VkInstance instance;
  473. Check(dispatch.vkCreateInstance(&ci, nullptr, &instance));
  474. if (!Proc(dispatch.vkDestroyInstance, dispatch, "vkDestroyInstance", instance)) {
  475. // We successfully created an instance but the destroy function couldn't be loaded.
  476. // This is a good moment to panic.
  477. throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
  478. }
  479. return Instance(instance, dispatch);
  480. }
  481. std::vector<VkPhysicalDevice> Instance::EnumeratePhysicalDevices() const {
  482. u32 num;
  483. Check(dld->vkEnumeratePhysicalDevices(handle, &num, nullptr));
  484. std::vector<VkPhysicalDevice> physical_devices(num);
  485. Check(dld->vkEnumeratePhysicalDevices(handle, &num, physical_devices.data()));
  486. SortPhysicalDevices(physical_devices, *dld);
  487. return physical_devices;
  488. }
  489. DebugUtilsMessenger Instance::CreateDebugUtilsMessenger(
  490. const VkDebugUtilsMessengerCreateInfoEXT& create_info) const {
  491. VkDebugUtilsMessengerEXT object;
  492. Check(dld->vkCreateDebugUtilsMessengerEXT(handle, &create_info, nullptr, &object));
  493. return DebugUtilsMessenger(object, handle, *dld);
  494. }
  495. void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const {
  496. Check(dld->vkBindBufferMemory(owner, handle, memory, offset));
  497. }
  498. void Buffer::SetObjectNameEXT(const char* name) const {
  499. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER, name);
  500. }
  501. void BufferView::SetObjectNameEXT(const char* name) const {
  502. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER_VIEW, name);
  503. }
  504. void Image::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const {
  505. Check(dld->vkBindImageMemory(owner, handle, memory, offset));
  506. }
  507. void Image::SetObjectNameEXT(const char* name) const {
  508. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE, name);
  509. }
  510. void ImageView::SetObjectNameEXT(const char* name) const {
  511. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE_VIEW, name);
  512. }
  513. int DeviceMemory::GetMemoryFdKHR() const {
  514. const VkMemoryGetFdInfoKHR get_fd_info{
  515. .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
  516. .pNext = nullptr,
  517. .memory = handle,
  518. .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
  519. };
  520. int fd;
  521. Check(dld->vkGetMemoryFdKHR(owner, &get_fd_info, &fd));
  522. return fd;
  523. }
  524. #ifdef _WIN32
  525. HANDLE DeviceMemory::GetMemoryWin32HandleKHR() const {
  526. const VkMemoryGetWin32HandleInfoKHR get_win32_handle_info{
  527. .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
  528. .pNext = nullptr,
  529. .memory = handle,
  530. .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
  531. };
  532. HANDLE win32_handle;
  533. Check(dld->vkGetMemoryWin32HandleKHR(owner, &get_win32_handle_info, &win32_handle));
  534. return win32_handle;
  535. }
  536. #endif
  537. void DeviceMemory::SetObjectNameEXT(const char* name) const {
  538. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_DEVICE_MEMORY, name);
  539. }
  540. void Fence::SetObjectNameEXT(const char* name) const {
  541. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_FENCE, name);
  542. }
  543. void Framebuffer::SetObjectNameEXT(const char* name) const {
  544. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_FRAMEBUFFER, name);
  545. }
  546. DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) const {
  547. const std::size_t num = ai.descriptorSetCount;
  548. std::unique_ptr sets = std::make_unique<VkDescriptorSet[]>(num);
  549. switch (const VkResult result = dld->vkAllocateDescriptorSets(owner, &ai, sets.get())) {
  550. case VK_SUCCESS:
  551. return DescriptorSets(std::move(sets), num, owner, handle, *dld);
  552. case VK_ERROR_OUT_OF_POOL_MEMORY:
  553. return {};
  554. default:
  555. throw Exception(result);
  556. }
  557. }
  558. void DescriptorPool::SetObjectNameEXT(const char* name) const {
  559. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_DESCRIPTOR_POOL, name);
  560. }
  561. CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const {
  562. const VkCommandBufferAllocateInfo ai{
  563. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
  564. .pNext = nullptr,
  565. .commandPool = handle,
  566. .level = level,
  567. .commandBufferCount = static_cast<u32>(num_buffers),
  568. };
  569. std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers);
  570. switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) {
  571. case VK_SUCCESS:
  572. return CommandBuffers(std::move(buffers), num_buffers, owner, handle, *dld);
  573. case VK_ERROR_OUT_OF_POOL_MEMORY:
  574. return {};
  575. default:
  576. throw Exception(result);
  577. }
  578. }
  579. void CommandPool::SetObjectNameEXT(const char* name) const {
  580. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_COMMAND_POOL, name);
  581. }
  582. std::vector<VkImage> SwapchainKHR::GetImages() const {
  583. u32 num;
  584. Check(dld->vkGetSwapchainImagesKHR(owner, handle, &num, nullptr));
  585. std::vector<VkImage> images(num);
  586. Check(dld->vkGetSwapchainImagesKHR(owner, handle, &num, images.data()));
  587. return images;
  588. }
  589. void Event::SetObjectNameEXT(const char* name) const {
  590. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_EVENT, name);
  591. }
  592. void ShaderModule::SetObjectNameEXT(const char* name) const {
  593. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SHADER_MODULE, name);
  594. }
  595. void PipelineCache::SetObjectNameEXT(const char* name) const {
  596. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_PIPELINE_CACHE, name);
  597. }
  598. void Semaphore::SetObjectNameEXT(const char* name) const {
  599. SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SEMAPHORE, name);
  600. }
  601. Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
  602. Span<const char*> enabled_extensions, const void* next,
  603. DeviceDispatch& dispatch) {
  604. const VkDeviceCreateInfo ci{
  605. .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
  606. .pNext = next,
  607. .flags = 0,
  608. .queueCreateInfoCount = queues_ci.size(),
  609. .pQueueCreateInfos = queues_ci.data(),
  610. .enabledLayerCount = 0,
  611. .ppEnabledLayerNames = nullptr,
  612. .enabledExtensionCount = enabled_extensions.size(),
  613. .ppEnabledExtensionNames = enabled_extensions.data(),
  614. .pEnabledFeatures = nullptr,
  615. };
  616. VkDevice device;
  617. Check(dispatch.vkCreateDevice(physical_device, &ci, nullptr, &device));
  618. Load(device, dispatch);
  619. return Device(device, dispatch);
  620. }
  621. Queue Device::GetQueue(u32 family_index) const noexcept {
  622. VkQueue queue;
  623. dld->vkGetDeviceQueue(handle, family_index, 0, &queue);
  624. return Queue(queue, *dld);
  625. }
  626. Buffer Device::CreateBuffer(const VkBufferCreateInfo& ci) const {
  627. VkBuffer object;
  628. Check(dld->vkCreateBuffer(handle, &ci, nullptr, &object));
  629. return Buffer(object, handle, *dld);
  630. }
  631. BufferView Device::CreateBufferView(const VkBufferViewCreateInfo& ci) const {
  632. VkBufferView object;
  633. Check(dld->vkCreateBufferView(handle, &ci, nullptr, &object));
  634. return BufferView(object, handle, *dld);
  635. }
  636. Image Device::CreateImage(const VkImageCreateInfo& ci) const {
  637. VkImage object;
  638. Check(dld->vkCreateImage(handle, &ci, nullptr, &object));
  639. return Image(object, handle, *dld);
  640. }
  641. ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const {
  642. VkImageView object;
  643. Check(dld->vkCreateImageView(handle, &ci, nullptr, &object));
  644. return ImageView(object, handle, *dld);
  645. }
  646. Semaphore Device::CreateSemaphore() const {
  647. static constexpr VkSemaphoreCreateInfo ci{
  648. .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
  649. .pNext = nullptr,
  650. .flags = 0,
  651. };
  652. return CreateSemaphore(ci);
  653. }
  654. Semaphore Device::CreateSemaphore(const VkSemaphoreCreateInfo& ci) const {
  655. VkSemaphore object;
  656. Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object));
  657. return Semaphore(object, handle, *dld);
  658. }
  659. Fence Device::CreateFence(const VkFenceCreateInfo& ci) const {
  660. VkFence object;
  661. Check(dld->vkCreateFence(handle, &ci, nullptr, &object));
  662. return Fence(object, handle, *dld);
  663. }
  664. DescriptorPool Device::CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const {
  665. VkDescriptorPool object;
  666. Check(dld->vkCreateDescriptorPool(handle, &ci, nullptr, &object));
  667. return DescriptorPool(object, handle, *dld);
  668. }
  669. RenderPass Device::CreateRenderPass(const VkRenderPassCreateInfo& ci) const {
  670. VkRenderPass object;
  671. Check(dld->vkCreateRenderPass(handle, &ci, nullptr, &object));
  672. return RenderPass(object, handle, *dld);
  673. }
  674. DescriptorSetLayout Device::CreateDescriptorSetLayout(
  675. const VkDescriptorSetLayoutCreateInfo& ci) const {
  676. VkDescriptorSetLayout object;
  677. Check(dld->vkCreateDescriptorSetLayout(handle, &ci, nullptr, &object));
  678. return DescriptorSetLayout(object, handle, *dld);
  679. }
  680. PipelineCache Device::CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const {
  681. VkPipelineCache cache;
  682. Check(dld->vkCreatePipelineCache(handle, &ci, nullptr, &cache));
  683. return PipelineCache(cache, handle, *dld);
  684. }
  685. PipelineLayout Device::CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const {
  686. VkPipelineLayout object;
  687. Check(dld->vkCreatePipelineLayout(handle, &ci, nullptr, &object));
  688. return PipelineLayout(object, handle, *dld);
  689. }
  690. Pipeline Device::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci,
  691. VkPipelineCache cache) const {
  692. VkPipeline object;
  693. Check(dld->vkCreateGraphicsPipelines(handle, cache, 1, &ci, nullptr, &object));
  694. return Pipeline(object, handle, *dld);
  695. }
  696. Pipeline Device::CreateComputePipeline(const VkComputePipelineCreateInfo& ci,
  697. VkPipelineCache cache) const {
  698. VkPipeline object;
  699. Check(dld->vkCreateComputePipelines(handle, cache, 1, &ci, nullptr, &object));
  700. return Pipeline(object, handle, *dld);
  701. }
  702. Sampler Device::CreateSampler(const VkSamplerCreateInfo& ci) const {
  703. VkSampler object;
  704. Check(dld->vkCreateSampler(handle, &ci, nullptr, &object));
  705. return Sampler(object, handle, *dld);
  706. }
  707. Framebuffer Device::CreateFramebuffer(const VkFramebufferCreateInfo& ci) const {
  708. VkFramebuffer object;
  709. Check(dld->vkCreateFramebuffer(handle, &ci, nullptr, &object));
  710. return Framebuffer(object, handle, *dld);
  711. }
  712. CommandPool Device::CreateCommandPool(const VkCommandPoolCreateInfo& ci) const {
  713. VkCommandPool object;
  714. Check(dld->vkCreateCommandPool(handle, &ci, nullptr, &object));
  715. return CommandPool(object, handle, *dld);
  716. }
  717. DescriptorUpdateTemplate Device::CreateDescriptorUpdateTemplate(
  718. const VkDescriptorUpdateTemplateCreateInfo& ci) const {
  719. VkDescriptorUpdateTemplate object;
  720. Check(dld->vkCreateDescriptorUpdateTemplate(handle, &ci, nullptr, &object));
  721. return DescriptorUpdateTemplate(object, handle, *dld);
  722. }
  723. QueryPool Device::CreateQueryPool(const VkQueryPoolCreateInfo& ci) const {
  724. VkQueryPool object;
  725. Check(dld->vkCreateQueryPool(handle, &ci, nullptr, &object));
  726. return QueryPool(object, handle, *dld);
  727. }
  728. ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) const {
  729. VkShaderModule object;
  730. Check(dld->vkCreateShaderModule(handle, &ci, nullptr, &object));
  731. return ShaderModule(object, handle, *dld);
  732. }
  733. Event Device::CreateEvent() const {
  734. static constexpr VkEventCreateInfo ci{
  735. .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
  736. .pNext = nullptr,
  737. .flags = 0,
  738. };
  739. VkEvent object;
  740. Check(dld->vkCreateEvent(handle, &ci, nullptr, &object));
  741. return Event(object, handle, *dld);
  742. }
  743. SwapchainKHR Device::CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const {
  744. VkSwapchainKHR object;
  745. Check(dld->vkCreateSwapchainKHR(handle, &ci, nullptr, &object));
  746. return SwapchainKHR(object, handle, *dld);
  747. }
  748. DeviceMemory Device::TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept {
  749. VkDeviceMemory memory;
  750. if (dld->vkAllocateMemory(handle, &ai, nullptr, &memory) != VK_SUCCESS) {
  751. return {};
  752. }
  753. return DeviceMemory(memory, handle, *dld);
  754. }
  755. DeviceMemory Device::AllocateMemory(const VkMemoryAllocateInfo& ai) const {
  756. VkDeviceMemory memory;
  757. Check(dld->vkAllocateMemory(handle, &ai, nullptr, &memory));
  758. return DeviceMemory(memory, handle, *dld);
  759. }
  760. VkMemoryRequirements Device::GetBufferMemoryRequirements(VkBuffer buffer,
  761. void* pnext) const noexcept {
  762. const VkBufferMemoryRequirementsInfo2 info{
  763. .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
  764. .pNext = nullptr,
  765. .buffer = buffer,
  766. };
  767. VkMemoryRequirements2 requirements{
  768. .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
  769. .pNext = pnext,
  770. .memoryRequirements{},
  771. };
  772. dld->vkGetBufferMemoryRequirements2(handle, &info, &requirements);
  773. return requirements.memoryRequirements;
  774. }
  775. VkMemoryRequirements Device::GetImageMemoryRequirements(VkImage image) const noexcept {
  776. VkMemoryRequirements requirements;
  777. dld->vkGetImageMemoryRequirements(handle, image, &requirements);
  778. return requirements;
  779. }
  780. std::vector<VkPipelineExecutablePropertiesKHR> Device::GetPipelineExecutablePropertiesKHR(
  781. VkPipeline pipeline) const {
  782. const VkPipelineInfoKHR info{
  783. .sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,
  784. .pNext = nullptr,
  785. .pipeline = pipeline,
  786. };
  787. u32 num{};
  788. dld->vkGetPipelineExecutablePropertiesKHR(handle, &info, &num, nullptr);
  789. std::vector<VkPipelineExecutablePropertiesKHR> properties(num);
  790. for (auto& property : properties) {
  791. property.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR;
  792. }
  793. Check(dld->vkGetPipelineExecutablePropertiesKHR(handle, &info, &num, properties.data()));
  794. return properties;
  795. }
  796. std::vector<VkPipelineExecutableStatisticKHR> Device::GetPipelineExecutableStatisticsKHR(
  797. VkPipeline pipeline, u32 executable_index) const {
  798. const VkPipelineExecutableInfoKHR executable_info{
  799. .sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,
  800. .pNext = nullptr,
  801. .pipeline = pipeline,
  802. .executableIndex = executable_index,
  803. };
  804. u32 num{};
  805. dld->vkGetPipelineExecutableStatisticsKHR(handle, &executable_info, &num, nullptr);
  806. std::vector<VkPipelineExecutableStatisticKHR> statistics(num);
  807. for (auto& statistic : statistics) {
  808. statistic.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR;
  809. }
  810. Check(dld->vkGetPipelineExecutableStatisticsKHR(handle, &executable_info, &num,
  811. statistics.data()));
  812. return statistics;
  813. }
  814. void Device::UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes,
  815. Span<VkCopyDescriptorSet> copies) const noexcept {
  816. dld->vkUpdateDescriptorSets(handle, writes.size(), writes.data(), copies.size(), copies.data());
  817. }
  818. VkPhysicalDeviceProperties PhysicalDevice::GetProperties() const noexcept {
  819. VkPhysicalDeviceProperties properties;
  820. dld->vkGetPhysicalDeviceProperties(physical_device, &properties);
  821. return properties;
  822. }
  823. void PhysicalDevice::GetProperties2(VkPhysicalDeviceProperties2& properties) const noexcept {
  824. dld->vkGetPhysicalDeviceProperties2(physical_device, &properties);
  825. }
  826. VkPhysicalDeviceFeatures PhysicalDevice::GetFeatures() const noexcept {
  827. VkPhysicalDeviceFeatures2 features2;
  828. features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  829. features2.pNext = nullptr;
  830. dld->vkGetPhysicalDeviceFeatures2(physical_device, &features2);
  831. return features2.features;
  832. }
  833. void PhysicalDevice::GetFeatures2(VkPhysicalDeviceFeatures2& features) const noexcept {
  834. dld->vkGetPhysicalDeviceFeatures2(physical_device, &features);
  835. }
  836. VkFormatProperties PhysicalDevice::GetFormatProperties(VkFormat format) const noexcept {
  837. VkFormatProperties properties;
  838. dld->vkGetPhysicalDeviceFormatProperties(physical_device, format, &properties);
  839. return properties;
  840. }
  841. std::vector<VkExtensionProperties> PhysicalDevice::EnumerateDeviceExtensionProperties() const {
  842. u32 num;
  843. dld->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &num, nullptr);
  844. std::vector<VkExtensionProperties> properties(num);
  845. dld->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &num, properties.data());
  846. return properties;
  847. }
  848. std::vector<VkQueueFamilyProperties> PhysicalDevice::GetQueueFamilyProperties() const {
  849. u32 num;
  850. dld->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &num, nullptr);
  851. std::vector<VkQueueFamilyProperties> properties(num);
  852. dld->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &num, properties.data());
  853. return properties;
  854. }
  855. std::vector<VkPhysicalDeviceToolProperties> PhysicalDevice::GetPhysicalDeviceToolProperties()
  856. const {
  857. u32 num = 0;
  858. if (!dld->vkGetPhysicalDeviceToolProperties) {
  859. return {};
  860. }
  861. dld->vkGetPhysicalDeviceToolProperties(physical_device, &num, nullptr);
  862. std::vector<VkPhysicalDeviceToolProperties> properties(num);
  863. dld->vkGetPhysicalDeviceToolProperties(physical_device, &num, properties.data());
  864. return properties;
  865. }
  866. bool PhysicalDevice::GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR surface) const {
  867. VkBool32 supported;
  868. Check(dld->vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_index, surface,
  869. &supported));
  870. return supported == VK_TRUE;
  871. }
  872. VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const {
  873. VkSurfaceCapabilitiesKHR capabilities;
  874. Check(dld->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &capabilities));
  875. return capabilities;
  876. }
  877. std::vector<VkSurfaceFormatKHR> PhysicalDevice::GetSurfaceFormatsKHR(VkSurfaceKHR surface) const {
  878. u32 num;
  879. Check(dld->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &num, nullptr));
  880. std::vector<VkSurfaceFormatKHR> formats(num);
  881. Check(
  882. dld->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &num, formats.data()));
  883. return formats;
  884. }
  885. std::vector<VkPresentModeKHR> PhysicalDevice::GetSurfacePresentModesKHR(
  886. VkSurfaceKHR surface) const {
  887. u32 num;
  888. Check(dld->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &num, nullptr));
  889. std::vector<VkPresentModeKHR> modes(num);
  890. Check(dld->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &num,
  891. modes.data()));
  892. return modes;
  893. }
  894. VkPhysicalDeviceMemoryProperties2 PhysicalDevice::GetMemoryProperties(
  895. void* next_structures) const noexcept {
  896. VkPhysicalDeviceMemoryProperties2 properties{};
  897. properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
  898. properties.pNext = next_structures;
  899. dld->vkGetPhysicalDeviceMemoryProperties2(physical_device, &properties);
  900. return properties;
  901. }
  902. u32 AvailableVersion(const InstanceDispatch& dld) noexcept {
  903. PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;
  904. if (!Proc(vkEnumerateInstanceVersion, dld, "vkEnumerateInstanceVersion")) {
  905. // If the procedure is not found, Vulkan 1.0 is assumed
  906. return VK_API_VERSION_1_0;
  907. }
  908. u32 version;
  909. if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) {
  910. LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1",
  911. ToString(result));
  912. return VK_API_VERSION_1_1;
  913. }
  914. return version;
  915. }
  916. std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
  917. const InstanceDispatch& dld) {
  918. u32 num;
  919. if (dld.vkEnumerateInstanceExtensionProperties(nullptr, &num, nullptr) != VK_SUCCESS) {
  920. return std::nullopt;
  921. }
  922. std::vector<VkExtensionProperties> properties(num);
  923. if (dld.vkEnumerateInstanceExtensionProperties(nullptr, &num, properties.data()) !=
  924. VK_SUCCESS) {
  925. return std::nullopt;
  926. }
  927. return properties;
  928. }
  929. std::optional<std::vector<VkLayerProperties>> EnumerateInstanceLayerProperties(
  930. const InstanceDispatch& dld) {
  931. u32 num;
  932. if (dld.vkEnumerateInstanceLayerProperties(&num, nullptr) != VK_SUCCESS) {
  933. return std::nullopt;
  934. }
  935. std::vector<VkLayerProperties> properties(num);
  936. if (dld.vkEnumerateInstanceLayerProperties(&num, properties.data()) != VK_SUCCESS) {
  937. return std::nullopt;
  938. }
  939. return properties;
  940. }
  941. } // namespace Vulkan::vk