VulkanGraphics/src/GPU/private/vulkan_utils.cpp
Ilya Shurupov f5bd6f85a8 plans
2024-11-24 12:21:50 +03:00

142 lines
No EOL
4.1 KiB
C++

#include "vulkan_utils.hpp"
#include <cstring>
#include <stdexcept>
bool checkValidationLayerSupport(const std::vector<const char *>& validationLayers) {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> 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<const char *>& deviceExtensions) {
uint32_t extensionsCount = 0;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionsCount, nullptr);
std::vector<VkExtensionProperties> 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) {
VkInstance out = VK_NULL_HANDLE;
const std::vector<const char *> validationLayers = {
#ifdef NDEBUG
#else
"VK_LAYER_KHRONOS_validation"
#endif
};
if (!checkValidationLayerSupport(validationLayers)) {
throw std::runtime_error("no required validation layers present");
}
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 = VK_API_VERSION_1_0,
};
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<VkPhysicalDevice> 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<VkQueueFamilyProperties> 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");
}