gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/internal/vk/vulkan.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  //go:build linux || freebsd
     4  // +build linux freebsd
     5  
     6  package vk
     7  
     8  /*
     9  #cgo linux freebsd LDFLAGS: -ldl
    10  #cgo freebsd CFLAGS: -I/usr/local/include
    11  #cgo CFLAGS: -Werror -Werror=return-type
    12  
    13  #define VK_NO_PROTOTYPES 1
    14  #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
    15  #include <vulkan/vulkan.h>
    16  #define __USE_GNU
    17  #include <dlfcn.h>
    18  #include <stdlib.h>
    19  
    20  static VkResult vkCreateInstance(PFN_vkCreateInstance f, VkInstanceCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
    21  	return f(&pCreateInfo, pAllocator, pInstance);
    22  }
    23  
    24  static void vkDestroyInstance(PFN_vkDestroyInstance f, VkInstance instance, const VkAllocationCallbacks *pAllocator) {
    25  	f(instance, pAllocator);
    26  }
    27  
    28  static VkResult vkEnumeratePhysicalDevices(PFN_vkEnumeratePhysicalDevices f, VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
    29  	return f(instance, pPhysicalDeviceCount, pPhysicalDevices);
    30  }
    31  
    32  static void vkGetPhysicalDeviceQueueFamilyProperties(PFN_vkGetPhysicalDeviceQueueFamilyProperties f, VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties) {
    33  	f(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
    34  }
    35  
    36  static void vkGetPhysicalDeviceFormatProperties(PFN_vkGetPhysicalDeviceFormatProperties f, VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
    37  	f(physicalDevice, format, pFormatProperties);
    38  }
    39  
    40  static VkResult vkCreateDevice(PFN_vkCreateDevice f, VkPhysicalDevice physicalDevice, VkDeviceCreateInfo pCreateInfo, VkDeviceQueueCreateInfo qinf, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
    41  	pCreateInfo.pQueueCreateInfos = &qinf;
    42  	return f(physicalDevice, &pCreateInfo, pAllocator, pDevice);
    43  }
    44  
    45  static void vkDestroyDevice(PFN_vkDestroyDevice f, VkDevice device, const VkAllocationCallbacks *pAllocator) {
    46  	f(device, pAllocator);
    47  }
    48  
    49  static void vkGetDeviceQueue(PFN_vkGetDeviceQueue f, VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
    50  	f(device, queueFamilyIndex, queueIndex, pQueue);
    51  }
    52  
    53  static VkResult vkCreateImageView(PFN_vkCreateImageView f, VkDevice device, const VkImageViewCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
    54  	return f(device, pCreateInfo, pAllocator, pView);
    55  }
    56  
    57  static void vkDestroyImageView(PFN_vkDestroyImageView f, VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
    58  	f(device, imageView, pAllocator);
    59  }
    60  
    61  static VkResult vkCreateFramebuffer(PFN_vkCreateFramebuffer f, VkDevice device, VkFramebufferCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) {
    62  	return f(device, &pCreateInfo, pAllocator, pFramebuffer);
    63  }
    64  
    65  static void vkDestroyFramebuffer(PFN_vkDestroyFramebuffer f, VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
    66  	f(device, framebuffer, pAllocator);
    67  }
    68  
    69  static VkResult vkDeviceWaitIdle(PFN_vkDeviceWaitIdle f, VkDevice device) {
    70  	return f(device);
    71  }
    72  
    73  static VkResult vkQueueWaitIdle(PFN_vkQueueWaitIdle f, VkQueue queue) {
    74  	return f(queue);
    75  }
    76  
    77  static VkResult vkCreateSemaphore(PFN_vkCreateSemaphore f, VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
    78  	return f(device, pCreateInfo, pAllocator, pSemaphore);
    79  }
    80  
    81  static void vkDestroySemaphore(PFN_vkDestroySemaphore f, VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
    82  	f(device, semaphore, pAllocator);
    83  }
    84  
    85  static VkResult vkCreateRenderPass(PFN_vkCreateRenderPass f, VkDevice device, VkRenderPassCreateInfo pCreateInfo, VkSubpassDescription subpassInf, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
    86  	pCreateInfo.pSubpasses = &subpassInf;
    87  	return f(device, &pCreateInfo, pAllocator, pRenderPass);
    88  }
    89  
    90  static void vkDestroyRenderPass(PFN_vkDestroyRenderPass f, VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
    91  	f(device, renderPass, pAllocator);
    92  }
    93  
    94  static VkResult vkCreateCommandPool(PFN_vkCreateCommandPool f, VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) {
    95  	return f(device, pCreateInfo, pAllocator, pCommandPool);
    96  }
    97  
    98  static void vkDestroyCommandPool(PFN_vkDestroyCommandPool f, VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
    99  	f(device, commandPool, pAllocator);
   100  }
   101  
   102  static VkResult vkAllocateCommandBuffers(PFN_vkAllocateCommandBuffers f, VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) {
   103  	return f(device, pAllocateInfo, pCommandBuffers);
   104  }
   105  
   106  static void vkFreeCommandBuffers(PFN_vkFreeCommandBuffers f, VkDevice  device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) {
   107  	f(device, commandPool, commandBufferCount, pCommandBuffers);
   108  }
   109  
   110  static VkResult vkBeginCommandBuffer(PFN_vkBeginCommandBuffer f, VkCommandBuffer commandBuffer, VkCommandBufferBeginInfo pBeginInfo) {
   111  	return f(commandBuffer, &pBeginInfo);
   112  }
   113  
   114  static VkResult vkEndCommandBuffer(PFN_vkEndCommandBuffer f, VkCommandBuffer commandBuffer) {
   115  	return f(commandBuffer);
   116  }
   117  
   118  static VkResult vkQueueSubmit(PFN_vkQueueSubmit f, VkQueue queue, VkSubmitInfo pSubmits, VkFence fence) {
   119  	return f(queue, 1, &pSubmits, fence);
   120  }
   121  
   122  static void vkCmdBeginRenderPass(PFN_vkCmdBeginRenderPass f, VkCommandBuffer commandBuffer, VkRenderPassBeginInfo pRenderPassBegin, VkSubpassContents contents) {
   123  	f(commandBuffer, &pRenderPassBegin, contents);
   124  }
   125  
   126  static void vkCmdEndRenderPass(PFN_vkCmdEndRenderPass f, VkCommandBuffer commandBuffer) {
   127  	f(commandBuffer);
   128  }
   129  
   130  static void vkCmdCopyBuffer(PFN_vkCmdCopyBuffer f, VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy *pRegions) {
   131  	f(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
   132  }
   133  
   134  static void vkCmdCopyBufferToImage(PFN_vkCmdCopyBufferToImage f, VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *pRegions) {
   135  	f(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
   136  }
   137  
   138  static void vkCmdPipelineBarrier(PFN_vkCmdPipelineBarrier f, 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) {
   139  	f(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
   140  }
   141  
   142  static void vkCmdPushConstants(PFN_vkCmdPushConstants f, VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void *pValues) {
   143  	f(commandBuffer, layout, stageFlags, offset, size, pValues);
   144  }
   145  
   146  static void vkCmdBindPipeline(PFN_vkCmdBindPipeline f, VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
   147  	f(commandBuffer, pipelineBindPoint, pipeline);
   148  }
   149  
   150  static void vkCmdBindVertexBuffers(PFN_vkCmdBindVertexBuffers f, VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) {
   151  	f(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
   152  }
   153  
   154  static void vkCmdSetViewport(PFN_vkCmdSetViewport f, VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
   155  	f(commandBuffer, firstViewport, viewportCount, pViewports);
   156  }
   157  
   158  static void vkCmdBindIndexBuffer(PFN_vkCmdBindIndexBuffer f, VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
   159  	f(commandBuffer, buffer, offset, indexType);
   160  }
   161  
   162  static void vkCmdDraw(PFN_vkCmdDraw f, VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
   163  	f(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
   164  }
   165  
   166  static void vkCmdDrawIndexed(PFN_vkCmdDrawIndexed f, VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
   167  	f(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
   168  }
   169  
   170  static void vkCmdBindDescriptorSets(PFN_vkCmdBindDescriptorSets f, VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
   171  	f(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
   172  }
   173  
   174  static void vkCmdCopyImageToBuffer(PFN_vkCmdCopyImageToBuffer f, VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) {
   175  	f(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
   176  }
   177  
   178  static void vkCmdDispatch(PFN_vkCmdDispatch f, VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
   179  	f(commandBuffer, groupCountX, groupCountY, groupCountZ);
   180  }
   181  
   182  static VkResult vkCreateImage(PFN_vkCreateImage f, VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
   183  	return f(device, pCreateInfo, pAllocator, pImage);
   184  }
   185  
   186  static void vkDestroyImage(PFN_vkDestroyImage f, VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
   187  	f(device, image, pAllocator);
   188  }
   189  
   190  static void vkGetImageMemoryRequirements(PFN_vkGetImageMemoryRequirements f, VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
   191  	f(device, image, pMemoryRequirements);
   192  }
   193  
   194  static VkResult vkAllocateMemory(PFN_vkAllocateMemory f, VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
   195  	return f(device, pAllocateInfo, pAllocator, pMemory);
   196  }
   197  
   198  static VkResult vkBindImageMemory(PFN_vkBindImageMemory f, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
   199  	return f(device, image, memory, memoryOffset);
   200  }
   201  
   202  static void vkFreeMemory(PFN_vkFreeMemory f, VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
   203  	f(device, memory, pAllocator);
   204  }
   205  
   206  static void vkGetPhysicalDeviceMemoryProperties(PFN_vkGetPhysicalDeviceMemoryProperties f, VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
   207  	f(physicalDevice, pMemoryProperties);
   208  }
   209  
   210  static VkResult vkCreateSampler(PFN_vkCreateSampler f,VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
   211  	return f(device, pCreateInfo, pAllocator, pSampler);
   212  }
   213  
   214  static void vkDestroySampler(PFN_vkDestroySampler f, VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
   215  	f(device, sampler, pAllocator);
   216  }
   217  
   218  static VkResult vkCreateBuffer(PFN_vkCreateBuffer f, VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
   219  	return f(device, pCreateInfo, pAllocator, pBuffer);
   220  }
   221  
   222  static void vkDestroyBuffer(PFN_vkDestroyBuffer f, VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
   223  	f(device, buffer, pAllocator);
   224  }
   225  
   226  static void vkGetBufferMemoryRequirements(PFN_vkGetBufferMemoryRequirements f, VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) {
   227  	f(device, buffer, pMemoryRequirements);
   228  }
   229  
   230  static VkResult vkBindBufferMemory(PFN_vkBindBufferMemory f, VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
   231  	return f(device, buffer, memory, memoryOffset);
   232  }
   233  
   234  static VkResult vkCreateShaderModule(PFN_vkCreateShaderModule f, VkDevice device, VkShaderModuleCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) {
   235  	return f(device, &pCreateInfo, pAllocator, pShaderModule);
   236  }
   237  
   238  static void vkDestroyShaderModule(PFN_vkDestroyShaderModule f, VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) {
   239  	f(device, shaderModule, pAllocator);
   240  }
   241  
   242  static VkResult vkCreateGraphicsPipelines(PFN_vkCreateGraphicsPipelines f, VkDevice device, VkPipelineCache pipelineCache, VkGraphicsPipelineCreateInfo pCreateInfo, VkPipelineDynamicStateCreateInfo dynInf, VkPipelineColorBlendStateCreateInfo blendInf, VkPipelineVertexInputStateCreateInfo vertexInf, VkPipelineViewportStateCreateInfo viewportInf, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
   243  	pCreateInfo.pDynamicState = &dynInf;
   244  	pCreateInfo.pViewportState = &viewportInf;
   245  	pCreateInfo.pColorBlendState = &blendInf;
   246  	pCreateInfo.pVertexInputState = &vertexInf;
   247  	return f(device, pipelineCache, 1, &pCreateInfo, pAllocator, pPipelines);
   248  }
   249  
   250  static void vkDestroyPipeline(PFN_vkDestroyPipeline f, VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
   251  	f(device, pipeline, pAllocator);
   252  }
   253  
   254  static VkResult vkCreatePipelineLayout(PFN_vkCreatePipelineLayout f, VkDevice device, VkPipelineLayoutCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) {
   255  	return f(device, &pCreateInfo, pAllocator, pPipelineLayout);
   256  }
   257  
   258  static void vkDestroyPipelineLayout(PFN_vkDestroyPipelineLayout f, VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) {
   259  	f(device, pipelineLayout, pAllocator);
   260  }
   261  
   262  static VkResult vkCreateDescriptorSetLayout(PFN_vkCreateDescriptorSetLayout f, VkDevice device, VkDescriptorSetLayoutCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) {
   263  	return f(device, &pCreateInfo, pAllocator, pSetLayout);
   264  }
   265  
   266  static void vkDestroyDescriptorSetLayout(PFN_vkDestroyDescriptorSetLayout f, VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) {
   267  	f(device, descriptorSetLayout, pAllocator);
   268  }
   269  
   270  static VkResult vkMapMemory(PFN_vkMapMemory f, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) {
   271  	return f(device, memory, offset, size, flags, ppData);
   272  }
   273  
   274  static void vkUnmapMemory(PFN_vkUnmapMemory f, VkDevice device, VkDeviceMemory memory) {
   275  	f(device, memory);
   276  }
   277  
   278  static VkResult vkResetCommandBuffer(PFN_vkResetCommandBuffer f, VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
   279  	return f(commandBuffer, flags);
   280  }
   281  
   282  static VkResult vkCreateDescriptorPool(PFN_vkCreateDescriptorPool f, VkDevice device, VkDescriptorPoolCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) {
   283  	return f(device, &pCreateInfo, pAllocator, pDescriptorPool);
   284  }
   285  
   286  static void vkDestroyDescriptorPool(PFN_vkDestroyDescriptorPool f, VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) {
   287  	f(device, descriptorPool, pAllocator);
   288  }
   289  
   290  static VkResult vkAllocateDescriptorSets(PFN_vkAllocateDescriptorSets f, VkDevice device, VkDescriptorSetAllocateInfo pAllocateInfo, VkDescriptorSet *pDescriptorSets) {
   291  	return f(device, &pAllocateInfo, pDescriptorSets);
   292  }
   293  
   294  static VkResult vkFreeDescriptorSets(PFN_vkFreeDescriptorSets f, VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets) {
   295  	return f(device, descriptorPool, descriptorSetCount, pDescriptorSets);
   296  }
   297  
   298  static void vkUpdateDescriptorSets(PFN_vkUpdateDescriptorSets f, VkDevice device, VkWriteDescriptorSet pDescriptorWrite, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
   299  	f(device, 1, &pDescriptorWrite, descriptorCopyCount, pDescriptorCopies);
   300  }
   301  
   302  static VkResult vkResetDescriptorPool(PFN_vkResetDescriptorPool f, VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
   303  	return f(device, descriptorPool, flags);
   304  }
   305  
   306  static void vkCmdBlitImage(PFN_vkCmdBlitImage f, VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter) {
   307  	f(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
   308  }
   309  
   310  static void vkCmdCopyImage(PFN_vkCmdCopyImage f, VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) {
   311  	f(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
   312  }
   313  
   314  static VkResult vkCreateComputePipelines(PFN_vkCreateComputePipelines f, VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
   315  	return f(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
   316  }
   317  
   318  static VkResult vkCreateFence(PFN_vkCreateFence f, VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
   319  	return f(device, pCreateInfo, pAllocator, pFence);
   320  }
   321  
   322  static void vkDestroyFence(PFN_vkDestroyFence f, VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
   323  	f(device, fence, pAllocator);
   324  }
   325  
   326  static VkResult vkWaitForFences(PFN_vkWaitForFences f, VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) {
   327  	return f(device, fenceCount, pFences, waitAll, timeout);
   328  }
   329  
   330  static VkResult vkResetFences(PFN_vkResetFences f, VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
   331  	return f(device, fenceCount, pFences);
   332  }
   333  
   334  static void vkGetPhysicalDeviceProperties(PFN_vkGetPhysicalDeviceProperties f, VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
   335  	f(physicalDevice, pProperties);
   336  }
   337  
   338  static VkResult vkGetPhysicalDeviceSurfaceSupportKHR(PFN_vkGetPhysicalDeviceSurfaceSupportKHR f, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 *pSupported) {
   339  	return f(physicalDevice, queueFamilyIndex, surface, pSupported);
   340  }
   341  
   342  static void vkDestroySurfaceKHR(PFN_vkDestroySurfaceKHR f, VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
   343  	f(instance, surface, pAllocator);
   344  }
   345  
   346  static VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(PFN_vkGetPhysicalDeviceSurfaceFormatsKHR f, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) {
   347  	return f(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
   348  }
   349  
   350  static VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(PFN_vkGetPhysicalDeviceSurfacePresentModesKHR f, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) {
   351  	return f(physicalDevice, surface, pPresentModeCount, pPresentModes);
   352  }
   353  
   354  static VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR f, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
   355  	return f(physicalDevice, surface, pSurfaceCapabilities);
   356  }
   357  
   358  static VkResult vkCreateSwapchainKHR(PFN_vkCreateSwapchainKHR f, VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
   359  	return f(device, pCreateInfo, pAllocator, pSwapchain);
   360  }
   361  
   362  static void vkDestroySwapchainKHR(PFN_vkDestroySwapchainKHR f, VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
   363  	f(device, swapchain, pAllocator);
   364  }
   365  
   366  static VkResult vkGetSwapchainImagesKHR(PFN_vkGetSwapchainImagesKHR f, VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
   367  	return f(device, swapchain, pSwapchainImageCount, pSwapchainImages);
   368  }
   369  
   370  // indexAndResult holds both an integer and a result returned by value, to
   371  // avoid Go heap allocation of the integer with Vulkan's return style.
   372  struct intAndResult {
   373  	uint32_t uint;
   374  	VkResult res;
   375  };
   376  
   377  static struct intAndResult vkAcquireNextImageKHR(PFN_vkAcquireNextImageKHR f, VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence) {
   378  	struct intAndResult res;
   379  	res.res = f(device, swapchain, timeout, semaphore, fence, &res.uint);
   380  	return res;
   381  }
   382  
   383  static VkResult vkQueuePresentKHR(PFN_vkQueuePresentKHR f, VkQueue queue, const VkPresentInfoKHR pPresentInfo) {
   384  	return f(queue, &pPresentInfo);
   385  }
   386  */
   387  import "C"
   388  import (
   389  	"errors"
   390  	"fmt"
   391  	"image"
   392  	"math"
   393  	"reflect"
   394  	"runtime"
   395  	"sync"
   396  	"unsafe"
   397  )
   398  
   399  type (
   400  	AttachmentLoadOp      = C.VkAttachmentLoadOp
   401  	AccessFlags           = C.VkAccessFlags
   402  	BlendFactor           = C.VkBlendFactor
   403  	Buffer                = C.VkBuffer
   404  	BufferImageCopy       = C.VkBufferImageCopy
   405  	BufferMemoryBarrier   = C.VkBufferMemoryBarrier
   406  	BufferUsageFlags      = C.VkBufferUsageFlags
   407  	CommandPool           = C.VkCommandPool
   408  	CommandBuffer         = C.VkCommandBuffer
   409  	DependencyFlags       = C.VkDependencyFlags
   410  	DescriptorPool        = C.VkDescriptorPool
   411  	DescriptorPoolSize    = C.VkDescriptorPoolSize
   412  	DescriptorSet         = C.VkDescriptorSet
   413  	DescriptorSetLayout   = C.VkDescriptorSetLayout
   414  	DescriptorType        = C.VkDescriptorType
   415  	Device                = C.VkDevice
   416  	DeviceMemory          = C.VkDeviceMemory
   417  	DeviceSize            = C.VkDeviceSize
   418  	Fence                 = C.VkFence
   419  	Queue                 = C.VkQueue
   420  	IndexType             = C.VkIndexType
   421  	Image                 = C.VkImage
   422  	ImageBlit             = C.VkImageBlit
   423  	ImageCopy             = C.VkImageCopy
   424  	ImageLayout           = C.VkImageLayout
   425  	ImageMemoryBarrier    = C.VkImageMemoryBarrier
   426  	ImageUsageFlags       = C.VkImageUsageFlags
   427  	ImageView             = C.VkImageView
   428  	Instance              = C.VkInstance
   429  	Filter                = C.VkFilter
   430  	Format                = C.VkFormat
   431  	FormatFeatureFlags    = C.VkFormatFeatureFlags
   432  	Framebuffer           = C.VkFramebuffer
   433  	MemoryBarrier         = C.VkMemoryBarrier
   434  	MemoryPropertyFlags   = C.VkMemoryPropertyFlags
   435  	Pipeline              = C.VkPipeline
   436  	PipelineBindPoint     = C.VkPipelineBindPoint
   437  	PipelineLayout        = C.VkPipelineLayout
   438  	PipelineStageFlags    = C.VkPipelineStageFlags
   439  	PhysicalDevice        = C.VkPhysicalDevice
   440  	PrimitiveTopology     = C.VkPrimitiveTopology
   441  	PushConstantRange     = C.VkPushConstantRange
   442  	QueueFamilyProperties = C.VkQueueFamilyProperties
   443  	QueueFlags            = C.VkQueueFlags
   444  	RenderPass            = C.VkRenderPass
   445  	Sampler               = C.VkSampler
   446  	SamplerMipmapMode     = C.VkSamplerMipmapMode
   447  	Semaphore             = C.VkSemaphore
   448  	ShaderModule          = C.VkShaderModule
   449  	ShaderStageFlags      = C.VkShaderStageFlags
   450  	SubpassDependency     = C.VkSubpassDependency
   451  	Viewport              = C.VkViewport
   452  	WriteDescriptorSet    = C.VkWriteDescriptorSet
   453  
   454  	Surface             = C.VkSurfaceKHR
   455  	SurfaceCapabilities = C.VkSurfaceCapabilitiesKHR
   456  
   457  	Swapchain = C.VkSwapchainKHR
   458  )
   459  
   460  type VertexInputBindingDescription struct {
   461  	Binding int
   462  	Stride  int
   463  }
   464  
   465  type VertexInputAttributeDescription struct {
   466  	Location int
   467  	Binding  int
   468  	Format   Format
   469  	Offset   int
   470  }
   471  
   472  type DescriptorSetLayoutBinding struct {
   473  	Binding        int
   474  	DescriptorType DescriptorType
   475  	StageFlags     ShaderStageFlags
   476  }
   477  
   478  type Error C.VkResult
   479  
   480  const (
   481  	FORMAT_R8G8B8A8_UNORM      Format = C.VK_FORMAT_R8G8B8A8_UNORM
   482  	FORMAT_B8G8R8A8_SRGB       Format = C.VK_FORMAT_B8G8R8A8_SRGB
   483  	FORMAT_R8G8B8A8_SRGB       Format = C.VK_FORMAT_R8G8B8A8_SRGB
   484  	FORMAT_R16_SFLOAT          Format = C.VK_FORMAT_R16_SFLOAT
   485  	FORMAT_R32_SFLOAT          Format = C.VK_FORMAT_R32_SFLOAT
   486  	FORMAT_R32G32_SFLOAT       Format = C.VK_FORMAT_R32G32_SFLOAT
   487  	FORMAT_R32G32B32_SFLOAT    Format = C.VK_FORMAT_R32G32B32_SFLOAT
   488  	FORMAT_R32G32B32A32_SFLOAT Format = C.VK_FORMAT_R32G32B32A32_SFLOAT
   489  
   490  	FORMAT_FEATURE_COLOR_ATTACHMENT_BIT            FormatFeatureFlags = C.VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
   491  	FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT      FormatFeatureFlags = C.VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
   492  	FORMAT_FEATURE_SAMPLED_IMAGE_BIT               FormatFeatureFlags = C.VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
   493  	FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT FormatFeatureFlags = C.VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT
   494  
   495  	IMAGE_USAGE_SAMPLED_BIT          ImageUsageFlags = C.VK_IMAGE_USAGE_SAMPLED_BIT
   496  	IMAGE_USAGE_COLOR_ATTACHMENT_BIT ImageUsageFlags = C.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
   497  	IMAGE_USAGE_STORAGE_BIT          ImageUsageFlags = C.VK_IMAGE_USAGE_STORAGE_BIT
   498  	IMAGE_USAGE_TRANSFER_DST_BIT     ImageUsageFlags = C.VK_IMAGE_USAGE_TRANSFER_DST_BIT
   499  	IMAGE_USAGE_TRANSFER_SRC_BIT     ImageUsageFlags = C.VK_IMAGE_USAGE_TRANSFER_SRC_BIT
   500  
   501  	FILTER_NEAREST Filter = C.VK_FILTER_NEAREST
   502  	FILTER_LINEAR  Filter = C.VK_FILTER_LINEAR
   503  
   504  	ATTACHMENT_LOAD_OP_CLEAR     AttachmentLoadOp = C.VK_ATTACHMENT_LOAD_OP_CLEAR
   505  	ATTACHMENT_LOAD_OP_DONT_CARE AttachmentLoadOp = C.VK_ATTACHMENT_LOAD_OP_DONT_CARE
   506  	ATTACHMENT_LOAD_OP_LOAD      AttachmentLoadOp = C.VK_ATTACHMENT_LOAD_OP_LOAD
   507  
   508  	IMAGE_LAYOUT_UNDEFINED                ImageLayout = C.VK_IMAGE_LAYOUT_UNDEFINED
   509  	IMAGE_LAYOUT_PRESENT_SRC_KHR          ImageLayout = C.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
   510  	IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ImageLayout = C.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
   511  	IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ImageLayout = C.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
   512  	IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL     ImageLayout = C.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
   513  	IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL     ImageLayout = C.VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
   514  	IMAGE_LAYOUT_GENERAL                  ImageLayout = C.VK_IMAGE_LAYOUT_GENERAL
   515  
   516  	BUFFER_USAGE_TRANSFER_DST_BIT   BufferUsageFlags = C.VK_BUFFER_USAGE_TRANSFER_DST_BIT
   517  	BUFFER_USAGE_TRANSFER_SRC_BIT   BufferUsageFlags = C.VK_BUFFER_USAGE_TRANSFER_SRC_BIT
   518  	BUFFER_USAGE_UNIFORM_BUFFER_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
   519  	BUFFER_USAGE_STORAGE_BUFFER_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
   520  	BUFFER_USAGE_INDEX_BUFFER_BIT   BufferUsageFlags = C.VK_BUFFER_USAGE_INDEX_BUFFER_BIT
   521  	BUFFER_USAGE_VERTEX_BUFFER_BIT  BufferUsageFlags = C.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
   522  
   523  	ERROR_OUT_OF_DATE_KHR  = Error(C.VK_ERROR_OUT_OF_DATE_KHR)
   524  	ERROR_SURFACE_LOST_KHR = Error(C.VK_ERROR_SURFACE_LOST_KHR)
   525  	ERROR_DEVICE_LOST      = Error(C.VK_ERROR_DEVICE_LOST)
   526  	SUBOPTIMAL_KHR         = Error(C.VK_SUBOPTIMAL_KHR)
   527  
   528  	FENCE_CREATE_SIGNALED_BIT = 0x00000001
   529  
   530  	BLEND_FACTOR_ZERO                BlendFactor = C.VK_BLEND_FACTOR_ZERO
   531  	BLEND_FACTOR_ONE                 BlendFactor = C.VK_BLEND_FACTOR_ONE
   532  	BLEND_FACTOR_ONE_MINUS_SRC_ALPHA BlendFactor = C.VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
   533  	BLEND_FACTOR_DST_COLOR           BlendFactor = C.VK_BLEND_FACTOR_DST_COLOR
   534  
   535  	PRIMITIVE_TOPOLOGY_TRIANGLE_LIST  PrimitiveTopology = C.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
   536  	PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP PrimitiveTopology = C.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
   537  
   538  	SHADER_STAGE_VERTEX_BIT   ShaderStageFlags = C.VK_SHADER_STAGE_VERTEX_BIT
   539  	SHADER_STAGE_FRAGMENT_BIT ShaderStageFlags = C.VK_SHADER_STAGE_FRAGMENT_BIT
   540  	SHADER_STAGE_COMPUTE_BIT  ShaderStageFlags = C.VK_SHADER_STAGE_COMPUTE_BIT
   541  
   542  	DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER DescriptorType = C.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
   543  	DESCRIPTOR_TYPE_UNIFORM_BUFFER         DescriptorType = C.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
   544  	DESCRIPTOR_TYPE_STORAGE_BUFFER         DescriptorType = C.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
   545  	DESCRIPTOR_TYPE_STORAGE_IMAGE          DescriptorType = C.VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
   546  
   547  	MEMORY_PROPERTY_DEVICE_LOCAL_BIT  MemoryPropertyFlags = C.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
   548  	MEMORY_PROPERTY_HOST_VISIBLE_BIT  MemoryPropertyFlags = C.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
   549  	MEMORY_PROPERTY_HOST_COHERENT_BIT MemoryPropertyFlags = C.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
   550  
   551  	DEPENDENCY_BY_REGION_BIT DependencyFlags = C.VK_DEPENDENCY_BY_REGION_BIT
   552  
   553  	PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
   554  	PIPELINE_STAGE_TRANSFER_BIT                PipelineStageFlags = C.VK_PIPELINE_STAGE_TRANSFER_BIT
   555  	PIPELINE_STAGE_FRAGMENT_SHADER_BIT         PipelineStageFlags = C.VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
   556  	PIPELINE_STAGE_COMPUTE_SHADER_BIT          PipelineStageFlags = C.VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
   557  	PIPELINE_STAGE_TOP_OF_PIPE_BIT             PipelineStageFlags = C.VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
   558  	PIPELINE_STAGE_HOST_BIT                    PipelineStageFlags = C.VK_PIPELINE_STAGE_HOST_BIT
   559  	PIPELINE_STAGE_VERTEX_INPUT_BIT            PipelineStageFlags = C.VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
   560  	PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT          PipelineStageFlags = C.VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
   561  
   562  	ACCESS_MEMORY_READ_BIT            AccessFlags = C.VK_ACCESS_MEMORY_READ_BIT
   563  	ACCESS_MEMORY_WRITE_BIT           AccessFlags = C.VK_ACCESS_MEMORY_WRITE_BIT
   564  	ACCESS_TRANSFER_READ_BIT          AccessFlags = C.VK_ACCESS_TRANSFER_READ_BIT
   565  	ACCESS_TRANSFER_WRITE_BIT         AccessFlags = C.VK_ACCESS_TRANSFER_WRITE_BIT
   566  	ACCESS_SHADER_READ_BIT            AccessFlags = C.VK_ACCESS_SHADER_READ_BIT
   567  	ACCESS_SHADER_WRITE_BIT           AccessFlags = C.VK_ACCESS_SHADER_WRITE_BIT
   568  	ACCESS_COLOR_ATTACHMENT_READ_BIT  AccessFlags = C.VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
   569  	ACCESS_COLOR_ATTACHMENT_WRITE_BIT AccessFlags = C.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
   570  	ACCESS_HOST_READ_BIT              AccessFlags = C.VK_ACCESS_HOST_READ_BIT
   571  	ACCESS_HOST_WRITE_BIT             AccessFlags = C.VK_ACCESS_HOST_WRITE_BIT
   572  	ACCESS_VERTEX_ATTRIBUTE_READ_BIT  AccessFlags = C.VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
   573  	ACCESS_INDEX_READ_BIT             AccessFlags = C.VK_ACCESS_INDEX_READ_BIT
   574  
   575  	PIPELINE_BIND_POINT_COMPUTE  PipelineBindPoint = C.VK_PIPELINE_BIND_POINT_COMPUTE
   576  	PIPELINE_BIND_POINT_GRAPHICS PipelineBindPoint = C.VK_PIPELINE_BIND_POINT_GRAPHICS
   577  
   578  	INDEX_TYPE_UINT16 IndexType = C.VK_INDEX_TYPE_UINT16
   579  	INDEX_TYPE_UINT32 IndexType = C.VK_INDEX_TYPE_UINT32
   580  
   581  	QUEUE_GRAPHICS_BIT QueueFlags = C.VK_QUEUE_GRAPHICS_BIT
   582  	QUEUE_COMPUTE_BIT  QueueFlags = C.VK_QUEUE_COMPUTE_BIT
   583  
   584  	SAMPLER_MIPMAP_MODE_NEAREST SamplerMipmapMode = C.VK_SAMPLER_MIPMAP_MODE_NEAREST
   585  	SAMPLER_MIPMAP_MODE_LINEAR  SamplerMipmapMode = C.VK_SAMPLER_MIPMAP_MODE_LINEAR
   586  
   587  	REMAINING_MIP_LEVELS = -1
   588  )
   589  
   590  var (
   591  	once    sync.Once
   592  	loadErr error
   593  
   594  	loadFuncs []func(dlopen func(name string) *[0]byte)
   595  )
   596  
   597  var funcs struct {
   598  	vkCreateInstance                         C.PFN_vkCreateInstance
   599  	vkDestroyInstance                        C.PFN_vkDestroyInstance
   600  	vkEnumeratePhysicalDevices               C.PFN_vkEnumeratePhysicalDevices
   601  	vkGetPhysicalDeviceQueueFamilyProperties C.PFN_vkGetPhysicalDeviceQueueFamilyProperties
   602  	vkGetPhysicalDeviceFormatProperties      C.PFN_vkGetPhysicalDeviceFormatProperties
   603  	vkCreateDevice                           C.PFN_vkCreateDevice
   604  	vkDestroyDevice                          C.PFN_vkDestroyDevice
   605  	vkGetDeviceQueue                         C.PFN_vkGetDeviceQueue
   606  	vkCreateImageView                        C.PFN_vkCreateImageView
   607  	vkDestroyImageView                       C.PFN_vkDestroyImageView
   608  	vkCreateFramebuffer                      C.PFN_vkCreateFramebuffer
   609  	vkDestroyFramebuffer                     C.PFN_vkDestroyFramebuffer
   610  	vkDeviceWaitIdle                         C.PFN_vkDeviceWaitIdle
   611  	vkQueueWaitIdle                          C.PFN_vkQueueWaitIdle
   612  	vkCreateSemaphore                        C.PFN_vkCreateSemaphore
   613  	vkDestroySemaphore                       C.PFN_vkDestroySemaphore
   614  	vkCreateRenderPass                       C.PFN_vkCreateRenderPass
   615  	vkDestroyRenderPass                      C.PFN_vkDestroyRenderPass
   616  	vkCreateCommandPool                      C.PFN_vkCreateCommandPool
   617  	vkDestroyCommandPool                     C.PFN_vkDestroyCommandPool
   618  	vkAllocateCommandBuffers                 C.PFN_vkAllocateCommandBuffers
   619  	vkFreeCommandBuffers                     C.PFN_vkFreeCommandBuffers
   620  	vkBeginCommandBuffer                     C.PFN_vkBeginCommandBuffer
   621  	vkEndCommandBuffer                       C.PFN_vkEndCommandBuffer
   622  	vkQueueSubmit                            C.PFN_vkQueueSubmit
   623  	vkCmdBeginRenderPass                     C.PFN_vkCmdBeginRenderPass
   624  	vkCmdEndRenderPass                       C.PFN_vkCmdEndRenderPass
   625  	vkCmdCopyBuffer                          C.PFN_vkCmdCopyBuffer
   626  	vkCmdCopyBufferToImage                   C.PFN_vkCmdCopyBufferToImage
   627  	vkCmdPipelineBarrier                     C.PFN_vkCmdPipelineBarrier
   628  	vkCmdPushConstants                       C.PFN_vkCmdPushConstants
   629  	vkCmdBindPipeline                        C.PFN_vkCmdBindPipeline
   630  	vkCmdBindVertexBuffers                   C.PFN_vkCmdBindVertexBuffers
   631  	vkCmdSetViewport                         C.PFN_vkCmdSetViewport
   632  	vkCmdBindIndexBuffer                     C.PFN_vkCmdBindIndexBuffer
   633  	vkCmdDraw                                C.PFN_vkCmdDraw
   634  	vkCmdDrawIndexed                         C.PFN_vkCmdDrawIndexed
   635  	vkCmdBindDescriptorSets                  C.PFN_vkCmdBindDescriptorSets
   636  	vkCmdCopyImageToBuffer                   C.PFN_vkCmdCopyImageToBuffer
   637  	vkCmdDispatch                            C.PFN_vkCmdDispatch
   638  	vkCreateImage                            C.PFN_vkCreateImage
   639  	vkDestroyImage                           C.PFN_vkDestroyImage
   640  	vkGetImageMemoryRequirements             C.PFN_vkGetImageMemoryRequirements
   641  	vkAllocateMemory                         C.PFN_vkAllocateMemory
   642  	vkBindImageMemory                        C.PFN_vkBindImageMemory
   643  	vkFreeMemory                             C.PFN_vkFreeMemory
   644  	vkGetPhysicalDeviceMemoryProperties      C.PFN_vkGetPhysicalDeviceMemoryProperties
   645  	vkCreateSampler                          C.PFN_vkCreateSampler
   646  	vkDestroySampler                         C.PFN_vkDestroySampler
   647  	vkCreateBuffer                           C.PFN_vkCreateBuffer
   648  	vkDestroyBuffer                          C.PFN_vkDestroyBuffer
   649  	vkGetBufferMemoryRequirements            C.PFN_vkGetBufferMemoryRequirements
   650  	vkBindBufferMemory                       C.PFN_vkBindBufferMemory
   651  	vkCreateShaderModule                     C.PFN_vkCreateShaderModule
   652  	vkDestroyShaderModule                    C.PFN_vkDestroyShaderModule
   653  	vkCreateGraphicsPipelines                C.PFN_vkCreateGraphicsPipelines
   654  	vkDestroyPipeline                        C.PFN_vkDestroyPipeline
   655  	vkCreatePipelineLayout                   C.PFN_vkCreatePipelineLayout
   656  	vkDestroyPipelineLayout                  C.PFN_vkDestroyPipelineLayout
   657  	vkCreateDescriptorSetLayout              C.PFN_vkCreateDescriptorSetLayout
   658  	vkDestroyDescriptorSetLayout             C.PFN_vkDestroyDescriptorSetLayout
   659  	vkMapMemory                              C.PFN_vkMapMemory
   660  	vkUnmapMemory                            C.PFN_vkUnmapMemory
   661  	vkResetCommandBuffer                     C.PFN_vkResetCommandBuffer
   662  	vkCreateDescriptorPool                   C.PFN_vkCreateDescriptorPool
   663  	vkDestroyDescriptorPool                  C.PFN_vkDestroyDescriptorPool
   664  	vkAllocateDescriptorSets                 C.PFN_vkAllocateDescriptorSets
   665  	vkFreeDescriptorSets                     C.PFN_vkFreeDescriptorSets
   666  	vkUpdateDescriptorSets                   C.PFN_vkUpdateDescriptorSets
   667  	vkResetDescriptorPool                    C.PFN_vkResetDescriptorPool
   668  	vkCmdBlitImage                           C.PFN_vkCmdBlitImage
   669  	vkCmdCopyImage                           C.PFN_vkCmdCopyImage
   670  	vkCreateComputePipelines                 C.PFN_vkCreateComputePipelines
   671  	vkCreateFence                            C.PFN_vkCreateFence
   672  	vkDestroyFence                           C.PFN_vkDestroyFence
   673  	vkWaitForFences                          C.PFN_vkWaitForFences
   674  	vkResetFences                            C.PFN_vkResetFences
   675  	vkGetPhysicalDeviceProperties            C.PFN_vkGetPhysicalDeviceProperties
   676  
   677  	vkGetPhysicalDeviceSurfaceSupportKHR      C.PFN_vkGetPhysicalDeviceSurfaceSupportKHR
   678  	vkDestroySurfaceKHR                       C.PFN_vkDestroySurfaceKHR
   679  	vkGetPhysicalDeviceSurfaceFormatsKHR      C.PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
   680  	vkGetPhysicalDeviceSurfacePresentModesKHR C.PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
   681  	vkGetPhysicalDeviceSurfaceCapabilitiesKHR C.PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
   682  
   683  	vkCreateSwapchainKHR    C.PFN_vkCreateSwapchainKHR
   684  	vkDestroySwapchainKHR   C.PFN_vkDestroySwapchainKHR
   685  	vkGetSwapchainImagesKHR C.PFN_vkGetSwapchainImagesKHR
   686  	vkAcquireNextImageKHR   C.PFN_vkAcquireNextImageKHR
   687  	vkQueuePresentKHR       C.PFN_vkQueuePresentKHR
   688  }
   689  
   690  var (
   691  	nilSurface             C.VkSurfaceKHR
   692  	nilSwapchain           C.VkSwapchainKHR
   693  	nilSemaphore           C.VkSemaphore
   694  	nilImageView           C.VkImageView
   695  	nilRenderPass          C.VkRenderPass
   696  	nilFramebuffer         C.VkFramebuffer
   697  	nilCommandPool         C.VkCommandPool
   698  	nilImage               C.VkImage
   699  	nilDeviceMemory        C.VkDeviceMemory
   700  	nilSampler             C.VkSampler
   701  	nilBuffer              C.VkBuffer
   702  	nilShaderModule        C.VkShaderModule
   703  	nilPipeline            C.VkPipeline
   704  	nilPipelineCache       C.VkPipelineCache
   705  	nilPipelineLayout      C.VkPipelineLayout
   706  	nilDescriptorSetLayout C.VkDescriptorSetLayout
   707  	nilDescriptorPool      C.VkDescriptorPool
   708  	nilDescriptorSet       C.VkDescriptorSet
   709  	nilFence               C.VkFence
   710  )
   711  
   712  func vkInit() error {
   713  	once.Do(func() {
   714  		var libName string
   715  		switch {
   716  		case runtime.GOOS == "android":
   717  			libName = "libvulkan.so"
   718  		default:
   719  			libName = "libvulkan.so.1"
   720  		}
   721  		lib := dlopen(libName)
   722  		if lib == nil {
   723  			loadErr = fmt.Errorf("vulkan: %s", C.GoString(C.dlerror()))
   724  			return
   725  		}
   726  		dlopen := func(name string) *[0]byte {
   727  			return (*[0]byte)(dlsym(lib, name))
   728  		}
   729  		must := func(name string) *[0]byte {
   730  			ptr := dlopen(name)
   731  			if ptr != nil {
   732  				return ptr
   733  			}
   734  			if loadErr == nil {
   735  				loadErr = fmt.Errorf("vulkan: function %q not found: %s", name, C.GoString(C.dlerror()))
   736  			}
   737  			return nil
   738  		}
   739  		funcs.vkCreateInstance = must("vkCreateInstance")
   740  		funcs.vkDestroyInstance = must("vkDestroyInstance")
   741  		funcs.vkEnumeratePhysicalDevices = must("vkEnumeratePhysicalDevices")
   742  		funcs.vkGetPhysicalDeviceQueueFamilyProperties = must("vkGetPhysicalDeviceQueueFamilyProperties")
   743  		funcs.vkGetPhysicalDeviceFormatProperties = must("vkGetPhysicalDeviceFormatProperties")
   744  		funcs.vkCreateDevice = must("vkCreateDevice")
   745  		funcs.vkDestroyDevice = must("vkDestroyDevice")
   746  		funcs.vkGetDeviceQueue = must("vkGetDeviceQueue")
   747  		funcs.vkCreateImageView = must("vkCreateImageView")
   748  		funcs.vkDestroyImageView = must("vkDestroyImageView")
   749  		funcs.vkCreateFramebuffer = must("vkCreateFramebuffer")
   750  		funcs.vkDestroyFramebuffer = must("vkDestroyFramebuffer")
   751  		funcs.vkDeviceWaitIdle = must("vkDeviceWaitIdle")
   752  		funcs.vkQueueWaitIdle = must("vkQueueWaitIdle")
   753  		funcs.vkCreateSemaphore = must("vkCreateSemaphore")
   754  		funcs.vkDestroySemaphore = must("vkDestroySemaphore")
   755  		funcs.vkCreateRenderPass = must("vkCreateRenderPass")
   756  		funcs.vkDestroyRenderPass = must("vkDestroyRenderPass")
   757  		funcs.vkCreateCommandPool = must("vkCreateCommandPool")
   758  		funcs.vkDestroyCommandPool = must("vkDestroyCommandPool")
   759  		funcs.vkAllocateCommandBuffers = must("vkAllocateCommandBuffers")
   760  		funcs.vkFreeCommandBuffers = must("vkFreeCommandBuffers")
   761  		funcs.vkBeginCommandBuffer = must("vkBeginCommandBuffer")
   762  		funcs.vkEndCommandBuffer = must("vkEndCommandBuffer")
   763  		funcs.vkQueueSubmit = must("vkQueueSubmit")
   764  		funcs.vkCmdBeginRenderPass = must("vkCmdBeginRenderPass")
   765  		funcs.vkCmdEndRenderPass = must("vkCmdEndRenderPass")
   766  		funcs.vkCmdCopyBuffer = must("vkCmdCopyBuffer")
   767  		funcs.vkCmdCopyBufferToImage = must("vkCmdCopyBufferToImage")
   768  		funcs.vkCmdPipelineBarrier = must("vkCmdPipelineBarrier")
   769  		funcs.vkCmdPushConstants = must("vkCmdPushConstants")
   770  		funcs.vkCmdBindPipeline = must("vkCmdBindPipeline")
   771  		funcs.vkCmdBindVertexBuffers = must("vkCmdBindVertexBuffers")
   772  		funcs.vkCmdSetViewport = must("vkCmdSetViewport")
   773  		funcs.vkCmdBindIndexBuffer = must("vkCmdBindIndexBuffer")
   774  		funcs.vkCmdDraw = must("vkCmdDraw")
   775  		funcs.vkCmdDrawIndexed = must("vkCmdDrawIndexed")
   776  		funcs.vkCmdBindDescriptorSets = must("vkCmdBindDescriptorSets")
   777  		funcs.vkCmdCopyImageToBuffer = must("vkCmdCopyImageToBuffer")
   778  		funcs.vkCmdDispatch = must("vkCmdDispatch")
   779  		funcs.vkCreateImage = must("vkCreateImage")
   780  		funcs.vkDestroyImage = must("vkDestroyImage")
   781  		funcs.vkGetImageMemoryRequirements = must("vkGetImageMemoryRequirements")
   782  		funcs.vkAllocateMemory = must("vkAllocateMemory")
   783  		funcs.vkBindImageMemory = must("vkBindImageMemory")
   784  		funcs.vkFreeMemory = must("vkFreeMemory")
   785  		funcs.vkGetPhysicalDeviceMemoryProperties = must("vkGetPhysicalDeviceMemoryProperties")
   786  		funcs.vkCreateSampler = must("vkCreateSampler")
   787  		funcs.vkDestroySampler = must("vkDestroySampler")
   788  		funcs.vkCreateBuffer = must("vkCreateBuffer")
   789  		funcs.vkDestroyBuffer = must("vkDestroyBuffer")
   790  		funcs.vkGetBufferMemoryRequirements = must("vkGetBufferMemoryRequirements")
   791  		funcs.vkBindBufferMemory = must("vkBindBufferMemory")
   792  		funcs.vkCreateShaderModule = must("vkCreateShaderModule")
   793  		funcs.vkDestroyShaderModule = must("vkDestroyShaderModule")
   794  		funcs.vkCreateGraphicsPipelines = must("vkCreateGraphicsPipelines")
   795  		funcs.vkDestroyPipeline = must("vkDestroyPipeline")
   796  		funcs.vkCreatePipelineLayout = must("vkCreatePipelineLayout")
   797  		funcs.vkDestroyPipelineLayout = must("vkDestroyPipelineLayout")
   798  		funcs.vkCreateDescriptorSetLayout = must("vkCreateDescriptorSetLayout")
   799  		funcs.vkDestroyDescriptorSetLayout = must("vkDestroyDescriptorSetLayout")
   800  		funcs.vkMapMemory = must("vkMapMemory")
   801  		funcs.vkUnmapMemory = must("vkUnmapMemory")
   802  		funcs.vkResetCommandBuffer = must("vkResetCommandBuffer")
   803  		funcs.vkCreateDescriptorPool = must("vkCreateDescriptorPool")
   804  		funcs.vkDestroyDescriptorPool = must("vkDestroyDescriptorPool")
   805  		funcs.vkAllocateDescriptorSets = must("vkAllocateDescriptorSets")
   806  		funcs.vkFreeDescriptorSets = must("vkFreeDescriptorSets")
   807  		funcs.vkUpdateDescriptorSets = must("vkUpdateDescriptorSets")
   808  		funcs.vkResetDescriptorPool = must("vkResetDescriptorPool")
   809  		funcs.vkCmdBlitImage = must("vkCmdBlitImage")
   810  		funcs.vkCmdCopyImage = must("vkCmdCopyImage")
   811  		funcs.vkCreateComputePipelines = must("vkCreateComputePipelines")
   812  		funcs.vkCreateFence = must("vkCreateFence")
   813  		funcs.vkDestroyFence = must("vkDestroyFence")
   814  		funcs.vkWaitForFences = must("vkWaitForFences")
   815  		funcs.vkResetFences = must("vkResetFences")
   816  		funcs.vkGetPhysicalDeviceProperties = must("vkGetPhysicalDeviceProperties")
   817  
   818  		funcs.vkGetPhysicalDeviceSurfaceSupportKHR = dlopen("vkGetPhysicalDeviceSurfaceSupportKHR")
   819  		funcs.vkDestroySurfaceKHR = dlopen("vkDestroySurfaceKHR")
   820  		funcs.vkGetPhysicalDeviceSurfaceFormatsKHR = dlopen("vkGetPhysicalDeviceSurfaceFormatsKHR")
   821  		funcs.vkGetPhysicalDeviceSurfacePresentModesKHR = dlopen("vkGetPhysicalDeviceSurfacePresentModesKHR")
   822  		funcs.vkGetPhysicalDeviceSurfaceCapabilitiesKHR = dlopen("vkGetPhysicalDeviceSurfaceCapabilitiesKHR")
   823  
   824  		funcs.vkCreateSwapchainKHR = dlopen("vkCreateSwapchainKHR")
   825  		funcs.vkDestroySwapchainKHR = dlopen("vkDestroySwapchainKHR")
   826  		funcs.vkGetSwapchainImagesKHR = dlopen("vkGetSwapchainImagesKHR")
   827  		funcs.vkAcquireNextImageKHR = dlopen("vkAcquireNextImageKHR")
   828  		funcs.vkQueuePresentKHR = dlopen("vkQueuePresentKHR")
   829  
   830  		for _, f := range loadFuncs {
   831  			f(dlopen)
   832  		}
   833  	})
   834  	return loadErr
   835  }
   836  
   837  func CreateInstance(exts ...string) (Instance, error) {
   838  	if err := vkInit(); err != nil {
   839  		return nil, err
   840  	}
   841  	// VK_MAKE_API_VERSION macro.
   842  	makeVer := func(variant, major, minor, patch int) C.uint32_t {
   843  		return ((((C.uint32_t)(variant)) << 29) | (((C.uint32_t)(major)) << 22) | (((C.uint32_t)(minor)) << 12) | ((C.uint32_t)(patch)))
   844  	}
   845  	appInf := C.VkApplicationInfo{
   846  		sType:      C.VK_STRUCTURE_TYPE_APPLICATION_INFO,
   847  		apiVersion: makeVer(0, 1, 0, 0),
   848  	}
   849  	inf := C.VkInstanceCreateInfo{
   850  		sType: C.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
   851  		// pApplicationInfo may be omitted according to the spec, but the Android
   852  		// emulator crashes without it.
   853  		pApplicationInfo: &appInf,
   854  	}
   855  	if len(exts) > 0 {
   856  		cexts := mallocCStringArr(exts)
   857  		defer freeCStringArr(cexts)
   858  		inf.enabledExtensionCount = C.uint32_t(len(exts))
   859  		inf.ppEnabledExtensionNames = &cexts[0]
   860  	}
   861  	var inst Instance
   862  	if err := vkErr(C.vkCreateInstance(funcs.vkCreateInstance, inf, nil, &inst)); err != nil {
   863  		return nil, fmt.Errorf("vulkan: vkCreateInstance: %w", err)
   864  	}
   865  	return inst, nil
   866  }
   867  
   868  func mallocCStringArr(s []string) []*C.char {
   869  	carr := make([]*C.char, len(s))
   870  	for i, ext := range s {
   871  		carr[i] = C.CString(ext)
   872  	}
   873  	return carr
   874  }
   875  
   876  func freeCStringArr(s []*C.char) {
   877  	for i := range s {
   878  		C.free(unsafe.Pointer(s[i]))
   879  		s[i] = nil
   880  	}
   881  }
   882  
   883  func DestroyInstance(inst Instance) {
   884  	C.vkDestroyInstance(funcs.vkDestroyInstance, inst, nil)
   885  }
   886  
   887  func GetPhysicalDeviceQueueFamilyProperties(pd PhysicalDevice) []QueueFamilyProperties {
   888  	var count C.uint32_t
   889  	C.vkGetPhysicalDeviceQueueFamilyProperties(funcs.vkGetPhysicalDeviceQueueFamilyProperties, pd, &count, nil)
   890  	if count == 0 {
   891  		return nil
   892  	}
   893  	queues := make([]C.VkQueueFamilyProperties, count)
   894  	C.vkGetPhysicalDeviceQueueFamilyProperties(funcs.vkGetPhysicalDeviceQueueFamilyProperties, pd, &count, &queues[0])
   895  	return queues
   896  }
   897  
   898  func EnumeratePhysicalDevices(inst Instance) ([]PhysicalDevice, error) {
   899  	var count C.uint32_t
   900  	if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, nil)); err != nil {
   901  		return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
   902  	}
   903  	if count == 0 {
   904  		return nil, nil
   905  	}
   906  	devs := make([]C.VkPhysicalDevice, count)
   907  	if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, &devs[0])); err != nil {
   908  		return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
   909  	}
   910  	return devs, nil
   911  }
   912  
   913  func ChoosePhysicalDevice(inst Instance, surf Surface) (PhysicalDevice, int, error) {
   914  	devs, err := EnumeratePhysicalDevices(inst)
   915  	if err != nil {
   916  		return nil, 0, err
   917  	}
   918  	for _, pd := range devs {
   919  		var props C.VkPhysicalDeviceProperties
   920  		C.vkGetPhysicalDeviceProperties(funcs.vkGetPhysicalDeviceProperties, pd, &props)
   921  		// The lavapipe software implementation doesn't work well rendering to a surface.
   922  		// See https://gitlab.freedesktop.org/mesa/mesa/-/issues/5473.
   923  		if surf != 0 && props.deviceType == C.VK_PHYSICAL_DEVICE_TYPE_CPU {
   924  			continue
   925  		}
   926  		const caps = C.VK_QUEUE_GRAPHICS_BIT | C.VK_QUEUE_COMPUTE_BIT
   927  		queueIdx, ok, err := chooseQueue(pd, surf, caps)
   928  		if err != nil {
   929  			return nil, 0, err
   930  		}
   931  		if !ok {
   932  			continue
   933  		}
   934  		if surf != nilSurface {
   935  			_, fmtFound, err := chooseFormat(pd, surf)
   936  			if err != nil {
   937  				return nil, 0, err
   938  			}
   939  			_, modFound, err := choosePresentMode(pd, surf)
   940  			if err != nil {
   941  				return nil, 0, err
   942  			}
   943  			if !fmtFound || !modFound {
   944  				continue
   945  			}
   946  		}
   947  		return pd, queueIdx, nil
   948  	}
   949  	return nil, 0, errors.New("vulkan: no suitable device found")
   950  }
   951  
   952  func CreateDeviceAndQueue(pd C.VkPhysicalDevice, queueIdx int, exts ...string) (Device, error) {
   953  	priority := C.float(1.0)
   954  	qinf := C.VkDeviceQueueCreateInfo{
   955  		sType:            C.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
   956  		queueCount:       1,
   957  		queueFamilyIndex: C.uint32_t(queueIdx),
   958  		pQueuePriorities: &priority,
   959  	}
   960  	inf := C.VkDeviceCreateInfo{
   961  		sType:                 C.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
   962  		queueCreateInfoCount:  1,
   963  		enabledExtensionCount: C.uint32_t(len(exts)),
   964  	}
   965  	if len(exts) > 0 {
   966  		cexts := mallocCStringArr(exts)
   967  		defer freeCStringArr(cexts)
   968  		inf.ppEnabledExtensionNames = &cexts[0]
   969  	}
   970  	var dev Device
   971  	if err := vkErr(C.vkCreateDevice(funcs.vkCreateDevice, pd, inf, qinf, nil, &dev)); err != nil {
   972  		return nil, fmt.Errorf("vulkan: vkCreateDevice: %w", err)
   973  	}
   974  	return dev, nil
   975  }
   976  
   977  func GetDeviceQueue(d Device, queueFamily, queueIndex int) Queue {
   978  	var queue Queue
   979  	C.vkGetDeviceQueue(funcs.vkGetDeviceQueue, d, C.uint32_t(queueFamily), C.uint32_t(queueIndex), &queue)
   980  	return queue
   981  }
   982  
   983  func GetPhysicalDeviceSurfaceCapabilities(pd PhysicalDevice, surf Surface) (SurfaceCapabilities, error) {
   984  	var caps C.VkSurfaceCapabilitiesKHR
   985  	err := vkErr(C.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(funcs.vkGetPhysicalDeviceSurfaceCapabilitiesKHR, pd, surf, &caps))
   986  	if err != nil {
   987  		return SurfaceCapabilities{}, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceCapabilitiesKHR: %w", err)
   988  	}
   989  	return caps, nil
   990  }
   991  
   992  func CreateSwapchain(pd PhysicalDevice, d Device, surf Surface, width, height int, old Swapchain) (Swapchain, []Image, Format, error) {
   993  	caps, err := GetPhysicalDeviceSurfaceCapabilities(pd, surf)
   994  	if err != nil {
   995  		return nilSwapchain, nil, 0, err
   996  	}
   997  	mode, modeOK, err := choosePresentMode(pd, surf)
   998  	if err != nil {
   999  		return nilSwapchain, nil, 0, err
  1000  	}
  1001  	format, fmtOK, err := chooseFormat(pd, surf)
  1002  	if err != nil {
  1003  		return nilSwapchain, nil, 0, err
  1004  	}
  1005  	if !modeOK || !fmtOK {
  1006  		// This shouldn't happen because CreateDeviceAndQueue found at least
  1007  		// one valid format and present mode.
  1008  		return nilSwapchain, nil, 0, errors.New("vulkan: no valid format and present mode found")
  1009  	}
  1010  	// Find supported alpha composite mode. It doesn't matter which one, because rendering is
  1011  	// always opaque.
  1012  	alphaComp := C.VkCompositeAlphaFlagBitsKHR(1)
  1013  	for caps.supportedCompositeAlpha&C.VkCompositeAlphaFlagsKHR(alphaComp) == 0 {
  1014  		alphaComp <<= 1
  1015  	}
  1016  	trans := C.VkSurfaceTransformFlagBitsKHR(C.VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
  1017  	if caps.supportedTransforms&C.VkSurfaceTransformFlagsKHR(trans) == 0 {
  1018  		return nilSwapchain, nil, 0, errors.New("vulkan: VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR not supported")
  1019  	}
  1020  	inf := C.VkSwapchainCreateInfoKHR{
  1021  		sType:            C.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
  1022  		surface:          surf,
  1023  		minImageCount:    caps.minImageCount,
  1024  		imageFormat:      format.format,
  1025  		imageColorSpace:  format.colorSpace,
  1026  		imageExtent:      C.VkExtent2D{width: C.uint32_t(width), height: C.uint32_t(height)},
  1027  		imageArrayLayers: 1,
  1028  		imageUsage:       C.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
  1029  		imageSharingMode: C.VK_SHARING_MODE_EXCLUSIVE,
  1030  		preTransform:     trans,
  1031  		presentMode:      mode,
  1032  		compositeAlpha:   C.VkCompositeAlphaFlagBitsKHR(alphaComp),
  1033  		clipped:          C.VK_TRUE,
  1034  		oldSwapchain:     old,
  1035  	}
  1036  	var swchain Swapchain
  1037  	if err := vkErr(C.vkCreateSwapchainKHR(funcs.vkCreateSwapchainKHR, d, &inf, nil, &swchain)); err != nil {
  1038  		return nilSwapchain, nil, 0, fmt.Errorf("vulkan: vkCreateSwapchainKHR: %w", err)
  1039  	}
  1040  	var count C.uint32_t
  1041  	if err := vkErr(C.vkGetSwapchainImagesKHR(funcs.vkGetSwapchainImagesKHR, d, swchain, &count, nil)); err != nil {
  1042  		DestroySwapchain(d, swchain)
  1043  		return nilSwapchain, nil, 0, fmt.Errorf("vulkan: vkGetSwapchainImagesKHR: %w", err)
  1044  	}
  1045  	if count == 0 {
  1046  		DestroySwapchain(d, swchain)
  1047  		return nilSwapchain, nil, 0, errors.New("vulkan: vkGetSwapchainImagesKHR returned no images")
  1048  	}
  1049  	imgs := make([]Image, count)
  1050  	if err := vkErr(C.vkGetSwapchainImagesKHR(funcs.vkGetSwapchainImagesKHR, d, swchain, &count, &imgs[0])); err != nil {
  1051  		DestroySwapchain(d, swchain)
  1052  		return nilSwapchain, nil, 0, fmt.Errorf("vulkan: vkGetSwapchainImagesKHR: %w", err)
  1053  	}
  1054  	return swchain, imgs, format.format, nil
  1055  }
  1056  
  1057  func DestroySwapchain(d Device, swchain Swapchain) {
  1058  	C.vkDestroySwapchainKHR(funcs.vkDestroySwapchainKHR, d, swchain, nil)
  1059  }
  1060  
  1061  func AcquireNextImage(d Device, swchain Swapchain, sem Semaphore, fence Fence) (int, error) {
  1062  	res := C.vkAcquireNextImageKHR(funcs.vkAcquireNextImageKHR, d, swchain, math.MaxUint64, sem, fence)
  1063  	if err := vkErr(res.res); err != nil {
  1064  		return 0, fmt.Errorf("vulkan: vkAcquireNextImageKHR: %w", err)
  1065  	}
  1066  	return int(res.uint), nil
  1067  }
  1068  
  1069  func PresentQueue(q Queue, swchain Swapchain, sem Semaphore, imgIdx int) error {
  1070  	cidx := C.uint32_t(imgIdx)
  1071  	inf := C.VkPresentInfoKHR{
  1072  		sType:          C.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
  1073  		swapchainCount: 1,
  1074  		pSwapchains:    &swchain,
  1075  		pImageIndices:  &cidx,
  1076  	}
  1077  	if sem != nilSemaphore {
  1078  		inf.waitSemaphoreCount = 1
  1079  		inf.pWaitSemaphores = &sem
  1080  	}
  1081  	if err := vkErr(C.vkQueuePresentKHR(funcs.vkQueuePresentKHR, q, inf)); err != nil {
  1082  		return fmt.Errorf("vulkan: vkQueuePresentKHR: %w", err)
  1083  	}
  1084  	return nil
  1085  }
  1086  
  1087  func CreateImageView(d Device, img Image, format Format) (ImageView, error) {
  1088  	inf := C.VkImageViewCreateInfo{
  1089  		sType:    C.VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
  1090  		image:    img,
  1091  		viewType: C.VK_IMAGE_VIEW_TYPE_2D,
  1092  		format:   format,
  1093  		subresourceRange: C.VkImageSubresourceRange{
  1094  			aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
  1095  			levelCount: C.VK_REMAINING_MIP_LEVELS,
  1096  			layerCount: C.VK_REMAINING_ARRAY_LAYERS,
  1097  		},
  1098  	}
  1099  	var view C.VkImageView
  1100  	if err := vkErr(C.vkCreateImageView(funcs.vkCreateImageView, d, &inf, nil, &view)); err != nil {
  1101  		return nilImageView, fmt.Errorf("vulkan: vkCreateImageView: %w", err)
  1102  	}
  1103  	return view, nil
  1104  }
  1105  
  1106  func DestroyImageView(d Device, view ImageView) {
  1107  	C.vkDestroyImageView(funcs.vkDestroyImageView, d, view, nil)
  1108  }
  1109  
  1110  func CreateRenderPass(d Device, format Format, loadOp AttachmentLoadOp, initialLayout, finalLayout ImageLayout, passDeps []SubpassDependency) (RenderPass, error) {
  1111  	att := C.VkAttachmentDescription{
  1112  		format:         format,
  1113  		samples:        C.VK_SAMPLE_COUNT_1_BIT,
  1114  		loadOp:         loadOp,
  1115  		storeOp:        C.VK_ATTACHMENT_STORE_OP_STORE,
  1116  		stencilLoadOp:  C.VK_ATTACHMENT_LOAD_OP_DONT_CARE,
  1117  		stencilStoreOp: C.VK_ATTACHMENT_STORE_OP_DONT_CARE,
  1118  		initialLayout:  initialLayout,
  1119  		finalLayout:    finalLayout,
  1120  	}
  1121  
  1122  	ref := C.VkAttachmentReference{
  1123  		attachment: 0,
  1124  		layout:     C.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  1125  	}
  1126  
  1127  	sub := C.VkSubpassDescription{
  1128  		pipelineBindPoint:    C.VK_PIPELINE_BIND_POINT_GRAPHICS,
  1129  		colorAttachmentCount: 1,
  1130  		pColorAttachments:    &ref,
  1131  	}
  1132  
  1133  	inf := C.VkRenderPassCreateInfo{
  1134  		sType:           C.VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
  1135  		attachmentCount: 1,
  1136  		pAttachments:    &att,
  1137  		subpassCount:    1,
  1138  	}
  1139  	if n := len(passDeps); n > 0 {
  1140  		inf.dependencyCount = C.uint32_t(n)
  1141  		inf.pDependencies = &passDeps[0]
  1142  	}
  1143  
  1144  	var pass RenderPass
  1145  	if err := vkErr(C.vkCreateRenderPass(funcs.vkCreateRenderPass, d, inf, sub, nil, &pass)); err != nil {
  1146  		return nilRenderPass, fmt.Errorf("vulkan: vkCreateRenderPass: %w", err)
  1147  	}
  1148  	return pass, nil
  1149  }
  1150  
  1151  func DestroyRenderPass(d Device, r RenderPass) {
  1152  	C.vkDestroyRenderPass(funcs.vkDestroyRenderPass, d, r, nil)
  1153  }
  1154  
  1155  func CreateFramebuffer(d Device, rp RenderPass, view ImageView, width, height int) (Framebuffer, error) {
  1156  	inf := C.VkFramebufferCreateInfo{
  1157  		sType:           C.VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
  1158  		renderPass:      rp,
  1159  		attachmentCount: 1,
  1160  		pAttachments:    &view,
  1161  		width:           C.uint32_t(width),
  1162  		height:          C.uint32_t(height),
  1163  		layers:          1,
  1164  	}
  1165  	var fbo Framebuffer
  1166  	if err := vkErr(C.vkCreateFramebuffer(funcs.vkCreateFramebuffer, d, inf, nil, &fbo)); err != nil {
  1167  		return nilFramebuffer, fmt.Errorf("vulkan: vkCreateFramebuffer: %w", err)
  1168  	}
  1169  	return fbo, nil
  1170  
  1171  }
  1172  
  1173  func DestroyFramebuffer(d Device, f Framebuffer) {
  1174  	C.vkDestroyFramebuffer(funcs.vkDestroyFramebuffer, d, f, nil)
  1175  }
  1176  
  1177  func DeviceWaitIdle(d Device) error {
  1178  	if err := vkErr(C.vkDeviceWaitIdle(funcs.vkDeviceWaitIdle, d)); err != nil {
  1179  		return fmt.Errorf("vulkan: vkDeviceWaitIdle: %w", err)
  1180  	}
  1181  	return nil
  1182  }
  1183  
  1184  func QueueWaitIdle(q Queue) error {
  1185  	if err := vkErr(C.vkQueueWaitIdle(funcs.vkQueueWaitIdle, q)); err != nil {
  1186  		return fmt.Errorf("vulkan: vkQueueWaitIdle: %w", err)
  1187  	}
  1188  	return nil
  1189  }
  1190  
  1191  func CreateSemaphore(d Device) (Semaphore, error) {
  1192  	inf := C.VkSemaphoreCreateInfo{
  1193  		sType: C.VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
  1194  	}
  1195  	var sem Semaphore
  1196  	err := vkErr(C.vkCreateSemaphore(funcs.vkCreateSemaphore, d, &inf, nil, &sem))
  1197  	if err != nil {
  1198  		return nilSemaphore, fmt.Errorf("vulkan: vkCreateSemaphore: %w", err)
  1199  	}
  1200  	return sem, err
  1201  }
  1202  
  1203  func DestroySemaphore(d Device, sem Semaphore) {
  1204  	C.vkDestroySemaphore(funcs.vkDestroySemaphore, d, sem, nil)
  1205  }
  1206  
  1207  func DestroyDevice(dev Device) {
  1208  	C.vkDestroyDevice(funcs.vkDestroyDevice, dev, nil)
  1209  }
  1210  
  1211  func DestroySurface(inst Instance, s Surface) {
  1212  	C.vkDestroySurfaceKHR(funcs.vkDestroySurfaceKHR, inst, s, nil)
  1213  }
  1214  
  1215  func CreateCommandPool(d Device, queueIndex int) (CommandPool, error) {
  1216  	inf := C.VkCommandPoolCreateInfo{
  1217  		sType:            C.VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
  1218  		queueFamilyIndex: C.uint32_t(queueIndex),
  1219  		flags:            C.VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | C.VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
  1220  	}
  1221  
  1222  	var pool CommandPool
  1223  	if err := vkErr(C.vkCreateCommandPool(funcs.vkCreateCommandPool, d, &inf, nil, &pool)); err != nil {
  1224  		return nilCommandPool, fmt.Errorf("vulkan: vkCreateCommandPool: %w", err)
  1225  	}
  1226  	return pool, nil
  1227  }
  1228  
  1229  func DestroyCommandPool(d Device, pool CommandPool) {
  1230  	C.vkDestroyCommandPool(funcs.vkDestroyCommandPool, d, pool, nil)
  1231  }
  1232  
  1233  func AllocateCommandBuffer(d Device, pool CommandPool) (CommandBuffer, error) {
  1234  	inf := C.VkCommandBufferAllocateInfo{
  1235  		sType:              C.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
  1236  		commandPool:        pool,
  1237  		level:              C.VK_COMMAND_BUFFER_LEVEL_PRIMARY,
  1238  		commandBufferCount: 1,
  1239  	}
  1240  
  1241  	var buf CommandBuffer
  1242  	if err := vkErr(C.vkAllocateCommandBuffers(funcs.vkAllocateCommandBuffers, d, &inf, &buf)); err != nil {
  1243  		return nil, fmt.Errorf("vulkan: vkAllocateCommandBuffers: %w", err)
  1244  	}
  1245  	return buf, nil
  1246  }
  1247  
  1248  func FreeCommandBuffers(d Device, pool CommandPool, bufs ...CommandBuffer) {
  1249  	if len(bufs) == 0 {
  1250  		return
  1251  	}
  1252  	C.vkFreeCommandBuffers(funcs.vkFreeCommandBuffers, d, pool, C.uint32_t(len(bufs)), &bufs[0])
  1253  }
  1254  
  1255  func BeginCommandBuffer(buf CommandBuffer) error {
  1256  	inf := C.VkCommandBufferBeginInfo{
  1257  		sType: C.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
  1258  		flags: C.VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
  1259  	}
  1260  	if err := vkErr(C.vkBeginCommandBuffer(funcs.vkBeginCommandBuffer, buf, inf)); err != nil {
  1261  		return fmt.Errorf("vulkan: vkBeginCommandBuffer: %w", err)
  1262  	}
  1263  	return nil
  1264  }
  1265  
  1266  func EndCommandBuffer(buf CommandBuffer) error {
  1267  	if err := vkErr(C.vkEndCommandBuffer(funcs.vkEndCommandBuffer, buf)); err != nil {
  1268  		return fmt.Errorf("vulkan: vkEndCommandBuffer: %w", err)
  1269  	}
  1270  	return nil
  1271  }
  1272  
  1273  func QueueSubmit(q Queue, buf CommandBuffer, waitSems []Semaphore, waitStages []PipelineStageFlags, sigSems []Semaphore, fence Fence) error {
  1274  	inf := C.VkSubmitInfo{
  1275  		sType:              C.VK_STRUCTURE_TYPE_SUBMIT_INFO,
  1276  		commandBufferCount: 1,
  1277  		pCommandBuffers:    &buf,
  1278  	}
  1279  	if len(waitSems) > 0 {
  1280  		if len(waitSems) != len(waitStages) {
  1281  			panic("len(waitSems) != len(waitStages)")
  1282  		}
  1283  		inf.waitSemaphoreCount = C.uint32_t(len(waitSems))
  1284  		inf.pWaitSemaphores = &waitSems[0]
  1285  		inf.pWaitDstStageMask = &waitStages[0]
  1286  	}
  1287  	if len(sigSems) > 0 {
  1288  		inf.signalSemaphoreCount = C.uint32_t(len(sigSems))
  1289  		inf.pSignalSemaphores = &sigSems[0]
  1290  	}
  1291  	if err := vkErr(C.vkQueueSubmit(funcs.vkQueueSubmit, q, inf, fence)); err != nil {
  1292  		return fmt.Errorf("vulkan: vkQueueSubmit: %w", err)
  1293  	}
  1294  	return nil
  1295  }
  1296  
  1297  func CmdBeginRenderPass(buf CommandBuffer, rp RenderPass, fbo Framebuffer, width, height int, clearCol [4]float32) {
  1298  	cclearCol := [4]C.float{C.float(clearCol[0]), C.float(clearCol[1]), C.float(clearCol[2]), C.float(clearCol[3])}
  1299  	inf := C.VkRenderPassBeginInfo{
  1300  		sType:           C.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
  1301  		renderPass:      rp,
  1302  		framebuffer:     fbo,
  1303  		renderArea:      C.VkRect2D{extent: C.VkExtent2D{width: C.uint32_t(width), height: C.uint32_t(height)}},
  1304  		clearValueCount: 1,
  1305  		pClearValues:    (*C.VkClearValue)(unsafe.Pointer(&cclearCol)),
  1306  	}
  1307  	C.vkCmdBeginRenderPass(funcs.vkCmdBeginRenderPass, buf, inf, C.VK_SUBPASS_CONTENTS_INLINE)
  1308  }
  1309  
  1310  func CmdEndRenderPass(buf CommandBuffer) {
  1311  	C.vkCmdEndRenderPass(funcs.vkCmdEndRenderPass, buf)
  1312  }
  1313  
  1314  func CmdCopyBuffer(cmdBuf CommandBuffer, src, dst Buffer, srcOff, dstOff, size int) {
  1315  	C.vkCmdCopyBuffer(funcs.vkCmdCopyBuffer, cmdBuf, src, dst, 1, &C.VkBufferCopy{
  1316  		srcOffset: C.VkDeviceSize(srcOff),
  1317  		dstOffset: C.VkDeviceSize(dstOff),
  1318  		size:      C.VkDeviceSize(size),
  1319  	})
  1320  }
  1321  
  1322  func CmdCopyBufferToImage(cmdBuf CommandBuffer, src Buffer, dst Image, layout ImageLayout, copy BufferImageCopy) {
  1323  	C.vkCmdCopyBufferToImage(funcs.vkCmdCopyBufferToImage, cmdBuf, src, dst, layout, 1, &copy)
  1324  }
  1325  
  1326  func CmdPipelineBarrier(cmdBuf CommandBuffer, srcStage, dstStage PipelineStageFlags, flags DependencyFlags, memBarriers []MemoryBarrier, bufBarriers []BufferMemoryBarrier, imgBarriers []ImageMemoryBarrier) {
  1327  	var memPtr *MemoryBarrier
  1328  	if len(memBarriers) > 0 {
  1329  		memPtr = &memBarriers[0]
  1330  	}
  1331  	var bufPtr *BufferMemoryBarrier
  1332  	if len(bufBarriers) > 0 {
  1333  		bufPtr = &bufBarriers[0]
  1334  	}
  1335  	var imgPtr *ImageMemoryBarrier
  1336  	if len(imgBarriers) > 0 {
  1337  		imgPtr = &imgBarriers[0]
  1338  	}
  1339  	C.vkCmdPipelineBarrier(funcs.vkCmdPipelineBarrier, cmdBuf, srcStage, dstStage, flags,
  1340  		C.uint32_t(len(memBarriers)), memPtr,
  1341  		C.uint32_t(len(bufBarriers)), bufPtr,
  1342  		C.uint32_t(len(imgBarriers)), imgPtr)
  1343  }
  1344  
  1345  func CmdPushConstants(cmdBuf CommandBuffer, layout PipelineLayout, stages ShaderStageFlags, offset int, data []byte) {
  1346  	if len(data) == 0 {
  1347  		return
  1348  	}
  1349  	C.vkCmdPushConstants(funcs.vkCmdPushConstants, cmdBuf, layout, stages, C.uint32_t(offset), C.uint32_t(len(data)), unsafe.Pointer(&data[0]))
  1350  }
  1351  
  1352  func CmdBindPipeline(cmdBuf CommandBuffer, bindPoint PipelineBindPoint, pipe Pipeline) {
  1353  	C.vkCmdBindPipeline(funcs.vkCmdBindPipeline, cmdBuf, bindPoint, pipe)
  1354  }
  1355  
  1356  func CmdBindVertexBuffers(cmdBuf CommandBuffer, first int, buffers []Buffer, sizes []DeviceSize) {
  1357  	if len(buffers) == 0 {
  1358  		return
  1359  	}
  1360  	C.vkCmdBindVertexBuffers(funcs.vkCmdBindVertexBuffers, cmdBuf, C.uint32_t(first), C.uint32_t(len(buffers)), &buffers[0], &sizes[0])
  1361  }
  1362  
  1363  func CmdSetViewport(cmdBuf CommandBuffer, first int, viewports ...Viewport) {
  1364  	if len(viewports) == 0 {
  1365  		return
  1366  	}
  1367  	C.vkCmdSetViewport(funcs.vkCmdSetViewport, cmdBuf, C.uint32_t(first), C.uint32_t(len(viewports)), &viewports[0])
  1368  }
  1369  
  1370  func CmdBindIndexBuffer(cmdBuf CommandBuffer, buffer Buffer, offset int, typ IndexType) {
  1371  	C.vkCmdBindIndexBuffer(funcs.vkCmdBindIndexBuffer, cmdBuf, buffer, C.VkDeviceSize(offset), typ)
  1372  }
  1373  
  1374  func CmdDraw(cmdBuf CommandBuffer, vertCount, instCount, firstVert, firstInst int) {
  1375  	C.vkCmdDraw(funcs.vkCmdDraw, cmdBuf, C.uint32_t(vertCount), C.uint32_t(instCount), C.uint32_t(firstVert), C.uint32_t(firstInst))
  1376  }
  1377  
  1378  func CmdDrawIndexed(cmdBuf CommandBuffer, idxCount, instCount, firstIdx, vertOff, firstInst int) {
  1379  	C.vkCmdDrawIndexed(funcs.vkCmdDrawIndexed, cmdBuf, C.uint32_t(idxCount), C.uint32_t(instCount), C.uint32_t(firstIdx), C.int32_t(vertOff), C.uint32_t(firstInst))
  1380  }
  1381  
  1382  func GetPhysicalDeviceFormatProperties(physDev PhysicalDevice, format Format) FormatFeatureFlags {
  1383  	var props C.VkFormatProperties
  1384  	C.vkGetPhysicalDeviceFormatProperties(funcs.vkGetPhysicalDeviceFormatProperties, physDev, format, &props)
  1385  	return FormatFeatureFlags(props.optimalTilingFeatures)
  1386  }
  1387  
  1388  func CmdBindDescriptorSets(cmdBuf CommandBuffer, point PipelineBindPoint, layout PipelineLayout, firstSet int, sets []DescriptorSet) {
  1389  	C.vkCmdBindDescriptorSets(funcs.vkCmdBindDescriptorSets, cmdBuf, point, layout, C.uint32_t(firstSet), C.uint32_t(len(sets)), &sets[0], 0, nil)
  1390  }
  1391  
  1392  func CmdBlitImage(cmdBuf CommandBuffer, src Image, srcLayout ImageLayout, dst Image, dstLayout ImageLayout, regions []ImageBlit, filter Filter) {
  1393  	if len(regions) == 0 {
  1394  		return
  1395  	}
  1396  	C.vkCmdBlitImage(funcs.vkCmdBlitImage, cmdBuf, src, srcLayout, dst, dstLayout, C.uint32_t(len(regions)), &regions[0], filter)
  1397  }
  1398  
  1399  func CmdCopyImage(cmdBuf CommandBuffer, src Image, srcLayout ImageLayout, dst Image, dstLayout ImageLayout, regions []ImageCopy) {
  1400  	if len(regions) == 0 {
  1401  		return
  1402  	}
  1403  	C.vkCmdCopyImage(funcs.vkCmdCopyImage, cmdBuf, src, srcLayout, dst, dstLayout, C.uint32_t(len(regions)), &regions[0])
  1404  }
  1405  
  1406  func CmdCopyImageToBuffer(cmdBuf CommandBuffer, src Image, srcLayout ImageLayout, dst Buffer, regions []BufferImageCopy) {
  1407  	if len(regions) == 0 {
  1408  		return
  1409  	}
  1410  	C.vkCmdCopyImageToBuffer(funcs.vkCmdCopyImageToBuffer, cmdBuf, src, srcLayout, dst, C.uint32_t(len(regions)), &regions[0])
  1411  }
  1412  
  1413  func CmdDispatch(cmdBuf CommandBuffer, x, y, z int) {
  1414  	C.vkCmdDispatch(funcs.vkCmdDispatch, cmdBuf, C.uint32_t(x), C.uint32_t(y), C.uint32_t(z))
  1415  }
  1416  
  1417  func CreateImage(pd PhysicalDevice, d Device, format Format, width, height, mipmaps int, usage ImageUsageFlags) (Image, DeviceMemory, error) {
  1418  	inf := C.VkImageCreateInfo{
  1419  		sType:     C.VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
  1420  		imageType: C.VK_IMAGE_TYPE_2D,
  1421  		format:    format,
  1422  		extent: C.VkExtent3D{
  1423  			width:  C.uint32_t(width),
  1424  			height: C.uint32_t(height),
  1425  			depth:  1,
  1426  		},
  1427  		mipLevels:     C.uint32_t(mipmaps),
  1428  		arrayLayers:   1,
  1429  		samples:       C.VK_SAMPLE_COUNT_1_BIT,
  1430  		tiling:        C.VK_IMAGE_TILING_OPTIMAL,
  1431  		usage:         usage,
  1432  		initialLayout: C.VK_IMAGE_LAYOUT_UNDEFINED,
  1433  	}
  1434  	var img C.VkImage
  1435  	if err := vkErr(C.vkCreateImage(funcs.vkCreateImage, d, &inf, nil, &img)); err != nil {
  1436  		return nilImage, nilDeviceMemory, fmt.Errorf("vulkan: vkCreateImage: %w", err)
  1437  	}
  1438  	var memReqs C.VkMemoryRequirements
  1439  	C.vkGetImageMemoryRequirements(funcs.vkGetImageMemoryRequirements, d, img, &memReqs)
  1440  
  1441  	memIdx, found := findMemoryTypeIndex(pd, memReqs.memoryTypeBits, C.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
  1442  	if !found {
  1443  		DestroyImage(d, img)
  1444  		return nilImage, nilDeviceMemory, errors.New("vulkan: no memory type suitable for images found")
  1445  	}
  1446  
  1447  	memInf := C.VkMemoryAllocateInfo{
  1448  		sType:           C.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
  1449  		allocationSize:  memReqs.size,
  1450  		memoryTypeIndex: C.uint32_t(memIdx),
  1451  	}
  1452  	var imgMem C.VkDeviceMemory
  1453  	if err := vkErr(C.vkAllocateMemory(funcs.vkAllocateMemory, d, &memInf, nil, &imgMem)); err != nil {
  1454  		DestroyImage(d, img)
  1455  		return nilImage, nilDeviceMemory, fmt.Errorf("vulkan: vkAllocateMemory: %w", err)
  1456  	}
  1457  
  1458  	if err := vkErr(C.vkBindImageMemory(funcs.vkBindImageMemory, d, img, imgMem, 0)); err != nil {
  1459  		FreeMemory(d, imgMem)
  1460  		DestroyImage(d, img)
  1461  		return nilImage, nilDeviceMemory, fmt.Errorf("vulkan: vkBindImageMemory: %w", err)
  1462  	}
  1463  	return img, imgMem, nil
  1464  }
  1465  
  1466  func DestroyImage(d Device, img Image) {
  1467  	C.vkDestroyImage(funcs.vkDestroyImage, d, img, nil)
  1468  }
  1469  
  1470  func FreeMemory(d Device, mem DeviceMemory) {
  1471  	C.vkFreeMemory(funcs.vkFreeMemory, d, mem, nil)
  1472  }
  1473  
  1474  func CreateSampler(d Device, minFilter, magFilter Filter, mipmapMode SamplerMipmapMode) (Sampler, error) {
  1475  	inf := C.VkSamplerCreateInfo{
  1476  		sType:        C.VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
  1477  		minFilter:    minFilter,
  1478  		magFilter:    magFilter,
  1479  		mipmapMode:   mipmapMode,
  1480  		maxLod:       C.VK_LOD_CLAMP_NONE,
  1481  		addressModeU: C.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
  1482  		addressModeV: C.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
  1483  	}
  1484  	var s C.VkSampler
  1485  	if err := vkErr(C.vkCreateSampler(funcs.vkCreateSampler, d, &inf, nil, &s)); err != nil {
  1486  		return nilSampler, fmt.Errorf("vulkan: vkCreateSampler: %w", err)
  1487  	}
  1488  	return s, nil
  1489  }
  1490  
  1491  func DestroySampler(d Device, sampler Sampler) {
  1492  	C.vkDestroySampler(funcs.vkDestroySampler, d, sampler, nil)
  1493  }
  1494  
  1495  func CreateBuffer(pd PhysicalDevice, d Device, size int, usage BufferUsageFlags, props MemoryPropertyFlags) (Buffer, DeviceMemory, error) {
  1496  	inf := C.VkBufferCreateInfo{
  1497  		sType: C.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
  1498  		size:  C.VkDeviceSize(size),
  1499  		usage: usage,
  1500  	}
  1501  	var buf C.VkBuffer
  1502  	if err := vkErr(C.vkCreateBuffer(funcs.vkCreateBuffer, d, &inf, nil, &buf)); err != nil {
  1503  		return nilBuffer, nilDeviceMemory, fmt.Errorf("vulkan: vkCreateBuffer: %w", err)
  1504  	}
  1505  
  1506  	var memReqs C.VkMemoryRequirements
  1507  	C.vkGetBufferMemoryRequirements(funcs.vkGetBufferMemoryRequirements, d, buf, &memReqs)
  1508  
  1509  	memIdx, found := findMemoryTypeIndex(pd, memReqs.memoryTypeBits, props)
  1510  	if !found {
  1511  		DestroyBuffer(d, buf)
  1512  		return nilBuffer, nilDeviceMemory, errors.New("vulkan: no memory suitable for buffers found")
  1513  	}
  1514  	memInf := C.VkMemoryAllocateInfo{
  1515  		sType:           C.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
  1516  		allocationSize:  memReqs.size,
  1517  		memoryTypeIndex: C.uint32_t(memIdx),
  1518  	}
  1519  
  1520  	var mem C.VkDeviceMemory
  1521  	if err := vkErr(C.vkAllocateMemory(funcs.vkAllocateMemory, d, &memInf, nil, &mem)); err != nil {
  1522  		DestroyBuffer(d, buf)
  1523  		return nilBuffer, nilDeviceMemory, fmt.Errorf("vulkan: vkAllocateMemory: %w", err)
  1524  	}
  1525  
  1526  	if err := vkErr(C.vkBindBufferMemory(funcs.vkBindBufferMemory, d, buf, mem, 0)); err != nil {
  1527  		FreeMemory(d, mem)
  1528  		DestroyBuffer(d, buf)
  1529  		return nilBuffer, nilDeviceMemory, fmt.Errorf("vulkan: vkBindBufferMemory: %w", err)
  1530  	}
  1531  	return buf, mem, nil
  1532  }
  1533  
  1534  func DestroyBuffer(d Device, buf Buffer) {
  1535  	C.vkDestroyBuffer(funcs.vkDestroyBuffer, d, buf, nil)
  1536  }
  1537  
  1538  func CreateShaderModule(d Device, spirv string) (ShaderModule, error) {
  1539  	ptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&spirv)).Data)
  1540  	inf := C.VkShaderModuleCreateInfo{
  1541  		sType:    C.VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
  1542  		codeSize: C.size_t(len(spirv)),
  1543  		pCode:    (*C.uint32_t)(ptr),
  1544  	}
  1545  
  1546  	var mod C.VkShaderModule
  1547  	if err := vkErr(C.vkCreateShaderModule(funcs.vkCreateShaderModule, d, inf, nil, &mod)); err != nil {
  1548  		return nilShaderModule, fmt.Errorf("vulkan: vkCreateShaderModule: %w", err)
  1549  	}
  1550  	return mod, nil
  1551  }
  1552  
  1553  func DestroyShaderModule(d Device, mod ShaderModule) {
  1554  	C.vkDestroyShaderModule(funcs.vkDestroyShaderModule, d, mod, nil)
  1555  }
  1556  
  1557  func CreateGraphicsPipeline(d Device, pass RenderPass, vmod, fmod ShaderModule, blend bool, srcFactor, dstFactor BlendFactor, topology PrimitiveTopology, bindings []VertexInputBindingDescription, attrs []VertexInputAttributeDescription, layout PipelineLayout) (Pipeline, error) {
  1558  	main := C.CString("main")
  1559  	defer C.free(unsafe.Pointer(main))
  1560  	stages := []C.VkPipelineShaderStageCreateInfo{
  1561  		{
  1562  			sType:  C.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  1563  			stage:  C.VK_SHADER_STAGE_VERTEX_BIT,
  1564  			module: vmod,
  1565  			pName:  main,
  1566  		},
  1567  		{
  1568  			sType:  C.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  1569  			stage:  C.VK_SHADER_STAGE_FRAGMENT_BIT,
  1570  			module: fmod,
  1571  			pName:  main,
  1572  		},
  1573  	}
  1574  	dynStates := []C.VkDynamicState{C.VK_DYNAMIC_STATE_VIEWPORT}
  1575  	dynInf := C.VkPipelineDynamicStateCreateInfo{
  1576  		sType:             C.VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
  1577  		dynamicStateCount: C.uint32_t(len(dynStates)),
  1578  		pDynamicStates:    &dynStates[0],
  1579  	}
  1580  	const maxDim = 0x7fffffff
  1581  	scissors := []C.VkRect2D{{extent: C.VkExtent2D{width: maxDim, height: maxDim}}}
  1582  	viewportInf := C.VkPipelineViewportStateCreateInfo{
  1583  		sType:         C.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
  1584  		viewportCount: 1,
  1585  		scissorCount:  C.uint32_t(len(scissors)),
  1586  		pScissors:     &scissors[0],
  1587  	}
  1588  	enable := C.VkBool32(0)
  1589  	if blend {
  1590  		enable = 1
  1591  	}
  1592  	attBlendInf := C.VkPipelineColorBlendAttachmentState{
  1593  		blendEnable:         enable,
  1594  		srcColorBlendFactor: srcFactor,
  1595  		srcAlphaBlendFactor: srcFactor,
  1596  		dstColorBlendFactor: dstFactor,
  1597  		dstAlphaBlendFactor: dstFactor,
  1598  		colorBlendOp:        C.VK_BLEND_OP_ADD,
  1599  		alphaBlendOp:        C.VK_BLEND_OP_ADD,
  1600  		colorWriteMask:      C.VK_COLOR_COMPONENT_R_BIT | C.VK_COLOR_COMPONENT_G_BIT | C.VK_COLOR_COMPONENT_B_BIT | C.VK_COLOR_COMPONENT_A_BIT,
  1601  	}
  1602  	blendInf := C.VkPipelineColorBlendStateCreateInfo{
  1603  		sType:           C.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
  1604  		attachmentCount: 1,
  1605  		pAttachments:    &attBlendInf,
  1606  	}
  1607  	var vkBinds []C.VkVertexInputBindingDescription
  1608  	var vkAttrs []C.VkVertexInputAttributeDescription
  1609  	for _, b := range bindings {
  1610  		vkBinds = append(vkBinds, C.VkVertexInputBindingDescription{
  1611  			binding: C.uint32_t(b.Binding),
  1612  			stride:  C.uint32_t(b.Stride),
  1613  		})
  1614  	}
  1615  	for _, a := range attrs {
  1616  		vkAttrs = append(vkAttrs, C.VkVertexInputAttributeDescription{
  1617  			location: C.uint32_t(a.Location),
  1618  			binding:  C.uint32_t(a.Binding),
  1619  			format:   a.Format,
  1620  			offset:   C.uint32_t(a.Offset),
  1621  		})
  1622  	}
  1623  	vertexInf := C.VkPipelineVertexInputStateCreateInfo{
  1624  		sType: C.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
  1625  	}
  1626  	if n := len(vkBinds); n > 0 {
  1627  		vertexInf.vertexBindingDescriptionCount = C.uint32_t(n)
  1628  		vertexInf.pVertexBindingDescriptions = &vkBinds[0]
  1629  	}
  1630  	if n := len(vkAttrs); n > 0 {
  1631  		vertexInf.vertexAttributeDescriptionCount = C.uint32_t(n)
  1632  		vertexInf.pVertexAttributeDescriptions = &vkAttrs[0]
  1633  	}
  1634  	inf := C.VkGraphicsPipelineCreateInfo{
  1635  		sType:      C.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
  1636  		stageCount: C.uint32_t(len(stages)),
  1637  		pStages:    &stages[0],
  1638  		renderPass: pass,
  1639  		layout:     layout,
  1640  		pRasterizationState: &C.VkPipelineRasterizationStateCreateInfo{
  1641  			sType:     C.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
  1642  			lineWidth: 1.0,
  1643  		},
  1644  		pMultisampleState: &C.VkPipelineMultisampleStateCreateInfo{
  1645  			sType:                C.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
  1646  			rasterizationSamples: C.VK_SAMPLE_COUNT_1_BIT,
  1647  		},
  1648  		pInputAssemblyState: &C.VkPipelineInputAssemblyStateCreateInfo{
  1649  			sType:    C.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
  1650  			topology: topology,
  1651  		},
  1652  	}
  1653  
  1654  	var pipe C.VkPipeline
  1655  	if err := vkErr(C.vkCreateGraphicsPipelines(funcs.vkCreateGraphicsPipelines, d, nilPipelineCache, inf, dynInf, blendInf, vertexInf, viewportInf, nil, &pipe)); err != nil {
  1656  		return nilPipeline, fmt.Errorf("vulkan: vkCreateGraphicsPipelines: %w", err)
  1657  	}
  1658  	return pipe, nil
  1659  }
  1660  
  1661  func DestroyPipeline(d Device, p Pipeline) {
  1662  	C.vkDestroyPipeline(funcs.vkDestroyPipeline, d, p, nil)
  1663  }
  1664  
  1665  func CreatePipelineLayout(d Device, pushRanges []PushConstantRange, sets []DescriptorSetLayout) (PipelineLayout, error) {
  1666  	inf := C.VkPipelineLayoutCreateInfo{
  1667  		sType: C.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
  1668  	}
  1669  	if n := len(sets); n > 0 {
  1670  		inf.setLayoutCount = C.uint32_t(n)
  1671  		inf.pSetLayouts = &sets[0]
  1672  	}
  1673  	if n := len(pushRanges); n > 0 {
  1674  		inf.pushConstantRangeCount = C.uint32_t(n)
  1675  		inf.pPushConstantRanges = &pushRanges[0]
  1676  	}
  1677  	var l C.VkPipelineLayout
  1678  	if err := vkErr(C.vkCreatePipelineLayout(funcs.vkCreatePipelineLayout, d, inf, nil, &l)); err != nil {
  1679  		return nilPipelineLayout, fmt.Errorf("vulkan: vkCreatePipelineLayout: %w", err)
  1680  	}
  1681  	return l, nil
  1682  }
  1683  
  1684  func DestroyPipelineLayout(d Device, l PipelineLayout) {
  1685  	C.vkDestroyPipelineLayout(funcs.vkDestroyPipelineLayout, d, l, nil)
  1686  }
  1687  
  1688  func CreateDescriptorSetLayout(d Device, bindings []DescriptorSetLayoutBinding) (DescriptorSetLayout, error) {
  1689  	var vkbinds []C.VkDescriptorSetLayoutBinding
  1690  	for _, b := range bindings {
  1691  		vkbinds = append(vkbinds, C.VkDescriptorSetLayoutBinding{
  1692  			binding:         C.uint32_t(b.Binding),
  1693  			descriptorType:  b.DescriptorType,
  1694  			descriptorCount: 1,
  1695  			stageFlags:      b.StageFlags,
  1696  		})
  1697  	}
  1698  	inf := C.VkDescriptorSetLayoutCreateInfo{
  1699  		sType: C.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
  1700  	}
  1701  	if n := len(vkbinds); n > 0 {
  1702  		inf.bindingCount = C.uint32_t(len(vkbinds))
  1703  		inf.pBindings = &vkbinds[0]
  1704  	}
  1705  	var l C.VkDescriptorSetLayout
  1706  	if err := vkErr(C.vkCreateDescriptorSetLayout(funcs.vkCreateDescriptorSetLayout, d, inf, nil, &l)); err != nil {
  1707  		return nilDescriptorSetLayout, fmt.Errorf("vulkan: vkCreateDescriptorSetLayout: %w", err)
  1708  	}
  1709  	return l, nil
  1710  }
  1711  
  1712  func DestroyDescriptorSetLayout(d Device, l DescriptorSetLayout) {
  1713  	C.vkDestroyDescriptorSetLayout(funcs.vkDestroyDescriptorSetLayout, d, l, nil)
  1714  }
  1715  
  1716  func MapMemory(d Device, mem DeviceMemory, offset, size int) ([]byte, error) {
  1717  	var ptr unsafe.Pointer
  1718  	if err := vkErr(C.vkMapMemory(funcs.vkMapMemory, d, mem, C.VkDeviceSize(offset), C.VkDeviceSize(size), 0, &ptr)); err != nil {
  1719  		return nil, fmt.Errorf("vulkan: vkMapMemory: %w", err)
  1720  	}
  1721  	return ((*[1 << 30]byte)(ptr))[:size:size], nil
  1722  }
  1723  
  1724  func UnmapMemory(d Device, mem DeviceMemory) {
  1725  	C.vkUnmapMemory(funcs.vkUnmapMemory, d, mem)
  1726  }
  1727  
  1728  func ResetCommandBuffer(buf CommandBuffer) error {
  1729  	if err := vkErr(C.vkResetCommandBuffer(funcs.vkResetCommandBuffer, buf, 0)); err != nil {
  1730  		return fmt.Errorf("vulkan: vkResetCommandBuffer. %w", err)
  1731  	}
  1732  	return nil
  1733  }
  1734  
  1735  func CreateDescriptorPool(d Device, maxSets int, sizes []DescriptorPoolSize) (DescriptorPool, error) {
  1736  	inf := C.VkDescriptorPoolCreateInfo{
  1737  		sType:         C.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
  1738  		maxSets:       C.uint32_t(maxSets),
  1739  		poolSizeCount: C.uint32_t(len(sizes)),
  1740  		pPoolSizes:    &sizes[0],
  1741  	}
  1742  	var pool C.VkDescriptorPool
  1743  	if err := vkErr(C.vkCreateDescriptorPool(funcs.vkCreateDescriptorPool, d, inf, nil, &pool)); err != nil {
  1744  		return nilDescriptorPool, fmt.Errorf("vulkan: vkCreateDescriptorPool: %w", err)
  1745  	}
  1746  	return pool, nil
  1747  }
  1748  
  1749  func DestroyDescriptorPool(d Device, pool DescriptorPool) {
  1750  	C.vkDestroyDescriptorPool(funcs.vkDestroyDescriptorPool, d, pool, nil)
  1751  }
  1752  
  1753  func ResetDescriptorPool(d Device, pool DescriptorPool) error {
  1754  	if err := vkErr(C.vkResetDescriptorPool(funcs.vkResetDescriptorPool, d, pool, 0)); err != nil {
  1755  		return fmt.Errorf("vulkan: vkResetDescriptorPool: %w", err)
  1756  	}
  1757  	return nil
  1758  }
  1759  
  1760  func UpdateDescriptorSet(d Device, write WriteDescriptorSet) {
  1761  	C.vkUpdateDescriptorSets(funcs.vkUpdateDescriptorSets, d, write, 0, nil)
  1762  }
  1763  
  1764  func AllocateDescriptorSets(d Device, pool DescriptorPool, layout DescriptorSetLayout, count int) ([]DescriptorSet, error) {
  1765  	layouts := make([]DescriptorSetLayout, count)
  1766  	for i := range layouts {
  1767  		layouts[i] = layout
  1768  	}
  1769  	inf := C.VkDescriptorSetAllocateInfo{
  1770  		sType:              C.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
  1771  		descriptorPool:     pool,
  1772  		descriptorSetCount: C.uint32_t(count),
  1773  		pSetLayouts:        &layouts[0],
  1774  	}
  1775  	sets := make([]DescriptorSet, count)
  1776  	if err := vkErr(C.vkAllocateDescriptorSets(funcs.vkAllocateDescriptorSets, d, inf, &sets[0])); err != nil {
  1777  		return nil, fmt.Errorf("vulkan: vkAllocateDescriptorSets: %w", err)
  1778  	}
  1779  	return sets, nil
  1780  }
  1781  
  1782  func CreateComputePipeline(d Device, mod ShaderModule, layout PipelineLayout) (Pipeline, error) {
  1783  	main := C.CString("main")
  1784  	defer C.free(unsafe.Pointer(main))
  1785  	inf := C.VkComputePipelineCreateInfo{
  1786  		sType: C.VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
  1787  		stage: C.VkPipelineShaderStageCreateInfo{
  1788  			sType:  C.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  1789  			stage:  C.VK_SHADER_STAGE_COMPUTE_BIT,
  1790  			module: mod,
  1791  			pName:  main,
  1792  		},
  1793  		layout: layout,
  1794  	}
  1795  	var pipe C.VkPipeline
  1796  	if err := vkErr(C.vkCreateComputePipelines(funcs.vkCreateComputePipelines, d, nilPipelineCache, 1, &inf, nil, &pipe)); err != nil {
  1797  		return nilPipeline, fmt.Errorf("vulkan: vkCreateComputePipelines: %w", err)
  1798  	}
  1799  	return pipe, nil
  1800  }
  1801  
  1802  func CreateFence(d Device, flags int) (Fence, error) {
  1803  	inf := C.VkFenceCreateInfo{
  1804  		sType: C.VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
  1805  		flags: C.VkFenceCreateFlags(flags),
  1806  	}
  1807  	var f C.VkFence
  1808  	if err := vkErr(C.vkCreateFence(funcs.vkCreateFence, d, &inf, nil, &f)); err != nil {
  1809  		return nilFence, fmt.Errorf("vulkan: vkCreateFence: %w", err)
  1810  	}
  1811  	return f, nil
  1812  }
  1813  
  1814  func DestroyFence(d Device, f Fence) {
  1815  	C.vkDestroyFence(funcs.vkDestroyFence, d, f, nil)
  1816  }
  1817  
  1818  func WaitForFences(d Device, fences ...Fence) error {
  1819  	if len(fences) == 0 {
  1820  		return nil
  1821  	}
  1822  	err := vkErr(C.vkWaitForFences(funcs.vkWaitForFences, d, C.uint32_t(len(fences)), &fences[0], C.VK_TRUE, 0xffffffffffffffff))
  1823  	if err != nil {
  1824  		return fmt.Errorf("vulkan: vkWaitForFences: %w", err)
  1825  	}
  1826  	return nil
  1827  }
  1828  
  1829  func ResetFences(d Device, fences ...Fence) error {
  1830  	if len(fences) == 0 {
  1831  		return nil
  1832  	}
  1833  	err := vkErr(C.vkResetFences(funcs.vkResetFences, d, C.uint32_t(len(fences)), &fences[0]))
  1834  	if err != nil {
  1835  		return fmt.Errorf("vulkan: vkResetFences: %w", err)
  1836  	}
  1837  	return nil
  1838  }
  1839  
  1840  func BuildSubpassDependency(srcStage, dstStage PipelineStageFlags, srcMask, dstMask AccessFlags, flags DependencyFlags) SubpassDependency {
  1841  	return C.VkSubpassDependency{
  1842  		srcSubpass:      C.VK_SUBPASS_EXTERNAL,
  1843  		srcStageMask:    srcStage,
  1844  		srcAccessMask:   srcMask,
  1845  		dstSubpass:      0,
  1846  		dstStageMask:    dstStage,
  1847  		dstAccessMask:   dstMask,
  1848  		dependencyFlags: flags,
  1849  	}
  1850  }
  1851  
  1852  func BuildPushConstantRange(stages ShaderStageFlags, offset, size int) PushConstantRange {
  1853  	return C.VkPushConstantRange{
  1854  		stageFlags: stages,
  1855  		offset:     C.uint32_t(offset),
  1856  		size:       C.uint32_t(size),
  1857  	}
  1858  }
  1859  
  1860  func BuildDescriptorPoolSize(typ DescriptorType, count int) DescriptorPoolSize {
  1861  	return C.VkDescriptorPoolSize{
  1862  		_type:           typ,
  1863  		descriptorCount: C.uint32_t(count),
  1864  	}
  1865  }
  1866  
  1867  func BuildWriteDescriptorSetImage(set DescriptorSet, binding int, typ DescriptorType, sampler Sampler, view ImageView, layout ImageLayout) WriteDescriptorSet {
  1868  	return C.VkWriteDescriptorSet{
  1869  		sType:           C.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
  1870  		dstSet:          set,
  1871  		dstBinding:      C.uint32_t(binding),
  1872  		descriptorCount: 1,
  1873  		descriptorType:  typ,
  1874  		pImageInfo: &C.VkDescriptorImageInfo{
  1875  			sampler:     sampler,
  1876  			imageView:   view,
  1877  			imageLayout: layout,
  1878  		},
  1879  	}
  1880  }
  1881  
  1882  func BuildWriteDescriptorSetBuffer(set DescriptorSet, binding int, typ DescriptorType, buf Buffer) WriteDescriptorSet {
  1883  	return C.VkWriteDescriptorSet{
  1884  		sType:           C.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
  1885  		dstSet:          set,
  1886  		dstBinding:      C.uint32_t(binding),
  1887  		descriptorCount: 1,
  1888  		descriptorType:  typ,
  1889  		pBufferInfo: &C.VkDescriptorBufferInfo{
  1890  			buffer: buf,
  1891  			_range: C.VK_WHOLE_SIZE,
  1892  		},
  1893  	}
  1894  }
  1895  
  1896  func (r PushConstantRange) StageFlags() ShaderStageFlags {
  1897  	return r.stageFlags
  1898  }
  1899  
  1900  func (r PushConstantRange) Offset() int {
  1901  	return int(r.offset)
  1902  }
  1903  
  1904  func (r PushConstantRange) Size() int {
  1905  	return int(r.size)
  1906  }
  1907  
  1908  func (p QueueFamilyProperties) Flags() QueueFlags {
  1909  	return p.queueFlags
  1910  }
  1911  
  1912  func (c SurfaceCapabilities) MinExtent() image.Point {
  1913  	return image.Pt(int(c.minImageExtent.width), int(c.minImageExtent.height))
  1914  }
  1915  
  1916  func (c SurfaceCapabilities) MaxExtent() image.Point {
  1917  	return image.Pt(int(c.maxImageExtent.width), int(c.maxImageExtent.height))
  1918  }
  1919  
  1920  func BuildViewport(x, y, width, height float32) Viewport {
  1921  	return C.VkViewport{
  1922  		x:        C.float(x),
  1923  		y:        C.float(y),
  1924  		width:    C.float(width),
  1925  		height:   C.float(height),
  1926  		maxDepth: 1.0,
  1927  	}
  1928  }
  1929  
  1930  func BuildImageMemoryBarrier(img Image, srcMask, dstMask AccessFlags, oldLayout, newLayout ImageLayout, baseMip, numMips int) ImageMemoryBarrier {
  1931  	return C.VkImageMemoryBarrier{
  1932  		sType:         C.VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
  1933  		srcAccessMask: srcMask,
  1934  		dstAccessMask: dstMask,
  1935  		oldLayout:     oldLayout,
  1936  		newLayout:     newLayout,
  1937  		image:         img,
  1938  		subresourceRange: C.VkImageSubresourceRange{
  1939  			aspectMask:   C.VK_IMAGE_ASPECT_COLOR_BIT,
  1940  			baseMipLevel: C.uint32_t(baseMip),
  1941  			levelCount:   C.uint32_t(numMips),
  1942  			layerCount:   C.VK_REMAINING_ARRAY_LAYERS,
  1943  		},
  1944  	}
  1945  }
  1946  
  1947  func BuildBufferMemoryBarrier(buf Buffer, srcMask, dstMask AccessFlags) BufferMemoryBarrier {
  1948  	return C.VkBufferMemoryBarrier{
  1949  		sType:         C.VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
  1950  		srcAccessMask: srcMask,
  1951  		dstAccessMask: dstMask,
  1952  		buffer:        buf,
  1953  		size:          C.VK_WHOLE_SIZE,
  1954  	}
  1955  }
  1956  
  1957  func BuildMemoryBarrier(srcMask, dstMask AccessFlags) MemoryBarrier {
  1958  	return C.VkMemoryBarrier{
  1959  		sType:         C.VK_STRUCTURE_TYPE_MEMORY_BARRIER,
  1960  		srcAccessMask: srcMask,
  1961  		dstAccessMask: dstMask,
  1962  	}
  1963  }
  1964  
  1965  func BuildBufferImageCopy(bufOff, bufStride, x, y, width, height int) BufferImageCopy {
  1966  	return C.VkBufferImageCopy{
  1967  		bufferOffset:    C.VkDeviceSize(bufOff),
  1968  		bufferRowLength: C.uint32_t(bufStride),
  1969  		imageSubresource: C.VkImageSubresourceLayers{
  1970  			aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
  1971  			layerCount: 1,
  1972  		},
  1973  		imageOffset: C.VkOffset3D{
  1974  			x: C.int32_t(x), y: C.int32_t(y), z: 0,
  1975  		},
  1976  		imageExtent: C.VkExtent3D{
  1977  			width: C.uint32_t(width), height: C.uint32_t(height), depth: 1,
  1978  		},
  1979  	}
  1980  }
  1981  
  1982  func BuildImageCopy(srcX, srcY, dstX, dstY, width, height int) ImageCopy {
  1983  	return C.VkImageCopy{
  1984  		srcSubresource: C.VkImageSubresourceLayers{
  1985  			aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
  1986  			layerCount: 1,
  1987  		},
  1988  		srcOffset: C.VkOffset3D{
  1989  			x: C.int32_t(srcX),
  1990  			y: C.int32_t(srcY),
  1991  		},
  1992  		dstSubresource: C.VkImageSubresourceLayers{
  1993  			aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
  1994  			layerCount: 1,
  1995  		},
  1996  		dstOffset: C.VkOffset3D{
  1997  			x: C.int32_t(dstX),
  1998  			y: C.int32_t(dstY),
  1999  		},
  2000  		extent: C.VkExtent3D{
  2001  			width:  C.uint32_t(width),
  2002  			height: C.uint32_t(height),
  2003  			depth:  1,
  2004  		},
  2005  	}
  2006  }
  2007  
  2008  func BuildImageBlit(srcX, srcY, dstX, dstY, srcWidth, srcHeight, dstWidth, dstHeight, srcMip, dstMip int) ImageBlit {
  2009  	return C.VkImageBlit{
  2010  		srcOffsets: [2]C.VkOffset3D{
  2011  			{C.int32_t(srcX), C.int32_t(srcY), 0},
  2012  			{C.int32_t(srcWidth), C.int32_t(srcHeight), 1},
  2013  		},
  2014  		srcSubresource: C.VkImageSubresourceLayers{
  2015  			aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
  2016  			layerCount: 1,
  2017  			mipLevel:   C.uint32_t(srcMip),
  2018  		},
  2019  		dstOffsets: [2]C.VkOffset3D{
  2020  			{C.int32_t(dstX), C.int32_t(dstY), 0},
  2021  			{C.int32_t(dstWidth), C.int32_t(dstHeight), 1},
  2022  		},
  2023  		dstSubresource: C.VkImageSubresourceLayers{
  2024  			aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
  2025  			layerCount: 1,
  2026  			mipLevel:   C.uint32_t(dstMip),
  2027  		},
  2028  	}
  2029  }
  2030  
  2031  func findMemoryTypeIndex(pd C.VkPhysicalDevice, constraints C.uint32_t, wantProps C.VkMemoryPropertyFlags) (int, bool) {
  2032  	var memProps C.VkPhysicalDeviceMemoryProperties
  2033  	C.vkGetPhysicalDeviceMemoryProperties(funcs.vkGetPhysicalDeviceMemoryProperties, pd, &memProps)
  2034  
  2035  	for i := 0; i < int(memProps.memoryTypeCount); i++ {
  2036  		if (constraints & (1 << i)) == 0 {
  2037  			continue
  2038  		}
  2039  		if (memProps.memoryTypes[i].propertyFlags & wantProps) != wantProps {
  2040  			continue
  2041  		}
  2042  		return i, true
  2043  	}
  2044  
  2045  	return 0, false
  2046  }
  2047  
  2048  func choosePresentMode(pd C.VkPhysicalDevice, surf Surface) (C.VkPresentModeKHR, bool, error) {
  2049  	var count C.uint32_t
  2050  	err := vkErr(C.vkGetPhysicalDeviceSurfacePresentModesKHR(funcs.vkGetPhysicalDeviceSurfacePresentModesKHR, pd, surf, &count, nil))
  2051  	if err != nil {
  2052  		return 0, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfacePresentModesKHR: %w", err)
  2053  	}
  2054  	if count == 0 {
  2055  		return 0, false, nil
  2056  	}
  2057  	modes := make([]C.VkPresentModeKHR, count)
  2058  	err = vkErr(C.vkGetPhysicalDeviceSurfacePresentModesKHR(funcs.vkGetPhysicalDeviceSurfacePresentModesKHR, pd, surf, &count, &modes[0]))
  2059  	if err != nil {
  2060  		return 0, false, fmt.Errorf("vulkan: kGetPhysicalDeviceSurfacePresentModesKHR: %w", err)
  2061  	}
  2062  	for _, m := range modes {
  2063  		if m == C.VK_PRESENT_MODE_MAILBOX_KHR || m == C.VK_PRESENT_MODE_FIFO_KHR {
  2064  			return m, true, nil
  2065  		}
  2066  	}
  2067  	return 0, false, nil
  2068  }
  2069  
  2070  func chooseFormat(pd C.VkPhysicalDevice, surf Surface) (C.VkSurfaceFormatKHR, bool, error) {
  2071  	var count C.uint32_t
  2072  	err := vkErr(C.vkGetPhysicalDeviceSurfaceFormatsKHR(funcs.vkGetPhysicalDeviceSurfaceFormatsKHR, pd, surf, &count, nil))
  2073  	if err != nil {
  2074  		return C.VkSurfaceFormatKHR{}, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceFormatsKHR: %w", err)
  2075  	}
  2076  	if count == 0 {
  2077  		return C.VkSurfaceFormatKHR{}, false, nil
  2078  	}
  2079  	formats := make([]C.VkSurfaceFormatKHR, count)
  2080  	err = vkErr(C.vkGetPhysicalDeviceSurfaceFormatsKHR(funcs.vkGetPhysicalDeviceSurfaceFormatsKHR, pd, surf, &count, &formats[0]))
  2081  	if err != nil {
  2082  		return C.VkSurfaceFormatKHR{}, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceFormatsKHR: %w", err)
  2083  	}
  2084  	// Query for format with sRGB support.
  2085  	// TODO: Support devices without sRGB.
  2086  	for _, f := range formats {
  2087  		if f.colorSpace != C.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR {
  2088  			continue
  2089  		}
  2090  		switch f.format {
  2091  		case C.VK_FORMAT_B8G8R8A8_SRGB, C.VK_FORMAT_R8G8B8A8_SRGB:
  2092  			return f, true, nil
  2093  		}
  2094  	}
  2095  	return C.VkSurfaceFormatKHR{}, false, nil
  2096  }
  2097  
  2098  func chooseQueue(pd C.VkPhysicalDevice, surf Surface, flags C.VkQueueFlags) (int, bool, error) {
  2099  	queues := GetPhysicalDeviceQueueFamilyProperties(pd)
  2100  	for i, q := range queues {
  2101  		// Check for presentation and feature support.
  2102  		if q.queueFlags&flags != flags {
  2103  			continue
  2104  		}
  2105  		if surf != nilSurface {
  2106  			// Check for presentation support. It is possible that a device has no
  2107  			// queue with both rendering and presentation support, but not in reality.
  2108  			// See https://github.com/KhronosGroup/Vulkan-Docs/issues/1234.
  2109  			var support C.VkBool32
  2110  			if err := vkErr(C.vkGetPhysicalDeviceSurfaceSupportKHR(funcs.vkGetPhysicalDeviceSurfaceSupportKHR, pd, C.uint32_t(i), surf, &support)); err != nil {
  2111  				return 0, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceSupportKHR: %w", err)
  2112  			}
  2113  			if support != C.VK_TRUE {
  2114  				continue
  2115  			}
  2116  		}
  2117  		return i, true, nil
  2118  	}
  2119  	return 0, false, nil
  2120  }
  2121  
  2122  func dlsym(handle unsafe.Pointer, s string) unsafe.Pointer {
  2123  	cs := C.CString(s)
  2124  	defer C.free(unsafe.Pointer(cs))
  2125  	return C.dlsym(handle, cs)
  2126  }
  2127  
  2128  func dlopen(lib string) unsafe.Pointer {
  2129  	clib := C.CString(lib)
  2130  	defer C.free(unsafe.Pointer(clib))
  2131  	return C.dlopen(clib, C.RTLD_NOW|C.RTLD_LOCAL)
  2132  }
  2133  
  2134  func vkErr(res C.VkResult) error {
  2135  	switch res {
  2136  	case C.VK_SUCCESS:
  2137  		return nil
  2138  	default:
  2139  		return Error(res)
  2140  	}
  2141  }
  2142  
  2143  func (e Error) Error() string {
  2144  	return fmt.Sprintf("error %d", e)
  2145  }