#include "VulkanUtils.hpp" #include #include bool checkValidationLayerSupport(const std::vector& validationLayers) { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); std::vector availableLayers(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); for (const auto &requestedLayer: validationLayers) { bool presents = false; for (auto &layer: availableLayers) { if (strcmp(requestedLayer, layer.layerName) == 0) { presents = true; break; } } if (!presents) return false; } return true; } bool checkDeviceExtensions(VkPhysicalDevice device, const std::vector& deviceExtensions) { uint32_t extensionsCount = 0; vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionsCount, nullptr); std::vector extensions(extensionsCount); vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionsCount, extensions.data()); for (const auto &requiredExtension: deviceExtensions) { bool found = false; for (const auto &extension: extensions) { if (strcmp(requiredExtension, extension.extensionName) == 0) { found = true; break; } } if (!found) return false; } return true; } VkInstance createInstance(const char ** instanceExtensions, uint32_t extensionsCount, uint32_t apiVersion) { VkInstance out = VK_NULL_HANDLE; std::vector validationLayers; #ifndef NDEBUG const std::vector requestedLayers = {"VK_LAYER_KHRONOS_validation"}; if (checkValidationLayerSupport(requestedLayers)) { validationLayers = requestedLayers; } #endif VkApplicationInfo appInfo{ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "App", .applicationVersion = VK_MAKE_VERSION(0, 0, 0), .pEngineName = "no", .engineVersion = VK_MAKE_VERSION(0, 0, 0), .apiVersion = apiVersion, }; VkInstanceCreateInfo createInfo{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &appInfo, .enabledLayerCount = (uint32_t) validationLayers.size(), .ppEnabledLayerNames = validationLayers.data(), .enabledExtensionCount = extensionsCount, .ppEnabledExtensionNames = instanceExtensions, }; if (vkCreateInstance(&createInfo, nullptr, &out) != VK_SUCCESS) { return VK_NULL_HANDLE; } return out; } VkPhysicalDevice pickPhysicalDevice(VkInstance instance, const PhysicalDevicePickPolicy& pickPolicy) { VkPhysicalDevice out = VK_NULL_HANDLE; uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); if (deviceCount == 0) { throw std::runtime_error("no gpu with vulkan support"); } std::vector devices(deviceCount); vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); for (auto device: devices) { if (pickPolicy(device)) { out = device; break; } } return out; } int findQueueFamilyIndex(VkPhysicalDevice physicalDevice, const QueuePickPolicy& pickPolicy) { int out = -1; uint32_t queuesCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queuesCount, nullptr); std::vector queueFamilyProperties(queuesCount); vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queuesCount, queueFamilyProperties.data()); int index = 0; for (const auto &familyProperty: queueFamilyProperties) { if (pickPolicy(familyProperty, index)) { out = index; } index++; } return out; } uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags flags) { VkPhysicalDeviceMemoryProperties memoryProperties; vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties); for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) { if (typeFilter & (1 << i) && (memoryProperties.memoryTypes[i].propertyFlags & flags) == flags) { return i; } } throw std::runtime_error("no suitable memory for vertex buffer found"); }