stories/engine/instance.cpp

111 lines
4.3 KiB
C++

#include "instance.h"
#include "engine.h"
Engine::Instance::Instance(Engine* eng) :
validationLayersEnabledAndSupported(false),
engine(eng),
vk(),
debugMessenger()
{
VkApplicationInfo appInfo {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Hello Triangle";
appInfo.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
appInfo.pEngineName = "Stories";
appInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1);
appInfo.apiVersion = VK_API_VERSION_1_0;
appInfo.pNext = nullptr;
//TODO handle exception
Support exts = getVulkanExtensions(engine->instanceExtensionNames, engine->getRequiredVulkanExtensions());
if (exts.unsupportedCritical.size() > 0) {
std::string error("Unable to create Vulkan instance, following critical extensions are unsupported:\n");
for (const char* ext : exts.unsupportedCritical) {
error += "\t" + std::string(ext) + "\n";
}
throw std::runtime_error(error);
}
//TODO log unsupported;
exts.logSupported("Applying extensions:");
//TODO handle exception
Support layers = getVulkanLayers(engine->layerNames);
//TODO log unsupported
layers.logSupported("Applying layers:");
VkInstanceCreateInfo createInfo {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
createInfo.flags = 0;
createInfo.enabledExtensionCount = static_cast<uint32_t>(exts.supported.size());
createInfo.ppEnabledExtensionNames = exts.supported.data();
createInfo.enabledLayerCount = static_cast<uint32_t>(layers.supported.size());
createInfo.ppEnabledLayerNames = layers.supported.data();
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
if (engine->enableValidationLayers()) {
validationLayersEnabledAndSupported = true; //TODO make sure it's actually supported, this shows that they are just enabled;
populateDebugMessengerCreateInfo(debugCreateInfo, debugCallback);
createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo;
}
VkResult res = vkCreateInstance(&createInfo, nullptr, &vk);
switch (res) {
case VK_SUCCESS:
break;
case VK_ERROR_INCOMPATIBLE_DRIVER:
throw std::runtime_error("unable to create vulkan instance, cannot find a compatible Vulkan ICD");
case VK_ERROR_OUT_OF_HOST_MEMORY:
throw std::runtime_error("unable to create vulkan instance, out of host memory");
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
throw std::runtime_error("unable to create vulkan instance, out of device memory");
case VK_ERROR_INITIALIZATION_FAILED:
throw std::runtime_error("unable to create vulkan instance, initialization failed");
case VK_ERROR_LAYER_NOT_PRESENT:
throw std::runtime_error("unable to create vulkan instance, layer not present");
case VK_ERROR_EXTENSION_NOT_PRESENT:
throw std::runtime_error("unable to create vulkan instance, extension not present");
default:
throw std::runtime_error("unable to create Vulkan instance: unknown error");
}
if (validationLayersEnabledAndSupported)
setupDebugMessenger();
}
Engine::Instance::~Instance() {
if (validationLayersEnabledAndSupported)
destroyDebugUtilsMessengerEXT(vk, debugMessenger, nullptr);
vkDestroyInstance(vk, nullptr);
}
void Engine::Instance::setupDebugMessenger() {
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
populateDebugMessengerCreateInfo(createInfo, debugCallback);
VkResult res = createDebugUtilsMessengerEXT(vk, &createInfo, nullptr, &debugMessenger);
switch (res) {
case VK_SUCCESS:
break;
case VK_ERROR_EXTENSION_NOT_PRESENT:
throw std::runtime_error("failed to set up debug messenger: extension not present");
break;
default:
throw std::runtime_error("failed to set up debug messenger");
}
}
std::vector<VkPhysicalDevice> Engine::Instance::enumeratePhysicalDevices() const {
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(vk, &deviceCount, nullptr);
std::vector<VkPhysicalDevice> devices(deviceCount);
if (deviceCount > 0)
vkEnumeratePhysicalDevices(vk, &deviceCount, devices.data());
return devices;
}