Implemented/fixed Vulkan instance and device creation.
This commit is contained in:
@@ -459,6 +459,7 @@ bool Application::init()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!initImGui())
|
||||
{
|
||||
@@ -501,6 +502,10 @@ void Application::cleanup()
|
||||
vk.DeviceWaitIdle(vk.device);
|
||||
vk.DestroyDevice(vk.device, nullptr);
|
||||
}
|
||||
if (vk.debugUtilsMessenger != nullptr)
|
||||
{
|
||||
vk.DestroyDebugUtilsMessengerEXT(vk.instance, vk.debugUtilsMessenger, /* pAllocator = */ nullptr);
|
||||
}
|
||||
if (vk.instance != nullptr)
|
||||
{
|
||||
vk.DestroyInstance(vk.instance, nullptr);
|
||||
@@ -592,18 +597,90 @@ bool Application::initOpenGL()
|
||||
bool Application::initVulkan()
|
||||
{
|
||||
vk.GetInstanceProc = reinterpret_cast<vkGetInstanceProcAddr_fn_t>(SDL_Vulkan_GetVkGetInstanceProcAddr());
|
||||
vk.EnumerateInstanceLayerProperties = reinterpret_cast<vkEnumerateInstanceLayerProperties_fn_t>(vk.GetInstanceProc(nullptr, "vkEnumerateInstanceLayerProperties"));
|
||||
vk.EnumerateInstanceExtensionProperties = reinterpret_cast<vkEnumerateInstanceExtensionProperties_fn_t>(vk.GetInstanceProc(nullptr, "vkEnumerateInstanceExtensionProperties"));
|
||||
vk.CreateInstance = reinterpret_cast<vkCreateInstance_fn_t>(vk.GetInstanceProc(nullptr, "vkCreateInstance"));
|
||||
|
||||
std::uint32_t numInstanceLayers = 0;
|
||||
if (const VkResult result = vk.EnumerateInstanceLayerProperties(&numInstanceLayers, nullptr); result != VK_SUCCESS && result != VK_INCOMPLETE)
|
||||
{
|
||||
msgError("Error enumerating instance layers: 0x{:x}.", static_cast<unsigned>(result));
|
||||
return false;
|
||||
}
|
||||
std::vector<VkLayerProperties> instanceLayers;
|
||||
instanceLayers.resize(numInstanceLayers);
|
||||
if (const VkResult result = vk.EnumerateInstanceLayerProperties(&numInstanceLayers, instanceLayers.data()); result != VK_SUCCESS && result != VK_INCOMPLETE)
|
||||
{
|
||||
msgError("Error enumerating instance layers: 0x{:x}.", static_cast<unsigned>(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<const char*> enabledInstanceLayers;
|
||||
for (const VkLayerProperties& props : instanceLayers) {
|
||||
if (std::strcmp(props.layerName, "VK_LAYER_KHRONOS_validation") == 0) {
|
||||
enabledInstanceLayers.push_back("VK_LAYER_KHRONOS_validation");
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t numInstanceExtensions = 0;
|
||||
if (const VkResult result = vk.EnumerateInstanceExtensionProperties(nullptr, &numInstanceExtensions, nullptr); result != VK_SUCCESS && result != VK_INCOMPLETE)
|
||||
{
|
||||
msgError("Error enumerating instance extensions: 0x{:x}.", static_cast<unsigned>(result));
|
||||
return false;
|
||||
}
|
||||
std::vector<VkExtensionProperties> instanceExtensions;
|
||||
instanceExtensions.resize(numInstanceExtensions);
|
||||
if (const VkResult result = vk.EnumerateInstanceExtensionProperties(nullptr, &numInstanceExtensions, instanceExtensions.data()); result != VK_SUCCESS && result != VK_INCOMPLETE)
|
||||
{
|
||||
msgError("Error enumerating instance extensions: 0x{:x}.", static_cast<unsigned>(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::uint32_t numSdlExtensions = 0;
|
||||
const char* const* sdlExtensions = SDL_Vulkan_GetInstanceExtensions(&numSdlExtensions);
|
||||
std::uint32_t numSupportedSdlExtensions = 0;
|
||||
|
||||
bool hasDebugUtils = false;
|
||||
std::vector<const char*> enabledInstanceExtensions;
|
||||
for (const VkExtensionProperties& props : instanceExtensions) {
|
||||
if (std::strcmp(props.extensionName, "VK_EXT_debug_utils") == 0)
|
||||
{
|
||||
enabledInstanceExtensions.push_back("VK_EXT_debug_utils");
|
||||
hasDebugUtils = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::uint32_t idx = 0; idx < numSdlExtensions; ++idx)
|
||||
{
|
||||
if (std::strncmp(props.extensionName, sdlExtensions[idx], VK_MAX_EXTENSION_NAME_SIZE) == 0)
|
||||
{
|
||||
enabledInstanceExtensions.push_back(sdlExtensions[idx]);
|
||||
++numSupportedSdlExtensions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numSupportedSdlExtensions != numSdlExtensions)
|
||||
{
|
||||
msgError("Cannot create Vulkan device, not all required instance extensions are supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const VkApplicationInfo applicationInfo = {
|
||||
.apiVersion = vkMakeApiVersion(0, 1, 3, 0) // TODO: probably should let the user specify this?
|
||||
};
|
||||
const VkInstanceCreateInfo instanceCreateInfo = {
|
||||
.pApplicationInfo = &applicationInfo
|
||||
.pApplicationInfo = &applicationInfo,
|
||||
.enabledLayerCount = static_cast<std::uint32_t>(enabledInstanceLayers.size()),
|
||||
.ppEnabledLayerNames = enabledInstanceLayers.data(),
|
||||
.enabledExtensionCount = static_cast<std::uint32_t>(enabledInstanceExtensions.size()),
|
||||
.ppEnabledExtensionNames = enabledInstanceExtensions.data()
|
||||
};
|
||||
|
||||
if (const VkResult result = vk.CreateInstance(&instanceCreateInfo, nullptr, &vk.instance); result != VK_SUCCESS)
|
||||
{
|
||||
msgError("Error creating Vulkan instance: {:x}.", static_cast<unsigned>(result));
|
||||
msgError("Error creating Vulkan instance: 0x{:x}.", static_cast<unsigned>(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -615,11 +692,35 @@ bool Application::initVulkan()
|
||||
vk.DeviceWaitIdle = reinterpret_cast<vkDeviceWaitIdle_fn_t>(vk.GetInstanceProc(vk.instance, "vkDeviceWaitIdle"));
|
||||
vk.GetDeviceQueue = reinterpret_cast<vkGetDeviceQueue_fn_t>(vk.GetInstanceProc(vk.instance, "vkGetDeviceQueue"));
|
||||
|
||||
if (hasDebugUtils)
|
||||
{
|
||||
vk.CreateDebugUtilsMessengerEXT = reinterpret_cast<vkCreateDebugUtilsMessengerEXT_fn_t>(vk.GetInstanceProc(vk.instance, "vkCreateDebugUtilsMessengerEXT"));
|
||||
vk.DestroyDebugUtilsMessengerEXT = reinterpret_cast<vkDestroyDebugUtilsMessengerEXT_fn_t>(vk.GetInstanceProc(vk.instance, "vkDestroyDebugUtilsMessengerEXT"));
|
||||
|
||||
const VkDebugUtilsMessengerCreateInfoEXT messengerCreateInfo = {
|
||||
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||
.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,
|
||||
.pfnUserCallback = [](VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
|
||||
return static_cast<Application*>(pUserData)->handleDebugUtilsMessage(messageSeverity, messageTypes, pCallbackData);
|
||||
},
|
||||
.pUserData = this
|
||||
};
|
||||
|
||||
if (const VkResult result = vk.CreateDebugUtilsMessengerEXT(vk.instance, &messengerCreateInfo, /* pAllocator = */ nullptr, &vk.debugUtilsMessenger); result != VK_SUCCESS)
|
||||
{
|
||||
msgWarning("Error creating Vulkan debug utils messenger: 0x{:x}.", static_cast<unsigned>(result));
|
||||
vk.debugUtilsMessenger = nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vk.debugUtilsMessenger = nullptr;
|
||||
}
|
||||
|
||||
// TODO: this is really cheap... (but should be sufficient in most cases)
|
||||
std::uint32_t physicalDeviceCount = 1;
|
||||
if (const VkResult result = vk.EnumeratePhysicalDevices(vk.instance, &physicalDeviceCount, &vk.physicalDevice); result != VK_SUCCESS)
|
||||
{
|
||||
msgError("Error enumerating Vulkan physical devices: {:x}.", static_cast<unsigned>(result));
|
||||
msgError("Error enumerating Vulkan physical devices: 0x{:x}.", static_cast<unsigned>(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -634,7 +735,10 @@ bool Application::initVulkan()
|
||||
std::uint32_t queueFamilyIndex = 0;
|
||||
for (; queueFamilyIndex < queueFamilyPropertyCount; ++queueFamilyIndex)
|
||||
{
|
||||
if (queueFamilyProperties[queueFamilyIndex].queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
const bool supportsGraphics = queueFamilyProperties[queueFamilyIndex].queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT;
|
||||
const bool supportsPresent = SDL_Vulkan_GetPresentationSupport(vk.instance, vk.physicalDevice, queueFamilyIndex);
|
||||
|
||||
if (supportsGraphics && supportsPresent) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -652,7 +756,7 @@ bool Application::initVulkan()
|
||||
.pQueuePriorities = &queuePriority
|
||||
};
|
||||
static const std::array DEVICE_EXTENSIONS = {
|
||||
"VK_KHR_surface"
|
||||
"VK_KHR_swapchain"
|
||||
};
|
||||
const VkDeviceCreateInfo deviceCreateInfo = {
|
||||
.queueCreateInfoCount = 1,
|
||||
@@ -662,7 +766,7 @@ bool Application::initVulkan()
|
||||
};
|
||||
if (const VkResult result = vk.CreateDevice(vk.physicalDevice, &deviceCreateInfo, nullptr, &vk.device); result != VK_SUCCESS)
|
||||
{
|
||||
msgError("Error creating Vulkan device: {:x}.", static_cast<unsigned>(result));
|
||||
msgError("Error creating Vulkan device: 0x{:x}.", static_cast<unsigned>(result));
|
||||
return false;
|
||||
}
|
||||
vk.GetDeviceQueue(vk.device, /* queueFamilyIndex = */ 0, /* queueIndex = */ 0, &vk.queue);
|
||||
@@ -788,6 +892,25 @@ void Application::saveImGuiConfig()
|
||||
}
|
||||
}
|
||||
|
||||
auto Application::handleDebugUtilsMessage(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT /* messageTypes */,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData) -> VkBool32
|
||||
{
|
||||
switch (messageSeverity)
|
||||
{
|
||||
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
|
||||
msgError("Vulkan debug error message: {}.", pCallbackData->pMessage);
|
||||
break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
|
||||
msgWarning("Vulkan debug warning message: {}.", pCallbackData->pMessage);
|
||||
break;
|
||||
default:
|
||||
msgInfo("Vulkan debug message: {}.", pCallbackData->pMessage);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QuickApp::preInit(QuickAppOptions options)
|
||||
{
|
||||
MIJIN_ASSERT_FATAL(options.callbacks.render, "Missing render callback.");
|
||||
|
||||
Reference in New Issue
Block a user