vulkan_wrapper.h 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368
  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_vkCmdDrawIndirectCount vkCmdDrawIndirectCount{};
  187. PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount{};
  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_vkCreatePipelineCache vkCreatePipelineCache{};
  242. PFN_vkCreatePipelineLayout vkCreatePipelineLayout{};
  243. PFN_vkCreateQueryPool vkCreateQueryPool{};
  244. PFN_vkCreateRenderPass vkCreateRenderPass{};
  245. PFN_vkCreateSampler vkCreateSampler{};
  246. PFN_vkCreateSemaphore vkCreateSemaphore{};
  247. PFN_vkCreateShaderModule vkCreateShaderModule{};
  248. PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR{};
  249. PFN_vkDestroyBuffer vkDestroyBuffer{};
  250. PFN_vkDestroyBufferView vkDestroyBufferView{};
  251. PFN_vkDestroyCommandPool vkDestroyCommandPool{};
  252. PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool{};
  253. PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout{};
  254. PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate{};
  255. PFN_vkDestroyEvent vkDestroyEvent{};
  256. PFN_vkDestroyFence vkDestroyFence{};
  257. PFN_vkDestroyFramebuffer vkDestroyFramebuffer{};
  258. PFN_vkDestroyImage vkDestroyImage{};
  259. PFN_vkDestroyImageView vkDestroyImageView{};
  260. PFN_vkDestroyPipeline vkDestroyPipeline{};
  261. PFN_vkDestroyPipelineCache vkDestroyPipelineCache{};
  262. PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout{};
  263. PFN_vkDestroyQueryPool vkDestroyQueryPool{};
  264. PFN_vkDestroyRenderPass vkDestroyRenderPass{};
  265. PFN_vkDestroySampler vkDestroySampler{};
  266. PFN_vkDestroySemaphore vkDestroySemaphore{};
  267. PFN_vkDestroyShaderModule vkDestroyShaderModule{};
  268. PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR{};
  269. PFN_vkDeviceWaitIdle vkDeviceWaitIdle{};
  270. PFN_vkEndCommandBuffer vkEndCommandBuffer{};
  271. PFN_vkFreeCommandBuffers vkFreeCommandBuffers{};
  272. PFN_vkFreeDescriptorSets vkFreeDescriptorSets{};
  273. PFN_vkFreeMemory vkFreeMemory{};
  274. PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2{};
  275. PFN_vkGetDeviceQueue vkGetDeviceQueue{};
  276. PFN_vkGetEventStatus vkGetEventStatus{};
  277. PFN_vkGetFenceStatus vkGetFenceStatus{};
  278. PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements{};
  279. PFN_vkGetPipelineCacheData vkGetPipelineCacheData{};
  280. PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR{};
  281. #ifdef _WIN32
  282. PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{};
  283. #endif
  284. PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR{};
  285. PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{};
  286. PFN_vkGetQueryPoolResults vkGetQueryPoolResults{};
  287. PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue{};
  288. PFN_vkMapMemory vkMapMemory{};
  289. PFN_vkQueueSubmit vkQueueSubmit{};
  290. PFN_vkResetFences vkResetFences{};
  291. PFN_vkResetQueryPool vkResetQueryPool{};
  292. PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT{};
  293. PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT{};
  294. PFN_vkUnmapMemory vkUnmapMemory{};
  295. PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate{};
  296. PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
  297. PFN_vkWaitForFences vkWaitForFences{};
  298. PFN_vkWaitSemaphores vkWaitSemaphores{};
  299. };
  300. /// Loads instance agnostic function pointers.
  301. /// @return True on success, false on error.
  302. bool Load(InstanceDispatch&) noexcept;
  303. /// Loads instance function pointers.
  304. /// @return True on success, false on error.
  305. bool Load(VkInstance, InstanceDispatch&) noexcept;
  306. void Destroy(VkInstance, const InstanceDispatch&) noexcept;
  307. void Destroy(VkDevice, const InstanceDispatch&) noexcept;
  308. void Destroy(VkDevice, VkBuffer, const DeviceDispatch&) noexcept;
  309. void Destroy(VkDevice, VkBufferView, const DeviceDispatch&) noexcept;
  310. void Destroy(VkDevice, VkCommandPool, const DeviceDispatch&) noexcept;
  311. void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept;
  312. void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept;
  313. void Destroy(VkDevice, VkDescriptorUpdateTemplate, const DeviceDispatch&) noexcept;
  314. void Destroy(VkDevice, VkDeviceMemory, const DeviceDispatch&) noexcept;
  315. void Destroy(VkDevice, VkEvent, const DeviceDispatch&) noexcept;
  316. void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept;
  317. void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept;
  318. void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept;
  319. void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept;
  320. void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept;
  321. void Destroy(VkDevice, VkPipelineCache, const DeviceDispatch&) noexcept;
  322. void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept;
  323. void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept;
  324. void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept;
  325. void Destroy(VkDevice, VkSampler, const DeviceDispatch&) noexcept;
  326. void Destroy(VkDevice, VkSwapchainKHR, const DeviceDispatch&) noexcept;
  327. void Destroy(VkDevice, VkSemaphore, const DeviceDispatch&) noexcept;
  328. void Destroy(VkDevice, VkShaderModule, const DeviceDispatch&) noexcept;
  329. void Destroy(VkInstance, VkDebugUtilsMessengerEXT, const InstanceDispatch&) noexcept;
  330. void Destroy(VkInstance, VkSurfaceKHR, const InstanceDispatch&) noexcept;
  331. VkResult Free(VkDevice, VkDescriptorPool, Span<VkDescriptorSet>, const DeviceDispatch&) noexcept;
  332. VkResult Free(VkDevice, VkCommandPool, Span<VkCommandBuffer>, const DeviceDispatch&) noexcept;
  333. template <typename Type, typename OwnerType, typename Dispatch>
  334. class Handle;
  335. /// Handle with an owning type.
  336. /// Analogue to std::unique_ptr.
  337. template <typename Type, typename OwnerType, typename Dispatch>
  338. class Handle {
  339. public:
  340. /// Construct a handle and hold it's ownership.
  341. explicit Handle(Type handle_, OwnerType owner_, const Dispatch& dld_) noexcept
  342. : handle{handle_}, owner{owner_}, dld{&dld_} {}
  343. /// Construct an empty handle.
  344. Handle() = default;
  345. /// Construct an empty handle.
  346. Handle(std::nullptr_t) {}
  347. /// Copying Vulkan objects is not supported and will never be.
  348. Handle(const Handle&) = delete;
  349. Handle& operator=(const Handle&) = delete;
  350. /// Construct a handle transfering the ownership from another handle.
  351. Handle(Handle&& rhs) noexcept
  352. : handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, dld{rhs.dld} {}
  353. /// Assign the current handle transfering the ownership from another handle.
  354. /// Destroys any previously held object.
  355. Handle& operator=(Handle&& rhs) noexcept {
  356. Release();
  357. handle = std::exchange(rhs.handle, nullptr);
  358. owner = rhs.owner;
  359. dld = rhs.dld;
  360. return *this;
  361. }
  362. /// Destroys the current handle if it existed.
  363. ~Handle() noexcept {
  364. Release();
  365. }
  366. /// Destroys any held object.
  367. void reset() noexcept {
  368. Release();
  369. handle = nullptr;
  370. }
  371. /// Returns the address of the held object.
  372. /// Intended for Vulkan structures that expect a pointer to an array.
  373. const Type* address() const noexcept {
  374. return std::addressof(handle);
  375. }
  376. /// Returns the held Vulkan handle.
  377. Type operator*() const noexcept {
  378. return handle;
  379. }
  380. /// Returns true when there's a held object.
  381. explicit operator bool() const noexcept {
  382. return handle != nullptr;
  383. }
  384. protected:
  385. Type handle = nullptr;
  386. OwnerType owner = nullptr;
  387. const Dispatch* dld = nullptr;
  388. private:
  389. /// Destroys the held object if it exists.
  390. void Release() noexcept {
  391. if (handle) {
  392. Destroy(owner, handle, *dld);
  393. }
  394. }
  395. };
  396. /// Dummy type used to specify a handle has no owner.
  397. struct NoOwner {};
  398. /// Handle without an owning type.
  399. /// Analogue to std::unique_ptr
  400. template <typename Type, typename Dispatch>
  401. class Handle<Type, NoOwner, Dispatch> {
  402. public:
  403. /// Construct a handle and hold it's ownership.
  404. explicit Handle(Type handle_, const Dispatch& dld_) noexcept : handle{handle_}, dld{&dld_} {}
  405. /// Construct an empty handle.
  406. Handle() noexcept = default;
  407. /// Copying Vulkan objects is not supported and will never be.
  408. Handle(const Handle&) = delete;
  409. Handle& operator=(const Handle&) = delete;
  410. /// Construct a handle transfering ownership from another handle.
  411. Handle(Handle&& rhs) noexcept : handle{std::exchange(rhs.handle, nullptr)}, dld{rhs.dld} {}
  412. /// Assign the current handle transfering the ownership from another handle.
  413. /// Destroys any previously held object.
  414. Handle& operator=(Handle&& rhs) noexcept {
  415. Release();
  416. handle = std::exchange(rhs.handle, nullptr);
  417. dld = rhs.dld;
  418. return *this;
  419. }
  420. /// Destroys the current handle if it existed.
  421. ~Handle() noexcept {
  422. Release();
  423. }
  424. /// Destroys any held object.
  425. void reset() noexcept {
  426. Release();
  427. handle = nullptr;
  428. }
  429. /// Returns the address of the held object.
  430. /// Intended for Vulkan structures that expect a pointer to an array.
  431. const Type* address() const noexcept {
  432. return std::addressof(handle);
  433. }
  434. /// Returns the held Vulkan handle.
  435. Type operator*() const noexcept {
  436. return handle;
  437. }
  438. /// Returns true when there's a held object.
  439. operator bool() const noexcept {
  440. return handle != nullptr;
  441. }
  442. protected:
  443. Type handle = nullptr;
  444. const Dispatch* dld = nullptr;
  445. private:
  446. /// Destroys the held object if it exists.
  447. void Release() noexcept {
  448. if (handle) {
  449. Destroy(handle, *dld);
  450. }
  451. }
  452. };
  453. /// Array of a pool allocation.
  454. /// Analogue to std::vector
  455. template <typename AllocationType, typename PoolType>
  456. class PoolAllocations {
  457. public:
  458. /// Construct an empty allocation.
  459. PoolAllocations() = default;
  460. /// Construct an allocation. Errors are reported through IsOutOfPoolMemory().
  461. explicit PoolAllocations(std::unique_ptr<AllocationType[]> allocations_, std::size_t num_,
  462. VkDevice device_, PoolType pool_, const DeviceDispatch& dld_) noexcept
  463. : allocations{std::move(allocations_)}, num{num_}, device{device_}, pool{pool_},
  464. dld{&dld_} {}
  465. /// Copying Vulkan allocations is not supported and will never be.
  466. PoolAllocations(const PoolAllocations&) = delete;
  467. PoolAllocations& operator=(const PoolAllocations&) = delete;
  468. /// Construct an allocation transfering ownership from another allocation.
  469. PoolAllocations(PoolAllocations&& rhs) noexcept
  470. : allocations{std::move(rhs.allocations)}, num{rhs.num}, device{rhs.device}, pool{rhs.pool},
  471. dld{rhs.dld} {}
  472. /// Assign an allocation transfering ownership from another allocation.
  473. PoolAllocations& operator=(PoolAllocations&& rhs) noexcept {
  474. allocations = std::move(rhs.allocations);
  475. num = rhs.num;
  476. device = rhs.device;
  477. pool = rhs.pool;
  478. dld = rhs.dld;
  479. return *this;
  480. }
  481. /// Returns the number of allocations.
  482. std::size_t size() const noexcept {
  483. return num;
  484. }
  485. /// Returns a pointer to the array of allocations.
  486. AllocationType const* data() const noexcept {
  487. return allocations.get();
  488. }
  489. /// Returns the allocation in the specified index.
  490. /// @pre index < size()
  491. AllocationType operator[](std::size_t index) const noexcept {
  492. return allocations[index];
  493. }
  494. /// True when a pool fails to construct.
  495. bool IsOutOfPoolMemory() const noexcept {
  496. return !device;
  497. }
  498. private:
  499. std::unique_ptr<AllocationType[]> allocations;
  500. std::size_t num = 0;
  501. VkDevice device = nullptr;
  502. PoolType pool = nullptr;
  503. const DeviceDispatch* dld = nullptr;
  504. };
  505. using DebugUtilsMessenger = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>;
  506. using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>;
  507. using DescriptorUpdateTemplate = Handle<VkDescriptorUpdateTemplate, VkDevice, DeviceDispatch>;
  508. using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>;
  509. using PipelineLayout = Handle<VkPipelineLayout, VkDevice, DeviceDispatch>;
  510. using QueryPool = Handle<VkQueryPool, VkDevice, DeviceDispatch>;
  511. using RenderPass = Handle<VkRenderPass, VkDevice, DeviceDispatch>;
  512. using Sampler = Handle<VkSampler, VkDevice, DeviceDispatch>;
  513. using SurfaceKHR = Handle<VkSurfaceKHR, VkInstance, InstanceDispatch>;
  514. using DescriptorSets = PoolAllocations<VkDescriptorSet, VkDescriptorPool>;
  515. using CommandBuffers = PoolAllocations<VkCommandBuffer, VkCommandPool>;
  516. /// Vulkan instance owning handle.
  517. class Instance : public Handle<VkInstance, NoOwner, InstanceDispatch> {
  518. using Handle<VkInstance, NoOwner, InstanceDispatch>::Handle;
  519. public:
  520. /// Creates a Vulkan instance.
  521. /// @throw Exception on initialization error.
  522. static Instance Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
  523. InstanceDispatch& dispatch);
  524. /// Enumerates physical devices.
  525. /// @return Physical devices and an empty handle on failure.
  526. /// @throw Exception on Vulkan error.
  527. std::vector<VkPhysicalDevice> EnumeratePhysicalDevices() const;
  528. /// Creates a debug callback messenger.
  529. /// @throw Exception on creation failure.
  530. DebugUtilsMessenger CreateDebugUtilsMessenger(
  531. const VkDebugUtilsMessengerCreateInfoEXT& create_info) const;
  532. /// Returns dispatch table.
  533. const InstanceDispatch& Dispatch() const noexcept {
  534. return *dld;
  535. }
  536. };
  537. class Queue {
  538. public:
  539. /// Construct an empty queue handle.
  540. constexpr Queue() noexcept = default;
  541. /// Construct a queue handle.
  542. constexpr Queue(VkQueue queue_, const DeviceDispatch& dld_) noexcept
  543. : queue{queue_}, dld{&dld_} {}
  544. VkResult Submit(Span<VkSubmitInfo> submit_infos,
  545. VkFence fence = VK_NULL_HANDLE) const noexcept {
  546. return dld->vkQueueSubmit(queue, submit_infos.size(), submit_infos.data(), fence);
  547. }
  548. VkResult Present(const VkPresentInfoKHR& present_info) const noexcept {
  549. return dld->vkQueuePresentKHR(queue, &present_info);
  550. }
  551. private:
  552. VkQueue queue = nullptr;
  553. const DeviceDispatch* dld = nullptr;
  554. };
  555. class Buffer : public Handle<VkBuffer, VkDevice, DeviceDispatch> {
  556. using Handle<VkBuffer, VkDevice, DeviceDispatch>::Handle;
  557. public:
  558. /// Attaches a memory allocation.
  559. void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const;
  560. /// Set object name.
  561. void SetObjectNameEXT(const char* name) const;
  562. };
  563. class BufferView : public Handle<VkBufferView, VkDevice, DeviceDispatch> {
  564. using Handle<VkBufferView, VkDevice, DeviceDispatch>::Handle;
  565. public:
  566. /// Set object name.
  567. void SetObjectNameEXT(const char* name) const;
  568. };
  569. class Image : public Handle<VkImage, VkDevice, DeviceDispatch> {
  570. using Handle<VkImage, VkDevice, DeviceDispatch>::Handle;
  571. public:
  572. /// Attaches a memory allocation.
  573. void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const;
  574. /// Set object name.
  575. void SetObjectNameEXT(const char* name) const;
  576. };
  577. class ImageView : public Handle<VkImageView, VkDevice, DeviceDispatch> {
  578. using Handle<VkImageView, VkDevice, DeviceDispatch>::Handle;
  579. public:
  580. /// Set object name.
  581. void SetObjectNameEXT(const char* name) const;
  582. };
  583. class DeviceMemory : public Handle<VkDeviceMemory, VkDevice, DeviceDispatch> {
  584. using Handle<VkDeviceMemory, VkDevice, DeviceDispatch>::Handle;
  585. public:
  586. int GetMemoryFdKHR() const;
  587. #ifdef _WIN32
  588. HANDLE GetMemoryWin32HandleKHR() const;
  589. #endif
  590. /// Set object name.
  591. void SetObjectNameEXT(const char* name) const;
  592. u8* Map(VkDeviceSize offset, VkDeviceSize size) const {
  593. void* data;
  594. Check(dld->vkMapMemory(owner, handle, offset, size, 0, &data));
  595. return static_cast<u8*>(data);
  596. }
  597. void Unmap() const noexcept {
  598. dld->vkUnmapMemory(owner, handle);
  599. }
  600. };
  601. class Fence : public Handle<VkFence, VkDevice, DeviceDispatch> {
  602. using Handle<VkFence, VkDevice, DeviceDispatch>::Handle;
  603. public:
  604. /// Set object name.
  605. void SetObjectNameEXT(const char* name) const;
  606. VkResult Wait(u64 timeout = std::numeric_limits<u64>::max()) const noexcept {
  607. return dld->vkWaitForFences(owner, 1, &handle, true, timeout);
  608. }
  609. VkResult GetStatus() const noexcept {
  610. return dld->vkGetFenceStatus(owner, handle);
  611. }
  612. void Reset() const {
  613. Check(dld->vkResetFences(owner, 1, &handle));
  614. }
  615. };
  616. class Framebuffer : public Handle<VkFramebuffer, VkDevice, DeviceDispatch> {
  617. using Handle<VkFramebuffer, VkDevice, DeviceDispatch>::Handle;
  618. public:
  619. /// Set object name.
  620. void SetObjectNameEXT(const char* name) const;
  621. };
  622. class DescriptorPool : public Handle<VkDescriptorPool, VkDevice, DeviceDispatch> {
  623. using Handle<VkDescriptorPool, VkDevice, DeviceDispatch>::Handle;
  624. public:
  625. DescriptorSets Allocate(const VkDescriptorSetAllocateInfo& ai) const;
  626. /// Set object name.
  627. void SetObjectNameEXT(const char* name) const;
  628. };
  629. class CommandPool : public Handle<VkCommandPool, VkDevice, DeviceDispatch> {
  630. using Handle<VkCommandPool, VkDevice, DeviceDispatch>::Handle;
  631. public:
  632. CommandBuffers Allocate(std::size_t num_buffers,
  633. VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY) const;
  634. /// Set object name.
  635. void SetObjectNameEXT(const char* name) const;
  636. };
  637. class SwapchainKHR : public Handle<VkSwapchainKHR, VkDevice, DeviceDispatch> {
  638. using Handle<VkSwapchainKHR, VkDevice, DeviceDispatch>::Handle;
  639. public:
  640. std::vector<VkImage> GetImages() const;
  641. };
  642. class Event : public Handle<VkEvent, VkDevice, DeviceDispatch> {
  643. using Handle<VkEvent, VkDevice, DeviceDispatch>::Handle;
  644. public:
  645. /// Set object name.
  646. void SetObjectNameEXT(const char* name) const;
  647. VkResult GetStatus() const noexcept {
  648. return dld->vkGetEventStatus(owner, handle);
  649. }
  650. };
  651. class ShaderModule : public Handle<VkShaderModule, VkDevice, DeviceDispatch> {
  652. using Handle<VkShaderModule, VkDevice, DeviceDispatch>::Handle;
  653. public:
  654. /// Set object name.
  655. void SetObjectNameEXT(const char* name) const;
  656. };
  657. class PipelineCache : public Handle<VkPipelineCache, VkDevice, DeviceDispatch> {
  658. using Handle<VkPipelineCache, VkDevice, DeviceDispatch>::Handle;
  659. public:
  660. /// Set object name.
  661. void SetObjectNameEXT(const char* name) const;
  662. VkResult Read(size_t* size, void* data) const noexcept {
  663. return dld->vkGetPipelineCacheData(owner, handle, size, data);
  664. }
  665. };
  666. class Semaphore : public Handle<VkSemaphore, VkDevice, DeviceDispatch> {
  667. using Handle<VkSemaphore, VkDevice, DeviceDispatch>::Handle;
  668. public:
  669. /// Set object name.
  670. void SetObjectNameEXT(const char* name) const;
  671. [[nodiscard]] u64 GetCounter() const {
  672. u64 value;
  673. Check(dld->vkGetSemaphoreCounterValue(owner, handle, &value));
  674. return value;
  675. }
  676. /**
  677. * Waits for a timeline semaphore on the host.
  678. *
  679. * @param value Value to wait
  680. * @param timeout Time in nanoseconds to timeout
  681. * @return True on successful wait, false on timeout
  682. */
  683. bool Wait(u64 value, u64 timeout = std::numeric_limits<u64>::max()) const {
  684. const VkSemaphoreWaitInfo wait_info{
  685. .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
  686. .pNext = nullptr,
  687. .flags = 0,
  688. .semaphoreCount = 1,
  689. .pSemaphores = &handle,
  690. .pValues = &value,
  691. };
  692. const VkResult result = dld->vkWaitSemaphores(owner, &wait_info, timeout);
  693. switch (result) {
  694. case VK_SUCCESS:
  695. return true;
  696. case VK_TIMEOUT:
  697. return false;
  698. default:
  699. throw Exception(result);
  700. }
  701. }
  702. };
  703. class Device : public Handle<VkDevice, NoOwner, DeviceDispatch> {
  704. using Handle<VkDevice, NoOwner, DeviceDispatch>::Handle;
  705. public:
  706. static Device Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
  707. Span<const char*> enabled_extensions, const void* next,
  708. DeviceDispatch& dispatch);
  709. Queue GetQueue(u32 family_index) const noexcept;
  710. Buffer CreateBuffer(const VkBufferCreateInfo& ci) const;
  711. BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const;
  712. Image CreateImage(const VkImageCreateInfo& ci) const;
  713. ImageView CreateImageView(const VkImageViewCreateInfo& ci) const;
  714. Semaphore CreateSemaphore() const;
  715. Semaphore CreateSemaphore(const VkSemaphoreCreateInfo& ci) const;
  716. Fence CreateFence(const VkFenceCreateInfo& ci) const;
  717. DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const;
  718. RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const;
  719. DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const;
  720. PipelineCache CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const;
  721. PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const;
  722. Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci,
  723. VkPipelineCache cache = nullptr) const;
  724. Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci,
  725. VkPipelineCache cache = nullptr) const;
  726. Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;
  727. Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const;
  728. CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const;
  729. DescriptorUpdateTemplate CreateDescriptorUpdateTemplate(
  730. const VkDescriptorUpdateTemplateCreateInfo& ci) const;
  731. QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const;
  732. ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const;
  733. Event CreateEvent() const;
  734. SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const;
  735. DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept;
  736. DeviceMemory AllocateMemory(const VkMemoryAllocateInfo& ai) const;
  737. VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer buffer,
  738. void* pnext = nullptr) const noexcept;
  739. VkMemoryRequirements GetImageMemoryRequirements(VkImage image) const noexcept;
  740. std::vector<VkPipelineExecutablePropertiesKHR> GetPipelineExecutablePropertiesKHR(
  741. VkPipeline pipeline) const;
  742. std::vector<VkPipelineExecutableStatisticKHR> GetPipelineExecutableStatisticsKHR(
  743. VkPipeline pipeline, u32 executable_index) const;
  744. void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes,
  745. Span<VkCopyDescriptorSet> copies) const noexcept;
  746. void UpdateDescriptorSet(VkDescriptorSet set, VkDescriptorUpdateTemplate update_template,
  747. const void* data) const noexcept {
  748. dld->vkUpdateDescriptorSetWithTemplate(handle, set, update_template, data);
  749. }
  750. VkResult AcquireNextImageKHR(VkSwapchainKHR swapchain, u64 timeout, VkSemaphore semaphore,
  751. VkFence fence, u32* image_index) const noexcept {
  752. return dld->vkAcquireNextImageKHR(handle, swapchain, timeout, semaphore, fence,
  753. image_index);
  754. }
  755. VkResult WaitIdle() const noexcept {
  756. return dld->vkDeviceWaitIdle(handle);
  757. }
  758. void ResetQueryPool(VkQueryPool query_pool, u32 first, u32 count) const noexcept {
  759. dld->vkResetQueryPool(handle, query_pool, first, count);
  760. }
  761. VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size,
  762. void* data, VkDeviceSize stride,
  763. VkQueryResultFlags flags) const noexcept {
  764. return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride,
  765. flags);
  766. }
  767. };
  768. class PhysicalDevice {
  769. public:
  770. constexpr PhysicalDevice() noexcept = default;
  771. constexpr PhysicalDevice(VkPhysicalDevice physical_device_,
  772. const InstanceDispatch& dld_) noexcept
  773. : physical_device{physical_device_}, dld{&dld_} {}
  774. constexpr operator VkPhysicalDevice() const noexcept {
  775. return physical_device;
  776. }
  777. VkPhysicalDeviceProperties GetProperties() const noexcept;
  778. void GetProperties2(VkPhysicalDeviceProperties2&) const noexcept;
  779. VkPhysicalDeviceFeatures GetFeatures() const noexcept;
  780. void GetFeatures2(VkPhysicalDeviceFeatures2&) const noexcept;
  781. VkFormatProperties GetFormatProperties(VkFormat) const noexcept;
  782. std::vector<VkExtensionProperties> EnumerateDeviceExtensionProperties() const;
  783. std::vector<VkQueueFamilyProperties> GetQueueFamilyProperties() const;
  784. std::vector<VkPhysicalDeviceToolProperties> GetPhysicalDeviceToolProperties() const;
  785. bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const;
  786. VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const;
  787. std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const;
  788. std::vector<VkPresentModeKHR> GetSurfacePresentModesKHR(VkSurfaceKHR) const;
  789. VkPhysicalDeviceMemoryProperties2 GetMemoryProperties(
  790. void* next_structures = nullptr) const noexcept;
  791. private:
  792. VkPhysicalDevice physical_device = nullptr;
  793. const InstanceDispatch* dld = nullptr;
  794. };
  795. class CommandBuffer {
  796. public:
  797. CommandBuffer() noexcept = default;
  798. explicit CommandBuffer(VkCommandBuffer handle_, const DeviceDispatch& dld_) noexcept
  799. : handle{handle_}, dld{&dld_} {}
  800. const VkCommandBuffer* address() const noexcept {
  801. return &handle;
  802. }
  803. void Begin(const VkCommandBufferBeginInfo& begin_info) const {
  804. Check(dld->vkBeginCommandBuffer(handle, &begin_info));
  805. }
  806. void End() const {
  807. Check(dld->vkEndCommandBuffer(handle));
  808. }
  809. void BeginRenderPass(const VkRenderPassBeginInfo& renderpass_bi,
  810. VkSubpassContents contents) const noexcept {
  811. dld->vkCmdBeginRenderPass(handle, &renderpass_bi, contents);
  812. }
  813. void EndRenderPass() const noexcept {
  814. dld->vkCmdEndRenderPass(handle);
  815. }
  816. void BeginQuery(VkQueryPool query_pool, u32 query, VkQueryControlFlags flags) const noexcept {
  817. dld->vkCmdBeginQuery(handle, query_pool, query, flags);
  818. }
  819. void EndQuery(VkQueryPool query_pool, u32 query) const noexcept {
  820. dld->vkCmdEndQuery(handle, query_pool, query);
  821. }
  822. void BindDescriptorSets(VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 first,
  823. Span<VkDescriptorSet> sets, Span<u32> dynamic_offsets) const noexcept {
  824. dld->vkCmdBindDescriptorSets(handle, bind_point, layout, first, sets.size(), sets.data(),
  825. dynamic_offsets.size(), dynamic_offsets.data());
  826. }
  827. void PushDescriptorSetWithTemplateKHR(VkDescriptorUpdateTemplate update_template,
  828. VkPipelineLayout layout, u32 set,
  829. const void* data) const noexcept {
  830. dld->vkCmdPushDescriptorSetWithTemplateKHR(handle, update_template, layout, set, data);
  831. }
  832. void BindPipeline(VkPipelineBindPoint bind_point, VkPipeline pipeline) const noexcept {
  833. dld->vkCmdBindPipeline(handle, bind_point, pipeline);
  834. }
  835. void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset,
  836. VkIndexType index_type) const noexcept {
  837. dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type);
  838. }
  839. void BindVertexBuffers(u32 first, u32 count, const VkBuffer* buffers,
  840. const VkDeviceSize* offsets) const noexcept {
  841. dld->vkCmdBindVertexBuffers(handle, first, count, buffers, offsets);
  842. }
  843. void BindVertexBuffer(u32 binding, VkBuffer buffer, VkDeviceSize offset) const noexcept {
  844. BindVertexBuffers(binding, 1, &buffer, &offset);
  845. }
  846. void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex,
  847. u32 first_instance) const noexcept {
  848. dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance);
  849. }
  850. void DrawIndexed(u32 index_count, u32 instance_count, u32 first_index, u32 vertex_offset,
  851. u32 first_instance) const noexcept {
  852. dld->vkCmdDrawIndexed(handle, index_count, instance_count, first_index, vertex_offset,
  853. first_instance);
  854. }
  855. void DrawIndirect(VkBuffer src_buffer, VkDeviceSize src_offset, u32 draw_count,
  856. u32 stride) const noexcept {
  857. dld->vkCmdDrawIndirect(handle, src_buffer, src_offset, draw_count, stride);
  858. }
  859. void DrawIndexedIndirect(VkBuffer src_buffer, VkDeviceSize src_offset, u32 draw_count,
  860. u32 stride) const noexcept {
  861. dld->vkCmdDrawIndexedIndirect(handle, src_buffer, src_offset, draw_count, stride);
  862. }
  863. void DrawIndirectCount(VkBuffer src_buffer, VkDeviceSize src_offset, VkBuffer count_buffer,
  864. VkDeviceSize count_offset, u32 draw_count, u32 stride) const noexcept {
  865. dld->vkCmdDrawIndirectCount(handle, src_buffer, src_offset, count_buffer, count_offset,
  866. draw_count, stride);
  867. }
  868. void DrawIndexedIndirectCount(VkBuffer src_buffer, VkDeviceSize src_offset,
  869. VkBuffer count_buffer, VkDeviceSize count_offset, u32 draw_count,
  870. u32 stride) const noexcept {
  871. dld->vkCmdDrawIndexedIndirectCount(handle, src_buffer, src_offset, count_buffer,
  872. count_offset, draw_count, stride);
  873. }
  874. void ClearAttachments(Span<VkClearAttachment> attachments,
  875. Span<VkClearRect> rects) const noexcept {
  876. dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(),
  877. rects.data());
  878. }
  879. void ClearColorImage(VkImage image, VkImageLayout layout, VkClearColorValue color,
  880. Span<VkImageSubresourceRange> ranges) {
  881. dld->vkCmdClearColorImage(handle, image, layout, &color, ranges.size(), ranges.data());
  882. }
  883. void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  884. VkImageLayout dst_layout, Span<VkImageBlit> regions,
  885. VkFilter filter) const noexcept {
  886. dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  887. regions.data(), filter);
  888. }
  889. void ResolveImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  890. VkImageLayout dst_layout, Span<VkImageResolve> regions) {
  891. dld->vkCmdResolveImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  892. regions.data());
  893. }
  894. void Dispatch(u32 x, u32 y, u32 z) const noexcept {
  895. dld->vkCmdDispatch(handle, x, y, z);
  896. }
  897. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  898. VkDependencyFlags dependency_flags, Span<VkMemoryBarrier> memory_barriers,
  899. Span<VkBufferMemoryBarrier> buffer_barriers,
  900. Span<VkImageMemoryBarrier> image_barriers) const noexcept {
  901. dld->vkCmdPipelineBarrier(handle, src_stage_mask, dst_stage_mask, dependency_flags,
  902. memory_barriers.size(), memory_barriers.data(),
  903. buffer_barriers.size(), buffer_barriers.data(),
  904. image_barriers.size(), image_barriers.data());
  905. }
  906. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  907. VkDependencyFlags dependency_flags = 0) const noexcept {
  908. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, {});
  909. }
  910. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  911. VkDependencyFlags dependency_flags,
  912. const VkMemoryBarrier& memory_barrier) const noexcept {
  913. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, memory_barrier, {}, {});
  914. }
  915. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  916. VkDependencyFlags dependency_flags,
  917. const VkBufferMemoryBarrier& buffer_barrier) const noexcept {
  918. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, buffer_barrier, {});
  919. }
  920. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  921. VkDependencyFlags dependency_flags,
  922. const VkImageMemoryBarrier& image_barrier) const noexcept {
  923. PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, image_barrier);
  924. }
  925. void CopyBufferToImage(VkBuffer src_buffer, VkImage dst_image, VkImageLayout dst_image_layout,
  926. Span<VkBufferImageCopy> regions) const noexcept {
  927. dld->vkCmdCopyBufferToImage(handle, src_buffer, dst_image, dst_image_layout, regions.size(),
  928. regions.data());
  929. }
  930. void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
  931. Span<VkBufferCopy> regions) const noexcept {
  932. dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data());
  933. }
  934. void CopyImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  935. VkImageLayout dst_layout, Span<VkImageCopy> regions) const noexcept {
  936. dld->vkCmdCopyImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  937. regions.data());
  938. }
  939. void CopyImageToBuffer(VkImage src_image, VkImageLayout src_layout, VkBuffer dst_buffer,
  940. Span<VkBufferImageCopy> regions) const noexcept {
  941. dld->vkCmdCopyImageToBuffer(handle, src_image, src_layout, dst_buffer, regions.size(),
  942. regions.data());
  943. }
  944. void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size,
  945. u32 data) const noexcept {
  946. dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data);
  947. }
  948. void PushConstants(VkPipelineLayout layout, VkShaderStageFlags flags, u32 offset, u32 size,
  949. const void* values) const noexcept {
  950. dld->vkCmdPushConstants(handle, layout, flags, offset, size, values);
  951. }
  952. template <typename T>
  953. void PushConstants(VkPipelineLayout layout, VkShaderStageFlags flags,
  954. const T& data) const noexcept {
  955. static_assert(std::is_trivially_copyable_v<T>, "<data> is not trivially copyable");
  956. dld->vkCmdPushConstants(handle, layout, flags, 0, static_cast<u32>(sizeof(T)), &data);
  957. }
  958. void SetViewport(u32 first, Span<VkViewport> viewports) const noexcept {
  959. dld->vkCmdSetViewport(handle, first, viewports.size(), viewports.data());
  960. }
  961. void SetScissor(u32 first, Span<VkRect2D> scissors) const noexcept {
  962. dld->vkCmdSetScissor(handle, first, scissors.size(), scissors.data());
  963. }
  964. void SetBlendConstants(const float blend_constants[4]) const noexcept {
  965. dld->vkCmdSetBlendConstants(handle, blend_constants);
  966. }
  967. void SetStencilCompareMask(VkStencilFaceFlags face_mask, u32 compare_mask) const noexcept {
  968. dld->vkCmdSetStencilCompareMask(handle, face_mask, compare_mask);
  969. }
  970. void SetStencilReference(VkStencilFaceFlags face_mask, u32 reference) const noexcept {
  971. dld->vkCmdSetStencilReference(handle, face_mask, reference);
  972. }
  973. void SetStencilWriteMask(VkStencilFaceFlags face_mask, u32 write_mask) const noexcept {
  974. dld->vkCmdSetStencilWriteMask(handle, face_mask, write_mask);
  975. }
  976. void SetDepthBias(float constant_factor, float clamp, float slope_factor) const noexcept {
  977. dld->vkCmdSetDepthBias(handle, constant_factor, clamp, slope_factor);
  978. }
  979. void SetDepthBounds(float min_depth_bounds, float max_depth_bounds) const noexcept {
  980. dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds);
  981. }
  982. void SetEvent(VkEvent event, VkPipelineStageFlags stage_flags) const noexcept {
  983. dld->vkCmdSetEvent(handle, event, stage_flags);
  984. }
  985. void WaitEvents(Span<VkEvent> events, VkPipelineStageFlags src_stage_mask,
  986. VkPipelineStageFlags dst_stage_mask, Span<VkMemoryBarrier> memory_barriers,
  987. Span<VkBufferMemoryBarrier> buffer_barriers,
  988. Span<VkImageMemoryBarrier> image_barriers) const noexcept {
  989. dld->vkCmdWaitEvents(handle, events.size(), events.data(), src_stage_mask, dst_stage_mask,
  990. memory_barriers.size(), memory_barriers.data(), buffer_barriers.size(),
  991. buffer_barriers.data(), image_barriers.size(), image_barriers.data());
  992. }
  993. void BindVertexBuffers2EXT(u32 first_binding, u32 binding_count, const VkBuffer* buffers,
  994. const VkDeviceSize* offsets, const VkDeviceSize* sizes,
  995. const VkDeviceSize* strides) const noexcept {
  996. dld->vkCmdBindVertexBuffers2EXT(handle, first_binding, binding_count, buffers, offsets,
  997. sizes, strides);
  998. }
  999. void SetCullModeEXT(VkCullModeFlags cull_mode) const noexcept {
  1000. dld->vkCmdSetCullModeEXT(handle, cull_mode);
  1001. }
  1002. void SetDepthBoundsTestEnableEXT(bool enable) const noexcept {
  1003. dld->vkCmdSetDepthBoundsTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1004. }
  1005. void SetDepthCompareOpEXT(VkCompareOp compare_op) const noexcept {
  1006. dld->vkCmdSetDepthCompareOpEXT(handle, compare_op);
  1007. }
  1008. void SetDepthTestEnableEXT(bool enable) const noexcept {
  1009. dld->vkCmdSetDepthTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1010. }
  1011. void SetDepthWriteEnableEXT(bool enable) const noexcept {
  1012. dld->vkCmdSetDepthWriteEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1013. }
  1014. void SetPrimitiveRestartEnableEXT(bool enable) const noexcept {
  1015. dld->vkCmdSetPrimitiveRestartEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1016. }
  1017. void SetRasterizerDiscardEnableEXT(bool enable) const noexcept {
  1018. dld->vkCmdSetRasterizerDiscardEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1019. }
  1020. void SetDepthBiasEnableEXT(bool enable) const noexcept {
  1021. dld->vkCmdSetDepthBiasEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1022. }
  1023. void SetLogicOpEnableEXT(bool enable) const noexcept {
  1024. dld->vkCmdSetLogicOpEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1025. }
  1026. void SetDepthClampEnableEXT(bool enable) const noexcept {
  1027. dld->vkCmdSetDepthClampEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1028. }
  1029. void SetFrontFaceEXT(VkFrontFace front_face) const noexcept {
  1030. dld->vkCmdSetFrontFaceEXT(handle, front_face);
  1031. }
  1032. void SetLogicOpEXT(VkLogicOp logic_op) const noexcept {
  1033. dld->vkCmdSetLogicOpEXT(handle, logic_op);
  1034. }
  1035. void SetPatchControlPointsEXT(uint32_t patch_control_points) const noexcept {
  1036. dld->vkCmdSetPatchControlPointsEXT(handle, patch_control_points);
  1037. }
  1038. void SetColorWriteMaskEXT(u32 first, Span<VkColorComponentFlags> masks) const noexcept {
  1039. dld->vkCmdSetColorWriteMaskEXT(handle, first, masks.size(), masks.data());
  1040. }
  1041. void SetColorBlendEnableEXT(u32 first, Span<VkBool32> enables) const noexcept {
  1042. dld->vkCmdSetColorBlendEnableEXT(handle, first, enables.size(), enables.data());
  1043. }
  1044. void SetColorBlendEquationEXT(u32 first,
  1045. Span<VkColorBlendEquationEXT> equations) const noexcept {
  1046. dld->vkCmdSetColorBlendEquationEXT(handle, first, equations.size(), equations.data());
  1047. }
  1048. void SetLineWidth(float line_width) const noexcept {
  1049. dld->vkCmdSetLineWidth(handle, line_width);
  1050. }
  1051. void SetPrimitiveTopologyEXT(VkPrimitiveTopology primitive_topology) const noexcept {
  1052. dld->vkCmdSetPrimitiveTopologyEXT(handle, primitive_topology);
  1053. }
  1054. void SetStencilOpEXT(VkStencilFaceFlags face_mask, VkStencilOp fail_op, VkStencilOp pass_op,
  1055. VkStencilOp depth_fail_op, VkCompareOp compare_op) const noexcept {
  1056. dld->vkCmdSetStencilOpEXT(handle, face_mask, fail_op, pass_op, depth_fail_op, compare_op);
  1057. }
  1058. void SetStencilTestEnableEXT(bool enable) const noexcept {
  1059. dld->vkCmdSetStencilTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  1060. }
  1061. void SetVertexInputEXT(
  1062. vk::Span<VkVertexInputBindingDescription2EXT> bindings,
  1063. vk::Span<VkVertexInputAttributeDescription2EXT> attributes) const noexcept {
  1064. dld->vkCmdSetVertexInputEXT(handle, bindings.size(), bindings.data(), attributes.size(),
  1065. attributes.data());
  1066. }
  1067. void BindTransformFeedbackBuffersEXT(u32 first, u32 count, const VkBuffer* buffers,
  1068. const VkDeviceSize* offsets,
  1069. const VkDeviceSize* sizes) const noexcept {
  1070. dld->vkCmdBindTransformFeedbackBuffersEXT(handle, first, count, buffers, offsets, sizes);
  1071. }
  1072. void BeginTransformFeedbackEXT(u32 first_counter_buffer, u32 counter_buffers_count,
  1073. const VkBuffer* counter_buffers,
  1074. const VkDeviceSize* counter_buffer_offsets) const noexcept {
  1075. dld->vkCmdBeginTransformFeedbackEXT(handle, first_counter_buffer, counter_buffers_count,
  1076. counter_buffers, counter_buffer_offsets);
  1077. }
  1078. void EndTransformFeedbackEXT(u32 first_counter_buffer, u32 counter_buffers_count,
  1079. const VkBuffer* counter_buffers,
  1080. const VkDeviceSize* counter_buffer_offsets) const noexcept {
  1081. dld->vkCmdEndTransformFeedbackEXT(handle, first_counter_buffer, counter_buffers_count,
  1082. counter_buffers, counter_buffer_offsets);
  1083. }
  1084. void BeginDebugUtilsLabelEXT(const char* label, std::span<float, 4> color) const noexcept {
  1085. const VkDebugUtilsLabelEXT label_info{
  1086. .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
  1087. .pNext = nullptr,
  1088. .pLabelName = label,
  1089. .color{color[0], color[1], color[2], color[3]},
  1090. };
  1091. dld->vkCmdBeginDebugUtilsLabelEXT(handle, &label_info);
  1092. }
  1093. void EndDebugUtilsLabelEXT() const noexcept {
  1094. dld->vkCmdEndDebugUtilsLabelEXT(handle);
  1095. }
  1096. private:
  1097. VkCommandBuffer handle;
  1098. const DeviceDispatch* dld;
  1099. };
  1100. u32 AvailableVersion(const InstanceDispatch& dld) noexcept;
  1101. std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
  1102. const InstanceDispatch& dld);
  1103. std::optional<std::vector<VkLayerProperties>> EnumerateInstanceLayerProperties(
  1104. const InstanceDispatch& dld);
  1105. } // namespace Vulkan::vk