]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/vulkan.h
Initial implementation of Vulkan backend
[libs/gl.git] / source / backends / vulkan / vulkan.h
diff --git a/source/backends/vulkan/vulkan.h b/source/backends/vulkan/vulkan.h
new file mode 100644 (file)
index 0000000..373b75a
--- /dev/null
@@ -0,0 +1,386 @@
+#ifndef MSP_GL_VULKAN_H_
+#define MSP_GL_VULKAN_H_
+
+#include <vulkan/vulkan.h>
+#include <msp/graphics/vulkancontext.h>
+#include "handles.h"
+
+namespace Msp {
+namespace GL {
+
+template<typename T> struct HandleTraits;
+template<> struct HandleTraits<VkBuffer> { using NativeHandle = ::VkBuffer; };
+template<> struct HandleTraits<::VkBuffer> { using Wrapper = VkBuffer; };
+template<> struct HandleTraits<VkCommandBuffer> { using NativeHandle = ::VkCommandBuffer; };
+template<> struct HandleTraits<::VkCommandBuffer> { using Wrapper = VkCommandBuffer; };
+template<> struct HandleTraits<VkCommandPool> { using NativeHandle = ::VkCommandPool; };
+template<> struct HandleTraits<::VkCommandPool> { using Wrapper = VkCommandPool; };
+template<> struct HandleTraits<VkDevice> { using NativeHandle = ::VkDevice; };
+template<> struct HandleTraits<::VkDevice> { using Wrapper = VkDevice; };
+template<> struct HandleTraits<VkDescriptorPool> { using NativeHandle = ::VkDescriptorPool; };
+template<> struct HandleTraits<::VkDescriptorPool> { using Wrapper = VkDescriptorPool; };
+template<> struct HandleTraits<VkDescriptorSet> { using NativeHandle = ::VkDescriptorSet; };
+template<> struct HandleTraits<::VkDescriptorSet> { using Wrapper = VkDescriptorSet; };
+template<> struct HandleTraits<VkDescriptorSetLayout> { using NativeHandle = ::VkDescriptorSetLayout; };
+template<> struct HandleTraits<::VkDescriptorSetLayout> { using Wrapper = VkDescriptorSetLayout; };
+template<> struct HandleTraits<VkDeviceMemory> { using NativeHandle = ::VkDeviceMemory; };
+template<> struct HandleTraits<::VkDeviceMemory> { using Wrapper = VkDeviceMemory; };
+template<> struct HandleTraits<VkFence> { using NativeHandle = ::VkFence; };
+template<> struct HandleTraits<::VkFence> { using Wrapper = VkFence; };
+template<> struct HandleTraits<VkFramebuffer> { using NativeHandle = ::VkFramebuffer; };
+template<> struct HandleTraits<::VkFramebuffer> { using Wrapper = VkFramebuffer; };
+template<> struct HandleTraits<VkImage> { using NativeHandle = ::VkImage; };
+template<> struct HandleTraits<::VkImage> { using Wrapper = VkImage; };
+template<> struct HandleTraits<VkImageView> { using NativeHandle = ::VkImageView; };
+template<> struct HandleTraits<::VkImageView> { using Wrapper = VkImageView; };
+template<> struct HandleTraits<VkPhysicalDevice> { using NativeHandle = ::VkPhysicalDevice; };
+template<> struct HandleTraits<::VkPhysicalDevice> { using Wrapper = VkPhysicalDevice; };
+template<> struct HandleTraits<VkPipeline> { using NativeHandle = ::VkPipeline; };
+template<> struct HandleTraits<::VkPipeline> { using Wrapper = VkPipeline; };
+template<> struct HandleTraits<VkPipelineCache> { using NativeHandle = ::VkPipelineCache; };
+template<> struct HandleTraits<::VkPipelineCache> { using Wrapper = VkPipelineCache; };
+template<> struct HandleTraits<VkPipelineLayout> { using NativeHandle = ::VkPipelineLayout; };
+template<> struct HandleTraits<::VkPipelineLayout> { using Wrapper = VkPipelineLayout; };
+template<> struct HandleTraits<VkQueue> { using NativeHandle = ::VkQueue; };
+template<> struct HandleTraits<::VkQueue> { using Wrapper = VkQueue; };
+template<> struct HandleTraits<VkRenderPass> { using NativeHandle = ::VkRenderPass; };
+template<> struct HandleTraits<::VkRenderPass> { using Wrapper = VkRenderPass; };
+template<> struct HandleTraits<VkSampler> { using NativeHandle = ::VkSampler; };
+template<> struct HandleTraits<::VkSampler> { using Wrapper = VkSampler; };
+template<> struct HandleTraits<VkSemaphore> { using NativeHandle = ::VkSemaphore; };
+template<> struct HandleTraits<::VkSemaphore> { using Wrapper = VkSemaphore; };
+template<> struct HandleTraits<VkShaderModule> { using NativeHandle = ::VkShaderModule; };
+template<> struct HandleTraits<::VkShaderModule> { using Wrapper = VkShaderModule; };
+template<> struct HandleTraits<VkSurface> { using NativeHandle = ::VkSurfaceKHR; };
+template<> struct HandleTraits<::VkSurfaceKHR> { using Wrapper = VkSurface; };
+template<> struct HandleTraits<VkSwapchain> { using NativeHandle = ::VkSwapchainKHR; };
+template<> struct HandleTraits<::VkSwapchainKHR> { using Wrapper = VkSwapchain; };
+
+template<typename T>
+T handle_cast(typename HandleTraits<T>::Wrapper handle)
+{ return reinterpret_cast<T>(handle); }
+
+template<typename T>
+T handle_cast(typename HandleTraits<T>::NativeHandle handle)
+{ return reinterpret_cast<T>(handle); }
+
+template<typename T>
+T handle_cast(typename HandleTraits<typename std::remove_pointer<T>::type>::Wrapper *handle)
+{ return reinterpret_cast<T>(handle); }
+
+template<typename T>
+T handle_cast(const typename HandleTraits<typename std::remove_const<typename std::remove_pointer<T>::type>::type>::Wrapper *handle)
+{ return reinterpret_cast<T>(handle); }
+
+
+class Result
+{
+private:
+       VkResult result;
+       const char *function;
+       bool checked = false;
+
+public:
+       Result(VkResult r, const char *f): result(r), function(f) { }
+       Result(Result &&r): result(r.result), function(r.function) { r.result = VK_SUCCESS; }
+       ~Result() noexcept(false) { if(!checked) check(); }
+
+       bool operator==(VkResult r) { checked = true; return result==r; }
+       void check() { if(result!=VK_SUCCESS) throw Graphics::vulkan_error(result, function); }
+};
+
+
+class VulkanFunctions
+{
+private:
+       const Graphics::VulkanContext &context;
+       ::VkDevice device;
+       ::VkPhysicalDevice physicalDevice;
+       ::VkQueue graphicsQueue;
+
+       PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = 0;  // 5.1
+       PFN_vkCreateCommandPool vkCreateCommandPool = 0;  // 6.2
+       PFN_vkResetCommandPool vkResetCommandPool = 0;  // 6.2
+       PFN_vkDestroyCommandPool vkDestroyCommandPool = 0;  // 6.2
+       PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = 0;  // 6.3
+       PFN_vkBeginCommandBuffer vkBeginCommandBuffer = 0;  // 6.4
+       PFN_vkEndCommandBuffer vkEndCommandBuffer = 0;  // 6.4
+       PFN_vkQueueSubmit vkQueueSubmit = 0;  // 6.5
+       PFN_vkCreateFence vkCreateFence = 0;  // 7.3
+       PFN_vkDestroyFence vkDestroyFence = 0;  // 7.3
+       PFN_vkGetFenceStatus vkGetFenceStatus = 0;  // 7.3
+       PFN_vkResetFences vkResetFences = 0;  // 7.3
+       PFN_vkWaitForFences vkWaitForFences = 0;  // 7.3
+       PFN_vkCreateSemaphore vkCreateSemaphore = 0;  // 7.4
+       PFN_vkDestroySemaphore vkDestroySemaphore = 0;  // 7.4
+       PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = 0;  // 7.6
+       PFN_vkQueueWaitIdle vkQueueWaitIdle = 0;  // 7.8
+       PFN_vkCreateRenderPass vkCreateRenderPass = 0;  // 8.1
+       PFN_vkDestroyRenderPass vkDestroyRenderPass = 0;  // 8.1
+       PFN_vkCreateFramebuffer vkCreateFramebuffer = 0;  // 8.3
+       PFN_vkDestroyFramebuffer vkDestroyFramebuffer = 0;  // 8.3
+       PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass = 0;  // 8.4
+       PFN_vkCmdEndRenderPass vkCmdEndRenderPass = 0;  // 8.4
+       PFN_vkCreateShaderModule vkCreateShaderModule = 0;  // 9.1
+       PFN_vkDestroyShaderModule vkDestroyShaderModule = 0;  // 9.1
+       PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines = 0;  // 10.2
+       PFN_vkDestroyPipeline vkDestroyPipeline = 0;  // 10.4
+       PFN_vkCmdBindPipeline vkCmdBindPipeline = 0;  // 10.10
+       PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties = 0;  // 11.2.1
+       PFN_vkAllocateMemory vkAllocateMemory = 0;  // 11.2.3
+       PFN_vkFreeMemory vkFreeMemory = 0;  // 11.2.8
+       PFN_vkMapMemory vkMapMemory = 0;  // 11.2.9
+       PFN_vkUnmapMemory vkUnmapMemory = 0;  // 11.2.9
+       PFN_vkCreateBuffer vkCreateBuffer = 0;  // 12.1
+       PFN_vkDestroyBuffer vkDestroyBuffer = 0;  // 12.1
+       PFN_vkCreateImageView vkCreateImageView = 0;  // 12.5
+       PFN_vkDestroyImageView vkDestroyImageView = 0;  // 12.5
+       PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements = 0;  // 12.7
+       PFN_vkBindBufferMemory vkBindBufferMemory = 0;  // 12.7
+       PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = 0;  // 14.2.1
+       PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = 0;  // 14.2.1
+       PFN_vkCreatePipelineLayout vkCreatePipelineLayout = 0;  // 14.2.2
+       PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = 0;  // 14.2.2
+       PFN_vkCreateDescriptorPool vkCreateDescriptorPool = 0;  // 14.2.3
+       PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = 0;  // 14.2.3
+       PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = 0;  // 14.2.3
+       PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = 0;  // 14.2.4
+       PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = 0;  // 14.2.7
+       PFN_vkCmdPushConstants vkCmdPushConstants = 0;  // 14.2.10
+       PFN_vkCmdCopyBuffer vkCmdCopyBuffer = 0;  // 19.2
+       PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = 0;  // 20.3
+       PFN_vkCmdDrawIndexed vkCmdDrawIndexed = 0;  // 20.3
+       PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = 0;  // 21.2
+       PFN_vkCmdSetViewport vkCmdSetViewport = 0;  // 24.5
+       PFN_vkCmdSetScissor vkCmdSetScissor = 0;  // 26.1
+       PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilities = 0;  // 30.5.1
+       PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormats = 0;  // 30.5.2
+       PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModes = 0;  // 30.5.3
+       PFN_vkCreateSwapchainKHR vkCreateSwapchain = 0;  // 30.8
+       PFN_vkDestroySwapchainKHR vkDestroySwapchain = 0;  // 30.8
+       PFN_vkGetSwapchainImagesKHR vkGetSwapchainImages = 0;  // 30.8
+       PFN_vkAcquireNextImageKHR vkAcquireNextImage = 0;  // 30.8
+       PFN_vkQueuePresentKHR vkQueuePresent = 0;  // 30.8
+       PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties = 0;  // 39.2
+       PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectName = 0;  // 45.1.1
+
+public:
+       VulkanFunctions(const Graphics::VulkanContext &);
+
+       // Chapter 5: Devices and Queues
+       void GetPhysicalDeviceProperties(VkPhysicalDeviceProperties &rProperties) const
+       { vkGetPhysicalDeviceProperties(physicalDevice, &rProperties); }
+
+       // Chapter 6: Command Buffers
+       Result CreateCommandPool(const VkCommandPoolCreateInfo &rCreateInfo, VkCommandPool &rCommandPool) const
+       { return { vkCreateCommandPool(device, &rCreateInfo, 0, handle_cast<::VkCommandPool *>(&rCommandPool)), "vkCreateCommandPool" }; }
+
+       Result ResetCommandPool(VkCommandPool commandPool, VkCommandPoolResetFlags flags) const
+       { return { vkResetCommandPool(device, handle_cast<::VkCommandPool>(commandPool), flags), "vkResetCommandPool" }; }
+
+       void DestroyCommandPool(VkCommandPool commandPool) const
+       { vkDestroyCommandPool(device, handle_cast<::VkCommandPool>(commandPool), 0); }
+
+       Result AllocateCommandBuffers(const VkCommandBufferAllocateInfo &rAllocateInfo, VkCommandBuffer *pCommandBuffers) const
+       { return { vkAllocateCommandBuffers(device, &rAllocateInfo, handle_cast<::VkCommandBuffer *>(pCommandBuffers)), "vkAllocateCommandBuffers" }; }
+
+       Result BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo &rBeginInfo) const
+       { return { vkBeginCommandBuffer(handle_cast<::VkCommandBuffer>(commandBuffer), &rBeginInfo), "vkBeginCommandBuffer" }; }
+
+       Result EndCommandBuffer(VkCommandBuffer commandBuffer) const
+       { return { vkEndCommandBuffer(handle_cast<::VkCommandBuffer>(commandBuffer)), "vkEndCommandBuffer" }; }
+
+       Result QueueSubmit(std::uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) const
+       { return { vkQueueSubmit(graphicsQueue, submitCount, pSubmits, handle_cast<::VkFence>(fence)), "vkQueueSubmit" }; }
+
+       // Chapter 7: Synchronization and Cache Control
+       Result CreateFence(const VkFenceCreateInfo &rCreateInfo, VkFence &rFence) const
+       { return { vkCreateFence(device, &rCreateInfo, 0, handle_cast<::VkFence *>(&rFence)), "vkCreateFence" }; }
+
+       void DestroyFence(VkFence fence) const
+       { vkDestroyFence(device, handle_cast<::VkFence>(fence), 0); }
+
+       Result GetFenceStatus(VkFence fence) const
+       { return { vkGetFenceStatus(device, handle_cast<::VkFence>(fence)), "vkGetFenceStatus" }; }
+
+       Result ResetFences(std::uint32_t fenceCount, const VkFence *pFences) const
+       { return { vkResetFences(device, fenceCount, handle_cast<const ::VkFence *>(pFences)), "vkResetFences" }; }
+
+       Result WaitForFences(std::uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, std::uint64_t timeout) const
+       { return { vkWaitForFences(device, fenceCount, handle_cast<const ::VkFence *>(pFences), waitAll, timeout), "vkWaitForFences" }; }
+
+       Result CreateSemaphore(const VkSemaphoreCreateInfo &rCreateInfo, VkSemaphore &rSemaphore) const
+       { return { vkCreateSemaphore(device, &rCreateInfo, 0, handle_cast<::VkSemaphore *>(&rSemaphore)), "vkCreateSemaphore" }; }
+
+       void DestroySemaphore(VkSemaphore semaphore) const
+       { vkDestroySemaphore(device, handle_cast<::VkSemaphore>(semaphore), 0); }
+
+       void CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) const
+       { vkCmdPipelineBarrier(handle_cast<::VkCommandBuffer>(commandBuffer), srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); }
+
+       Result QueueWaitIdle() const
+       { return { vkQueueWaitIdle(graphicsQueue), "vkQueueWaitIdle" }; }
+
+       // Chapter 8: Render Pass
+       Result CreateRenderPass(const VkRenderPassCreateInfo &rCreateInfo, VkRenderPass &rRenderPass) const
+       { return { vkCreateRenderPass(device, &rCreateInfo, 0, handle_cast<::VkRenderPass *>(&rRenderPass)), "vkCreateRenderPass" }; }
+
+       void DestroyRenderPass(VkRenderPass renderPass) const
+       { vkDestroyRenderPass(device, handle_cast<::VkRenderPass>(renderPass), 0); }
+
+       Result CreateFramebuffer(const VkFramebufferCreateInfo &rCreateInfo, VkFramebuffer &rFramebuffer) const
+       { return { vkCreateFramebuffer(device, &rCreateInfo, 0, handle_cast<::VkFramebuffer *>(&rFramebuffer)), "vkCreateFramebuffer" }; }
+
+       void DestroyFramebuffer(VkFramebuffer framebuffer) const
+       { vkDestroyFramebuffer(device, handle_cast<::VkFramebuffer>(framebuffer), 0); }
+
+       void CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo &rRenderPassBegin, VkSubpassContents contents) const
+       { vkCmdBeginRenderPass(handle_cast<::VkCommandBuffer>(commandBuffer), &rRenderPassBegin, contents); }
+
+       void CmdEndRenderPass(VkCommandBuffer commandBuffer) const
+       { vkCmdEndRenderPass(handle_cast<::VkCommandBuffer>(commandBuffer)); }
+
+       // Chapter 9: Shaders
+       Result CreateShaderModule(const VkShaderModuleCreateInfo &rCreateInfo, VkShaderModule &rShaderModule) const
+       { return { vkCreateShaderModule(device, &rCreateInfo, 0, handle_cast<::VkShaderModule *>(&rShaderModule)), "vkCreateShaderModule" }; }
+
+       void DestroyShaderModule(VkShaderModule shaderModule) const
+       { vkDestroyShaderModule(device, handle_cast<::VkShaderModule>(shaderModule), 0); }
+
+       // Chapter 10: Pipelines
+       Result CreateGraphicsPipelines(VkPipelineCache pipelineCache, std::uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo *pCreateInfos, VkPipeline *pPipelines) const
+       { return { vkCreateGraphicsPipelines(device, handle_cast<::VkPipelineCache>(pipelineCache), createInfoCount, pCreateInfos, 0, handle_cast<::VkPipeline *>(pPipelines)), "vkCreateGraphicsPipelines" }; }
+
+       void DestroyPipeline(VkPipeline pipeline) const
+       { vkDestroyPipeline(device, handle_cast<::VkPipeline>(pipeline), 0); }
+
+       void CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) const
+       { vkCmdBindPipeline(handle_cast<::VkCommandBuffer>(commandBuffer), pipelineBindPoint, handle_cast<::VkPipeline>(pipeline)); }
+
+       // Chapter 11: Memory Allocation
+       void GetPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties &rMemoryProperties) const
+       { vkGetPhysicalDeviceMemoryProperties(physicalDevice, &rMemoryProperties); }
+
+       Result AllocateMemory(const VkMemoryAllocateInfo &rAllocateInfo, VkDeviceMemory &rMemory) const
+       { return { vkAllocateMemory(device, &rAllocateInfo, 0, handle_cast<::VkDeviceMemory *>(&rMemory)), "vkAllocateMemory" }; }
+
+       Result MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) const
+       { return { vkMapMemory(device, handle_cast<::VkDeviceMemory>(memory), offset, size, flags, ppData), "vkMapMemory" }; }
+
+       void UnmapMemory(VkDeviceMemory memory) const
+       { vkUnmapMemory(device, handle_cast<::VkDeviceMemory>(memory)); }
+
+       void FreeMemory(VkDeviceMemory memory) const
+       { vkFreeMemory(device, handle_cast<::VkDeviceMemory>(memory), 0); }
+
+       // Chapter 12: Resource Creation
+       Result CreateBuffer(const VkBufferCreateInfo &rCreateInfo, VkBuffer &rBuffer) const
+       { return { vkCreateBuffer(device, &rCreateInfo, 0, handle_cast<::VkBuffer *>(&rBuffer)), "vkCreateBuffer" }; }
+
+       void DestroyBuffer(VkBuffer image) const
+       { vkDestroyBuffer(device, handle_cast<::VkBuffer>(image), 0); }
+
+       Result CreateImageView(const VkImageViewCreateInfo &rCreateInfo, VkImageView &rView) const
+       { return { vkCreateImageView(device, &rCreateInfo, 0, handle_cast<::VkImageView *>(&rView)), "vkCreateImageView" }; }
+
+       void DestroyImageView(VkImageView imageView) const
+       { vkDestroyImageView(device, handle_cast<::VkImageView>(imageView), 0); }
+
+       void GetBufferMemoryRequirements(VkBuffer image, VkMemoryRequirements &rMemoryRequirements) const
+       { vkGetBufferMemoryRequirements(device, handle_cast<::VkBuffer>(image), &rMemoryRequirements); }
+
+       Result BindBufferMemory(VkBuffer image, VkDeviceMemory memory, VkDeviceSize memoryOffset) const
+       { return { vkBindBufferMemory(device, handle_cast<::VkBuffer>(image), handle_cast<::VkDeviceMemory>(memory), memoryOffset), "vkBindBufferMemory" }; }
+
+       // Chapter 14: Resource Descriptors
+       Result CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo &rCreateInfo, VkDescriptorSetLayout &rSetLayout) const
+       { return { vkCreateDescriptorSetLayout(device, &rCreateInfo, 0, handle_cast<::VkDescriptorSetLayout *>(&rSetLayout)), "vkCreateDescriptorSetLayout" }; }
+
+       void DestroyDescriptorSetLayout(VkDescriptorSetLayout descriptorSetLayout) const
+       { vkDestroyDescriptorSetLayout(device, handle_cast<::VkDescriptorSetLayout>(descriptorSetLayout), 0); }
+
+       Result CreatePipelineLayout(const VkPipelineLayoutCreateInfo &rCreateInfo, VkPipelineLayout &rPipelineLayout) const
+       { return { vkCreatePipelineLayout(device, &rCreateInfo, 0, handle_cast<::VkPipelineLayout *>(&rPipelineLayout)), "vkCreatePipelineLayout" }; }
+
+       void DestroyPipelineLayout(VkPipelineLayout pipelineLayout) const
+       { vkDestroyPipelineLayout(device, handle_cast<::VkPipelineLayout>(pipelineLayout), 0); }
+
+       Result CreateDescriptorPool(const VkDescriptorPoolCreateInfo &rCreateInfo, VkDescriptorPool &rDescriptorPool) const
+       { return { vkCreateDescriptorPool(device, &rCreateInfo, 0, handle_cast<::VkDescriptorPool *>(&rDescriptorPool)), "vkCreateDescriptorPool" }; }
+
+       void DestroyDescriptorPool(VkDescriptorPool descriptorPool) const
+       { vkDestroyDescriptorPool(device, handle_cast<::VkDescriptorPool>(descriptorPool), 0); }
+
+       Result AllocateDescriptorSets(const VkDescriptorSetAllocateInfo &rAllocateInfo, VkDescriptorSet *pDescriptorSets) const
+       { return { vkAllocateDescriptorSets(device, &rAllocateInfo, handle_cast<::VkDescriptorSet *>(pDescriptorSets)), "vkAllocateDescriptorSets" }; }
+
+       void UpdateDescriptorSets(std::uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, std::uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) const
+       { vkUpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); }
+
+       void CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, std::uint32_t firstSet, std::uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets, std::uint32_t dynamicOffsetCount, const std::uint32_t *pDynamicOffsets) const
+       { vkCmdBindDescriptorSets(handle_cast<::VkCommandBuffer>(commandBuffer), pipelineBindPoint, handle_cast<::VkPipelineLayout>(layout), firstSet, descriptorSetCount, handle_cast<const ::VkDescriptorSet *>(pDescriptorSets), dynamicOffsetCount, pDynamicOffsets); }
+
+       void CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, std::uint32_t offset, std::uint32_t size, const void *pValues) const
+       { vkCmdPushConstants(handle_cast<::VkCommandBuffer>(commandBuffer), handle_cast<::VkPipelineLayout>(layout), stageFlags, offset, size, pValues); }
+
+       // Chapter 19: Copy Commands
+       void CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, std::uint32_t regionCount, const VkBufferCopy *pRegions) const
+       { vkCmdCopyBuffer(handle_cast<::VkCommandBuffer>(commandBuffer), handle_cast<::VkBuffer>(srcBuffer), handle_cast<::VkBuffer>(dstBuffer), regionCount, pRegions); }
+
+       // Chapter 20: Drawing Commands
+       void CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) const
+       { vkCmdBindIndexBuffer(handle_cast<::VkCommandBuffer>(commandBuffer), handle_cast<::VkBuffer>(buffer), offset, indexType); }
+
+       void CmdDrawIndexed(VkCommandBuffer commandBuffer, std::uint32_t indexCount, std::uint32_t instanceCount, std::uint32_t firstIndex, std::int32_t vertexOffset, std::uint32_t firstInstance) const
+       { vkCmdDrawIndexed(handle_cast<::VkCommandBuffer>(commandBuffer), indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); }
+
+       // Chapter 21: Fixed-Function Vertex Processing
+       void CmdBindVertexBuffers(VkCommandBuffer commandBuffer, std::uint32_t firstBinding, std::uint32_t bindingCount, const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) const
+       { vkCmdBindVertexBuffers(handle_cast<::VkCommandBuffer>(commandBuffer), firstBinding, bindingCount, handle_cast<const ::VkBuffer *>(pBuffers), pOffsets); }
+
+       // Chapter 24: Fixed-Function Vertex Post-Processing
+       void CmdSetViewport(VkCommandBuffer commandBuffer, std::uint32_t firstViewport, std::uint32_t viewportCount, const VkViewport *pViewports) const
+       { vkCmdSetViewport(handle_cast<::VkCommandBuffer>(commandBuffer), firstViewport, viewportCount, pViewports); }
+
+       // Chapter 26: Fragment Operations
+       void CmdSetScissor(VkCommandBuffer commandBuffer, std::uint32_t firstScissor, std::uint32_t scissorCount, const VkRect2D *pScissors) const
+       { vkCmdSetScissor(handle_cast<::VkCommandBuffer>(commandBuffer), firstScissor, scissorCount, pScissors); }
+
+       // Chapter 30: Window System Integration (WSI)
+       Result GetPhysicalDeviceSurfaceCapabilities(VkSurface surface, VkSurfaceCapabilitiesKHR &rSurfaceCapabilities) const
+       { return { vkGetPhysicalDeviceSurfaceCapabilities(physicalDevice, handle_cast<::VkSurfaceKHR>(surface), &rSurfaceCapabilities), "vkGetPhysicalDeviceSurfaceCapabilities" }; }
+
+       Result GetPhysicalDeviceSurfaceFormats(VkSurface surface, std::uint32_t &rSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
+       { return { vkGetPhysicalDeviceSurfaceFormats(physicalDevice, handle_cast<::VkSurfaceKHR>(surface), &rSurfaceFormatCount, pSurfaceFormats), "vkGetPhysicalDeviceSurfaceFormats" }; }
+
+       Result GetPhysicalDeviceSurfacePresentModes(VkSurface surface, std::uint32_t &rPresentModeCount, VkPresentModeKHR *pPresentModes) const
+       { return { vkGetPhysicalDeviceSurfacePresentModes(physicalDevice, handle_cast<::VkSurfaceKHR>(surface), &rPresentModeCount, pPresentModes), "vkGetPhysicalDeviceSurfacePresentModes" }; }
+
+       Result CreateSwapchain(const VkSwapchainCreateInfoKHR &rCreateInfo, VkSwapchain &rSwapchain) const
+       { return { vkCreateSwapchain(device, &rCreateInfo, 0, handle_cast<::VkSwapchainKHR *>(&rSwapchain)), "vkCreateSwapchain" }; }
+
+       void DestroySwapchain(VkSwapchain swapchain) const
+       { vkDestroySwapchain(device, handle_cast<::VkSwapchainKHR>(swapchain), 0); }
+
+       void GetSwapchainImages(VkSwapchain swapchain, std::uint32_t &rSwapchainImageCount, VkImage *pSwapchainImages) const
+       { vkGetSwapchainImages(device, handle_cast<::VkSwapchainKHR>(swapchain), &rSwapchainImageCount, handle_cast<::VkImage *>(pSwapchainImages)); }
+
+       Result AcquireNextImage(VkSwapchain swapchain, std::uint64_t timeout, VkSemaphore semaphore, VkFence fence, std::uint32_t &rImageIndex) const
+       { return { vkAcquireNextImageKHR(device, handle_cast<::VkSwapchainKHR>(swapchain), timeout, handle_cast<::VkSemaphore>(semaphore), handle_cast<::VkFence>(fence), &rImageIndex), "vkAcquireNextImageKHR" }; }
+
+       Result QueuePresent(const VkPresentInfoKHR &rPresentInfo) const
+       { return { vkQueuePresent(graphicsQueue, &rPresentInfo), "vkQueuePresent" }; }
+
+       // Chapter 39: Formats
+       void GetPhysicalDeviceFormatProperties(VkFormat format, VkFormatProperties &rFormatProperties) const
+       { vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &rFormatProperties); }
+
+       // Chapter 45: Debugging
+       Result SetDebugUtilsObjectName(const VkDebugUtilsObjectNameInfoEXT &rNameInfo) const
+       { return { vkSetDebugUtilsObjectName(device, &rNameInfo), "vkSetDebugUtilsObjectName" }; }
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif