mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (MG_Backend/DirectVulkan): inspect SwapchainCapabilities
This commit is contained in:
@@ -212,7 +212,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Vector<VkPhysicalDevice> devices(deviceCount);
|
Vector<VkPhysicalDevice> devices(deviceCount);
|
||||||
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
|
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
|
||||||
for (Int i = 0; i < deviceCount; i++) {
|
for (Int i = 0; i < deviceCount; i++) {
|
||||||
if (GetMoreCapablePhysicalDevice(devices[i], m_physicalDevice, m_physicalDevice))
|
if (GetMoreCapablePhysicalDevice(devices[i], m_surface, m_physicalDevice, m_physicalDevice))
|
||||||
MGLOG_I("Picked physical device %d.", i);
|
MGLOG_I("Picked physical device %d.", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bool VulkanRenderer::GetMoreCapablePhysicalDevice(
|
Bool VulkanRenderer::GetMoreCapablePhysicalDevice(
|
||||||
VkPhysicalDevice newVkDevice, const PhysicalDevice& otherDevice, PhysicalDevice& outBetterDevice) {
|
VkPhysicalDevice newVkDevice, VkSurfaceKHR surface, const PhysicalDevice& otherDevice, PhysicalDevice& outBetterDevice) {
|
||||||
const auto deviceTypeToStr = [](VkPhysicalDeviceType type) {
|
const auto deviceTypeToStr = [](VkPhysicalDeviceType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
|
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
|
||||||
@@ -254,6 +254,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion),
|
VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion),
|
||||||
deviceTypeToStr(deviceProperties.deviceType));
|
deviceTypeToStr(deviceProperties.deviceType));
|
||||||
|
|
||||||
|
// Check device extensions (including swapchain extension)
|
||||||
Bool deviceExtSupported = IsNecessaryDeviceExtensionSupported(newVkDevice);
|
Bool deviceExtSupported = IsNecessaryDeviceExtensionSupported(newVkDevice);
|
||||||
if (!deviceExtSupported) {
|
if (!deviceExtSupported) {
|
||||||
outBetterDevice = otherDevice;
|
outBetterDevice = otherDevice;
|
||||||
@@ -261,6 +262,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check swapchain capabilities
|
||||||
|
newDevice.swapchainCapabilities = GetSwapchainCapabilities(newVkDevice, surface);
|
||||||
|
if (!newDevice.swapchainCapabilities.IsComplete()) {
|
||||||
|
outBetterDevice = otherDevice;
|
||||||
|
MGLOG_I(" Ignored physical device: Swapchain capabilities not met.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check queue families
|
||||||
Vector<VkQueueFamilyProperties> queueFamilies = GetQueueFamilyFromPhysicalDevice(newVkDevice);
|
Vector<VkQueueFamilyProperties> queueFamilies = GetQueueFamilyFromPhysicalDevice(newVkDevice);
|
||||||
newDevice.queueFamilies.graphicsFamily = GetQueueFamilyIndex(queueFamilies, VK_QUEUE_GRAPHICS_BIT);
|
newDevice.queueFamilies.graphicsFamily = GetQueueFamilyIndex(queueFamilies, VK_QUEUE_GRAPHICS_BIT);
|
||||||
if (newDevice.queueFamilies.graphicsFamily == -1) {
|
if (newDevice.queueFamilies.graphicsFamily == -1) {
|
||||||
@@ -270,7 +280,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newDevice.queueFamilies.presentFamily =
|
newDevice.queueFamilies.presentFamily =
|
||||||
GetPresentQueueFamilyIndex(newDevice, queueFamilies, newDevice.queueFamilies.graphicsFamily);
|
GetPresentQueueFamilyIndex(newDevice, surface, queueFamilies, newDevice.queueFamilies.graphicsFamily);
|
||||||
if (newDevice.queueFamilies.presentFamily == -1) {
|
if (newDevice.queueFamilies.presentFamily == -1) {
|
||||||
outBetterDevice = otherDevice;
|
outBetterDevice = otherDevice;
|
||||||
MGLOG_I(" Ignored physical device: No present queue family.");
|
MGLOG_I(" Ignored physical device: No present queue family.");
|
||||||
@@ -289,7 +299,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (newDevice.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU &&
|
if (newDevice.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU &&
|
||||||
otherDevice.properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
otherDevice.properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
||||||
outBetterDevice = newDevice;
|
outBetterDevice = newDevice;
|
||||||
MGLOG_I(" Picked physical device: Integrated GPU and the other is not discrete.");
|
MGLOG_I(" Picked physical device: Integrated GPU and no discrete one found yet.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,17 +330,43 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Bool found = false;
|
Bool found = false;
|
||||||
for (const auto& extension : availableExtensions) {
|
for (const auto& extension : availableExtensions) {
|
||||||
if (strcmp(extension.extensionName, s_deviceExtensionNames[i]) == 0) {
|
if (strcmp(extension.extensionName, s_deviceExtensionNames[i]) == 0) {
|
||||||
|
MGLOG_I("Required extension found: %s", s_deviceExtensionNames[i]);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found) {
|
||||||
|
MGLOG_I("Required extension not found: %s", s_deviceExtensionNames[i]);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VulkanRenderer::SwapchainCapabilities VulkanRenderer::GetSwapchainCapabilities(VkPhysicalDevice device, VkSurfaceKHR surface) {
|
||||||
|
SwapchainCapabilities swapchainCapabilities;
|
||||||
|
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &swapchainCapabilities.capabilities));
|
||||||
|
Uint32 formatCount;
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr));
|
||||||
|
|
||||||
|
if (formatCount != 0) {
|
||||||
|
swapchainCapabilities.surfaceFormats.resize(formatCount);
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, swapchainCapabilities.surfaceFormats.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 presentModeCount;
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr));
|
||||||
|
|
||||||
|
if (presentModeCount != 0) {
|
||||||
|
swapchainCapabilities.presentModes.resize(presentModeCount);
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, swapchainCapabilities.presentModes.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return swapchainCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateLogicalDeviceAndQueues() {
|
void VulkanRenderer::CreateLogicalDeviceAndQueues() {
|
||||||
Float queuePriority = 1.0f;
|
Float queuePriority = 1.0f;
|
||||||
|
|
||||||
@@ -365,6 +401,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
} else {
|
} else {
|
||||||
deviceCreateInfo.enabledLayerCount = 0;
|
deviceCreateInfo.enabledLayerCount = 0;
|
||||||
}
|
}
|
||||||
|
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(std::size(s_deviceExtensionNames));
|
||||||
|
deviceCreateInfo.ppEnabledExtensionNames = s_deviceExtensionNames;
|
||||||
VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &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.");
|
||||||
|
|
||||||
@@ -416,18 +454,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Int VulkanRenderer::GetPresentQueueFamilyIndex(
|
Int VulkanRenderer::GetPresentQueueFamilyIndex(
|
||||||
const PhysicalDevice& physicalDevice,
|
const PhysicalDevice& physicalDevice, VkSurfaceKHR surface,
|
||||||
const Vector<VkQueueFamilyProperties>& queueFamilies, Int preferredFamilyIndex) const {
|
const Vector<VkQueueFamilyProperties>& queueFamilies, Int preferredFamilyIndex) {
|
||||||
if (preferredFamilyIndex != -1) {
|
if (preferredFamilyIndex != -1) {
|
||||||
VkBool32 supportsPresent = false;
|
VkBool32 supportsPresent = false;
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice.handle, preferredFamilyIndex, m_surface, &supportsPresent);
|
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice.handle, preferredFamilyIndex, 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(physicalDevice.handle, i, m_surface, &supportsPresent);
|
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice.handle, i, surface, &supportsPresent);
|
||||||
if (supportsPresent)
|
if (supportsPresent)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,27 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Int32 presentFamily = -1;
|
Int32 presentFamily = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SwapchainCapabilities {
|
||||||
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
Vector<VkSurfaceFormatKHR> surfaceFormats;
|
||||||
|
Vector<VkPresentModeKHR> presentModes;
|
||||||
|
|
||||||
|
Bool IsComplete() const {
|
||||||
|
return !surfaceFormats.empty() && !presentModes.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct PhysicalDevice {
|
struct PhysicalDevice {
|
||||||
QueueFamilyIndices queueFamilies;
|
QueueFamilyIndices queueFamilies;
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
|
SwapchainCapabilities swapchainCapabilities;
|
||||||
VkPhysicalDevice handle = VK_NULL_HANDLE;
|
VkPhysicalDevice handle = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
Bool IsComplete() const {
|
||||||
|
return handle != VK_NULL_HANDLE &&
|
||||||
|
queueFamilies.graphicsFamily != -1 &&
|
||||||
|
queueFamilies.presentFamily != -1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NativeWindowType m_window = 0;
|
NativeWindowType m_window = 0;
|
||||||
@@ -80,16 +97,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkResult DestroyDebugMessenger();
|
VkResult DestroyDebugMessenger();
|
||||||
VkDebugUtilsMessengerCreateInfoEXT PopulateDebugMessengerCreateInfo();
|
VkDebugUtilsMessengerCreateInfoEXT PopulateDebugMessengerCreateInfo();
|
||||||
void PickPhysicalDevice();
|
void PickPhysicalDevice();
|
||||||
Bool GetMoreCapablePhysicalDevice(VkPhysicalDevice newVkDevice, const PhysicalDevice& compareWithDevice, PhysicalDevice& outBetterDevice);
|
|
||||||
void CreateLogicalDeviceAndQueues();
|
void CreateLogicalDeviceAndQueues();
|
||||||
void CreateSurface();
|
void CreateSurface();
|
||||||
|
|
||||||
Int GetPresentQueueFamilyIndex(const PhysicalDevice& physicalDevice, const Vector<VkQueueFamilyProperties>& queueFamilies, Int preferredFamilyIndex = -1) const;
|
static Int GetPresentQueueFamilyIndex(
|
||||||
|
const PhysicalDevice& physicalDevice, VkSurfaceKHR surface,
|
||||||
|
const Vector<VkQueueFamilyProperties>& queueFamilies, Int preferredFamilyIndex = -1);
|
||||||
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);
|
||||||
static Vector<VkExtensionProperties> EnumerateInstanceExtensions();
|
static Vector<VkExtensionProperties> EnumerateInstanceExtensions();
|
||||||
static Bool IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device);
|
static Bool IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device);
|
||||||
|
static SwapchainCapabilities GetSwapchainCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface);
|
||||||
|
static Bool GetMoreCapablePhysicalDevice(VkPhysicalDevice newVkDevice, VkSurfaceKHR surface, const PhysicalDevice& compareWithDevice, PhysicalDevice& outBetterDevice);
|
||||||
static constexpr const char* s_validationLayerNames[] = {
|
static constexpr const char* s_validationLayerNames[] = {
|
||||||
"VK_LAYER_KHRONOS_validation"
|
"VK_LAYER_KHRONOS_validation"
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user