project-aster/aster/context.cpp

131 lines
4.7 KiB
C++

// =============================================
// Aster: context.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#include "context.h"
#include <EASTL/array.h>
#include <EASTL/fixed_vector.h>
constexpr eastl::array VALIDATION_LAYERS = {
"VK_LAYER_KHRONOS_validation",
};
VKAPI_ATTR b32 VKAPI_CALL
DebugCallback(const VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
const VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData)
{
using Severity = vk::DebugUtilsMessageSeverityFlagsEXT;
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
using MessageType = vk::DebugUtilsMessageTypeFlagsEXT;
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
const auto severity = Severity(messageSeverity);
if (MessageType(messageType) & MessageTypeBits::eValidation)
{
if (severity & SeverityBits::eError)
ERROR("{}", callbackData->pMessage);
if (severity & SeverityBits::eWarning)
WARN("{}", callbackData->pMessage);
if (severity & SeverityBits::eInfo)
INFO("{}", callbackData->pMessage);
if (severity & SeverityBits::eVerbose)
VERBOSE("{}", callbackData->pMessage);
}
return false;
}
Context::Context(const cstr appName, const Version version, bool enableValidation)
{
INFO_IF(enableValidation, "Validation Layers enabled");
// TODO Get/Check API Version
// Creating Instance
const vk::ApplicationInfo appInfo = {
.pApplicationName = appName,
.applicationVersion = version.GetVkVersion(),
.pEngineName = PROJECT_NAME,
.engineVersion = version.GetVkVersion(),
.apiVersion = ASTER_API_VERSION,
};
const vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfo = {
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo,
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation,
.pfnUserCallback = DebugCallback,
.pUserData = nullptr,
};
u32 glfwExtensionCount = 0;
cstr *glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
eastl::fixed_vector<cstr, 3> instanceExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
if (enableValidation)
{
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
const vk::DynamicLoader dl;
// ReSharper disable once CppInconsistentNaming
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
const auto instanceCreateInfo = vk::InstanceCreateInfo{
.pNext = enableValidation ? &debugUtilsMessengerCreateInfo : nullptr,
.pApplicationInfo = &appInfo,
.enabledLayerCount = enableValidation ? Cast<u32>(VALIDATION_LAYERS.size()) : 0,
.ppEnabledLayerNames = enableValidation ? VALIDATION_LAYERS.data() : nullptr,
.enabledExtensionCount = Cast<u32>(instanceExtensions.size()),
.ppEnabledExtensionNames = instanceExtensions.data(),
};
// May throw. Irrecoverable.
vk::Result result = createInstance(&instanceCreateInfo, nullptr, &m_Instance);
ERROR_IF(result, "Instance creation failed. Cause: {}", result)
THEN_ABORT(result)
ELSE_DEBUG("Instance Created.");
VULKAN_HPP_DEFAULT_DISPATCHER.init(m_Instance);
// Debug Messenger
if (enableValidation)
{
result = m_Instance.createDebugUtilsMessengerEXT(&debugUtilsMessengerCreateInfo, nullptr, &m_DebugMessenger);
ERROR_IF(result, "Debug Messenger creation failed. Cause: {}", result) // Non-critical. Continue.
ELSE_DEBUG("Debug Messenger Created.");
}
}
Context::~Context()
{
if (m_DebugMessenger)
{
m_Instance.destroy(m_DebugMessenger, nullptr);
DEBUG("Debug Messenger destroyed");
}
m_Instance.destroy(nullptr);
DEBUG("Instance destroyed");
}
Context::Context(Context &&other) noexcept
: m_Instance(Take(other.m_Instance))
, m_DebugMessenger(Take(other.m_DebugMessenger))
{
}
Context &
Context::operator=(Context &&other) noexcept
{
if (this == &other)
return *this;
m_Instance = Take(other.m_Instance);
m_DebugMessenger = Take(other.m_DebugMessenger);
return *this;
}