mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 21:28:32 +09:00
[Feat] (MG_Test/Backend/DirectVulkan): pick and compare physical device
This commit is contained in:
@@ -207,69 +207,112 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MGLOG_I("Found %d physical device(s).", deviceCount);
|
MGLOG_I("Found %d physical device(s).", deviceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto deviceTypeToStr = [](VkPhysicalDeviceType type) {
|
MOBILEGL_ASSERT(deviceCount > 0, "No physical devices found.");
|
||||||
switch (type) {
|
|
||||||
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
|
|
||||||
return "INTEGRATED_GPU";
|
|
||||||
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
|
|
||||||
return "DISCRETE_GPU";
|
|
||||||
case VK_PHYSICAL_DEVICE_TYPE_CPU:
|
|
||||||
return "CPU";
|
|
||||||
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
|
|
||||||
return "VIRTUAL_GPU";
|
|
||||||
case VK_PHYSICAL_DEVICE_TYPE_OTHER:
|
|
||||||
return "OTHER";
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector<VkPhysicalDevice> devices(deviceCount);
|
Vector<VkPhysicalDevice> devices(deviceCount);
|
||||||
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
|
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
|
||||||
for (const auto& device : devices) {
|
for (Int i = 0; i < deviceCount; i++) {
|
||||||
VkPhysicalDeviceProperties deviceProperties;
|
if (CheckPhysicalDeviceEligibilityAndCompare(devices[i], m_physicalDevice, m_physicalDevice))
|
||||||
vkGetPhysicalDeviceProperties(device, &deviceProperties);
|
MGLOG_I("Picked physical device %d.", i);
|
||||||
auto apiVersion = deviceProperties.apiVersion;
|
|
||||||
MGLOG_I(" %s (Vulkan %d.%d.%d, %s)",
|
|
||||||
deviceProperties.deviceName,
|
|
||||||
VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion),
|
|
||||||
deviceTypeToStr(deviceProperties.deviceType));
|
|
||||||
// TODO: Properly check device eligibility
|
|
||||||
m_queueFamilies = GetQueueFamilyFromPhysicalDevice(device);
|
|
||||||
auto gfxQueueFamily = GetQueueFamilyIndex(m_queueFamilies, VK_QUEUE_GRAPHICS_BIT);
|
|
||||||
if (m_physicalDevice == VK_NULL_HANDLE && gfxQueueFamily != -1) {
|
|
||||||
m_physicalDevice = device;
|
|
||||||
m_queueFamilyIndices.graphicsFamily = gfxQueueFamily;
|
|
||||||
MGLOG_I("Physical device picked.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MOBILEGL_ASSERT(!devices.empty(), "No physical devices found.");
|
if (m_physicalDevice.handle == VK_NULL_HANDLE) {
|
||||||
if (m_physicalDevice == VK_NULL_HANDLE) {
|
m_physicalDevice.handle = devices[0];
|
||||||
m_physicalDevice = devices[0];
|
vkGetPhysicalDeviceProperties(devices[0], &m_physicalDevice.properties);
|
||||||
MGLOG_I("No suitable physical device picked yet, defaulting to device 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?");
|
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);
|
Bool VulkanRenderer::CheckPhysicalDeviceEligibilityAndCompare(
|
||||||
|
VkPhysicalDevice device, const PhysicalDevice& otherDevice, PhysicalDevice& outDevice) {
|
||||||
|
const auto deviceTypeToStr = [](VkPhysicalDeviceType type) {
|
||||||
|
switch (type) {
|
||||||
|
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
|
||||||
|
return "INTEGRATED_GPU";
|
||||||
|
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
|
||||||
|
return "DISCRETE_GPU";
|
||||||
|
case VK_PHYSICAL_DEVICE_TYPE_CPU:
|
||||||
|
return "CPU";
|
||||||
|
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
|
||||||
|
return "VIRTUAL_GPU";
|
||||||
|
case VK_PHYSICAL_DEVICE_TYPE_OTHER:
|
||||||
|
return "OTHER";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PhysicalDevice newDevice;
|
||||||
|
newDevice.handle = device;
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceProperties(device, &newDevice.properties);
|
||||||
|
const auto& deviceProperties = newDevice.properties;
|
||||||
|
auto apiVersion = deviceProperties.apiVersion;
|
||||||
|
MGLOG_I(" %s (Vulkan %d.%d.%d, %s)",
|
||||||
|
deviceProperties.deviceName,
|
||||||
|
VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion),
|
||||||
|
deviceTypeToStr(deviceProperties.deviceType));
|
||||||
|
|
||||||
|
Vector<VkQueueFamilyProperties> queueFamilies = GetQueueFamilyFromPhysicalDevice(device);
|
||||||
|
newDevice.queueFamilies.graphicsFamily = GetQueueFamilyIndex(queueFamilies, VK_QUEUE_GRAPHICS_BIT);
|
||||||
|
if (newDevice.queueFamilies.graphicsFamily == -1) {
|
||||||
|
outDevice = otherDevice;
|
||||||
|
MGLOG_I(" Ignored physical device: No graphics queue family.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
newDevice.queueFamilies.presentFamily =
|
||||||
|
GetPresentQueueFamilyIndex(newDevice, queueFamilies, newDevice.queueFamilies.graphicsFamily);
|
||||||
|
if (newDevice.queueFamilies.presentFamily == -1) {
|
||||||
|
outDevice = otherDevice;
|
||||||
|
MGLOG_I(" Ignored physical device: No present queue family.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick discrete GPU
|
||||||
|
if (newDevice.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&
|
||||||
|
otherDevice.properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
||||||
|
outDevice = newDevice;
|
||||||
|
MGLOG_I(" Picked physical device: Discrete GPU.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
MGLOG_I(" Picked physical device: Integrated GPU and the other is not discrete.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
MGLOG_I(" Ignored physical device: Already picked discrete GPU.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateLogicalDeviceAndQueues() {
|
void VulkanRenderer::CreateLogicalDeviceAndQueues() {
|
||||||
Float queuePriority = 1.0f;
|
Float queuePriority = 1.0f;
|
||||||
|
|
||||||
Vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
Vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||||
MOBILEGL_ASSERT(m_queueFamilyIndices.graphicsFamily != -1, "Graphics queue family not found.");
|
MOBILEGL_ASSERT(m_physicalDevice.queueFamilies.graphicsFamily != -1, "Graphics queue family not found.");
|
||||||
VkDeviceQueueCreateInfo& gfxQueueCreateInfo = queueCreateInfos.emplace_back();
|
VkDeviceQueueCreateInfo& gfxQueueCreateInfo = queueCreateInfos.emplace_back();
|
||||||
gfxQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
gfxQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
gfxQueueCreateInfo.queueFamilyIndex = m_queueFamilyIndices.graphicsFamily;
|
gfxQueueCreateInfo.queueFamilyIndex = m_physicalDevice.queueFamilies.graphicsFamily;
|
||||||
gfxQueueCreateInfo.queueCount = 1;
|
gfxQueueCreateInfo.queueCount = 1;
|
||||||
gfxQueueCreateInfo.pQueuePriorities = &queuePriority;
|
gfxQueueCreateInfo.pQueuePriorities = &queuePriority;
|
||||||
|
|
||||||
if (m_queueFamilyIndices.graphicsFamily != m_queueFamilyIndices.presentFamily) {
|
if (m_physicalDevice.queueFamilies.graphicsFamily != m_physicalDevice.queueFamilies.presentFamily) {
|
||||||
MOBILEGL_ASSERT(m_queueFamilyIndices.presentFamily != -1, "Present queue family not found.");
|
MOBILEGL_ASSERT(m_physicalDevice.queueFamilies.presentFamily != -1, "Present queue family not found.");
|
||||||
VkDeviceQueueCreateInfo& presentQueueCreateInfo = queueCreateInfos.emplace_back();
|
VkDeviceQueueCreateInfo& presentQueueCreateInfo = queueCreateInfos.emplace_back();
|
||||||
presentQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
presentQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
presentQueueCreateInfo.queueFamilyIndex = m_queueFamilyIndices.presentFamily;
|
presentQueueCreateInfo.queueFamilyIndex = m_physicalDevice.queueFamilies.presentFamily;
|
||||||
presentQueueCreateInfo.queueCount = 1;
|
presentQueueCreateInfo.queueCount = 1;
|
||||||
presentQueueCreateInfo.pQueuePriorities = &queuePriority;
|
presentQueueCreateInfo.pQueuePriorities = &queuePriority;
|
||||||
}
|
}
|
||||||
@@ -288,12 +331,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
} else {
|
} else {
|
||||||
deviceCreateInfo.enabledLayerCount = 0;
|
deviceCreateInfo.enabledLayerCount = 0;
|
||||||
}
|
}
|
||||||
VK_VERIFY(vkCreateDevice(m_physicalDevice, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice");
|
VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice");
|
||||||
MGLOG_I("Logical device created.");
|
MGLOG_I("Logical device created.");
|
||||||
|
|
||||||
// Queues
|
// Queues
|
||||||
vkGetDeviceQueue(m_device, m_queueFamilyIndices.graphicsFamily, 0, &m_graphicsQueue);
|
vkGetDeviceQueue(m_device, m_physicalDevice.queueFamilies.graphicsFamily, 0, &m_graphicsQueue);
|
||||||
vkGetDeviceQueue(m_device, m_queueFamilyIndices.presentFamily, 0, &m_presentQueue);
|
vkGetDeviceQueue(m_device, m_physicalDevice.queueFamilies.presentFamily, 0, &m_presentQueue);
|
||||||
MGLOG_I("Queues got successfully.");
|
MGLOG_I("Queues got successfully.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,18 +381,19 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int VulkanRenderer::GetPresentQueueFamilyIndex(const Vector<VkQueueFamilyProperties>& queueFamilies,
|
Int VulkanRenderer::GetPresentQueueFamilyIndex(
|
||||||
Int preferredFamilyIndex) const {
|
const PhysicalDevice& physicalDevice,
|
||||||
|
const Vector<VkQueueFamilyProperties>& queueFamilies, Int preferredFamilyIndex) const {
|
||||||
if (preferredFamilyIndex != -1) {
|
if (preferredFamilyIndex != -1) {
|
||||||
VkBool32 supportsPresent = false;
|
VkBool32 supportsPresent = false;
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, preferredFamilyIndex, m_surface, &supportsPresent);
|
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice.handle, preferredFamilyIndex, m_surface, &supportsPresent);
|
||||||
if (supportsPresent)
|
if (supportsPresent)
|
||||||
return preferredFamilyIndex;
|
return preferredFamilyIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Uint32 i = 0; i < queueFamilies.size(); i++) {
|
for (Uint32 i = 0; i < queueFamilies.size(); i++) {
|
||||||
VkBool32 supportsPresent = false;
|
VkBool32 supportsPresent = false;
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &supportsPresent);
|
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice.handle, i, m_surface, &supportsPresent);
|
||||||
if (supportsPresent)
|
if (supportsPresent)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Int32 presentFamily = -1;
|
Int32 presentFamily = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PhysicalDevice {
|
||||||
|
QueueFamilyIndices queueFamilies;
|
||||||
|
VkPhysicalDeviceProperties properties;
|
||||||
|
VkPhysicalDevice handle = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
|
||||||
NativeWindowType m_window = 0;
|
NativeWindowType m_window = 0;
|
||||||
RendererConfig m_config;
|
RendererConfig m_config;
|
||||||
|
|
||||||
@@ -57,12 +63,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Vector<VkExtensionProperties> m_extensions;
|
Vector<VkExtensionProperties> m_extensions;
|
||||||
VkInstance m_instance = VK_NULL_HANDLE;
|
VkInstance m_instance = VK_NULL_HANDLE;
|
||||||
VkDebugUtilsMessengerEXT m_debugMessenger = VK_NULL_HANDLE;
|
VkDebugUtilsMessengerEXT m_debugMessenger = VK_NULL_HANDLE;
|
||||||
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
PhysicalDevice m_physicalDevice;
|
||||||
|
// VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||||
|
|
||||||
Vector<VkQueueFamilyProperties> m_queueFamilies;
|
// Vector<VkQueueFamilyProperties> m_queueFamilies;
|
||||||
QueueFamilyIndices m_queueFamilyIndices;
|
// QueueFamilyIndices m_queueFamilyIndices;
|
||||||
|
|
||||||
VkQueue m_graphicsQueue = VK_NULL_HANDLE;
|
VkQueue m_graphicsQueue = VK_NULL_HANDLE;
|
||||||
VkQueue m_presentQueue = VK_NULL_HANDLE;
|
VkQueue m_presentQueue = VK_NULL_HANDLE;
|
||||||
@@ -73,10 +80,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkResult DestroyDebugMessenger();
|
VkResult DestroyDebugMessenger();
|
||||||
VkDebugUtilsMessengerCreateInfoEXT PopulateDebugMessengerCreateInfo();
|
VkDebugUtilsMessengerCreateInfoEXT PopulateDebugMessengerCreateInfo();
|
||||||
void PickPhysicalDevice();
|
void PickPhysicalDevice();
|
||||||
|
Bool CheckPhysicalDeviceEligibilityAndCompare(VkPhysicalDevice device, const PhysicalDevice& compareWithDevice, PhysicalDevice& outDevice);
|
||||||
void CreateLogicalDeviceAndQueues();
|
void CreateLogicalDeviceAndQueues();
|
||||||
void CreateSurface();
|
void CreateSurface();
|
||||||
|
|
||||||
Int GetPresentQueueFamilyIndex(const Vector<VkQueueFamilyProperties>& queueFamilies, Int preferredFamilyIndex = -1) const;
|
Int GetPresentQueueFamilyIndex(const PhysicalDevice& physicalDevice, const Vector<VkQueueFamilyProperties>& queueFamilies, Int preferredFamilyIndex = -1) const;
|
||||||
|
|
||||||
static Vector<VkQueueFamilyProperties> GetQueueFamilyFromPhysicalDevice(VkPhysicalDevice device);
|
static Vector<VkQueueFamilyProperties> GetQueueFamilyFromPhysicalDevice(VkPhysicalDevice device);
|
||||||
static Int GetQueueFamilyIndex(const Vector<VkQueueFamilyProperties>& queueFamilies, VkQueueFlagBits flag);
|
static Int GetQueueFamilyIndex(const Vector<VkQueueFamilyProperties>& queueFamilies, VkQueueFlagBits flag);
|
||||||
|
|||||||
Reference in New Issue
Block a user