wrapper.h 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  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_vkMapMemory vkMapMemory;
  242. PFN_vkQueueSubmit vkQueueSubmit;
  243. PFN_vkResetFences vkResetFences;
  244. PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT;
  245. PFN_vkUnmapMemory vkUnmapMemory;
  246. PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR;
  247. PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;
  248. PFN_vkWaitForFences vkWaitForFences;
  249. };
  250. /// Loads instance agnostic function pointers.
  251. /// @return True on success, false on error.
  252. bool Load(InstanceDispatch&) noexcept;
  253. /// Loads instance function pointers.
  254. /// @return True on success, false on error.
  255. bool Load(VkInstance, InstanceDispatch&) noexcept;
  256. void Destroy(VkInstance, const InstanceDispatch&) noexcept;
  257. void Destroy(VkDevice, const InstanceDispatch&) noexcept;
  258. void Destroy(VkDevice, VkBuffer, const DeviceDispatch&) noexcept;
  259. void Destroy(VkDevice, VkBufferView, const DeviceDispatch&) noexcept;
  260. void Destroy(VkDevice, VkCommandPool, const DeviceDispatch&) noexcept;
  261. void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept;
  262. void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept;
  263. void Destroy(VkDevice, VkDescriptorUpdateTemplateKHR, const DeviceDispatch&) noexcept;
  264. void Destroy(VkDevice, VkDeviceMemory, const DeviceDispatch&) noexcept;
  265. void Destroy(VkDevice, VkEvent, const DeviceDispatch&) noexcept;
  266. void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept;
  267. void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept;
  268. void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept;
  269. void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept;
  270. void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept;
  271. void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept;
  272. void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept;
  273. void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept;
  274. void Destroy(VkDevice, VkSampler, const DeviceDispatch&) noexcept;
  275. void Destroy(VkDevice, VkSwapchainKHR, const DeviceDispatch&) noexcept;
  276. void Destroy(VkDevice, VkSemaphore, const DeviceDispatch&) noexcept;
  277. void Destroy(VkDevice, VkShaderModule, const DeviceDispatch&) noexcept;
  278. void Destroy(VkInstance, VkDebugUtilsMessengerEXT, const InstanceDispatch&) noexcept;
  279. void Destroy(VkInstance, VkSurfaceKHR, const InstanceDispatch&) noexcept;
  280. VkResult Free(VkDevice, VkDescriptorPool, Span<VkDescriptorSet>, const DeviceDispatch&) noexcept;
  281. VkResult Free(VkDevice, VkCommandPool, Span<VkCommandBuffer>, const DeviceDispatch&) noexcept;
  282. template <typename Type, typename OwnerType, typename Dispatch>
  283. class Handle;
  284. /// Handle with an owning type.
  285. /// Analogue to std::unique_ptr.
  286. template <typename Type, typename OwnerType, typename Dispatch>
  287. class Handle {
  288. public:
  289. /// Construct a handle and hold it's ownership.
  290. explicit Handle(Type handle_, OwnerType owner_, const Dispatch& dld_) noexcept
  291. : handle{handle_}, owner{owner_}, dld{&dld_} {}
  292. /// Construct an empty handle.
  293. Handle() = default;
  294. /// Copying Vulkan objects is not supported and will never be.
  295. Handle(const Handle&) = delete;
  296. Handle& operator=(const Handle&) = delete;
  297. /// Construct a handle transfering the ownership from another handle.
  298. Handle(Handle&& rhs) noexcept
  299. : handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, dld{rhs.dld} {}
  300. /// Assign the current handle transfering the ownership from another handle.
  301. /// Destroys any previously held object.
  302. Handle& operator=(Handle&& rhs) noexcept {
  303. Release();
  304. handle = std::exchange(rhs.handle, nullptr);
  305. owner = rhs.owner;
  306. dld = rhs.dld;
  307. return *this;
  308. }
  309. /// Destroys the current handle if it existed.
  310. ~Handle() noexcept {
  311. Release();
  312. }
  313. /// Destroys any held object.
  314. void reset() noexcept {
  315. Release();
  316. handle = nullptr;
  317. }
  318. /// Returns the address of the held object.
  319. /// Intended for Vulkan structures that expect a pointer to an array.
  320. const Type* address() const noexcept {
  321. return std::addressof(handle);
  322. }
  323. /// Returns the held Vulkan handle.
  324. Type operator*() const noexcept {
  325. return handle;
  326. }
  327. /// Returns true when there's a held object.
  328. explicit operator bool() const noexcept {
  329. return handle != nullptr;
  330. }
  331. protected:
  332. Type handle = nullptr;
  333. OwnerType owner = nullptr;
  334. const Dispatch* dld = nullptr;
  335. private:
  336. /// Destroys the held object if it exists.
  337. void Release() noexcept {
  338. if (handle) {
  339. Destroy(owner, handle, *dld);
  340. }
  341. }
  342. };
  343. /// Dummy type used to specify a handle has no owner.
  344. struct NoOwner {};
  345. /// Handle without an owning type.
  346. /// Analogue to std::unique_ptr
  347. template <typename Type, typename Dispatch>
  348. class Handle<Type, NoOwner, Dispatch> {
  349. public:
  350. /// Construct a handle and hold it's ownership.
  351. explicit Handle(Type handle_, const Dispatch& dld_) noexcept : handle{handle_}, dld{&dld_} {}
  352. /// Construct an empty handle.
  353. Handle() noexcept = default;
  354. /// Copying Vulkan objects is not supported and will never be.
  355. Handle(const Handle&) = delete;
  356. Handle& operator=(const Handle&) = delete;
  357. /// Construct a handle transfering ownership from another handle.
  358. Handle(Handle&& rhs) noexcept : handle{std::exchange(rhs.handle, nullptr)}, dld{rhs.dld} {}
  359. /// Assign the current handle transfering the ownership from another handle.
  360. /// Destroys any previously held object.
  361. Handle& operator=(Handle&& rhs) noexcept {
  362. Release();
  363. handle = std::exchange(rhs.handle, nullptr);
  364. dld = rhs.dld;
  365. return *this;
  366. }
  367. /// Destroys the current handle if it existed.
  368. ~Handle() noexcept {
  369. Release();
  370. }
  371. /// Destroys any held object.
  372. void reset() noexcept {
  373. Release();
  374. handle = nullptr;
  375. }
  376. /// Returns the address of the held object.
  377. /// Intended for Vulkan structures that expect a pointer to an array.
  378. const Type* address() const noexcept {
  379. return std::addressof(handle);
  380. }
  381. /// Returns the held Vulkan handle.
  382. Type operator*() const noexcept {
  383. return handle;
  384. }
  385. /// Returns true when there's a held object.
  386. operator bool() const noexcept {
  387. return handle != nullptr;
  388. }
  389. protected:
  390. Type handle = nullptr;
  391. const Dispatch* dld = nullptr;
  392. private:
  393. /// Destroys the held object if it exists.
  394. void Release() noexcept {
  395. if (handle) {
  396. Destroy(handle, *dld);
  397. }
  398. }
  399. };
  400. /// Array of a pool allocation.
  401. /// Analogue to std::vector
  402. template <typename AllocationType, typename PoolType>
  403. class PoolAllocations {
  404. public:
  405. /// Construct an empty allocation.
  406. PoolAllocations() = default;
  407. /// Construct an allocation. Errors are reported through IsOutOfPoolMemory().
  408. explicit PoolAllocations(std::unique_ptr<AllocationType[]> allocations, std::size_t num,
  409. VkDevice device, PoolType pool, const DeviceDispatch& dld) noexcept
  410. : allocations{std::move(allocations)}, num{num}, device{device}, pool{pool}, dld{&dld} {}
  411. /// Copying Vulkan allocations is not supported and will never be.
  412. PoolAllocations(const PoolAllocations&) = delete;
  413. PoolAllocations& operator=(const PoolAllocations&) = delete;
  414. /// Construct an allocation transfering ownership from another allocation.
  415. PoolAllocations(PoolAllocations&& rhs) noexcept
  416. : allocations{std::move(rhs.allocations)}, num{rhs.num}, device{rhs.device}, pool{rhs.pool},
  417. dld{rhs.dld} {}
  418. /// Assign an allocation transfering ownership from another allocation.
  419. /// Releases any previously held allocation.
  420. PoolAllocations& operator=(PoolAllocations&& rhs) noexcept {
  421. Release();
  422. allocations = std::move(rhs.allocations);
  423. num = rhs.num;
  424. device = rhs.device;
  425. pool = rhs.pool;
  426. dld = rhs.dld;
  427. return *this;
  428. }
  429. /// Destroys any held allocation.
  430. ~PoolAllocations() {
  431. Release();
  432. }
  433. /// Returns the number of allocations.
  434. std::size_t size() const noexcept {
  435. return num;
  436. }
  437. /// Returns a pointer to the array of allocations.
  438. AllocationType const* data() const noexcept {
  439. return allocations.get();
  440. }
  441. /// Returns the allocation in the specified index.
  442. /// @pre index < size()
  443. AllocationType operator[](std::size_t index) const noexcept {
  444. return allocations[index];
  445. }
  446. /// True when a pool fails to construct.
  447. bool IsOutOfPoolMemory() const noexcept {
  448. return !device;
  449. }
  450. private:
  451. /// Destroys the held allocations if they exist.
  452. void Release() noexcept {
  453. if (!allocations) {
  454. return;
  455. }
  456. const Span<AllocationType> span(allocations.get(), num);
  457. const VkResult result = Free(device, pool, span, *dld);
  458. // There's no way to report errors from a destructor.
  459. if (result != VK_SUCCESS) {
  460. std::terminate();
  461. }
  462. }
  463. std::unique_ptr<AllocationType[]> allocations;
  464. std::size_t num = 0;
  465. VkDevice device = nullptr;
  466. PoolType pool = nullptr;
  467. const DeviceDispatch* dld = nullptr;
  468. };
  469. using BufferView = Handle<VkBufferView, VkDevice, DeviceDispatch>;
  470. using DebugCallback = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>;
  471. using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>;
  472. using DescriptorUpdateTemplateKHR = Handle<VkDescriptorUpdateTemplateKHR, VkDevice, DeviceDispatch>;
  473. using Framebuffer = Handle<VkFramebuffer, VkDevice, DeviceDispatch>;
  474. using ImageView = Handle<VkImageView, VkDevice, DeviceDispatch>;
  475. using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>;
  476. using PipelineLayout = Handle<VkPipelineLayout, VkDevice, DeviceDispatch>;
  477. using QueryPool = Handle<VkQueryPool, VkDevice, DeviceDispatch>;
  478. using RenderPass = Handle<VkRenderPass, VkDevice, DeviceDispatch>;
  479. using Sampler = Handle<VkSampler, VkDevice, DeviceDispatch>;
  480. using Semaphore = Handle<VkSemaphore, VkDevice, DeviceDispatch>;
  481. using ShaderModule = Handle<VkShaderModule, VkDevice, DeviceDispatch>;
  482. using SurfaceKHR = Handle<VkSurfaceKHR, VkInstance, InstanceDispatch>;
  483. using DescriptorSets = PoolAllocations<VkDescriptorSet, VkDescriptorPool>;
  484. using CommandBuffers = PoolAllocations<VkCommandBuffer, VkCommandPool>;
  485. /// Vulkan instance owning handle.
  486. class Instance : public Handle<VkInstance, NoOwner, InstanceDispatch> {
  487. using Handle<VkInstance, NoOwner, InstanceDispatch>::Handle;
  488. public:
  489. /// Creates a Vulkan instance. Use "operator bool" for error handling.
  490. static Instance Create(Span<const char*> layers, Span<const char*> extensions,
  491. InstanceDispatch& dld) noexcept;
  492. /// Enumerates physical devices.
  493. /// @return Physical devices and an empty handle on failure.
  494. std::optional<std::vector<VkPhysicalDevice>> EnumeratePhysicalDevices();
  495. /// Tries to create a debug callback messenger. Returns an empty handle on failure.
  496. DebugCallback TryCreateDebugCallback(PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept;
  497. };
  498. class Queue {
  499. public:
  500. /// Construct an empty queue handle.
  501. constexpr Queue() noexcept = default;
  502. /// Construct a queue handle.
  503. constexpr Queue(VkQueue queue, const DeviceDispatch& dld) noexcept : queue{queue}, dld{&dld} {}
  504. VkResult Submit(Span<VkSubmitInfo> submit_infos, VkFence fence) const noexcept {
  505. return dld->vkQueueSubmit(queue, submit_infos.size(), submit_infos.data(), fence);
  506. }
  507. VkResult Present(const VkPresentInfoKHR& present_info) const noexcept {
  508. return dld->vkQueuePresentKHR(queue, &present_info);
  509. }
  510. private:
  511. VkQueue queue = nullptr;
  512. const DeviceDispatch* dld = nullptr;
  513. };
  514. class Buffer : public Handle<VkBuffer, VkDevice, DeviceDispatch> {
  515. using Handle<VkBuffer, VkDevice, DeviceDispatch>::Handle;
  516. public:
  517. /// Attaches a memory allocation.
  518. void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const;
  519. };
  520. class Image : public Handle<VkImage, VkDevice, DeviceDispatch> {
  521. using Handle<VkImage, VkDevice, DeviceDispatch>::Handle;
  522. public:
  523. /// Attaches a memory allocation.
  524. void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const;
  525. };
  526. class DeviceMemory : public Handle<VkDeviceMemory, VkDevice, DeviceDispatch> {
  527. using Handle<VkDeviceMemory, VkDevice, DeviceDispatch>::Handle;
  528. public:
  529. u8* Map(VkDeviceSize offset, VkDeviceSize size) const {
  530. void* data;
  531. Check(dld->vkMapMemory(owner, handle, offset, size, 0, &data));
  532. return static_cast<u8*>(data);
  533. }
  534. void Unmap() const noexcept {
  535. dld->vkUnmapMemory(owner, handle);
  536. }
  537. };
  538. class Fence : public Handle<VkFence, VkDevice, DeviceDispatch> {
  539. using Handle<VkFence, VkDevice, DeviceDispatch>::Handle;
  540. public:
  541. VkResult Wait(u64 timeout = std::numeric_limits<u64>::max()) const noexcept {
  542. return dld->vkWaitForFences(owner, 1, &handle, true, timeout);
  543. }
  544. VkResult GetStatus() const noexcept {
  545. return dld->vkGetFenceStatus(owner, handle);
  546. }
  547. void Reset() const {
  548. Check(dld->vkResetFences(owner, 1, &handle));
  549. }
  550. };
  551. class DescriptorPool : public Handle<VkDescriptorPool, VkDevice, DeviceDispatch> {
  552. using Handle<VkDescriptorPool, VkDevice, DeviceDispatch>::Handle;
  553. public:
  554. DescriptorSets Allocate(const VkDescriptorSetAllocateInfo& ai) const;
  555. };
  556. class CommandPool : public Handle<VkCommandPool, VkDevice, DeviceDispatch> {
  557. using Handle<VkCommandPool, VkDevice, DeviceDispatch>::Handle;
  558. public:
  559. CommandBuffers Allocate(std::size_t num_buffers,
  560. VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY) const;
  561. };
  562. class SwapchainKHR : public Handle<VkSwapchainKHR, VkDevice, DeviceDispatch> {
  563. using Handle<VkSwapchainKHR, VkDevice, DeviceDispatch>::Handle;
  564. public:
  565. std::vector<VkImage> GetImages() const;
  566. };
  567. class Event : public Handle<VkEvent, VkDevice, DeviceDispatch> {
  568. using Handle<VkEvent, VkDevice, DeviceDispatch>::Handle;
  569. public:
  570. VkResult GetStatus() const noexcept {
  571. return dld->vkGetEventStatus(owner, handle);
  572. }
  573. };
  574. class Device : public Handle<VkDevice, NoOwner, DeviceDispatch> {
  575. using Handle<VkDevice, NoOwner, DeviceDispatch>::Handle;
  576. public:
  577. static Device Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
  578. Span<const char*> enabled_extensions, const void* next,
  579. DeviceDispatch& dld) noexcept;
  580. Queue GetQueue(u32 family_index) const noexcept;
  581. Buffer CreateBuffer(const VkBufferCreateInfo& ci) const;
  582. BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const;
  583. Image CreateImage(const VkImageCreateInfo& ci) const;
  584. ImageView CreateImageView(const VkImageViewCreateInfo& ci) const;
  585. Semaphore CreateSemaphore() const;
  586. Fence CreateFence(const VkFenceCreateInfo& ci) const;
  587. DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const;
  588. RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const;
  589. DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const;
  590. PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const;
  591. Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci) const;
  592. Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci) const;
  593. Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;
  594. Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const;
  595. CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const;
  596. DescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplateKHR(
  597. const VkDescriptorUpdateTemplateCreateInfoKHR& ci) const;
  598. QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const;
  599. ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const;
  600. Event CreateNewEvent() const;
  601. SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const;
  602. DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept;
  603. DeviceMemory AllocateMemory(const VkMemoryAllocateInfo& ai) const;
  604. VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer buffer) const noexcept;
  605. VkMemoryRequirements GetImageMemoryRequirements(VkImage image) const noexcept;
  606. void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes,
  607. Span<VkCopyDescriptorSet> copies) const noexcept;
  608. void UpdateDescriptorSet(VkDescriptorSet set, VkDescriptorUpdateTemplateKHR update_template,
  609. const void* data) const noexcept {
  610. dld->vkUpdateDescriptorSetWithTemplateKHR(handle, set, update_template, data);
  611. }
  612. VkResult AcquireNextImageKHR(VkSwapchainKHR swapchain, u64 timeout, VkSemaphore semaphore,
  613. VkFence fence, u32* image_index) const noexcept {
  614. return dld->vkAcquireNextImageKHR(handle, swapchain, timeout, semaphore, fence,
  615. image_index);
  616. }
  617. VkResult WaitIdle() const noexcept {
  618. return dld->vkDeviceWaitIdle(handle);
  619. }
  620. void ResetQueryPoolEXT(VkQueryPool query_pool, u32 first, u32 count) const noexcept {
  621. dld->vkResetQueryPoolEXT(handle, query_pool, first, count);
  622. }
  623. VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size,
  624. void* data, VkDeviceSize stride,
  625. VkQueryResultFlags flags) const noexcept {
  626. return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride,
  627. flags);
  628. }
  629. };
  630. class PhysicalDevice {
  631. public:
  632. constexpr PhysicalDevice() noexcept = default;
  633. constexpr PhysicalDevice(VkPhysicalDevice physical_device, const InstanceDispatch& dld) noexcept
  634. : physical_device{physical_device}, dld{&dld} {}
  635. constexpr operator VkPhysicalDevice() const noexcept {
  636. return physical_device;
  637. }
  638. VkPhysicalDeviceProperties GetProperties() const noexcept;
  639. void GetProperties2KHR(VkPhysicalDeviceProperties2KHR&) const noexcept;
  640. VkPhysicalDeviceFeatures GetFeatures() const noexcept;
  641. void GetFeatures2KHR(VkPhysicalDeviceFeatures2KHR&) const noexcept;
  642. VkFormatProperties GetFormatProperties(VkFormat) const noexcept;
  643. std::vector<VkExtensionProperties> EnumerateDeviceExtensionProperties() const;
  644. std::vector<VkQueueFamilyProperties> GetQueueFamilyProperties() const;
  645. bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const;
  646. VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const;
  647. std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const;
  648. std::vector<VkPresentModeKHR> GetSurfacePresentModesKHR(VkSurfaceKHR) const;
  649. VkPhysicalDeviceMemoryProperties GetMemoryProperties() const noexcept;
  650. private:
  651. VkPhysicalDevice physical_device = nullptr;
  652. const InstanceDispatch* dld = nullptr;
  653. };
  654. class CommandBuffer {
  655. public:
  656. CommandBuffer() noexcept = default;
  657. explicit CommandBuffer(VkCommandBuffer handle, const DeviceDispatch& dld) noexcept
  658. : handle{handle}, dld{&dld} {}
  659. const VkCommandBuffer* address() const noexcept {
  660. return &handle;
  661. }
  662. void Begin(const VkCommandBufferBeginInfo& begin_info) const {
  663. Check(dld->vkBeginCommandBuffer(handle, &begin_info));
  664. }
  665. void End() const {
  666. Check(dld->vkEndCommandBuffer(handle));
  667. }
  668. void BeginRenderPass(const VkRenderPassBeginInfo& renderpass_bi,
  669. VkSubpassContents contents) const noexcept {
  670. dld->vkCmdBeginRenderPass(handle, &renderpass_bi, contents);
  671. }
  672. void EndRenderPass() const noexcept {
  673. dld->vkCmdEndRenderPass(handle);
  674. }
  675. void BeginQuery(VkQueryPool query_pool, u32 query, VkQueryControlFlags flags) const noexcept {
  676. dld->vkCmdBeginQuery(handle, query_pool, query, flags);
  677. }
  678. void EndQuery(VkQueryPool query_pool, u32 query) const noexcept {
  679. dld->vkCmdEndQuery(handle, query_pool, query);
  680. }
  681. void BindDescriptorSets(VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 first,
  682. Span<VkDescriptorSet> sets, Span<u32> dynamic_offsets) const noexcept {
  683. dld->vkCmdBindDescriptorSets(handle, bind_point, layout, first, sets.size(), sets.data(),
  684. dynamic_offsets.size(), dynamic_offsets.data());
  685. }
  686. void BindPipeline(VkPipelineBindPoint bind_point, VkPipeline pipeline) const noexcept {
  687. dld->vkCmdBindPipeline(handle, bind_point, pipeline);
  688. }
  689. void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset,
  690. VkIndexType index_type) const noexcept {
  691. dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type);
  692. }
  693. void BindVertexBuffers(u32 first, u32 count, const VkBuffer* buffers,
  694. const VkDeviceSize* offsets) const noexcept {
  695. dld->vkCmdBindVertexBuffers(handle, first, count, buffers, offsets);
  696. }
  697. void BindVertexBuffer(u32 binding, VkBuffer buffer, VkDeviceSize offset) const noexcept {
  698. BindVertexBuffers(binding, 1, &buffer, &offset);
  699. }
  700. void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex,
  701. u32 first_instance) const noexcept {
  702. dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance);
  703. }
  704. void DrawIndexed(u32 index_count, u32 instance_count, u32 first_index, u32 vertex_offset,
  705. u32 first_instance) const noexcept {
  706. dld->vkCmdDrawIndexed(handle, index_count, instance_count, first_index, vertex_offset,
  707. first_instance);
  708. }
  709. void ClearAttachments(Span<VkClearAttachment> attachments,
  710. Span<VkClearRect> rects) const noexcept {
  711. dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(),
  712. rects.data());
  713. }
  714. void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  715. VkImageLayout dst_layout, Span<VkImageBlit> regions,
  716. VkFilter filter) const noexcept {
  717. dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  718. regions.data(), filter);
  719. }
  720. void Dispatch(u32 x, u32 y, u32 z) const noexcept {
  721. dld->vkCmdDispatch(handle, x, y, z);
  722. }
  723. void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
  724. VkDependencyFlags dependency_flags, Span<VkMemoryBarrier> memory_barriers,
  725. Span<VkBufferMemoryBarrier> buffer_barriers,
  726. Span<VkImageMemoryBarrier> image_barriers) const noexcept {
  727. dld->vkCmdPipelineBarrier(handle, src_stage_mask, dst_stage_mask, dependency_flags,
  728. memory_barriers.size(), memory_barriers.data(),
  729. buffer_barriers.size(), buffer_barriers.data(),
  730. image_barriers.size(), image_barriers.data());
  731. }
  732. void CopyBufferToImage(VkBuffer src_buffer, VkImage dst_image, VkImageLayout dst_image_layout,
  733. Span<VkBufferImageCopy> regions) const noexcept {
  734. dld->vkCmdCopyBufferToImage(handle, src_buffer, dst_image, dst_image_layout, regions.size(),
  735. regions.data());
  736. }
  737. void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
  738. Span<VkBufferCopy> regions) const noexcept {
  739. dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data());
  740. }
  741. void CopyImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
  742. VkImageLayout dst_layout, Span<VkImageCopy> regions) const noexcept {
  743. dld->vkCmdCopyImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
  744. regions.data());
  745. }
  746. void CopyImageToBuffer(VkImage src_image, VkImageLayout src_layout, VkBuffer dst_buffer,
  747. Span<VkBufferImageCopy> regions) const noexcept {
  748. dld->vkCmdCopyImageToBuffer(handle, src_image, src_layout, dst_buffer, regions.size(),
  749. regions.data());
  750. }
  751. void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size,
  752. u32 data) const noexcept {
  753. dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data);
  754. }
  755. void PushConstants(VkPipelineLayout layout, VkShaderStageFlags flags, u32 offset, u32 size,
  756. const void* values) const noexcept {
  757. dld->vkCmdPushConstants(handle, layout, flags, offset, size, values);
  758. }
  759. void SetViewport(u32 first, Span<VkViewport> viewports) const noexcept {
  760. dld->vkCmdSetViewport(handle, first, viewports.size(), viewports.data());
  761. }
  762. void SetScissor(u32 first, Span<VkRect2D> scissors) const noexcept {
  763. dld->vkCmdSetScissor(handle, first, scissors.size(), scissors.data());
  764. }
  765. void SetBlendConstants(const float blend_constants[4]) const noexcept {
  766. dld->vkCmdSetBlendConstants(handle, blend_constants);
  767. }
  768. void SetStencilCompareMask(VkStencilFaceFlags face_mask, u32 compare_mask) const noexcept {
  769. dld->vkCmdSetStencilCompareMask(handle, face_mask, compare_mask);
  770. }
  771. void SetStencilReference(VkStencilFaceFlags face_mask, u32 reference) const noexcept {
  772. dld->vkCmdSetStencilReference(handle, face_mask, reference);
  773. }
  774. void SetStencilWriteMask(VkStencilFaceFlags face_mask, u32 write_mask) const noexcept {
  775. dld->vkCmdSetStencilWriteMask(handle, face_mask, write_mask);
  776. }
  777. void SetDepthBias(float constant_factor, float clamp, float slope_factor) const noexcept {
  778. dld->vkCmdSetDepthBias(handle, constant_factor, clamp, slope_factor);
  779. }
  780. void SetDepthBounds(float min_depth_bounds, float max_depth_bounds) const noexcept {
  781. dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds);
  782. }
  783. void SetEvent(VkEvent event, VkPipelineStageFlags stage_flags) const noexcept {
  784. dld->vkCmdSetEvent(handle, event, stage_flags);
  785. }
  786. void WaitEvents(Span<VkEvent> events, VkPipelineStageFlags src_stage_mask,
  787. VkPipelineStageFlags dst_stage_mask, Span<VkMemoryBarrier> memory_barriers,
  788. Span<VkBufferMemoryBarrier> buffer_barriers,
  789. Span<VkImageMemoryBarrier> image_barriers) const noexcept {
  790. dld->vkCmdWaitEvents(handle, events.size(), events.data(), src_stage_mask, dst_stage_mask,
  791. memory_barriers.size(), memory_barriers.data(), buffer_barriers.size(),
  792. buffer_barriers.data(), image_barriers.size(), image_barriers.data());
  793. }
  794. void BindVertexBuffers2EXT(u32 first_binding, u32 binding_count, const VkBuffer* buffers,
  795. const VkDeviceSize* offsets, const VkDeviceSize* sizes,
  796. const VkDeviceSize* strides) const noexcept {
  797. dld->vkCmdBindVertexBuffers2EXT(handle, first_binding, binding_count, buffers, offsets,
  798. sizes, strides);
  799. }
  800. void SetCullModeEXT(VkCullModeFlags cull_mode) const noexcept {
  801. dld->vkCmdSetCullModeEXT(handle, cull_mode);
  802. }
  803. void SetDepthBoundsTestEnableEXT(bool enable) const noexcept {
  804. dld->vkCmdSetDepthBoundsTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  805. }
  806. void SetDepthCompareOpEXT(VkCompareOp compare_op) const noexcept {
  807. dld->vkCmdSetDepthCompareOpEXT(handle, compare_op);
  808. }
  809. void SetDepthTestEnableEXT(bool enable) const noexcept {
  810. dld->vkCmdSetDepthTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  811. }
  812. void SetDepthWriteEnableEXT(bool enable) const noexcept {
  813. dld->vkCmdSetDepthWriteEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  814. }
  815. void SetFrontFaceEXT(VkFrontFace front_face) const noexcept {
  816. dld->vkCmdSetFrontFaceEXT(handle, front_face);
  817. }
  818. void SetPrimitiveTopologyEXT(VkPrimitiveTopology primitive_topology) const noexcept {
  819. dld->vkCmdSetPrimitiveTopologyEXT(handle, primitive_topology);
  820. }
  821. void SetStencilOpEXT(VkStencilFaceFlags face_mask, VkStencilOp fail_op, VkStencilOp pass_op,
  822. VkStencilOp depth_fail_op, VkCompareOp compare_op) const noexcept {
  823. dld->vkCmdSetStencilOpEXT(handle, face_mask, fail_op, pass_op, depth_fail_op, compare_op);
  824. }
  825. void SetStencilTestEnableEXT(bool enable) const noexcept {
  826. dld->vkCmdSetStencilTestEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
  827. }
  828. void BindTransformFeedbackBuffersEXT(u32 first, u32 count, const VkBuffer* buffers,
  829. const VkDeviceSize* offsets,
  830. const VkDeviceSize* sizes) const noexcept {
  831. dld->vkCmdBindTransformFeedbackBuffersEXT(handle, first, count, buffers, offsets, sizes);
  832. }
  833. void BeginTransformFeedbackEXT(u32 first_counter_buffer, u32 counter_buffers_count,
  834. const VkBuffer* counter_buffers,
  835. const VkDeviceSize* counter_buffer_offsets) const noexcept {
  836. dld->vkCmdBeginTransformFeedbackEXT(handle, first_counter_buffer, counter_buffers_count,
  837. counter_buffers, counter_buffer_offsets);
  838. }
  839. void EndTransformFeedbackEXT(u32 first_counter_buffer, u32 counter_buffers_count,
  840. const VkBuffer* counter_buffers,
  841. const VkDeviceSize* counter_buffer_offsets) const noexcept {
  842. dld->vkCmdEndTransformFeedbackEXT(handle, first_counter_buffer, counter_buffers_count,
  843. counter_buffers, counter_buffer_offsets);
  844. }
  845. private:
  846. VkCommandBuffer handle;
  847. const DeviceDispatch* dld;
  848. };
  849. std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
  850. const InstanceDispatch& dld);
  851. std::optional<std::vector<VkLayerProperties>> EnumerateInstanceLayerProperties(
  852. const InstanceDispatch& dld);
  853. } // namespace Vulkan::vk