diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index fc060360..2aee0270 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -62,7 +62,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { CreateInstance(); CreateSurface(); PickPhysicalDevice(); - CreateLogicalDevice(); + CreateLogicalDeviceAndQueues(); MGLOG_D("VulkanRenderer initialized"); } @@ -248,24 +248,39 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (m_physicalDevice == VK_NULL_HANDLE) { m_physicalDevice = devices[0]; MGLOG_I("No suitable physical device picked yet, defaulting to device 0."); + MGLOG_W("No graphics queue found on physical device. Picking a device that doesn't do graphics?"); } + + m_queueFamilyIndices.presentFamily = GetPresentQueueFamilyIndex(m_queueFamilies, m_queueFamilyIndices.graphicsFamily); } - void VulkanRenderer::CreateLogicalDevice() { - VkDeviceQueueCreateInfo queueCreateInfo{}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = m_queueFamilyIndices.graphicsFamily; - queueCreateInfo.queueCount = 1; + void VulkanRenderer::CreateLogicalDeviceAndQueues() { Float queuePriority = 1.0f; - queueCreateInfo.pQueuePriorities = &queuePriority; + + Vector queueCreateInfos; + MOBILEGL_ASSERT(m_queueFamilyIndices.graphicsFamily != -1, "Graphics queue family not found."); + VkDeviceQueueCreateInfo& gfxQueueCreateInfo = queueCreateInfos.emplace_back(); + gfxQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + gfxQueueCreateInfo.queueFamilyIndex = m_queueFamilyIndices.graphicsFamily; + gfxQueueCreateInfo.queueCount = 1; + gfxQueueCreateInfo.pQueuePriorities = &queuePriority; + + if (m_queueFamilyIndices.graphicsFamily != m_queueFamilyIndices.presentFamily) { + MOBILEGL_ASSERT(m_queueFamilyIndices.presentFamily != -1, "Present queue family not found."); + VkDeviceQueueCreateInfo& presentQueueCreateInfo = queueCreateInfos.emplace_back(); + presentQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + presentQueueCreateInfo.queueFamilyIndex = m_queueFamilyIndices.presentFamily; + presentQueueCreateInfo.queueCount = 1; + presentQueueCreateInfo.pQueuePriorities = &queuePriority; + } VkPhysicalDeviceFeatures deviceFeatures{}; // TODO: query and make use of device features VkDeviceCreateInfo deviceCreateInfo{}; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; - deviceCreateInfo.queueCreateInfoCount = 1; + deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data(); + deviceCreateInfo.queueCreateInfoCount = queueCreateInfos.size(); deviceCreateInfo.pEnabledFeatures = &deviceFeatures; if (m_validationLayersEnabled) { deviceCreateInfo.enabledLayerCount = static_cast(std::size(s_validationLayerNames)); @@ -274,7 +289,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { deviceCreateInfo.enabledLayerCount = 0; } VK_VERIFY(vkCreateDevice(m_physicalDevice, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice"); + MGLOG_I("Logical device created."); + + // Queues vkGetDeviceQueue(m_device, m_queueFamilyIndices.graphicsFamily, 0, &m_graphicsQueue); + vkGetDeviceQueue(m_device, m_queueFamilyIndices.presentFamily, 0, &m_presentQueue); + MGLOG_I("Queues got successfully."); } void VulkanRenderer::CreateSurface() { @@ -308,7 +328,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { return queueFamilies; } - Uint32 VulkanRenderer::GetQueueFamilyIndex(const Vector& queueFamilies, VkQueueFlagBits flag) { + Int VulkanRenderer::GetQueueFamilyIndex(const Vector& queueFamilies, + VkQueueFlagBits flag) { for (Uint32 i = 0; i < queueFamilies.size(); i++) { if (queueFamilies[i].queueFlags & flag) { return i; @@ -317,6 +338,24 @@ namespace MobileGL::MG_Backend::DirectVulkan { return -1; } + Int VulkanRenderer::GetPresentQueueFamilyIndex(const Vector& queueFamilies, + Int preferredFamilyIndex) const { + if (preferredFamilyIndex != -1) { + VkBool32 supportsPresent = false; + vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, preferredFamilyIndex, m_surface, &supportsPresent); + if (supportsPresent) + return preferredFamilyIndex; + } + + for (Uint32 i = 0; i < queueFamilies.size(); i++) { + VkBool32 supportsPresent = false; + vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &supportsPresent); + if (supportsPresent) + return i; + } + return -1; + } + Vector VulkanRenderer::EnumerateInstanceExtensions() { Uint32 extensionCount = 0; VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr)); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 8d394827..ad92d0c2 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -65,6 +65,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { QueueFamilyIndices m_queueFamilyIndices; VkQueue m_graphicsQueue = VK_NULL_HANDLE; + VkQueue m_presentQueue = VK_NULL_HANDLE; void CreateInstance(); void DestroyInstance(); @@ -72,11 +73,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkResult DestroyDebugMessenger(); VkDebugUtilsMessengerCreateInfoEXT PopulateDebugMessengerCreateInfo(); void PickPhysicalDevice(); - void CreateLogicalDevice(); + void CreateLogicalDeviceAndQueues(); void CreateSurface(); + Int GetPresentQueueFamilyIndex(const Vector& queueFamilies, Int preferredFamilyIndex = -1) const; + static Vector GetQueueFamilyFromPhysicalDevice(VkPhysicalDevice device); - static Uint32 GetQueueFamilyIndex(const Vector& queueFamilies, VkQueueFlagBits flag); + static Int GetQueueFamilyIndex(const Vector& queueFamilies, VkQueueFlagBits flag); static Vector EnumerateInstanceExtensions(); static constexpr const char* s_validationLayerNames[] = { "VK_LAYER_KHRONOS_validation"