vulkan_wrapper.h 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <exception>
  5. #include <limits>
  6. #include <memory>
  7. #include <optional>
  8. #include <span>
  9. #include <type_traits>
  10. #include <utility>
  11. #include <vector>
  12. #define VK_NO_PROTOTYPES
  13. #ifdef _WIN32
  14. #define VK_USE_PLATFORM_WIN32_KHR
  15. #endif
  16. #include <vulkan/vulkan.h>
  17. // Sanitize macros
  18. #ifdef CreateEvent
  19. #undef CreateEvent
  20. #endif
  21. #ifdef CreateSemaphore
  22. #undef CreateSemaphore
  23. #endif
  24. #include "common/common_types.h"
  25. #ifdef _MSC_VER
  26. #pragma warning(disable : 26812) // Disable prefer enum class over enum
  27. #endif
  28. namespace Vulkan::vk {
  29. /**
  30. * Span for Vulkan arrays.
  31. * Based on std::span but optimized for array access instead of iterators.
  32. * Size returns uint32_t instead of size_t to ease interaction with Vulkan functions.
  33. */
  34. template <typename T>
  35. class Span {
  36. public:
  37. using value_type = T;
  38. using size_type = u32;
  39. using difference_type = std::ptrdiff_t;
  40. using reference = const T&;
  41. using const_reference = const T&;
  42. using pointer = const T*;
  43. using const_pointer = const T*;
  44. using iterator = const T*;
  45. using const_iterator = const T*;
  46. /// Construct an empty span.
  47. constexpr Span() noexcept = default;
  48. /// Construct an empty span
  49. constexpr Span(std::nullptr_t) noexcept {}
  50. /// Construct a span from a single element.
  51. constexpr Span(const T& value) noexcept : ptr{&value}, num{1} {}
  52. /// Construct a span from a range.
  53. template <typename Range>
  54. // requires std::data(const Range&)
  55. // requires std::size(const Range&)
  56. constexpr Span(const Range& range) : ptr{std::data(range)}, num{std::size(range)} {}
  57. /// Construct a span from a pointer and a size.
  58. /// This is inteded for subranges.
  59. constexpr Span(const T* ptr_, std::size_t num_) noexcept : ptr{ptr_}, num{num_} {}
  60. /// Returns the data pointer by the span.
  61. constexpr const T* data() const noexcept {
  62. return ptr;
  63. }
  64. /// Returns the number of elements in the span.
  65. /// @note Returns a 32 bits integer because most Vulkan functions expect this type.
  66. constexpr u32 size() const noexcept {
  67. return static_cast<u32>(num);
  68. }
  69. /// Returns true when the span is empty.
  70. constexpr bool empty() const noexcept {
  71. return num == 0;
  72. }
  73. /// Returns a reference to the element in the passed index.
  74. /// @pre: index < size()
  75. constexpr const T& operator[](std::size_t index) const noexcept {
  76. return ptr[index];
  77. }
  78. /// Returns an iterator to the beginning of the span.
  79. constexpr const T* begin() const noexcept {
  80. return ptr;
  81. }
  82. /// Returns an iterator to the end of the span.
  83. constexpr const T* end() const noexcept {
  84. return ptr + num;
  85. }
  86. /// Returns an iterator to the beginning of the span.
  87. constexpr const T* cbegin() const noexcept {
  88. return ptr;
  89. }
  90. /// Returns an iterator to the end of the span.
  91. constexpr const T* cend() const noexcept {
  92. return ptr + num;
  93. }
  94. private:
  95. const T* ptr = nullptr;
  96. std::size_t num = 0;
  97. };
  98. /// Vulkan exception generated from a VkResult.
  99. class Exception final : public std::exception {
  100. public:
  101. /// Construct the exception with a result.
  102. /// @pre result != VK_SUCCESS
  103. explicit Exception(VkResult result_) : result{result_} {}
  104. virtual ~Exception() = default;
  105. const char* what() const noexcept override;
  106. private:
  107. VkResult result;
  108. };
  109. /// Converts a VkResult enum into a rodata string
  110. const char* ToString(VkResult) noexcept;
  111. /// Throws a Vulkan exception if result is not success.
  112. inline void Check(VkResult result) {
  113. if (result != VK_SUCCESS) {
  114. throw Exception(result);
  115. }
  116. }
  117. /// Throws a Vulkan exception if result is an error.
  118. /// @return result
  119. inline VkResult Filter(VkResult result) {
  120. if (result < 0) {
  121. throw Exception(result);
  122. }
  123. return result;
  124. }
  125. /// Table holding Vulkan instance function pointers.
  126. struct InstanceDispatch {
  127. PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{};
  128. PFN_vkCreateInstance vkCreateInstance{};
  129. PFN_vkDestroyInstance vkDestroyInstance{};
  130. PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties{};
  131. PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties{};
  132. PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT{};
  133. PFN_vkCreateDevice vkCreateDevice{};
  134. PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT{};
  135. PFN_vkDestroyDevice vkDestroyDevice{};
  136. PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR{};
  137. PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties{};
  138. PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices{};
  139. PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr{};
  140. PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2{};
  141. PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties{};
  142. PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties{};
  143. PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2{};
  144. PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties{};
  145. PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2{};
  146. PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties{};
  147. PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties{};
  148. PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR{};
  149. PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR{};
  150. PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR{};
  151. PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR{};
  152. PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR{};
  153. PFN_vkQueuePresentKHR vkQueuePresentKHR{};
  154. };
  155. /// Table holding Vulkan device function pointers.
  156. struct DeviceDispatch : InstanceDispatch {
  157. PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR{};
  158. PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers{};
  159. PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets{};
  160. PFN_vkAllocateMemory vkAllocateMemory{};
  161. PFN_vkBeginCommandBuffer vkBeginCommandBuffer{};
  162. PFN_vkBindBufferMemory vkBindBufferMemory{};
  163. PFN_vkBindImageMemory vkBindImageMemory{};
  164. PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT{};
  165. PFN_vkCmdBeginQuery vkCmdBeginQuery{};
  166. PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass{};
  167. PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT{};
  168. PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets{};
  169. PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer{};
  170. PFN_vkCmdBindPipeline vkCmdBindPipeline{};
  171. PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT{};
  172. PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers{};
  173. PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT{};
  174. PFN_vkCmdBlitImage vkCmdBlitImage{};
  175. PFN_vkCmdClearAttachments vkCmdClearAttachments{};
  176. PFN_vkCmdClearColorImage vkCmdClearColorImage{};
  177. PFN_vkCmdCopyBuffer vkCmdCopyBuffer{};
  178. PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage{};
  179. PFN_vkCmdCopyImage vkCmdCopyImage{};
  180. PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer{};
  181. PFN_vkCmdDispatch vkCmdDispatch{};
  182. PFN_vkCmdDraw vkCmdDraw{};
  183. PFN_vkCmdDrawIndexed vkCmdDrawIndexed{};
  184. PFN_vkCmdDrawIndirect vkCmdDrawIndirect{};
  185. PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect{};
  186. PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR{};
  187. PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR{};
  188. PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{};
  189. PFN_vkCmdEndQuery vkCmdEndQuery{};
  190. PFN_vkCmdEndRenderPass vkCmdEndRenderPass{};
  191. PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{};
  192. PFN_vkCmdFillBuffer vkCmdFillBuffer{};
  193. PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{};
  194. PFN_vkCmdPushConstants vkCmdPushConstants{};
  195. PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{};
  196. PFN_vkCmdResolveImage vkCmdResolveImage{};
  197. PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{};
  198. PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{};
  199. PFN_vkCmdSetDepthBias vkCmdSetDepthBias{};
  200. PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds{};
  201. PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT{};
  202. PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT{};
  203. PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT{};
  204. PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT{};
  205. PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT{};
  206. PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT{};
  207. PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT{};
  208. PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT{};
  209. PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT{};
  210. PFN_vkCmdSetEvent vkCmdSetEvent{};
  211. PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{};
  212. PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT{};
  213. PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT{};
  214. PFN_vkCmdSetLineWidth vkCmdSetLineWidth{};
  215. PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT{};
  216. PFN_vkCmdSetScissor vkCmdSetScissor{};
  217. PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask{};
  218. PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT{};
  219. PFN_vkCmdSetStencilReference vkCmdSetStencilReference{};
  220. PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT{};
  221. PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask{};
  222. PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT{};
  223. PFN_vkCmdSetViewport vkCmdSetViewport{};
  224. PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT{};
  225. PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{};
  226. PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{};
  227. PFN_vkCmdWaitEvents vkCmdWaitEvents{};
  228. PFN_vkCreateBuffer vkCreateBuffer{};
  229. PFN_vkCreateBufferView vkCreateBufferView{};
  230. PFN_vkCreateCommandPool vkCreateCommandPool{};
  231. PFN_vkCreateComputePipelines vkCreateComputePipelines{};
  232. PFN_vkCreateDescriptorPool vkCreateDescriptorPool{};
  233. PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout{};
  234. PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate{};
  235. PFN_vkCreateEvent vkCreateEvent{};
  236. PFN_vkCreateFence vkCreateFence{};
  237. PFN_vkCreateFramebuffer vkCreateFramebuffer{};
  238. PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines{};
  239. PFN_vkCreateImage vkCreateImage{};
  240. PFN_vkCreateImageView vkCreateImageView{};
  241. PFN_vkCreatePipelineLayout vkCreatePipelineLayout{};
  242. PFN_vkCreateQueryPool vkCreateQueryPool{};
  243. PFN_vkCreateRenderPass vkCreateRenderPass{};
  244. PFN_vkCreateSampler vkCreateSampler{};
  245. PFN_vkCreateSemaphore vkCreateSemaphore{};
  246. PFN_vkCreateShaderModule vkCreateShaderModule{};
  247. PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR{};
  248. PFN_vkDestroyBuffer vkDestroyBuffer{};
  249. PFN_vkDestroyBufferView vkDestroyBufferView{};
  250. PFN_vkDestroyCommandPool vkDestroyCommandPool{};
  251. PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool{};
  252. PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout{};
  253. PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate{};
  254. PFN_vkDestroyEvent vkDestroyEvent{};
  255. PFN_vkDestroyFence vkDestroyFence{};
  256. PFN_vkDestroyFramebuffer vkDestroyFramebuffer{};
  257. PFN_vkDestroyImage vkDestroyImage{};
  258. PFN_vkDestroyImageView vkDestroyImageView{};
  259. PFN_vkDestroyPipeline vkDestroyPipeline{};
  260. PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout{};
  261. PFN_vkDestroyQueryPool vkDestroyQueryPool{};
  262. PFN_vkDestroyRenderPass vkDestroyRenderPass{};
  263. PFN_vkDestroySampler vkDestroySampler{};
  264. PFN_vkDestroySemaphore vkDestroySemaphore{};
  265. PFN_vkDestroyShaderModule vkDestroyShaderModule{};
  266. PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR{};
  267. PFN_vkDeviceWaitIdle vkDeviceWaitIdle{};
  268. PFN_vkEndCommandBuffer vkEndCommandBuffer{};
  269. PFN_vkFreeCommandBuffers vkFreeCommandBuffers{};
  270. PFN_vkFreeDescriptorSets vkFreeDescriptorSets{};
  271. PFN_vkFreeMemory vkFreeMemory{};
  272. PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2{};
  273. PFN_vkGetDeviceQueue vkGetDeviceQueue{};
  274. PFN_vkGetEventStatus vkGetEventStatus{};
  275. PFN_vkGetFenceStatus vkGetFenceStatus{};
  276. PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements{};
  277. PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR{};
  278. #ifdef _WIN32
  279. PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{};
  280. #endif
  281. PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR{};
  282. PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{};
  283. PFN_vkGetQueryPoolResults vkGetQueryPoolResults{};
  284. PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue{};
  285. PFN_vkMapMemory vkMapMemory{};
  286. PFN_vkQueueSubmit vkQueueSubmit{};
  287. PFN_vkResetFences vkResetFences{};
  288. PFN_vkResetQueryPool vkResetQueryPool{};
  289. PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT{};
  290. PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT{};
  291. PFN_vkUnmapMemory vkUnmapMemory{};
  292. PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate{};
  293. PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
  294. PFN_vkWaitForFences vkWaitForFences{};
  295. PFN_vkWaitSemaphores vkWaitSemaphores{};
  296. };
  297. /// Loads instance agnostic function pointers.
  298. /// @return True on success, false on error.
  299. bool Load(InstanceDispatch&) noexcept;
  300. /// Loads instance function pointers.
  301. /// @return True on success, false on error.
  302. bool Load(VkInstance, InstanceDispatch&) noexcept;
  303. void Destroy(VkInstance, const InstanceDispatch&) noexcept;
  304. void Destroy(VkDevice, const InstanceDispatch&) noexcept;
  305. void Destroy(VkDevice, VkBuffer, const DeviceDispatch&) noexcept;
  306. void Destroy(VkDevice, VkBufferView, const DeviceDispatch&) noexcept;
  307. void Destroy(VkDevice, VkCommandPool, const DeviceDispatch&) noexcept;
  308. void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept;
  309. void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept;
  310. void Destroy(VkDevice, VkDescriptorUpdateTemplate, const DeviceDispatch&) noexcept;
  311. void Destroy(VkDevice, VkDeviceMemory, const DeviceDispatch&) noexcept;
  312. void Destroy(VkDevice, VkEvent, const DeviceDispatch&) noexcept;
  313. void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept;
  314. void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept;
  315. void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept;
  316. void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept;
  317. void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept;
  318. void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept;
  319. void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept;
  320. void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept;
  321. void Destroy(VkDevice, VkSampler, const DeviceDispatch&) noexcept;
  322. void Destroy(VkDevice, VkSwapchainKHR, const DeviceDispatch&) noexcept;
  323. void Destroy(VkDevice, VkSemaphore, const DeviceDispatch&) noexcept;
  324. void Destroy(VkDevice, VkShaderModule, const DeviceDispatch&) noexcept;
  325. void Destroy(VkInstance, VkDebugUtilsMessengerEXT, const InstanceDispatch&) noexcept;
  326. void Destroy(VkInstance, VkSurfaceKHR, const InstanceDispatch&) noexcept;
  327. VkResult Free(VkDevice, VkDescriptorPool, Span<VkDescriptorSet>, const DeviceDispatch&) noexcept;
  328. VkResult Free(VkDevice, VkCommandPool, Span<VkCommandBuffer>, const DeviceDispatch&) noexcept;
  329. template <typename Type, typename OwnerType, typename Dispatch>
  330. class Handle;
  331. /// Handle with an owning type.
  332. /// Analogue to std::unique_ptr.
  333. template <typename Type, typename OwnerType, typename Dispatch>
  334. class Handle {
  335. public:
  336. /// Construct a handle and hold it's ownership.
  337. explicit Handle(Type handle_, OwnerType owner_, const Dispatch& dld_) noexcept
  338. : handle{handle_}, owner{owner_}, dld{&dld_} {}
  339. /// Construct an empty handle.
  340. Handle() = default;
  341. /// Construct an empty handle.
  342. Handle(std::nullptr_t) {}
  343. /// Copying Vulkan objects is not supported and will never be.
  344. Handle(const Handle&) = delete;
  345. Handle& operator=(const Handle&) = delete;
  346. /// Construct a handle transfering the ownership from another handle.
  347. Handle(Handle&& rhs) noexcept
  348. : handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, dld{rhs.dld} {}
  349. /// Assign the current handle transfering the ownership from another handle.
  350. /// Destroys any previously held object.
  351. Handle& operator=(Handle&& rhs) noexcept {
  352. Release();
  353. handle = std::exchange(rhs.handle, nullptr);
  354. owner = rhs.owner;
  355. dld = rhs.dld;
  356. return *this;
  357. }
  358. /// Destroys the current handle if it existed.
  359. ~Handle() noexcept {
  360. Release();
  361. }
  362. /// Destroys any held object.
  363. void reset() noexcept {
  364. Release();
  365. handle = nullptr;
  366. }
  367. /// Returns the address of the held object.
  368. /// Intended for Vulkan structures that expect a pointer to an array.
  369. const Type* address() const noexcept {
  370. return std::addressof(handle);
  371. }
  372. /// Returns the held Vulkan handle.
  373. Type operator*() const noexcept {
  374. return handle;
  375. }
  376. /// Returns true when there's a held object.
  377. explicit operator bool() const noexcept {
  378. return handle != nullptr;
  379. }
  380. protected:
  381. Type handle = nullptr;
  382. OwnerType owner = nullptr;
  383. const Dispatch* dld = nullptr;
  384. private:
  385. /// Destroys the held object if it exists.
  386. void Release() noexcept {
  387. if (handle) {
  388. Destroy(owner, handle, *dld);
  389. }
  390. }
  391. };
  392. /// Dummy type used to specify a handle has no owner.
  393. struct NoOwner {};
  394. /// Handle without an owning type.
  395. /// Analogue to std::unique_ptr
  396. template <typename Type, typename Dispatch>
  397. class Handle<Type, NoOwner, Dispatch> {
  398. public:
  399. /// Construct a handle and hold it's ownership.
  400. explicit Handle(Type handle_, const Dispatch& dld_) noexcept : handle{handle_}, dld{&dld_} {}
  401. /// Construct an empty handle.
  402. Handle() noexcept = default;
  403. /// Copying Vulkan objects is not supported and will never be.
  404. Handle(const Handle&) = delete;
  405. Handle& operator=(const Handle&) = delete;
  406. /// Construct a handle transfering ownership from another handle.
  407. Handle(Handle&& rhs) noexcept : handle{std::exchange(rhs.handle, nullptr)}, dld{rhs.dld} {}
  408. /// Assign the current handle transfering the ownership from another handle.
  409. /// Destroys any previously held object.
  410. Handle& operator=(Handle&& rhs) noexcept {
  411. Release();
  412. handle = std::exchange(rhs.handle, nullptr);
  413. dld = rhs.dld;
  414. return *this;
  415. }
  416. /// Destroys the current handle if it existed.
  417. ~Handle() noexcept {
  418. Release();
  419. }
  420. /// Destroys any held object.
  421. void reset() noexcept {
  422. Release();
  423. handle = nullptr;
  424. }
  425. /// Returns the address of the held object.
  426. /// Intended for Vulkan structures that expect a pointer to an array.
  427. const Type* address() const noexcept {
  428. return std::addressof(handle);
  429. }
  430. /// Returns the held Vulkan handle.
  431. Type operator*() const noexcept {
  432. return handle;
  433. }
  434. /// Returns true when there's a held object.
  435. operator bool() const noexcept {
  436. return handle != nullptr;
  437. }
  438. protected:
  439. Type handle = nullptr;
  440. const Dispatch* dld = nullptr;
  441. private:
  442. /// Destroys the held object if it exists.
  443. void Release() noexcept {
  444. if (handle) {
  445. Destroy(handle, *dld);
  446. }
  447. }
  448. };
  449. /// Array of a pool allocation.
  450. /// Analogue to std::vector
  451. template <typename AllocationType, typename PoolType>
  452. class PoolAllocations {
  453. public:
  454. /// Construct an empty allocation.
  455. PoolAllocations() = default;
  456. /// Construct an allocation. Errors are reported through IsOutOfPoolMemory().
  457. explicit PoolAllocations(std::unique_ptr<AllocationType[]> allocations_, std::size_t num_,
  458. VkDevice device_, PoolType pool_, const DeviceDispatch& dld_) noexcept
  459. : allocations{std::move(allocations_)}, num{num_}, device{device_}, pool{pool_},
  460. dld{&dld_} {}
  461. /// Copying Vulkan allocations is not supported and will never be.
  462. PoolAllocations(const PoolAllocations&) = delete;
  463. PoolAllocations& operator=(const PoolAllocations&) = delete;
  464. /// Construct an allocation transfering ownership from another allocation.
  465. PoolAllocations(PoolAllocations&& rhs) noexcept
  466. : allocations{std::move(rhs.allocations)}, num{rhs.num}, device{rhs.device}, pool{rhs.pool},
  467. dld{rhs.dld} {}
  468. /// Assign an allocation transfering ownership from another allocation.
  469. PoolAllocations& operator=(PoolAllocations&& rhs) noexcept {
  470. allocations = std::move(rhs.allocations);
  471. num = rhs.num;
  472. device = rhs.device;
  473. pool = rhs.pool;
  474. dld = rhs.dld;
  475. return *this;
  476. }
  477. /// Returns the number of allocations.
  478. std::size_t size() const noexcept {
  479. return num;
  480. }
  481. /// Returns a pointer to the array of allocations.
  482. AllocationType const* data() const noexcept {
  483. return allocations.get();
  484. }
  485. /// Returns the allocation in the specified index.
  486. /// @pre index < size()
  487. AllocationType operator[](std::size_t index) const noexcept {
  488. return allocations[index];
  489. }
  490. /// True when a pool fails to construct.
  491. bool IsOutOfPoolMemory() const noexcept {
  492. return !device;
  493. }
  494. private:
  495. std::unique_ptr<AllocationType[]> allocations;
  496. std::size_t num = 0;
  497. VkDevice device = nullptr;
  498. PoolType pool = nullptr;
  499. const DeviceDispatch* dld = nullptr;
  500. };
  501. using DebugUtilsMessenger = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>;
  502. using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>;
  503. using DescriptorUpdateTemplate = Handle<VkDescriptorUpdateTemplate, VkDevice, DeviceDispatch>;
  504. using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>;
  505. using PipelineLayout = Handle<VkPipelineLayout, VkDevice, DeviceDispatch>;
  506. using QueryPool = Handle<VkQueryPool, VkDevice, DeviceDispatch>;
  507. using RenderPass = Handle<VkRenderPass, VkDevice, DeviceDispatch>;
  508. using Sampler = Handle<VkSampler, VkDevice, DeviceDispatch>;
  509. using SurfaceKHR = Handle<VkSurfaceKHR, VkInstance, InstanceDispatch>;
  510. using DescriptorSets = PoolAllocations<VkDescriptorSet, VkDescriptorPool>;
  511. using CommandBuffers = PoolAllocations<VkCommandBuffer, VkCommandPool>;
  512. /// Vulkan instance owning handle.
  513. class Instance : public Handle<VkInstance, NoOwner, InstanceDispatch> {
  514. using Handle<VkInstance, NoOwner, InstanceDispatch>::Handle;
  515. public:
  516. /// Creates a Vulkan instance.
  517. /// @throw Exception on initialization error.
  518. static Instance Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
  519. InstanceDispatch& dispatch);
  520. /// Enumerates physical devices.
  521. /// @return Physical devices and an empty handle on failure.
  522. /// @throw Exception on Vulkan error.
  523. std::vector<VkPhysicalDevice> EnumeratePhysicalDevices() const;
  524. /// Creates a debug callback messenger.
  525. /// @throw Exception on creation failure.
  526. DebugUtilsMessenger CreateDebugUtilsMessenger(
  527. const VkDebugUtilsMessengerCreateInfoEXT& create_info) const;
  528. /// Returns dispatch table.
  529. const InstanceDispatch& Dispatch() const noexcept {
  530. return *dld;
  531. }
  532. };
  533. class Queue {
  534. public:
  535. /// Construct an empty queue handle.
  536. constexpr Queue() noexcept = default;
  537. /// Construct a queue handle.
  538. constexpr Queue(VkQueue queue_, const DeviceDispatch& dld_) noexcept
  539. : queue{queue_}, dld{&dld_} {}
  540. VkResult Submit(Span<VkSubmitInfo> submit_infos,
  541. VkFence fence = VK_NULL_HANDLE) const noexcept {
  542. return dld->vkQueueSubmit(queue, submit_infos.size(), submit_infos.data(), fence);
  543. }
  544. VkResult Present(const VkPresentInfoKHR& present_info) const noexcept {
  545. return dld->vkQueuePresentKHR(queue, &present_info);
  546. }
  547. private:
  548. VkQueue queue = nullptr;
  549. const DeviceDispatch* dld = nullptr;
  550. };
  551. class Buffer : public Handle<VkBuffer, VkDevice, DeviceDispatch> {
  552. using Handle<VkBuffer, VkDevice, DeviceDispatch>::Handle;
  553. public:
  554. /// Attaches a memory allocation.
  555. void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const;
  556. /// Set object name.
  557. void SetObjectNameEXT(const char* name) const;
  558. };
  559. class BufferView : public Handle<VkBufferView, VkDevice, DeviceDispatch> {
  560. using Handle<VkBufferView, VkDevice, DeviceDispatch>::Handle;
  561. public:
  562. /// Set object name.
  563. void SetObjectNameEXT(const char* name) const;
  564. };
  565. class Image : public Handle<VkImage, VkDevice, DeviceDispatch> {
  566. using Handle<VkImage, VkDevice, DeviceDispatch>::Handle;
  567. public:
  568. /// Attaches a memory allocation.
  569. void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const;
  570. /// Set object name.
  571. void SetObjectNameEXT(const char* name) const;
  572. };
  573. class ImageView : public Handle<VkImageView, VkDevice, DeviceDispatch> {
  574. using Handle<VkImageView, VkDevice, DeviceDispatch>::Handle;
  575. public:
  576. /// Set object name.
  577. void SetObjectNameEXT(const char* name) const;
  578. };
  579. class DeviceMemory : public Handle<VkDeviceMemory, VkDevice, DeviceDispatch> {
  580. using Handle<VkDeviceMemory, VkDevice, DeviceDispatch>::Handle;
  581. public:
  582. int GetMemoryFdKHR() const;
  583. #ifdef _WIN32
  584. HANDLE GetMemoryWin32HandleKHR() const;
  585. #endif
  586. /// Set object name.
  587. void SetObjectNameEXT(const char* name) const;
  588. u8* Map(VkDeviceSize offset, VkDeviceSize size) const {
  589. void* data;
  590. Check(dld->vkMapMemory(owner, handle, offset, size, 0, &data));
  591. return static_cast<u8*>(data);
  592. }
  593. void Unmap() const noexcept {
  594. dld->vkUnmapMemory(owner, handle);
  595. }
  596. };
  597. class Fence : public Handle<VkFence, VkDevice, DeviceDispatch> {
  598. using Handle<VkFence, VkDevice, DeviceDispatch>::Handle;
  599. public:
  600. /// Set object name.
  601. void SetObjectNameEXT(const char* name) const;
  602. VkResult Wait(u64 timeout = std::numeric_limits<u64>::max()) const noexcept {
  603. return dld->vkWaitForFences(owner, 1, &handle, true, timeout);
  604. }
  605. VkResult GetStatus() const noexcept {
  606. return dld->vkGetFenceStatus(owner, handle);
  607. }
  608. void Reset() const {
  609. Check(dld->vkResetFences(owner, 1, &handle));
  610. }
  611. };
  612. class Framebuffer : public Handle<VkFramebuffer, VkDevice, DeviceDispatch> {
  613. using Handle<VkFramebuffer, VkDevice, DeviceDispatch>::Handle;
  614. public:
  615. /// Set object name.
  616. void SetObjectNameEXT(const char* name) const;
  617. };
  618. class DescriptorPool : public Handle<VkDescriptorPool, VkDevice, DeviceDispatch> {
  619. using Handle<VkDescriptorPool, VkDevice, DeviceDispatch>::Handle;
  620. public:
  621. DescriptorSets Allocate(const VkDescriptorSetAllocateInfo& ai) const;
  622. /// Set object name.
  623. void SetObjectNameEXT(const char* name) const;
  624. };
  625. class CommandPool : public Handle<VkCommandPool, VkDevice, DeviceDispatch> {
  626. using Handle<VkCommandPool, VkDevice, DeviceDispatch>::Handle;
  627. public:
  628. CommandBuffers Allocate(std::size_t num_buffers,
  629. VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY) const;
  630. /// Set object name.
  631. void SetObjectNameEXT(const char* name) const;
  632. };
  633. class SwapchainKHR : public Handle<VkSwapchainKHR, VkDevice, DeviceDispatch> {
  634. using Handle<VkSwapchainKHR, VkDevice, DeviceDispatch>::Handle;
  635. public:
  636. std::vector<VkImage> GetImages() const;
  637. };
  638. class Event : public Handle<VkEvent, VkDevice, DeviceDispatch> {
  639. using Handle<VkEvent, VkDevice, DeviceDispatch>::Handle;
  640. public:
  641. /// Set object name.
  642. void SetObjectNameEXT(const char* name) const;
  643. VkResult GetStatus() const noexcept {
  644. return dld->vkGetEventStatus(owner, handle);
  645. }
  646. };
  647. class ShaderModule : public Handle<VkShaderModule, VkDevice, DeviceDispatch> {
  648. using Handle<VkShaderModule, VkDevice, DeviceDispatch>::Handle;
  649. public:
  650. /// Set object name.
  651. void SetObjectNameEXT(const char* name) const;
  652. };
  653. class Semaphore : public Handle<VkSemaphore, VkDevice, DeviceDispatch> {
  654. using Handle<VkSemaphore, VkDevice, DeviceDispatch>::Handle;
  655. public:
  656. /// Set object name.
  657. void SetObjectNameEXT(const char* name) const;
  658. [[nodiscard]] u64 GetCounter() const {
  659. u64 value;
  660. Check(dld->vkGetSemaphoreCounterValue(owner, handle, &value));
  661. return value;
  662. }
  663. /**
  664. * Waits for a timeline semaphore on the host.
  665. *
  666. * @param value Value to wait
  667. * @param timeout Time in nanoseconds to timeout
  668. * @return True on successful wait, false on timeout
  669. */
  670. bool Wait(u64 value, u64 timeout = std::numeric_limits<u64>::max()) const {
  671. const VkSemaphoreWaitInfo wait_info{
  672. .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
  673. .pNext = nullptr,
  674. .flags = 0,
  675. .semaphoreCount = 1,
  676. .pSemaphores = &handle,
  677. .pValues = &value,
  678. };
  679. const VkResult result = dld->vkWaitSemaphores(owner, &wait_info, timeout);
  680. switch (result) {
  681. case VK_SUCCESS:
  682. return true;
  683. case VK_TIMEOUT:
  684. return false;
  685. default:
  686. throw Exception(result);
  687. }
  688. }
  689. };
  690. class Device : public Handle<VkDevice, NoOwner, DeviceDispatch> {
  691. using Handle<VkDevice, NoOwner, DeviceDispatch>::Handle;
  692. public:
  693. static Device Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
  694. Span<const char*> enabled_extensions, const void* next,
  695. DeviceDispatch& dispatch);
  696. Queue GetQueue(u32 family_index) const noexcept;
  697. Buffer CreateBuffer(const VkBufferCreateInfo& ci) const;
  698. BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const;
  699. Image CreateImage(const VkImageCreateInfo& ci) const;
  700. ImageView CreateImageView(const VkImageViewCreateInfo& ci) const;
  701. Semaphore CreateSemaphore() const;
  702. Semaphore CreateSemaphore(const VkSemaphoreCreateInfo& ci) const;
  703. Fence CreateFence(const VkFenceCreateInfo& ci) const;
  704. DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const;
  705. RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const;
  706. DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const;
  707. PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const;
  708. Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci) const;
  709. Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci) const;
  710. Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;
  711. Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const;
  712. CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const;
  713. DescriptorUpdateTemplate CreateDescriptorUpdateTemplate(
  714. const VkDescriptorUpdateTemplateCreateInfo& ci) const;
  715. QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const;
  716. ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const;
  717. Event CreateEvent() const;
  718. SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const;
  719. DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept;
  720. DeviceMemory AllocateMemory(const VkMemoryAllocateInfo& ai) const;
  721. VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer buffer,
  722. void* pnext = nullptr) const noexcept;
  723. VkMemoryRequirements GetImageMemoryRequirements(VkImage image) const noexcept;
  724. std::vector<VkPipelineExecutablePropertiesKHR> GetPipelineExecutablePropertiesKHR(
  725. VkPipeline pipeline) const;
  726. std::vector<VkPipelineExecutableStatisticKHR> GetPipelineExecutableStatisticsKHR(
  727. VkPipeline pipeline, u32 executable_index) const;
  728. void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes,
  729. Span<VkCopyDescriptorSet> copies) const noexcept;
  730. void UpdateDescriptorSet(VkDescriptorSet set, VkDescriptorUpdateTemplate update_template,
  731. const void* data) const noexcept {
  732. dld->vkUpdateDescriptorSetWithTemplate(handle, set, update_template, data);
  733. }
  734. VkResult AcquireNextImageKHR(VkSwapchainKHR swapchain, u64 timeout, VkSemaphore semaphore,
  735. VkFence fence, u32* image_index) const noexcept {
  736. return dld->vkAcquireNextImageKHR(handle, swapchain, timeout, semaphore, fence,
  737. image_index);
  738. }
  739. VkResult WaitIdle() const noexcept {
  740. return dld->vkDeviceWaitIdle(handle);
  741. }
  742. void ResetQueryPool(VkQueryPool query_pool, u32 first, u32 count) const noexcept {
  743. dld->vkResetQueryPool(handle, query_pool, first, count);
  744. }
  745. VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size,
  746. void* data, VkDeviceSize stride,
  747. VkQueryResultFlags flags) const noexcept {
  748. return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride,
  749. flags);
  750. }
  751. };
  752. class PhysicalDevice {
  753. public:
  754. constexpr PhysicalDevice() noexcept = default;
  755. constexpr PhysicalDevice(VkPhysicalDevice physical_device_,
  756. const InstanceDispatch& dld_) noexcept
  757. : physical_device{physical_device_}, dld{&dld_} {}
  758. constexpr operator VkPhysicalDevice() const noexcept {
  759. return physical_device;
  760. }
  761. VkPhysicalDeviceProperties GetProperties() const noexcept;
  762. void GetProperties2(VkPhysicalDeviceProperties2&) const noexcept;
  763. VkPhysicalDeviceFeatures GetFeatures() const noexcept;
  764. void GetFeatures2(VkPhysicalDeviceFeatures2&) const noexcept;
  765. VkFormatProperties GetFormatProperties(VkFormat) const noexcept;
  766. std::vector<VkExtensionProperties> EnumerateDeviceExtensionProperties() const;
  767. std::vector<VkQueueFamilyProperties> GetQueueFamilyProperties() const;
  768. std::vector<VkPhysicalDeviceToolProperties> GetPhysicalDeviceToolProperties() const;
  769. bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const;
  770. VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const;
  771. std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const;
  772. std::vector<VkPresentModeKHR> GetSurfacePresentModesKHR(VkSurfaceKHR) const;
  773. VkPhysicalDeviceMemoryProperties2 GetMemoryProperties(
  774. void* next_structures = nullptr) const noexcept;
  775. private:
  776. VkPhysicalDevice physical_device = nullptr;
  777. const InstanceDispatch* dld = nullptr;
  778. };
  779. class CommandBuffer {
  780. public:
  781. CommandBuffer() noexcept = default;
  782. explicit CommandBuffer(VkCommandBuffer handle_, const DeviceDispatch& dld_) noexcept
  783. : handle{handle_}, dld{&dld_} {}
  784. const VkCommandBuffer* address() const noexcept {
  785. return &handle;
  786. }
  787. void Begin(const VkCommandBufferBeginInfo& begin_info) const {
  788. Check(dld->vkBeginCommandBuffer(handle, &begin_info));
  789. }
  790. void End() const {
  791. Check(dld->vkEndCommandBuffer(handle));
  792. }
  793. void BeginRenderPass(const VkRenderPassBeginInfo& renderpass_bi,
  794. VkSubpassContents contents) const noexcept {
  795. dld->vkCmdBeginRenderPass(handle, &renderpass_bi, contents);
  796. }
  797. void EndRenderPass() const noexcept {
  798. dld->vkCmdEndRenderPass(handle);
  799. }
  800. void BeginQuery(VkQueryPool query_pool, u32 query, VkQueryControlFlags flags) const noexcept {
  801. dld->vkCmdBeginQuery(handle, query_pool, query, flags);
  802. }
  803. void EndQuery(VkQueryPool query_pool, u32 query) const noexcept {
  804. dld->vkCmdEndQuery(handle, query_pool, query);
  805. }
  806. void BindDescriptorSets(VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 first,
  807. Span<VkDescriptorSet> sets, Span<u32> dynamic_offsets) const noexcept {
  808. dld->vkCmdBindDescriptorSets(handle, bind_point, layout, first, sets.size(), sets.data(),
  809. dynamic_offsets.size(), dynamic_offsets.data());
  810. }
  811. void PushDescriptorSetWithTemplateKHR(VkDescriptorUpdateTemplate update_template,
  812. VkPipelineLayout layout, u32 set,
  813. const void* data) const noexcept {
  814. dld->vkCmdPushDescriptorSetWithTemplateKHR(handle, update_template, layout, set, data);
  815. }
  816. void BindPipeline(VkPipelineBindPoint bind_point, VkPipeline pipeline) const noexcept {
  817. dld->vkCmdBindPipeline(handle, bind_point, pipeline);
  818. }
  819. void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset,
  820. VkIndexType index_type) const noexcept {
  821. dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type);
  822. }
  823. void BindVertexBuffers(u32 first, u32 count, const VkBuffer* buffers,
  824. const VkDeviceSize* offsets) const noexcept {
  825. dld->vkCmdBindVertexBuffers(handle, first, count, buffers, offsets);
  826. }
  827. void BindVertexBuffer(u32 binding, VkBuffer buffer, VkDeviceSize offset) const noexcept {
  828. BindVertexBuffers(binding, 1, &buffer, &offset);
  829. }
  830. void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex,
  831. u32 first_instance) const noexcept {
  832. dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance);
  833. }
  834. void DrawIndexed(u32 index_count, u32 instance_count, u32 first_index, u32 vertex_offset,
  835. u32 first_instance) const noexcept {
  836. dld->vkCmdDrawIndexed(handle, index_count, instance_count, first_index, vertex_offset,
  837. first_instance);
  838. }
  839. void DrawIndirect(VkBuffer src_buffer, VkDeviceSize src_offset, u32 draw_count,
  840. u32 stride) const noexcept {
  841. dld->vkCmdDrawIndirect(handle, src_buffer, src_offset, draw_count, stride);
  842. }
  843. void DrawIndexedIndirect(VkBuffer src_buffer, VkDeviceSize src_offset, u32 draw_count,
  844. u32 stride) const noexcept {
  845. dld->vkCmdDrawIndexedIndirect(handle, src_buffer, src_offset, draw_count, stride);
  846. }
  847. void DrawIndirectCount(VkBuffer src_buffer, VkDeviceSize src_offset, VkBuffer count_buffer,
  848. VkDeviceSize count_offset, u32 draw_count, u32 stride) const noexcept {
  849. dld->vkCmdDrawIndirectCountKHR(handle, src_buffer, src_offset, count_buffer, count_offset,
  850. draw_count, stride);
  851. }
  852. void DrawIndexedIndirectCount(VkBuffer src_buffer, VkDeviceSize src_offset,
  853. VkBuffer count_buffer, VkDeviceSize count_offset, u32 draw_count,
  854. u32 stride) const noexcept {
  855. dld->vkCmdDrawIndexedIndirectCountKHR(handle, src_buffer, src_offset, count_buffer,
  856. count_offset, draw_count, stride);
  857. }
  858. void ClearAttachments(Span<VkClearAttachment> attachments,
  859. Span<VkClearRect> rects) const noexcept {
  860. dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(),
  861. rects.data());
  862. }
  863. void ClearColorImage(VkImage image, VkImageLayout layout, VkClearColorValue color,
  864. Span<VkImageSubresourceRange> ranges) {
  865. dld->vkCmdClearColorImage(handle, image, layout, &color, ranges.size(), ranges.data());
  866. }
  867. void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  868. VkImageLayout dst_layout, Span<VkImageBlit> regions,
  869. VkFilter filter) const noexcept {
  870. dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  871. regions.data(), filter);
  872. }
  873. void ResolveImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  874. VkImageLayout dst_layout, Span<VkImageResolve> regions) {
  875. dld->vkCmdResolveImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  876. regions.data());
  877. }
  878. void Dispatch(u32 x, u32 y, u32 z) const noexcept {
  879. dld->vkCmdDispatch(handle, x, y, z);
  880. }
  881. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  882. VkDependencyFlags dependency_flags, Span<VkMemoryBarrier> memory_barriers,
  883. Span<VkBufferMemoryBarrier> buffer_barriers,
  884. Span<VkImageMemoryBarrier> image_barriers) const noexcept {
  885. dld->vkCmdPipelineBarrier(handle, src_stage_mask, dst_stage_mask, dependency_flags,
  886. memory_barriers.size(), memory_barriers.data(),
  887. buffer_barriers.size(), buffer_barriers.data(),
  888. image_barriers.size(), image_barriers.data());
  889. }
  890. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  891. VkDependencyFlags dependency_flags = 0) const noexcept {
  892. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, {});
  893. }
  894. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  895. VkDependencyFlags dependency_flags,
  896. const VkMemoryBarrier& memory_barrier) const noexcept {
  897. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, memory_barrier, {}, {});
  898. }
  899. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  900. VkDependencyFlags dependency_flags,
  901. const VkBufferMemoryBarrier& buffer_barrier) const noexcept {
  902. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, buffer_barrier, {});
  903. }
  904. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  905. VkDependencyFlags dependency_flags,
  906. const VkImageMemoryBarrier& image_barrier) const noexcept {
  907. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, image_barrier);
  908. }
  909. void CopyBufferToImage(VkBuffer src_buffer, VkImage dst_image, VkImageLayout dst_image_layout,
  910. Span<VkBufferImageCopy> regions) const noexcept {
  911. dld->vkCmdCopyBufferToImage(handle, src_buffer, dst_image, dst_image_layout, regions.size(),
  912. regions.data());
  913. }
  914. void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
  915. Span<VkBufferCopy> regions) const noexcept {
  916. dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data());
  917. }
  918. void CopyImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  919. VkImageLayout dst_layout, Span<VkImageCopy> regions) const noexcept {
  920. dld->vkCmdCopyImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  921. regions.data());
  922. }
  923. void CopyImageToBuffer(VkImage src_image, VkImageLayout src_layout, VkBuffer dst_buffer,
  924. Span<VkBufferImageCopy> regions) const noexcept {
  925. dld->vkCmdCopyImageToBuffer(handle, src_image, src_layout, dst_buffer, regions.size(),
  926. regions.data());
  927. }
  928. void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size,
  929. u32 data) const noexcept {
  930. dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data);
  931. }
  932. void PushConstants(VkPipelineLayout layout, VkShaderStageFlags flags, u32 offset, u32 size,
  933. const void* values) const noexcept {
  934. dld->vkCmdPushConstants(handle, layout, flags, offset, size, values);
  935. }
  936. template <typename T>
  937. void PushConstants(VkPipelineLayout layout, VkShaderStageFlags flags,
  938. const T& data) const noexcept {
  939. static_assert(std::is_trivially_copyable_v<T>, "<data> is not trivially copyable");
  940. dld->vkCmdPushConstants(handle, layout, flags, 0, static_cast<u32>(sizeof(T)), &data);
  941. }
  942. void SetViewport(u32 first, Span<VkViewport> viewports) const noexcept {
  943. dld->vkCmdSetViewport(handle, first, viewports.size(), viewports.data());
  944. }
  945. void SetScissor(u32 first, Span<VkRect2D> scissors) const noexcept {
  946. dld->vkCmdSetScissor(handle, first, scissors.size(), scissors.data());
  947. }
  948. void SetBlendConstants(const float blend_constants[4]) const noexcept {
  949. dld->vkCmdSetBlendConstants(handle, blend_constants);
  950. }
  951. void SetStencilCompareMask(VkStencilFaceFlags face_mask, u32 compare_mask) const noexcept {
  952. dld->vkCmdSetStencilCompareMask(handle, face_mask, compare_mask);
  953. }
  954. void SetStencilReference(VkStencilFaceFlags face_mask, u32 reference) const noexcept {
  955. dld->vkCmdSetStencilReference(handle, face_mask, reference);
  956. }
  957. void SetStencilWriteMask(VkStencilFaceFlags face_mask, u32 write_mask) const noexcept {
  958. dld->vkCmdSetStencilWriteMask(handle, face_mask, write_mask);
  959. }
  960. void SetDepthBias(float constant_factor, float clamp, float slope_factor) const noexcept {
  961. dld->vkCmdSetDepthBias(handle, constant_factor, clamp, slope_factor);
  962. }
  963. void SetDepthBounds(float min_depth_bounds, float max_depth_bounds) const noexcept {
  964. dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds);
  965. }
  966. void SetEvent(VkEvent event, VkPipelineStageFlags stage_flags) const noexcept {
  967. dld->vkCmdSetEvent(handle, event, stage_flags);
  968. }
  969. void WaitEvents(Span<VkEvent> events, VkPipelineStageFlags src_stage_mask,
  970. VkPipelineStageFlags dst_stage_mask, Span<VkMemoryBarrier> memory_barriers,
  971. Span<VkBufferMemoryBarrier> buffer_barriers,
  972. Span<VkImageMemoryBarrier> image_barriers) const noexcept {
  973. dld->vkCmdWaitEvents(handle, events.size(), events.data(), src_stage_mask, dst_stage_mask,
  974. memory_barriers.size(), memory_barriers.data(), buffer_barriers.size(),
  975. buffer_barriers.data(), image_barriers.size(), image_barriers.data());
  976. }
  977. void BindVertexBuffers2EXT(u32 first_binding, u32 binding_count, const VkBuffer* buffers,
  978. const VkDeviceSize* offsets, const VkDeviceSize* sizes,
  979. const VkDeviceSize* strides) const noexcept {
  980. dld->vkCmdBindVertexBuffers2EXT(handle, first_binding, binding_count, buffers, offsets,
  981. sizes, strides);
  982. }
  983. void SetCullModeEXT(VkCullModeFlags cull_mode) const noexcept {
  984. dld->vkCmdSetCullModeEXT(handle, cull_mode);
  985. }
  986. void SetDepthBoundsTestEnableEXT(bool enable) const noexcept {
  987. dld->vkCmdSetDepthBoundsTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  988. }
  989. void SetDepthCompareOpEXT(VkCompareOp compare_op) const noexcept {
  990. dld->vkCmdSetDepthCompareOpEXT(handle, compare_op);
  991. }
  992. void SetDepthTestEnableEXT(bool enable) const noexcept {
  993. dld->vkCmdSetDepthTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  994. }
  995. void SetDepthWriteEnableEXT(bool enable) const noexcept {
  996. dld->vkCmdSetDepthWriteEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  997. }
  998. void SetPrimitiveRestartEnableEXT(bool enable) const noexcept {
  999. dld->vkCmdSetPrimitiveRestartEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1000. }
  1001. void SetRasterizerDiscardEnableEXT(bool enable) const noexcept {
  1002. dld->vkCmdSetRasterizerDiscardEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1003. }
  1004. void SetDepthBiasEnableEXT(bool enable) const noexcept {
  1005. dld->vkCmdSetDepthBiasEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1006. }
  1007. void SetLogicOpEnableEXT(bool enable) const noexcept {
  1008. dld->vkCmdSetLogicOpEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1009. }
  1010. void SetDepthClampEnableEXT(bool enable) const noexcept {
  1011. dld->vkCmdSetDepthClampEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1012. }
  1013. void SetFrontFaceEXT(VkFrontFace front_face) const noexcept {
  1014. dld->vkCmdSetFrontFaceEXT(handle, front_face);
  1015. }
  1016. void SetLogicOpEXT(VkLogicOp logic_op) const noexcept {
  1017. dld->vkCmdSetLogicOpEXT(handle, logic_op);
  1018. }
  1019. void SetPatchControlPointsEXT(uint32_t patch_control_points) const noexcept {
  1020. dld->vkCmdSetPatchControlPointsEXT(handle, patch_control_points);
  1021. }
  1022. void SetColorWriteMaskEXT(u32 first, Span<VkColorComponentFlags> masks) const noexcept {
  1023. dld->vkCmdSetColorWriteMaskEXT(handle, first, masks.size(), masks.data());
  1024. }
  1025. void SetColorBlendEnableEXT(u32 first, Span<VkBool32> enables) const noexcept {
  1026. dld->vkCmdSetColorBlendEnableEXT(handle, first, enables.size(), enables.data());
  1027. }
  1028. void SetColorBlendEquationEXT(u32 first,
  1029. Span<VkColorBlendEquationEXT> equations) const noexcept {
  1030. dld->vkCmdSetColorBlendEquationEXT(handle, first, equations.size(), equations.data());
  1031. }
  1032. void SetLineWidth(float line_width) const noexcept {
  1033. dld->vkCmdSetLineWidth(handle, line_width);
  1034. }
  1035. void SetPrimitiveTopologyEXT(VkPrimitiveTopology primitive_topology) const noexcept {
  1036. dld->vkCmdSetPrimitiveTopologyEXT(handle, primitive_topology);
  1037. }
  1038. void SetStencilOpEXT(VkStencilFaceFlags face_mask, VkStencilOp fail_op, VkStencilOp pass_op,
  1039. VkStencilOp depth_fail_op, VkCompareOp compare_op) const noexcept {
  1040. dld->vkCmdSetStencilOpEXT(handle, face_mask, fail_op, pass_op, depth_fail_op, compare_op);
  1041. }
  1042. void SetStencilTestEnableEXT(bool enable) const noexcept {
  1043. dld->vkCmdSetStencilTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1044. }
  1045. void SetVertexInputEXT(
  1046. vk::Span<VkVertexInputBindingDescription2EXT> bindings,
  1047. vk::Span<VkVertexInputAttributeDescription2EXT> attributes) const noexcept {
  1048. dld->vkCmdSetVertexInputEXT(handle, bindings.size(), bindings.data(), attributes.size(),
  1049. attributes.data());
  1050. }
  1051. void BindTransformFeedbackBuffersEXT(u32 first, u32 count, const VkBuffer* buffers,
  1052. const VkDeviceSize* offsets,
  1053. const VkDeviceSize* sizes) const noexcept {
  1054. dld->vkCmdBindTransformFeedbackBuffersEXT(handle, first, count, buffers, offsets, sizes);
  1055. }
  1056. void BeginTransformFeedbackEXT(u32 first_counter_buffer, u32 counter_buffers_count,
  1057. const VkBuffer* counter_buffers,
  1058. const VkDeviceSize* counter_buffer_offsets) const noexcept {
  1059. dld->vkCmdBeginTransformFeedbackEXT(handle, first_counter_buffer, counter_buffers_count,
  1060. counter_buffers, counter_buffer_offsets);
  1061. }
  1062. void EndTransformFeedbackEXT(u32 first_counter_buffer, u32 counter_buffers_count,
  1063. const VkBuffer* counter_buffers,
  1064. const VkDeviceSize* counter_buffer_offsets) const noexcept {
  1065. dld->vkCmdEndTransformFeedbackEXT(handle, first_counter_buffer, counter_buffers_count,
  1066. counter_buffers, counter_buffer_offsets);
  1067. }
  1068. void BeginDebugUtilsLabelEXT(const char* label, std::span<float, 4> color) const noexcept {
  1069. const VkDebugUtilsLabelEXT label_info{
  1070. .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
  1071. .pNext = nullptr,
  1072. .pLabelName = label,
  1073. .color{color[0], color[1], color[2], color[3]},
  1074. };
  1075. dld->vkCmdBeginDebugUtilsLabelEXT(handle, &label_info);
  1076. }
  1077. void EndDebugUtilsLabelEXT() const noexcept {
  1078. dld->vkCmdEndDebugUtilsLabelEXT(handle);
  1079. }
  1080. private:
  1081. VkCommandBuffer handle;
  1082. const DeviceDispatch* dld;
  1083. };
  1084. u32 AvailableVersion(const InstanceDispatch& dld) noexcept;
  1085. std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
  1086. const InstanceDispatch& dld);
  1087. std::optional<std::vector<VkLayerProperties>> EnumerateInstanceLayerProperties(
  1088. const InstanceDispatch& dld);
  1089. } // namespace Vulkan::vk