vulkan_wrapper.h 48 KB

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