142 lines
No EOL
4.1 KiB
C++
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");
|
|
} |