From ba7bf87ee0d9ed3c88d4eed2ad3cfb6526fe366f Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 12 Feb 2026 11:08:57 +0800 Subject: [PATCH] [Feat] (MG_Backend/DirectVulkan): retrieve and check device extension --- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 58 +++++++++++++++---- .../DirectVulkan/Renderer/VulkanRenderer.h | 6 +- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 6ea7501b..b80b4887 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -77,7 +77,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { DestroyDebugMessenger(); DestroyInstance(); - MGLOG_D("VulkanRenderer shut down completed"); + MGLOG_I("VulkanRenderer shut down completed"); } void VulkanRenderer::Render() { @@ -212,7 +212,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Vector devices(deviceCount); vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data()); for (Int i = 0; i < deviceCount; i++) { - if (CheckPhysicalDeviceEligibilityAndCompare(devices[i], m_physicalDevice, m_physicalDevice)) + if (GetMoreCapablePhysicalDevice(devices[i], m_physicalDevice, m_physicalDevice)) MGLOG_I("Picked physical device %d.", i); } @@ -224,8 +224,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } - Bool VulkanRenderer::CheckPhysicalDeviceEligibilityAndCompare( - VkPhysicalDevice device, const PhysicalDevice& otherDevice, PhysicalDevice& outDevice) { + Bool VulkanRenderer::GetMoreCapablePhysicalDevice( + VkPhysicalDevice newVkDevice, const PhysicalDevice& otherDevice, PhysicalDevice& outBetterDevice) { const auto deviceTypeToStr = [](VkPhysicalDeviceType type) { switch (type) { case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: @@ -244,9 +244,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { }; PhysicalDevice newDevice; - newDevice.handle = device; + newDevice.handle = newVkDevice; - vkGetPhysicalDeviceProperties(device, &newDevice.properties); + vkGetPhysicalDeviceProperties(newVkDevice, &newDevice.properties); const auto& deviceProperties = newDevice.properties; auto apiVersion = deviceProperties.apiVersion; MGLOG_I(" %s (Vulkan %d.%d.%d, %s)", @@ -254,10 +254,17 @@ namespace MobileGL::MG_Backend::DirectVulkan { VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion), deviceTypeToStr(deviceProperties.deviceType)); - Vector queueFamilies = GetQueueFamilyFromPhysicalDevice(device); + Bool deviceExtSupported = IsNecessaryDeviceExtensionSupported(newVkDevice); + if (!deviceExtSupported) { + outBetterDevice = otherDevice; + MGLOG_I(" Ignored physical device: Some of the required device extension not supported on this device."); + return false; + } + + Vector queueFamilies = GetQueueFamilyFromPhysicalDevice(newVkDevice); newDevice.queueFamilies.graphicsFamily = GetQueueFamilyIndex(queueFamilies, VK_QUEUE_GRAPHICS_BIT); if (newDevice.queueFamilies.graphicsFamily == -1) { - outDevice = otherDevice; + outBetterDevice = otherDevice; MGLOG_I(" Ignored physical device: No graphics queue family."); return false; } @@ -265,7 +272,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { newDevice.queueFamilies.presentFamily = GetPresentQueueFamilyIndex(newDevice, queueFamilies, newDevice.queueFamilies.graphicsFamily); if (newDevice.queueFamilies.presentFamily == -1) { - outDevice = otherDevice; + outBetterDevice = otherDevice; MGLOG_I(" Ignored physical device: No present queue family."); return false; } @@ -273,7 +280,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // Pick discrete GPU if (newDevice.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && otherDevice.properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - outDevice = newDevice; + outBetterDevice = newDevice; MGLOG_I(" Picked physical device: Discrete GPU."); return true; } @@ -281,7 +288,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // Pick integrated GPU if no discrete GPU if (newDevice.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && otherDevice.properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - outDevice = newDevice; + outBetterDevice = newDevice; MGLOG_I(" Picked physical device: Integrated GPU and the other is not discrete."); return true; } @@ -289,7 +296,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // Ignore other GPU when discrete GPU found if (newDevice.properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && otherDevice.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - outDevice = newDevice; + outBetterDevice = newDevice; MGLOG_I(" Ignored physical device: Already picked discrete GPU."); return false; } @@ -297,6 +304,33 @@ namespace MobileGL::MG_Backend::DirectVulkan { return false; } + Bool VulkanRenderer::IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device) { + Uint32 extensionCount = 0; + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); + + std::vector availableExtensions(extensionCount); + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); + + MGLOG_I("Got %u Vulkan device extensions: ", extensionCount); + for (auto& extension : availableExtensions) { + MGLOG_I(" %s (r.%u)", extension.extensionName, extension.specVersion); + } + + for (SizeT i = 0; i < std::size(s_deviceExtensionNames); ++i) { + Bool found = false; + for (const auto& extension : availableExtensions) { + if (strcmp(extension.extensionName, s_deviceExtensionNames[i]) == 0) { + found = true; + break; + } + } + if (!found) + return false; + } + + return true; + } + void VulkanRenderer::CreateLogicalDeviceAndQueues() { Float queuePriority = 1.0f; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 3b18498c..69c5ce46 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -80,7 +80,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkResult DestroyDebugMessenger(); VkDebugUtilsMessengerCreateInfoEXT PopulateDebugMessengerCreateInfo(); void PickPhysicalDevice(); - Bool CheckPhysicalDeviceEligibilityAndCompare(VkPhysicalDevice device, const PhysicalDevice& compareWithDevice, PhysicalDevice& outDevice); + Bool GetMoreCapablePhysicalDevice(VkPhysicalDevice newVkDevice, const PhysicalDevice& compareWithDevice, PhysicalDevice& outBetterDevice); void CreateLogicalDeviceAndQueues(); void CreateSurface(); @@ -89,9 +89,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { static Vector GetQueueFamilyFromPhysicalDevice(VkPhysicalDevice device); static Int GetQueueFamilyIndex(const Vector& queueFamilies, VkQueueFlagBits flag); static Vector EnumerateInstanceExtensions(); + static Bool IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device); static constexpr const char* s_validationLayerNames[] = { "VK_LAYER_KHRONOS_validation" }; + static constexpr const char* s_deviceExtensionNames[] = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; static Bool CheckValidationLayerSupport(); static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(