wrapper.h 42 KB

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