2022-09-13 18:25:18 +00:00
|
|
|
#ifdef ENGINE_BUILD_VULKAN
|
|
|
|
|
|
|
|
#include "gfx_device.hpp"
|
|
|
|
|
|
|
|
#include "config.h"
|
2022-09-13 21:43:24 +00:00
|
|
|
#include "log.hpp"
|
|
|
|
|
2022-09-13 21:55:08 +00:00
|
|
|
#define VOLK_IMPLEMENTATION
|
|
|
|
#include "volk.h"
|
2022-09-13 18:25:18 +00:00
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
#include <SDL_vulkan.h>
|
|
|
|
|
2022-09-13 18:25:18 +00:00
|
|
|
#include <assert.h>
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-13 18:25:18 +00:00
|
|
|
#include <iostream>
|
2022-09-13 21:43:24 +00:00
|
|
|
#include <optional>
|
2022-09-19 17:33:56 +00:00
|
|
|
#include <unordered_set>
|
2022-09-13 18:25:18 +00:00
|
|
|
|
|
|
|
namespace engine::gfx {
|
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
static std::vector<const char*> getRequiredVulkanExtensions(SDL_Window* window)
|
|
|
|
{
|
|
|
|
SDL_bool res;
|
|
|
|
|
|
|
|
unsigned int sdlExtensionCount = 0;
|
|
|
|
res = SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, nullptr);
|
|
|
|
assert(res == SDL_TRUE);
|
|
|
|
std::vector<const char*> requiredExtensions(sdlExtensionCount);
|
|
|
|
res = SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, requiredExtensions.data());
|
|
|
|
assert(res == SDL_TRUE);
|
|
|
|
|
|
|
|
return requiredExtensions;
|
2022-09-19 08:57:02 +00:00
|
|
|
}
|
2022-09-17 00:22:35 +00:00
|
|
|
|
2022-09-13 18:25:18 +00:00
|
|
|
class Device::Impl {
|
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
public:
|
|
|
|
Impl(AppInfo appInfo, SDL_Window* window)
|
|
|
|
{
|
2022-09-19 08:57:02 +00:00
|
|
|
#ifdef NDEBUG
|
2022-09-19 17:33:56 +00:00
|
|
|
// release mode; don't use validation layer
|
|
|
|
m_layerInfo = std::make_unique<LayerInfo>(false);
|
2022-09-19 08:57:02 +00:00
|
|
|
#else
|
2022-09-19 17:33:56 +00:00
|
|
|
// debug mode; use validation layer
|
|
|
|
m_layerInfo = std::make_unique<LayerInfo>(true);
|
2022-09-13 21:43:24 +00:00
|
|
|
#endif
|
2022-09-19 17:33:56 +00:00
|
|
|
m_instance = std::make_shared<Instance>(appInfo, *m_layerInfo, getRequiredVulkanExtensions(window));
|
2022-09-19 08:57:02 +00:00
|
|
|
m_debugMessenger = std::make_unique<DebugMessenger>(m_instance);
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
// enumerate physical devices
|
|
|
|
uint32_t physDeviceCount = 0;
|
|
|
|
VkResult res;
|
|
|
|
res = vkEnumeratePhysicalDevices(m_instance->getHandle(), &physDeviceCount, nullptr);
|
|
|
|
assert(res == VK_SUCCESS);
|
|
|
|
if (physDeviceCount == 0) {
|
|
|
|
throw std::runtime_error("No GPU found with vulkan support!");
|
|
|
|
}
|
|
|
|
std::vector<VkPhysicalDevice> physicalDevices(physDeviceCount);
|
|
|
|
res = vkEnumeratePhysicalDevices(m_instance->getHandle(), &physDeviceCount, physicalDevices.data());
|
|
|
|
assert(res == VK_SUCCESS);
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
// find suitable device
|
|
|
|
const std::vector<const char*> requiredDeviceExtensions{
|
|
|
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
|
|
|
};
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
2022-09-19 08:57:02 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
for (const auto& dev : physicalDevices) {
|
2022-09-19 08:57:02 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
uint32_t extensionCount;
|
|
|
|
res = vkEnumerateDeviceExtensionProperties(dev, nullptr, &extensionCount, nullptr);
|
|
|
|
assert(res == VK_SUCCESS);
|
|
|
|
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
|
|
|
|
res = vkEnumerateDeviceExtensionProperties(dev, nullptr, &extensionCount, availableExtensions.data());
|
|
|
|
assert(res == VK_SUCCESS);
|
2022-09-19 08:57:02 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
bool suitable = true;
|
2022-09-19 08:57:02 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
for (const auto& extToFind : requiredDeviceExtensions) {
|
2022-09-19 08:57:02 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
bool extFound = false;
|
|
|
|
|
|
|
|
for (const auto& ext : availableExtensions) {
|
|
|
|
if (strcmp(extToFind, ext.extensionName) == 0) {
|
|
|
|
extFound = true;
|
|
|
|
}
|
|
|
|
}
|
2022-09-19 08:57:02 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
if (!extFound) {
|
|
|
|
suitable = false;
|
2022-09-19 08:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-19 17:33:56 +00:00
|
|
|
|
|
|
|
if (suitable) {
|
|
|
|
physicalDevice = dev;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (physicalDevice == VK_NULL_HANDLE) {
|
|
|
|
throw std::runtime_error("No suitable Vulkan physical device found");
|
|
|
|
}
|
|
|
|
|
|
|
|
VkPhysicalDeviceProperties devProps;
|
|
|
|
vkGetPhysicalDeviceProperties(physicalDevice, &devProps);
|
|
|
|
TRACE("Physical device to use: {}", devProps.deviceName);
|
|
|
|
|
|
|
|
// queue families
|
|
|
|
|
|
|
|
uint32_t queueFamilyCount = 0;
|
|
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
|
|
|
|
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
|
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilies.data());
|
|
|
|
|
|
|
|
std::optional<uint32_t> graphicsFamilyIndex;
|
|
|
|
std::optional<uint32_t> transferFamilyIndex;
|
|
|
|
std::optional<uint32_t> computeFamilyIndex;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < queueFamilyCount; i++) {
|
|
|
|
VkQueueFamilyProperties family = queueFamilies[i];
|
|
|
|
if (family.queueCount > 0) {
|
|
|
|
if (graphicsFamilyIndex.has_value() == false && family.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
|
|
|
TRACE("GRAPHICS:");
|
|
|
|
graphicsFamilyIndex = i;
|
|
|
|
}
|
|
|
|
if (transferFamilyIndex.has_value() == false && family.queueFlags & VK_QUEUE_TRANSFER_BIT) {
|
|
|
|
TRACE("TRANSFER:");
|
|
|
|
transferFamilyIndex = i;
|
|
|
|
}
|
|
|
|
if (computeFamilyIndex.has_value() == false && family.queueFlags & VK_QUEUE_COMPUTE_BIT) {
|
|
|
|
TRACE("COMPUTE:");
|
|
|
|
computeFamilyIndex = i;
|
|
|
|
}
|
|
|
|
TRACE("\t\ti = {}\t\tcount = {}", i, family.queueCount);
|
2022-09-19 08:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-19 17:33:56 +00:00
|
|
|
if (graphicsFamilyIndex.has_value() == false || transferFamilyIndex.has_value() == false) {
|
|
|
|
throw std::runtime_error("Unable to find a queue with the GRAPHICS family flag");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
|
|
|
|
|
|
|
|
// use a set to filter out duplicate indices
|
|
|
|
std::unordered_set<uint32_t> uniqueQueueFamilies{ graphicsFamilyIndex.value(), transferFamilyIndex.value(), computeFamilyIndex.value() };
|
|
|
|
float queuePriority = 1.0f;
|
|
|
|
for (uint32_t family : uniqueQueueFamilies) {
|
|
|
|
// create a queue for each unique type to ensure that there are queues available for graphics, transfer, and compute
|
|
|
|
TRACE("Creating queue from family {}", family);
|
|
|
|
VkDeviceQueueCreateInfo queueCreateInfo{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
|
|
|
.pNext = nullptr,
|
|
|
|
.flags = 0,
|
|
|
|
.queueFamilyIndex = family,
|
|
|
|
.queueCount = 1,
|
|
|
|
.pQueuePriorities = &queuePriority,
|
|
|
|
};
|
|
|
|
queueCreateInfos.push_back(queueCreateInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
VkDeviceCreateInfo deviceCreateInfo{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
|
|
|
.pNext = nullptr,
|
|
|
|
.flags = 0,
|
|
|
|
.queueCreateInfoCount = (uint32_t)queueCreateInfos.size(),
|
|
|
|
.pQueueCreateInfos = queueCreateInfos.data(),
|
|
|
|
// IGNORED: .enabledLayerCount
|
|
|
|
// IGNORED: .ppEnabledLayerNames
|
|
|
|
.enabledExtensionCount = (uint32_t)requiredDeviceExtensions.size(),
|
|
|
|
.ppEnabledExtensionNames = requiredDeviceExtensions.data(),
|
|
|
|
.pEnabledFeatures = nullptr,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkDevice device;
|
|
|
|
|
|
|
|
res = vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
|
|
|
|
if (res != VK_SUCCESS) {
|
|
|
|
throw std::runtime_error("Unable to create Vulkan logical device, error code: " + std::to_string(res));
|
|
|
|
}
|
|
|
|
|
|
|
|
volkLoadDevice(device);
|
|
|
|
|
|
|
|
vkDestroyDevice(device, nullptr);
|
|
|
|
|
2022-09-19 08:57:02 +00:00
|
|
|
}
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
// VkSurfaceKHR m_surface;
|
|
|
|
|
|
|
|
struct LayerInfo {
|
|
|
|
|
|
|
|
LayerInfo(bool useValidation)
|
|
|
|
{
|
|
|
|
VkResult res;
|
|
|
|
|
|
|
|
uint32_t layerCount;
|
|
|
|
res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
|
|
|
assert(res == VK_SUCCESS);
|
|
|
|
layersAvailable.resize(layerCount);
|
|
|
|
res = vkEnumerateInstanceLayerProperties(&layerCount, layersAvailable.data());
|
|
|
|
assert(res == VK_SUCCESS);
|
|
|
|
|
|
|
|
if (useValidation == true) {
|
|
|
|
// find validation layer and print all layers to log
|
|
|
|
for (auto it = layersAvailable.begin(); it != layersAvailable.end(); it++) {
|
|
|
|
if (strncmp(it->layerName, LayerInfo::VALIDATION_LAYER_NAME, 256) == 0) {
|
|
|
|
validationLayer = it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (validationLayer.has_value() == false) {
|
|
|
|
throw std::runtime_error("The validation layer was not found. Quitting.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr const char* VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation";
|
|
|
|
|
|
|
|
std::vector<VkLayerProperties> layersAvailable{};
|
|
|
|
std::optional<std::vector<VkLayerProperties>::iterator> validationLayer;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
class Instance {
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
public:
|
2022-09-19 08:57:02 +00:00
|
|
|
Instance(AppInfo appInfo, const LayerInfo& layerInfo, const std::vector<const char*>& windowExtensions)
|
2022-09-17 00:22:35 +00:00
|
|
|
{
|
|
|
|
VkResult res;
|
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
int appVersionMajor = 0, appVersionMinor = 0, appVersionPatch = 0;
|
2022-09-17 00:22:35 +00:00
|
|
|
assert(versionFromCharArray(appInfo.version, &appVersionMajor, &appVersionMinor, &appVersionPatch));
|
2022-09-19 17:33:56 +00:00
|
|
|
int engineVersionMajor = 0, engineVersionMinor = 0, engineVersionPatch = 0;
|
2022-09-17 00:22:35 +00:00
|
|
|
assert(versionFromCharArray(ENGINE_VERSION, &engineVersionMajor, &engineVersionMinor, &engineVersionPatch));
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
VkApplicationInfo applicationInfo{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
|
|
|
.pNext = nullptr,
|
|
|
|
.pApplicationName = appInfo.name,
|
|
|
|
.applicationVersion = VK_MAKE_VERSION(appVersionMajor, appVersionMinor, appVersionPatch),
|
|
|
|
.pEngineName = "engine",
|
|
|
|
.engineVersion = VK_MAKE_VERSION(engineVersionMajor, engineVersionMinor, engineVersionPatch),
|
|
|
|
.apiVersion = VK_API_VERSION_1_0,
|
|
|
|
};
|
|
|
|
|
|
|
|
// make a list of all extensions to use
|
|
|
|
std::vector<const char*> extensions{};
|
|
|
|
extensions.insert(extensions.end(), windowExtensions.begin(), windowExtensions.end());
|
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
// also use debug utils extension
|
|
|
|
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
std::vector<const char*> layers{};
|
|
|
|
|
2022-09-19 08:57:02 +00:00
|
|
|
if (layerInfo.validationLayer.has_value()) {
|
|
|
|
layers.push_back(layerInfo.validationLayer.value()->layerName);
|
2022-09-17 00:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VkInstanceCreateInfo instanceInfo{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
|
|
|
.pNext = nullptr,
|
|
|
|
.flags = 0,
|
|
|
|
.pApplicationInfo = &applicationInfo,
|
|
|
|
.enabledLayerCount = (uint32_t)layers.size(),
|
|
|
|
.ppEnabledLayerNames = layers.data(),
|
|
|
|
.enabledExtensionCount = (uint32_t)extensions.size(),
|
|
|
|
.ppEnabledExtensionNames = extensions.data(),
|
|
|
|
};
|
|
|
|
|
2022-09-19 08:57:02 +00:00
|
|
|
VkDebugUtilsMessengerCreateInfoEXT debugMessengerCreateInfo = DebugMessenger::getCreateInfo();
|
|
|
|
|
|
|
|
if (layerInfo.validationLayer.has_value()) {
|
2022-09-17 00:22:35 +00:00
|
|
|
instanceInfo.pNext = &debugMessengerCreateInfo;
|
|
|
|
}
|
2022-09-13 21:43:24 +00:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2022-09-17 00:22:35 +00:00
|
|
|
for (const char* ext : extensions) {
|
|
|
|
TRACE("Using Vulkan instance extension: {}", ext);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
res = vkCreateInstance(&instanceInfo, nullptr, &m_handle);
|
|
|
|
if (res == VK_ERROR_INCOMPATIBLE_DRIVER) {
|
2022-09-19 17:33:56 +00:00
|
|
|
throw std::runtime_error("The graphics driver is incompatible with vulkan");
|
2022-09-13 21:43:24 +00:00
|
|
|
}
|
2022-09-17 00:22:35 +00:00
|
|
|
assert(res == VK_SUCCESS);
|
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
volkLoadInstanceOnly(m_handle);
|
2022-09-17 00:22:35 +00:00
|
|
|
|
2022-09-13 21:43:24 +00:00
|
|
|
}
|
2022-09-17 00:22:35 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
Instance(const Instance&) = delete;
|
|
|
|
Instance& operator=(const Instance&) = delete;
|
2022-09-17 00:22:35 +00:00
|
|
|
~Instance()
|
|
|
|
{
|
|
|
|
vkDestroyInstance(m_handle, nullptr);
|
2022-09-13 21:43:24 +00:00
|
|
|
}
|
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
VkInstance getHandle()
|
|
|
|
{
|
|
|
|
return m_handle;
|
|
|
|
}
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
private:
|
|
|
|
VkInstance m_handle;
|
|
|
|
|
|
|
|
};
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
class DebugMessenger {
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
public:
|
2022-09-19 08:57:02 +00:00
|
|
|
DebugMessenger(std::shared_ptr<Instance> instance) : m_instance(instance)
|
2022-09-17 00:22:35 +00:00
|
|
|
{
|
|
|
|
VkDebugUtilsMessengerCreateInfoEXT createInfo = getCreateInfo();
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-19 08:57:02 +00:00
|
|
|
VkResult res = vkCreateDebugUtilsMessengerEXT(instance->getHandle(), &createInfo, nullptr, &m_messengerHandle);
|
2022-09-17 00:22:35 +00:00
|
|
|
assert(res == VK_SUCCESS);
|
|
|
|
}
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
DebugMessenger(const DebugMessenger&) = delete;
|
|
|
|
DebugMessenger& operator=(const DebugMessenger&) = delete;
|
2022-09-17 00:22:35 +00:00
|
|
|
~DebugMessenger()
|
|
|
|
{
|
2022-09-19 08:57:02 +00:00
|
|
|
vkDestroyDebugUtilsMessengerEXT(m_instance->getHandle(), m_messengerHandle, nullptr);
|
2022-09-17 00:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static VkDebugUtilsMessengerCreateInfoEXT getCreateInfo()
|
|
|
|
{
|
|
|
|
VkDebugUtilsMessengerCreateInfoEXT createInfo{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
|
|
|
.pNext = nullptr,
|
|
|
|
.flags = 0,
|
|
|
|
.messageSeverity = 0,
|
|
|
|
.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,
|
2022-09-19 08:57:02 +00:00
|
|
|
.pfnUserCallback = messengerCallback,
|
2022-09-17 00:22:35 +00:00
|
|
|
.pUserData = nullptr,
|
|
|
|
};
|
|
|
|
|
|
|
|
switch (MESSAGE_LEVEL) {
|
2022-09-19 17:33:56 +00:00
|
|
|
case Severity::VERBOSE:
|
2022-09-17 00:22:35 +00:00
|
|
|
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
|
|
|
|
// fall-through
|
2022-09-19 17:33:56 +00:00
|
|
|
case Severity::INFO:
|
2022-09-17 00:22:35 +00:00
|
|
|
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
|
|
|
|
// fall-through
|
2022-09-19 17:33:56 +00:00
|
|
|
case Severity::WARNING:
|
2022-09-17 00:22:35 +00:00
|
|
|
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
|
|
|
|
// fall-through
|
2022-09-19 17:33:56 +00:00
|
|
|
case Severity::ERROR:
|
2022-09-17 00:22:35 +00:00
|
|
|
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
|
|
|
// fall-through
|
2022-09-13 21:43:24 +00:00
|
|
|
default:
|
|
|
|
break;
|
2022-09-17 00:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return createInfo;
|
2022-09-13 21:43:24 +00:00
|
|
|
}
|
2022-09-17 00:22:35 +00:00
|
|
|
|
|
|
|
private:
|
2022-09-19 08:57:02 +00:00
|
|
|
VkDebugUtilsMessengerEXT m_messengerHandle;
|
|
|
|
std::shared_ptr<Instance> m_instance;
|
2022-09-19 17:33:56 +00:00
|
|
|
|
|
|
|
enum class Severity {
|
|
|
|
VERBOSE,
|
|
|
|
INFO,
|
|
|
|
WARNING,
|
|
|
|
ERROR
|
|
|
|
};
|
|
|
|
static constexpr Severity MESSAGE_LEVEL = Severity::WARNING;
|
2022-09-19 08:57:02 +00:00
|
|
|
|
|
|
|
static VkBool32 messengerCallback(
|
|
|
|
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
|
|
|
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
|
|
|
|
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
|
|
|
void* pUserData)
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string msgType{};
|
|
|
|
|
|
|
|
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
|
|
|
|
msgType += " (GENERAL)";
|
|
|
|
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
|
|
|
|
msgType += " (PERF.)";
|
|
|
|
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
|
|
|
|
msgType += " (VALID.)";
|
|
|
|
|
|
|
|
switch (messageSeverity) {
|
|
|
|
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
|
|
|
|
TRACE("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
|
|
|
|
break;
|
|
|
|
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
|
|
|
|
INFO("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
|
|
|
|
break;
|
|
|
|
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
|
|
|
|
WARN("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
|
|
|
|
break;
|
|
|
|
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
|
|
|
|
ERROR("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return VK_FALSE;
|
|
|
|
}
|
2022-09-17 00:22:35 +00:00
|
|
|
|
|
|
|
};
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
std::unique_ptr<LayerInfo> m_layerInfo;
|
2022-09-19 08:57:02 +00:00
|
|
|
std::shared_ptr<Instance> m_instance;
|
2022-09-17 00:22:35 +00:00
|
|
|
std::unique_ptr<DebugMessenger> m_debugMessenger;
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
void createSurface(SDL_Window* window)
|
|
|
|
{
|
|
|
|
if (SDL_Vulkan_CreateSurface(window, m_instance, &m_surface) == false) {
|
|
|
|
CRITICAL("Unable to create window surface");
|
|
|
|
throw std::runtime_error("Unable to create window surface");
|
|
|
|
}
|
2022-09-13 21:43:24 +00:00
|
|
|
}
|
2022-09-17 00:22:35 +00:00
|
|
|
*/
|
2022-09-13 21:43:24 +00:00
|
|
|
|
2022-09-13 18:25:18 +00:00
|
|
|
};
|
|
|
|
|
2022-09-17 00:22:35 +00:00
|
|
|
Device::Device(AppInfo appInfo, SDL_Window* window)
|
2022-09-13 21:43:24 +00:00
|
|
|
{
|
2022-09-17 00:22:35 +00:00
|
|
|
VkResult res;
|
|
|
|
res = volkInitialize();
|
|
|
|
if (res == VK_ERROR_INITIALIZATION_FAILED) {
|
|
|
|
throw std::runtime_error("Unable to load vulkan, is it installed?");
|
|
|
|
}
|
|
|
|
assert(res == VK_SUCCESS);
|
|
|
|
|
|
|
|
pimpl = std::make_unique<Impl>(appInfo, window);
|
|
|
|
|
2022-09-19 08:57:02 +00:00
|
|
|
|
2022-09-13 18:25:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Device::~Device()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-09-19 17:33:56 +00:00
|
|
|
#endif
|