186 lines
6.4 KiB
C++
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;
|
|
}
|