#define VK_NO_PROTOTYPES 1 #include #if defined(__linux__) #include #include #else #include #endif #define VK_GLOBAL_PROCS(X) \ X(vkCreateInstance) \ X(vkEnumerateInstanceExtensionProperties) \ X(vkEnumerateInstanceLayerProperties) #if defined(__linux__) #define VK_PLATFORM_INSTANCE_PROCS(X) X(vkCreateXcbSurfaceKHR) #else #define VK_PLATFORM_INSTANCE_PROCS(X) X(vkCreateWin32SurfaceKHR) #endif #define VK_INSTANCE_PROCS(X) \ X(vkGetDeviceProcAddr) \ X(vkCreateDevice) \ X(vkEnumeratePhysicalDevices) \ X(vkEnumerateDeviceExtensionProperties) \ X(vkGetPhysicalDeviceProperties) \ X(vkGetPhysicalDeviceMemoryProperties) \ X(vkGetPhysicalDeviceQueueFamilyProperties) \ X(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \ X(vkGetPhysicalDeviceSurfaceFormatsKHR) \ X(vkGetPhysicalDeviceSurfacePresentModesKHR) \ X(vkCreateDebugUtilsMessengerEXT) \ VK_PLATFORM_INSTANCE_PROCS(X) #define VK_DEVICE_PROCS(X) \ X(vkGetDeviceQueue) \ X(vkCreateSwapchainKHR) \ X(vkDestroySwapchainKHR) \ X(vkGetSwapchainImagesKHR) \ X(vkAcquireNextImageKHR) \ X(vkQueuePresentKHR) \ X(vkCreateCommandPool) \ X(vkAllocateCommandBuffers) \ X(vkFreeCommandBuffers) \ X(vkResetCommandBuffer) \ X(vkBeginCommandBuffer) \ X(vkEndCommandBuffer) \ X(vkCreateSemaphore) \ X(vkWaitSemaphores) \ X(vkDeviceWaitIdle) \ X(vkQueueSubmit) \ X(vkCreateDescriptorPool) \ X(vkCreateDescriptorSetLayout) \ X(vkAllocateDescriptorSets) \ X(vkUpdateDescriptorSets) \ X(vkCreateBuffer) \ X(vkDestroyBuffer) \ X(vkGetBufferMemoryRequirements) \ X(vkCreateImage) \ X(vkDestroyImage) \ X(vkGetImageMemoryRequirements) \ X(vkAllocateMemory) \ X(vkFreeMemory) \ X(vkBindBufferMemory) \ X(vkBindImageMemory) \ X(vkMapMemory) \ X(vkUnmapMemory) \ X(vkInvalidateMappedMemoryRanges) \ X(vkCreateImageView) \ X(vkDestroyImageView) \ X(vkCreateSampler) \ X(vkDestroySampler) \ X(vkCreateShaderModule) \ X(vkDestroyShaderModule) \ X(vkCreatePipelineLayout) \ X(vkDestroyPipelineLayout) \ X(vkCreateGraphicsPipelines) \ X(vkDestroyPipeline) \ X(vkCmdPipelineBarrier2) \ X(vkCmdBindDescriptorSets) \ X(vkCmdCopyBuffer) \ X(vkCmdCopyBufferToImage) \ X(vkCmdCopyImageToBuffer) \ X(vkCmdCopyImage) \ X(vkCmdBeginRendering) \ X(vkCmdEndRendering) \ X(vkCmdSetViewport) \ X(vkCmdSetScissor) \ X(vkCmdBindPipeline) \ X(vkCmdPushConstants) \ X(vkCmdBindVertexBuffers) \ X(vkCmdBindIndexBuffer) \ X(vkCmdDraw) \ X(vkCmdDrawIndexed) \ X(vkSetDebugUtilsObjectNameEXT) \ X(vkCmdSetCheckpointNV) \ X(vkGetQueueCheckpointDataNV) struct VulkanProcs { void* lib = nullptr; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = nullptr; #define VK_DECL(name) PFN_##name name = nullptr; VK_GLOBAL_PROCS(VK_DECL) VK_INSTANCE_PROCS(VK_DECL) VK_DEVICE_PROCS(VK_DECL) #undef VK_DECL }; inline VulkanProcs vulkanProcs; inline auto VulkanLoadGlobalProcs() -> bool { auto getProcAddress = [&](const char* name) -> void* { #if defined(__linux__) return dlsym(vulkanProcs.lib, name); #else return reinterpret_cast(GetProcAddress(reinterpret_cast(vulkanProcs.lib), name)); #endif }; if (!vulkanProcs.lib) { #if defined(__linux__) vulkanProcs.lib = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL); #else vulkanProcs.lib = reinterpret_cast(LoadLibraryA("vulkan-1.dll")); #endif } if (!vulkanProcs.lib) return false; vulkanProcs.vkGetInstanceProcAddr = reinterpret_cast(getProcAddress("vkGetInstanceProcAddr")); if (!vulkanProcs.vkGetInstanceProcAddr) return false; #define VK_LOAD_GLOBAL(name) \ vulkanProcs.name = reinterpret_cast(vulkanProcs.vkGetInstanceProcAddr(nullptr, #name)); VK_GLOBAL_PROCS(VK_LOAD_GLOBAL) #undef VK_LOAD_GLOBAL return vulkanProcs.vkCreateInstance && vulkanProcs.vkEnumerateInstanceExtensionProperties && vulkanProcs.vkEnumerateInstanceLayerProperties; } inline auto VulkanLoadInstanceProcs(VkInstance instance) -> bool { ASSERT(vulkanProcs.vkGetInstanceProcAddr); #define VK_LOAD_INSTANCE(name) \ vulkanProcs.name = reinterpret_cast(vulkanProcs.vkGetInstanceProcAddr(instance, #name)); VK_INSTANCE_PROCS(VK_LOAD_INSTANCE) #undef VK_LOAD_INSTANCE return vulkanProcs.vkGetDeviceProcAddr != nullptr; } inline auto VulkanLoadDeviceProcs(VkDevice device) -> bool { ASSERT(vulkanProcs.vkGetDeviceProcAddr); #define VK_LOAD_DEVICE(name) \ vulkanProcs.name = reinterpret_cast(vulkanProcs.vkGetDeviceProcAddr(device, #name)); VK_DEVICE_PROCS(VK_LOAD_DEVICE) #undef VK_LOAD_DEVICE return true; } #define UNPAREN(...) __VA_ARGS__ #define VK_WRAP_RESULT(ret, name, params, callargs) \ inline auto name UNPAREN(params) -> ret \ { \ ASSERT(vulkanProcs.name); \ return vulkanProcs.name UNPAREN(callargs); \ } #define VK_WRAP_VOID(name, params, callargs) \ inline auto name UNPAREN(params) -> void \ { \ ASSERT(vulkanProcs.name); \ vulkanProcs.name UNPAREN(callargs); \ } // Global procs VK_WRAP_RESULT(VkResult, vkCreateInstance, (const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance), (pCreateInfo, pAllocator, pInstance)) VK_WRAP_RESULT(VkResult, vkEnumerateInstanceExtensionProperties, (const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties), (pLayerName, pPropertyCount, pProperties)) VK_WRAP_RESULT(VkResult, vkEnumerateInstanceLayerProperties, (uint32_t* pPropertyCount, VkLayerProperties* pProperties), (pPropertyCount, pProperties)) // Instance procs VK_WRAP_RESULT(VkResult, vkCreateDevice, (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice), (physicalDevice, pCreateInfo, pAllocator, pDevice)) VK_WRAP_RESULT(VkResult, vkEnumeratePhysicalDevices, (VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices), (instance, pPhysicalDeviceCount, pPhysicalDevices)) VK_WRAP_RESULT(VkResult, vkEnumerateDeviceExtensionProperties, (VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties), (physicalDevice, pLayerName, pPropertyCount, pProperties)) VK_WRAP_VOID(vkGetPhysicalDeviceProperties, (VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties), (physicalDevice, pProperties)) VK_WRAP_VOID(vkGetPhysicalDeviceMemoryProperties, (VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties), (physicalDevice, pMemoryProperties)) VK_WRAP_VOID(vkGetPhysicalDeviceQueueFamilyProperties, (VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties), (physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties)) VK_WRAP_RESULT(VkResult, vkGetPhysicalDeviceSurfaceCapabilitiesKHR, (VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities), (physicalDevice, surface, pSurfaceCapabilities)) VK_WRAP_RESULT(VkResult, vkGetPhysicalDeviceSurfaceFormatsKHR, (VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats), (physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats)) VK_WRAP_RESULT(VkResult, vkGetPhysicalDeviceSurfacePresentModesKHR, (VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes), (physicalDevice, surface, pPresentModeCount, pPresentModes)) VK_WRAP_RESULT(VkResult, vkCreateDebugUtilsMessengerEXT, (VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger), (instance, pCreateInfo, pAllocator, pMessenger)) #if defined(__linux__) VK_WRAP_RESULT(VkResult, vkCreateXcbSurfaceKHR, (VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface), (instance, pCreateInfo, pAllocator, pSurface)) #else VK_WRAP_RESULT(VkResult, vkCreateWin32SurfaceKHR, (VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface), (instance, pCreateInfo, pAllocator, pSurface)) #endif // Device procs VK_WRAP_VOID(vkGetDeviceQueue, (VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue), (device, queueFamilyIndex, queueIndex, pQueue)) VK_WRAP_RESULT(VkResult, vkCreateSwapchainKHR, (VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain), (device, pCreateInfo, pAllocator, pSwapchain)) VK_WRAP_VOID(vkDestroySwapchainKHR, (VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator), (device, swapchain, pAllocator)) VK_WRAP_RESULT(VkResult, vkGetSwapchainImagesKHR, (VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages), (device, swapchain, pSwapchainImageCount, pSwapchainImages)) VK_WRAP_RESULT(VkResult, vkAcquireNextImageKHR, (VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex), (device, swapchain, timeout, semaphore, fence, pImageIndex)) VK_WRAP_RESULT(VkResult, vkQueuePresentKHR, (VkQueue queue, const VkPresentInfoKHR* pPresentInfo), (queue, pPresentInfo)) VK_WRAP_RESULT(VkResult, vkCreateCommandPool, (VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool), (device, pCreateInfo, pAllocator, pCommandPool)) VK_WRAP_RESULT(VkResult, vkAllocateCommandBuffers, (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers), (device, pAllocateInfo, pCommandBuffers)) VK_WRAP_VOID(vkFreeCommandBuffers, (VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers), (device, commandPool, commandBufferCount, pCommandBuffers)) VK_WRAP_RESULT(VkResult, vkResetCommandBuffer, (VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags), (commandBuffer, flags)) VK_WRAP_RESULT(VkResult, vkBeginCommandBuffer, (VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo), (commandBuffer, pBeginInfo)) VK_WRAP_RESULT(VkResult, vkEndCommandBuffer, (VkCommandBuffer commandBuffer), (commandBuffer)) VK_WRAP_RESULT(VkResult, vkCreateSemaphore, (VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore), (device, pCreateInfo, pAllocator, pSemaphore)) VK_WRAP_RESULT(VkResult, vkWaitSemaphores, (VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout), (device, pWaitInfo, timeout)) VK_WRAP_RESULT(VkResult, vkDeviceWaitIdle, (VkDevice device), (device)) VK_WRAP_RESULT(VkResult, vkQueueSubmit, (VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence), (queue, submitCount, pSubmits, fence)) VK_WRAP_RESULT(VkResult, vkCreateDescriptorPool, (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool), (device, pCreateInfo, pAllocator, pDescriptorPool)) VK_WRAP_RESULT(VkResult, vkCreateDescriptorSetLayout, (VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout), (device, pCreateInfo, pAllocator, pSetLayout)) VK_WRAP_RESULT(VkResult, vkAllocateDescriptorSets, (VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets), (device, pAllocateInfo, pDescriptorSets)) VK_WRAP_VOID(vkUpdateDescriptorSets, (VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies), (device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies)) VK_WRAP_RESULT(VkResult, vkCreateBuffer, (VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer), (device, pCreateInfo, pAllocator, pBuffer)) VK_WRAP_VOID(vkDestroyBuffer, (VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator), (device, buffer, pAllocator)) VK_WRAP_VOID(vkGetBufferMemoryRequirements, (VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements), (device, buffer, pMemoryRequirements)) VK_WRAP_RESULT(VkResult, vkCreateImage, (VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage), (device, pCreateInfo, pAllocator, pImage)) VK_WRAP_VOID(vkDestroyImage, (VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator), (device, image, pAllocator)) VK_WRAP_VOID(vkGetImageMemoryRequirements, (VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements), (device, image, pMemoryRequirements)) VK_WRAP_RESULT(VkResult, vkAllocateMemory, (VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory), (device, pAllocateInfo, pAllocator, pMemory)) VK_WRAP_VOID(vkFreeMemory, (VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator), (device, memory, pAllocator)) VK_WRAP_RESULT(VkResult, vkBindBufferMemory, (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset), (device, buffer, memory, memoryOffset)) VK_WRAP_RESULT(VkResult, vkBindImageMemory, (VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset), (device, image, memory, memoryOffset)) VK_WRAP_RESULT(VkResult, vkMapMemory, (VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData), (device, memory, offset, size, flags, ppData)) VK_WRAP_VOID(vkUnmapMemory, (VkDevice device, VkDeviceMemory memory), (device, memory)) VK_WRAP_RESULT(VkResult, vkInvalidateMappedMemoryRanges, (VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges), (device, memoryRangeCount, pMemoryRanges)) VK_WRAP_RESULT(VkResult, vkCreateImageView, (VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView), (device, pCreateInfo, pAllocator, pView)) VK_WRAP_VOID(vkDestroyImageView, (VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator), (device, imageView, pAllocator)) VK_WRAP_RESULT(VkResult, vkCreateSampler, (VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler), (device, pCreateInfo, pAllocator, pSampler)) VK_WRAP_VOID(vkDestroySampler, (VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator), (device, sampler, pAllocator)) VK_WRAP_RESULT(VkResult, vkCreateShaderModule, (VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule), (device, pCreateInfo, pAllocator, pShaderModule)) VK_WRAP_VOID(vkDestroyShaderModule, (VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator), (device, shaderModule, pAllocator)) VK_WRAP_RESULT(VkResult, vkCreatePipelineLayout, (VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout), (device, pCreateInfo, pAllocator, pPipelineLayout)) VK_WRAP_VOID(vkDestroyPipelineLayout, (VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator), (device, pipelineLayout, pAllocator)) VK_WRAP_RESULT(VkResult, vkCreateGraphicsPipelines, (VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines), (device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines)) VK_WRAP_VOID(vkDestroyPipeline, (VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator), (device, pipeline, pAllocator)) VK_WRAP_VOID(vkCmdPipelineBarrier2, (VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo), (commandBuffer, pDependencyInfo)) VK_WRAP_VOID(vkCmdBindDescriptorSets, (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets), (commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets)) VK_WRAP_VOID(vkCmdCopyBuffer, (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions), (commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions)) VK_WRAP_VOID(vkCmdCopyBufferToImage, (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions), (commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions)) VK_WRAP_VOID(vkCmdCopyImage, (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions), (commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions)) VK_WRAP_VOID(vkCmdCopyImageToBuffer, (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions), (commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions)) VK_WRAP_VOID(vkCmdBeginRendering, (VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo), (commandBuffer, pRenderingInfo)) VK_WRAP_VOID(vkCmdEndRendering, (VkCommandBuffer commandBuffer), (commandBuffer)) VK_WRAP_VOID(vkCmdSetViewport, (VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports), (commandBuffer, firstViewport, viewportCount, pViewports)) VK_WRAP_VOID(vkCmdSetScissor, (VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors), (commandBuffer, firstScissor, scissorCount, pScissors)) VK_WRAP_VOID(vkCmdBindPipeline, (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline), (commandBuffer, pipelineBindPoint, pipeline)) VK_WRAP_VOID(vkCmdPushConstants, (VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues), (commandBuffer, layout, stageFlags, offset, size, pValues)) VK_WRAP_VOID(vkCmdBindVertexBuffers, (VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets), (commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets)) VK_WRAP_VOID(vkCmdBindIndexBuffer, (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType), (commandBuffer, buffer, offset, indexType)) VK_WRAP_VOID(vkCmdDraw, (VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance), (commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance)) VK_WRAP_VOID(vkCmdDrawIndexed, (VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance), (commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance)) VK_WRAP_RESULT(VkResult, vkSetDebugUtilsObjectNameEXT, (VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo), (device, pNameInfo)) VK_WRAP_VOID(vkCmdSetCheckpointNV, (VkCommandBuffer commandBuffer, const void* pCheckpointMarker), (commandBuffer, pCheckpointMarker)) VK_WRAP_VOID(vkGetQueueCheckpointDataNV, (VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData), (queue, pCheckpointDataCount, pCheckpointData)) #undef VK_WRAP_VOID #undef VK_WRAP_RESULT #undef UNPAREN #undef VK_DEVICE_PROCS #undef VK_INSTANCE_PROCS #undef VK_PLATFORM_INSTANCE_PROCS #undef VK_GLOBAL_PROCS static const char* string_VkResult(VkResult res) { switch (res) { case VK_SUCCESS: return "VK_SUCCESS"; case VK_NOT_READY: return "VK_NOT_READY"; case VK_TIMEOUT: return "VK_TIMEOUT"; case VK_EVENT_SET: return "VK_EVENT_SET"; case VK_EVENT_RESET: return "VK_EVENT_RESET"; case VK_INCOMPLETE: return "VK_INCOMPLETE"; case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY"; case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED"; case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST"; case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED"; case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT"; case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT"; case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT"; case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER"; case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS"; case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED"; case VK_ERROR_FRAGMENTED_POOL: return "VK_ERROR_FRAGMENTED_POOL"; case VK_ERROR_UNKNOWN: return "VK_ERROR_UNKNOWN"; case VK_ERROR_OUT_OF_POOL_MEMORY: return "VK_ERROR_OUT_OF_POOL_MEMORY"; case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; case VK_ERROR_FRAGMENTATION: return "VK_ERROR_FRAGMENTATION"; case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS"; case VK_PIPELINE_COMPILE_REQUIRED: return "VK_PIPELINE_COMPILE_REQUIRED"; case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR"; case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR"; case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR"; case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; case VK_ERROR_VALIDATION_FAILED_EXT: return "VK_ERROR_VALIDATION_FAILED_EXT"; case VK_ERROR_INVALID_SHADER_NV: return "VK_ERROR_INVALID_SHADER_NV"; case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; } return {}; } static const char* string_VkPresentModeKHR(VkPresentModeKHR mode) { switch (mode) { case VK_PRESENT_MODE_IMMEDIATE_KHR: return "VK_PRESENT_MODE_IMMEDIATE_KHR"; case VK_PRESENT_MODE_MAILBOX_KHR: return "VK_PRESENT_MODE_MAILBOX_KHR"; case VK_PRESENT_MODE_FIFO_KHR: return "VK_PRESENT_MODE_FIFO_KHR"; case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "VK_PRESENT_MODE_FIFO_RELAXED_KHR"; case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: return "VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR"; case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: return "VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR"; } return {}; } static void VkCheckImpl(VkResult res) { switch (res) { case VK_SUCCESS: break; case VK_ERROR_DEVICE_LOST: // TODO: // LOG("Last checkpoint: %I64d", RhiGetLastCheckpointData(rhi_queue_type::Graphics)); // default: { LOG("Vulkan error: %s", string_VkResult(res)); ASSERT(false); } } } #define VK_CHECK(res) VkCheckImpl(res) enum vulkan_flags { VulkanFlag_Used = 1 << 0, VulkanFlag_DescriptorWritten = 1 << 1, VulkanFlag_Dirty = 1 << 2, VulkanFlag_Dynamic = 1 << 3, }; struct rhi_buffer_data { uint32_t Flags; VkBuffer buffer; uint64_t size; rhi_memory_usage memoryUsage; VkDeviceMemory memory; uint8_t* mapped; rhi_buffer_state state; uint32_t dirtyBegin; uint32_t dirtyEnd; }; struct rhi_buffer_view_data { uint32_t Flags; rhi_buffer buffer; uint32_t size; uint32_t offset; uint32_t range; }; struct rhi_cmdlist_data { uint32_t Flags; VkCommandBuffer cmdbuf; rhi_queue_type queueType; rhi_graphics_pipeline boundGraphicsPipeline; uint32_t frameConstantHead; uint32_t passConstantHead; uint32_t drawConstantHead; }; struct rhi_graphics_pipeline_data { uint32_t Flags; VkPipelineLayout layout; VkPipeline pipeline; VkPipelineBindPoint bindPoint; }; struct rhi_shader_data { uint32_t Flags; uint32_t *spv; uint64_t spvCount; }; struct rhi_texture_data { uint32_t Flags; VkImage image; VkDeviceMemory memory; rhi_texture_state state; VkImageLayout layout; VkFormat format; VkImageAspectFlags aspectMask; VkExtent3D extent; }; struct rhi_texture_view_data { uint32_t Flags; rhi_texture texture; VkImageView imageView; VkImageViewType imageViewType; VkFormat format; VkImageSubresourceRange subresourceRange; }; struct rhi_sampler_data { uint32_t Flags; VkSampler sampler; }; struct rhi_descriptor_table { VkDescriptorSetLayout layout; VkDescriptorSet set; }; struct vulkan_device_queue { VkQueue queue; uint32_t queueFamilyIndex; VkCommandPool cmdPool; rhi_cmdlist cmd; uint64_t cmdDone; VkSemaphore timeline; uint64_t timelineNext; }; struct rhi_state { VkAllocationCallbacks* vkAlloc; rhi_flags flags; rhi_limits limits; VkInstance instance; VkDevice dev; VkPhysicalDevice physDev; VkPhysicalDeviceProperties physDevProps; VkPhysicalDeviceMemoryProperties physDevMemProps; VkDescriptorPool descriptorPool; VkSurfaceKHR surface; VkSwapchainKHR swapchain; bool swapchainUsable; bool recreateSwapchain; struct { rhi_render_target_view View; VkSemaphore Semaphore; } SwapChain[16]; uint32_t SwapChainCount; uint32_t SwapChainIndex; VkSemaphore SwapChainAcquireSemaphore; rhi_cmdlist_data* CmdLists; rhi_buffer_data* Buffers; rhi_buffer_view_data* ConstantBufferViews; rhi_texture_data* Textures; rhi_texture_view_data* DepthStencilViews; rhi_texture_view_data* RenderTargetViews; rhi_texture_view_data* SampledTextureViews; rhi_sampler_data* Samplers; rhi_shader_data* Shaders; rhi_graphics_pipeline_data* GraphicsPipelines; rhi_descriptor_table constantsDescriptorTable; rhi_buffer constantsUniformBuffer; rhi_descriptor_table texturesDescriptorTable; rhi_descriptor_table SamplersDescriptorTable; vulkan_device_queue graphicsQueue; // vulkan_device_queue computeQueue; // vulkan_device_queue transferQueue; }; static rhi_state* rhi; static uint32_t CbvOffset(uint32_t offset) { return ALIGN_UP(offset, rhi->physDevProps.limits.minUniformBufferOffsetAlignment); } static VkMemoryPropertyFlags ConvertMemoryUsageIntoVkMemoryPropertyFlags(rhi_memory_usage usage) { // TODO: not all GPUs support HOST_COHERENT, HOST_CACHED switch (usage) { case MemoryUsage_GpuOnly: return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; case MemoryUsage_CpuToGpu: return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; case MemoryUsage_GpuToCpu: return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; } ASSERT(false); return 0; } static VkFormat ConvertVertexFormatIntoVkFormat(rhi_vertex_format format) { switch (format) { case R32G32B32A32Float: return VK_FORMAT_R32G32B32A32_SFLOAT; case R32G32B32Float: return VK_FORMAT_R32G32B32_SFLOAT; case R32G32Float: return VK_FORMAT_R32G32_SFLOAT; case R32G32B32A32Uint: return VK_FORMAT_R32G32B32A32_UINT; } ASSERT(false); return static_cast(0); } static VkShaderStageFlags ConvertShaderStageIntoVkShaderStageFlags(rhi_shader_stage stageFlags) { VkShaderStageFlags ret = 0; if (stageFlags & Shader_Vertex) { ret |= VK_SHADER_STAGE_VERTEX_BIT; } if (stageFlags & Shader_Pixel) { ret |= VK_SHADER_STAGE_FRAGMENT_BIT; } return ret; } static VkCullModeFlags ConvertVulkanCullMode(rhi_pipeline_flags Flags) { if (Flags & Pipeline_CullFront) return VK_CULL_MODE_FRONT_BIT; if (Flags & Pipeline_CullBack) return VK_CULL_MODE_BACK_BIT; return VK_CULL_MODE_NONE; } static VkFrontFace ConvertVulkanFrontFace(rhi_pipeline_flags Flags) { if (Flags & Pipeline_CW) return VK_FRONT_FACE_CLOCKWISE; else return VK_FRONT_FACE_COUNTER_CLOCKWISE; } static VkFilter ConvertFilter(rhi_filter filter) { switch (filter) { case FilterLinear: return VK_FILTER_LINEAR; case FilterNearest: return VK_FILTER_NEAREST; } ASSERT(false); return { }; } static VkSamplerAddressMode ConvertSamplerAddressMode(rhi_sampler_address_mode addressMode) { switch (addressMode) { case AddressRepeat: return VK_SAMPLER_ADDRESS_MODE_REPEAT; case AddressClampToEdge: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; } ASSERT(false); return { }; } static VkVertexInputRate ConvertVulkanInputRate(rhi_input_rate inputRate) { switch (inputRate) { case PerInstance: return VK_VERTEX_INPUT_RATE_INSTANCE; case PerVertex: return VK_VERTEX_INPUT_RATE_VERTEX; } ASSERT(false); return static_cast(0); } struct vulkan_texture_state_sync_info { VkPipelineStageFlags2 stage; VkAccessFlags2 access; VkImageLayout layout; }; static vulkan_texture_state_sync_info VulkanTextureStateGetSyncInfo(rhi_texture_state state) { vulkan_texture_state_sync_info ret{}; switch (state) { case TextureState_Undefined: { ret.stage = VK_PIPELINE_STAGE_2_NONE; ret.access = VK_ACCESS_2_NONE; ret.layout = VK_IMAGE_LAYOUT_UNDEFINED; } break; case TextureState_ColorTarget: { ret.stage = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; ret.access = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; ret.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } break; case TextureState_DepthTarget: { ret.stage = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT; ret.access = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT; ret.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } break; case TextureState_ShaderRead: { ret.stage = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; ret.access = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT; ret.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } break; case TextureState_Present: { ret.stage = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; ret.access = VK_ACCESS_2_NONE; ret.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; } break; case TextureState_TransferSrc: { ret.stage = VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT | VK_PIPELINE_STAGE_2_RESOLVE_BIT; ret.access = VK_ACCESS_2_TRANSFER_READ_BIT; ret.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; } break; case TextureState_TransferDst: { ret.stage = VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT | VK_PIPELINE_STAGE_2_RESOLVE_BIT; ret.access = VK_ACCESS_2_TRANSFER_WRITE_BIT; ret.layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; } break; default: { ASSERT(false); } break; } return ret; } static VkFormat ConvertTextureFormatIntoVkFormat(rhi_texture_format format, VkImageAspectFlags* outAspectMask) { switch (format) { case TextureFormatNone: { if (outAspectMask) *outAspectMask = 0; return VK_FORMAT_UNDEFINED; } case R8_UNORM: { if (outAspectMask) *outAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; return VK_FORMAT_R8_UNORM; } case R8G8B8A8_sRGB: { if (outAspectMask) *outAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; return VK_FORMAT_R8G8B8A8_SRGB; } case B8G8R8A8_sRGB: { if (outAspectMask) *outAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; return VK_FORMAT_B8G8R8A8_SRGB; } case D32_Float: { if (outAspectMask) *outAspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; return VK_FORMAT_D32_SFLOAT; } case D32_Float_S8_UINT: { if (outAspectMask) *outAspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; return VK_FORMAT_D32_SFLOAT_S8_UINT; } } ASSERT(false); return (VkFormat)0; } static rhi_texture_format ConvertVkFormatIntoTextureFormat(VkFormat format) { switch (format) { case VK_FORMAT_R8G8B8A8_SRGB: return R8G8B8A8_sRGB; case VK_FORMAT_B8G8R8A8_SRGB: return B8G8R8A8_sRGB; case VK_FORMAT_D32_SFLOAT: return D32_Float; case VK_FORMAT_D32_SFLOAT_S8_UINT: return D32_Float_S8_UINT; default: break; } ASSERT(false); return TextureFormatNone; } static VkImageUsageFlags ConvertTextureUsageToVkImageUsageFlags(rhi_texture_usage usage) { VkImageUsageFlags flags = 0; if (usage & TextureUsage_ShaderSampled) { flags |= VK_IMAGE_USAGE_SAMPLED_BIT; } if (usage & TextureUsage_ColorTarget) { flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } if (usage & TextureUsage_DepthStencil) { flags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; } if (usage & TextureUsage_TransferSrc) { flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; } if (usage & TextureUsage_TransferDst) { flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; } if (usage & TextureUsage_Storage) { flags |= VK_IMAGE_USAGE_STORAGE_BIT; } if (usage & TextureUsage_Present) { } return flags; } static uint32_t GetVertexFormatSize(rhi_vertex_format format) { switch (format) { case R32G32Float: return 8; case R32G32B32Float: return 12; case R32G32B32A32Float: return 16; case R32G32B32A32Uint: return 16; } ASSERT(false); return 0; } static void VulkanNameHandle(VkObjectType type, uint64_t handle, const char* name) { #if RHI_VALIDATIONS VkDebugUtilsObjectNameInfoEXT nameInfo{}; nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; nameInfo.objectType = type; nameInfo.objectHandle = handle; nameInfo.pObjectName = name; vkSetDebugUtilsObjectNameEXT(rhi->dev, &nameInfo); #endif } static uint32_t VulkanFindMemoryTypeIndex(VkMemoryRequirements memRequirements, VkMemoryPropertyFlags properties) { // TODO: not all GPUs support HOST_COHERENT, HOST_CACHED VkPhysicalDeviceMemoryProperties memPropertities; vkGetPhysicalDeviceMemoryProperties(rhi->physDev, &memPropertities); for (uint32_t i = 0; i < memPropertities.memoryTypeCount; ++i) { if (!(memRequirements.memoryTypeBits & (1 << i))) { continue; } if ((memPropertities.memoryTypes[i].propertyFlags & properties) != properties) { continue; } return i; } ASSERT(false); return 0; } static vulkan_device_queue* GetDeviceQueue(rhi_queue_type queueType) { switch (queueType) { case QueueType_Graphics: return &rhi->graphicsQueue; } ASSERT(false); return 0; } #if RHI_VALIDATIONS static void VulkanLogToFile(const char* message) { // Truncate once per process so the file only holds the current run. static bool truncated = false; FILE* f = fopen("vk.log", truncated ? "a" : "w"); truncated = true; if (f) { fprintf(f, "%s\n", message); fclose(f); } } static VkBool32 DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* pUserData) { if (messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT || messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { VulkanLogToFile(callbackData->pMessage); } switch (messageSeverity) { case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: { LOG("%s", callbackData->pMessage); ASSERT(false); } break; case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: { LOG("%s", callbackData->pMessage); } break; default: { LOG("%s", callbackData->pMessage); } break; } return VK_FALSE; } #endif static VkSemaphore VulkanCreateTimelineSemaphore(uint64_t initialValue) { VkSemaphoreTypeCreateInfo timelineCreateInfo{}; timelineCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO; timelineCreateInfo.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; timelineCreateInfo.initialValue = initialValue; VkSemaphoreCreateInfo semaphoreCreateInfo{}; semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreCreateInfo.pNext = &timelineCreateInfo; VkSemaphore semaphore; vkCreateSemaphore(rhi->dev, &semaphoreCreateInfo, nullptr, &semaphore); return semaphore; } static void VulkanWaitTimelineSemaphore(VkSemaphore timeline, uint64_t waitValue) { VkSemaphoreWaitInfo waitInfo{}; waitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO; waitInfo.pNext = NULL; waitInfo.flags = 0; waitInfo.semaphoreCount = 1; waitInfo.pSemaphores = &timeline; waitInfo.pValues = &waitValue; VK_CHECK(vkWaitSemaphores(rhi->dev, &waitInfo, (uint64_t)1'000'000'000)); } uint32_t Rhi_GetMinUniformBufferOffsetAlignment() { return rhi->physDevProps.limits.minUniformBufferOffsetAlignment; } uint32_t Rhi_GetOptimalBufferCopyOffsetAlignment() { return rhi->physDevProps.limits.optimalBufferCopyOffsetAlignment; } void Rhi_CmdSetCheckpoint(rhi_cmdlist cmd, uint64_t data) { #if RHI_VALIDATIONS vkCmdSetCheckpointNV(((rhi_cmdlist_data*)cmd)->cmdbuf, reinterpret_cast(data)); #endif } uint64_t Rhi_GetLastCheckpointData(rhi_queue_type queueType) { #if RHI_VALIDATIONS uint32_t dataCount = 1; VkCheckpointDataNV data {}; VkQueue queue = GetDeviceQueue(queueType)->queue; vkGetQueueCheckpointDataNV(queue, &dataCount, &data); return (uint64_t)data.pCheckpointMarker; #else (void)queueType; return 0; #endif } rhi_shader Rhi_CreateShader(rhi_shader_stage stage, byteview shader) { rhi_shader_data* Shader = nullptr; for (uint32_t i = 0; i < rhi->limits.ShadersCount; ++i) { if (!(rhi->Shaders[i].Flags & VulkanFlag_Used)) { Shader = &rhi->Shaders[i]; break; } } ASSERT(Shader); MEM_ZERO(Shader, 0); Shader->Flags = VulkanFlag_Used; // TODO: Shader->stage = stage; Shader->spv = (uint32_t*)shader.data; Shader->spvCount = shader.size / 4; ASSERT((shader.size % 4) == 0); return Shader; } rhi_sampler Rhi_CreateSampler(const char* name, rhi_filter minFilter, rhi_filter magFilter, rhi_sampler_address_mode addressModeU, rhi_sampler_address_mode addressModeV, rhi_sampler_address_mode addressModeW) { rhi_sampler_data* Sampler = nullptr; for (uint32_t i = 0; i < rhi->limits.SamplersCount; ++i) { if (!(rhi->Samplers[i].Flags & VulkanFlag_Used)) { Sampler = &rhi->Samplers[i]; break; } } ASSERT(Sampler); MEM_ZERO(Sampler, 0); Sampler->Flags = VulkanFlag_Used; VkSamplerCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; createInfo.magFilter = ConvertFilter(magFilter); createInfo.minFilter = ConvertFilter(minFilter); createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; createInfo.addressModeU = ConvertSamplerAddressMode(addressModeU); createInfo.addressModeV = ConvertSamplerAddressMode(addressModeV); createInfo.addressModeW = ConvertSamplerAddressMode(addressModeW); createInfo.mipLodBias = 0.f; createInfo.anisotropyEnable = false; createInfo.maxAnisotropy = 0.f; createInfo.minLod = 0.f; createInfo.maxLod = 0.f; VK_CHECK(vkCreateSampler(rhi->dev, &createInfo, rhi->vkAlloc, &Sampler->sampler)); VulkanNameHandle(VK_OBJECT_TYPE_SAMPLER, (uint64_t)Sampler->sampler, name); return Sampler; } rhi_render_target_view Rhi_GetBackbufferView() { return rhi->SwapChain[rhi->SwapChainIndex].View; } void Rhi_TriggerSwapchainRecreate() { rhi->recreateSwapchain = true; } void Rhi_WaitGpuIdle() { vkDeviceWaitIdle(rhi->dev); } #include "commons/rhi/vulkan/rhi_vulkan_cmdlist.cc" #include "commons/rhi/vulkan/rhi_vulkan_buffer.cc" #include "commons/rhi/vulkan/rhi_vulkan_texture.cc" #include "commons/rhi/vulkan/rhi_vulkan_descriptor.cc" #include "commons/rhi/vulkan/rhi_vulkan_shader.cc" #include "commons/rhi/vulkan/rhi_vulkan_graphics_pipeline.cc" #include "commons/rhi/vulkan/rhi_vulkan_frame_pass.cc" #include "commons/rhi/vulkan/rhi_vulkan_bootstrap.cc"