stories/engine/utils.cpp

186 lines
6.4 KiB
C++

#include "utils.h"
bool discoveredLayers = false;
bool discoveredExtensions = false;
std::map<std::string, VkLayerProperties> availableLayers;
std::map<std::string, VkExtensionProperties> availableExtensions;
Engine::Support Engine::getVulkanLayers(const std::set<std::string>& requestedLayers)
{
Engine::Support result;
if (!discoveredLayers) {
std::vector<VkLayerProperties> props = getAvailableVulkanLayers();
for (const VkLayerProperties& prop : props)
availableLayers.insert(std::make_pair(prop.layerName, prop));
discoveredLayers = true;
}
for (const std::string& ext : requestedLayers) {
if (availableLayers.count(ext) > 0)
result.supported.push_back(ext.c_str());
else
result.unsupported.push_back(ext.c_str());
}
return result;
}
Engine::Support Engine::getVulkanExtensions(
const std::set<std::string>& requestedExtensions,
const std::vector<const char*>& criticalExtensions
) {
Support result;
if (!discoveredExtensions) {
std::vector<VkExtensionProperties> props = getAvailableVulkanExtensions();
for (const VkExtensionProperties& prop : props)
availableExtensions.insert(std::make_pair(prop.extensionName, prop));
discoveredExtensions = true;
}
for (const char* ext : criticalExtensions) {
if (availableExtensions.count(ext) > 0)
result.supported.push_back(ext);
else
result.unsupportedCritical.push_back(ext);
}
for (const std::string& ext : requestedExtensions) {
if (availableExtensions.count(ext) > 0)
result.supported.push_back(ext.c_str());
else
result.unsupported.push_back(ext.c_str());
}
return result;
}
std::vector<VkExtensionProperties> Engine::getAvailableVulkanExtensions() {
unsigned int extCount = 0;
VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
if (res != VK_SUCCESS)
throw std::runtime_error("unable to query vulkan extension property count");
std::vector<VkExtensionProperties> extensions(extCount);
res = vkEnumerateInstanceExtensionProperties(nullptr, &extCount, extensions.data());
if (res != VK_SUCCESS)
throw std::runtime_error("unable to retrieve vulkan instance layer names");
return extensions;
}
void Engine::populateDebugMessengerCreateInfo(
VkDebugUtilsMessengerCreateInfoEXT& createInfo,
PFN_vkDebugUtilsMessengerCallbackEXT debugCallback)
{
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback = debugCallback;
createInfo.pUserData = nullptr; // Optional
}
std::vector<VkLayerProperties> Engine::getAvailableVulkanLayers() {
unsigned int layerCount = 0;
VkResult res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
if (res != VK_SUCCESS)
throw std::runtime_error("unable to query vulkan instance layer property count");
std::vector<VkLayerProperties> layers(layerCount);
res = vkEnumerateInstanceLayerProperties(&layerCount, layers.data());
if (res != VK_SUCCESS)
throw std::runtime_error("unable to retrieve vulkan instance layer names");
return layers;
}
VkResult Engine::createDebugUtilsMessengerEXT(
VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDebugUtilsMessengerEXT* pDebugMessenger)
{
PFN_vkVoidFunction vdfunc = vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)(vdfunc);
if (func != nullptr)
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
else
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
void Engine::destroyDebugUtilsMessengerEXT(
VkInstance instance,
VkDebugUtilsMessengerEXT debugMessenger,
const VkAllocationCallbacks* pAllocator)
{
PFN_vkVoidFunction vdfunc = vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)(vdfunc);
if (func != nullptr)
func(instance, debugMessenger, pAllocator);
}
Engine::Support::Support():
supported(),
unsupported(),
unsupportedCritical()
{}
void Engine::Support::logSupported(const std::string& header) {
if (!supported.empty()) {
std::cout << header << std::endl;
for (const char* element : supported)
std::cout << "\t" << element << std::endl;
}
}
bool Engine::SwapChainSupportDetails::adequate() const {
return !formats.empty() && !presentModes.empty();
}
bool Engine::QueueFamilyIndices::isComplete() const {
return graphicsFamily.has_value() && presentFamily.has_value();
}
std::vector<char> Engine::readFile(const std::string& filename) {
std::ifstream file(filename, std::ios::ate | std::ios::binary);
if (!file.is_open())
throw std::runtime_error("failed to open file " + filename);
size_t fileSize = (size_t) file.tellg();
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
return buffer;
}
VkSurfaceFormatKHR Engine::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
for (const VkSurfaceFormatKHR& availableFormat : availableFormats) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
return availableFormat;
}
return availableFormats[0];
}
VkPresentModeKHR Engine::chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {
for (const auto& availablePresentMode : availablePresentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
return availablePresentMode;
}
return VK_PRESENT_MODE_FIFO_KHR;
}