#ifndef _VULKAN_UTILS_H #define _VULKAN_UTILS_H #include #include #include #include #include #include #include using namespace std; struct QueueFamilyIndices { optional graphicsFamily; optional presentFamily; bool isComplete() { return graphicsFamily.has_value() && presentFamily.has_value(); } }; struct SwapChainSupportDetails { VkSurfaceCapabilitiesKHR capabilities; vector formats; vector presentModes; }; struct VulkanImage { VkImage image; VkDeviceMemory imageMemory; VkImageView imageView; }; class VulkanUtils { public: static bool checkValidationLayerSupport(const vector &validationLayers); static VkResult createDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger); static void destroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator); static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface); static bool checkDeviceExtensionSupport(VkPhysicalDevice physicalDevice, const vector& deviceExtensions); static SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface); static VkSurfaceFormatKHR chooseSwapSurfaceFormat(const vector& availableFormats); static VkPresentModeKHR chooseSwapPresentMode(const vector& availablePresentModes); static VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, int width, int height); static VkImageView createImageView(VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags); static VkFormat findSupportedFormat(VkPhysicalDevice physicalDevice, const vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features); static void createBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory); static uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties); static void createVulkanImageFromFile(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, string filename, VulkanImage& image, VkQueue graphicsQueue); static void createVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice, SDL_Texture* texture, VulkanImage& image); static void populateVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, SDL_Texture* texture, SDL_Renderer* renderer, VulkanImage& image, VkQueue graphicsQueue); static void createDepthImage(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkFormat depthFormat, VkExtent2D extent, VulkanImage& image, VkQueue graphicsQueue); static void createImage(VkDevice device, VkPhysicalDevice physicalDevice, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VulkanImage& image); static void transitionImageLayout(VkDevice device, VkCommandPool commandPool, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, VkQueue graphicsQueue); static VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool); static void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkCommandBuffer commandBuffer, VkQueue graphicsQueue); static void copyBufferToImage(VkDevice device, VkCommandPool commandPool, VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, VkQueue graphicsQueue); template static void copyDataToBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, const vector& srcData, VkBuffer dstBuffer, size_t dstVertexOffset, VkQueue graphicsQueue); static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size, VkQueue graphicsQueue); template static void copyDataToMemory(VkDevice device, VkDeviceMemory bufferMemory, const DataType& srcData); static bool hasStencilComponent(VkFormat format); static void destroyVulkanImage(VkDevice& device, VulkanImage& image); }; template void VulkanUtils::copyDataToBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, const vector& srcData, VkBuffer dstBuffer, size_t dstVertexOffset, VkQueue graphicsQueue) { VkDeviceSize srcDataSize = srcData.size() * sizeof(DataType); VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; createBuffer(device, physicalDevice, srcDataSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); void* data; vkMapMemory(device, stagingBufferMemory, 0, srcDataSize, 0, &data); memcpy(data, srcData.data(), (size_t)srcDataSize); vkUnmapMemory(device, stagingBufferMemory); copyBuffer(device, commandPool, stagingBuffer, dstBuffer, 0, dstVertexOffset * sizeof(DataType), srcDataSize, graphicsQueue); vkDestroyBuffer(device, stagingBuffer, nullptr); vkFreeMemory(device, stagingBufferMemory, nullptr); } template void VulkanUtils::copyDataToMemory(VkDevice device, VkDeviceMemory bufferMemory, const DataType& srcData) { void* data; vkMapMemory(device, bufferMemory, 0, sizeof(DataType), 0, &data); memcpy(data, &srcData, sizeof(DataType)); vkUnmapMemory(device, bufferMemory); } #endif // _VULKAN_UTILS_H