From c4d9d175e8b6c4393bf2fe1c3ce7564939f292a0 Mon Sep 17 00:00:00 2001 From: camdenorrb Date: Fri, 20 Dec 2024 22:31:48 -0600 Subject: [PATCH 1/3] Vulkan DRM/KMS Support --- Source/Core/DolphinNoGUI/CMakeLists.txt | 4 +- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 3 +- Source/Core/DolphinNoGUI/PlatformDRM.cpp | 1 - .../Core/VideoBackends/Vulkan/VKSwapChain.cpp | 298 +++++++++--------- .../Core/VideoBackends/Vulkan/VKSwapChain.h | 3 +- .../Vulkan/VulkanEntryPoints.inl | 12 +- .../VideoBackends/Vulkan/VulkanLoader.cpp | 4 + .../Core/VideoBackends/Vulkan/VulkanLoader.h | 2 +- 8 files changed, 173 insertions(+), 154 deletions(-) diff --git a/Source/Core/DolphinNoGUI/CMakeLists.txt b/Source/Core/DolphinNoGUI/CMakeLists.txt index 9f1180c435..3a8c9f18ea 100644 --- a/Source/Core/DolphinNoGUI/CMakeLists.txt +++ b/Source/Core/DolphinNoGUI/CMakeLists.txt @@ -21,9 +21,11 @@ endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") target_sources(dolphin-nogui PRIVATE PlatformFBDev.cpp) - target_sources(dolphin-nogui PRIVATE PlatformDRM.cpp) endif() +if(ENABLE_DRM) + target_sources(dolphin-nogui PRIVATE PlatformDRM.cpp) +endif() set_target_properties(dolphin-nogui PROPERTIES OUTPUT_NAME dolphin-emu-nogui) diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index d92b9173e8..3327d2df6a 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -221,7 +221,8 @@ int main(int argc, char* argv[]) "fbdev" #endif #if HAVE_DRM - ,"drm" + , + "drm" #endif #if HAVE_X11 , diff --git a/Source/Core/DolphinNoGUI/PlatformDRM.cpp b/Source/Core/DolphinNoGUI/PlatformDRM.cpp index 4f07dc0df8..b7f81f290f 100644 --- a/Source/Core/DolphinNoGUI/PlatformDRM.cpp +++ b/Source/Core/DolphinNoGUI/PlatformDRM.cpp @@ -29,7 +29,6 @@ public: WindowSystemInfo GetWindowSystemInfo() const override; }; - void PlatformDRM::SetTitle(const std::string& string) { std::fprintf(stdout, "%s\n", string.c_str()); diff --git a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp index 86efb94361..5cf3069cae 100644 --- a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp @@ -36,159 +36,172 @@ SwapChain::~SwapChain() DestroySurface(); } -VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, VkPhysicalDevice physical_device, const WindowSystemInfo& wsi) +VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, VkPhysicalDevice physical_device, + const WindowSystemInfo& wsi) { - #if defined(VK_USE_PLATFORM_DISPLAY_KHR) -if (wsi.type == WindowSystemType::DRM) -{ - // Get the first display - uint32_t display_count = 1; - VkDisplayPropertiesKHR display_props; - if (VkResult err = vkGetPhysicalDeviceDisplayPropertiesKHR(physical_device, &display_count, &display_props); err != VK_SUCCESS && err != VK_INCOMPLETE) + if (wsi.type == WindowSystemType::DRM) { - LOG_VULKAN_ERROR(err, "vkGetPhysicalDeviceDisplayPropertiesKHR failed: "); - return VK_NULL_HANDLE; - } - - // Get the first mode of the display - uint32_t mode_count = 0; - if (VkResult err = vkGetDisplayModePropertiesKHR(physical_device, display_props.display, &mode_count, nullptr); err != VK_SUCCESS) - { - LOG_VULKAN_ERROR(err, "vkGetDisplayModePropertiesKHR failed: "); - return VK_NULL_HANDLE; - } - - if (mode_count == 0) - { - ERROR_LOG_FMT(VIDEO, "Cannot find any mode for the display!"); - return VK_NULL_HANDLE; - } - - VkDisplayModePropertiesKHR mode_props; - mode_count = 1; - if (VkResult err = vkGetDisplayModePropertiesKHR(physical_device, display_props.display, &mode_count, &mode_props); err != VK_SUCCESS && err != VK_INCOMPLETE) - { - LOG_VULKAN_ERROR(err, "vkGetDisplayModePropertiesKHR failed: "); - return VK_NULL_HANDLE; - } - - // Get the list of planes - uint32_t plane_count = 0; - if (VkResult err = vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physical_device, &plane_count, nullptr); err != VK_SUCCESS) - { - LOG_VULKAN_ERROR(err, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR failed: "); - return VK_NULL_HANDLE; - } - - if (plane_count == 0) - { - ERROR_LOG_FMT(VIDEO, "No display planes found!"); - return VK_NULL_HANDLE; - } - - // Find a plane compatible with the display - // Find a plane compatible with the display - uint32_t compatible_plane_index = UINT32_MAX; - - for (uint32_t plane_index = 0; plane_index < plane_count; plane_index++) - { - // Query the number of displays supported by the plane - display_count = 0; - VkResult err = vkGetDisplayPlaneSupportedDisplaysKHR(physical_device, plane_index, &display_count, nullptr); - if (err != VK_SUCCESS) + // Get the first display + uint32_t display_count = 1; + VkDisplayPropertiesKHR display_props; + if (VkResult err = vkGetPhysicalDeviceDisplayPropertiesKHR(physical_device, &display_count, + &display_props); + err != VK_SUCCESS && err != VK_INCOMPLETE) { - LOG_VULKAN_ERROR(err, "vkGetDisplayPlaneSupportedDisplaysKHR (count query) failed: "); + LOG_VULKAN_ERROR(err, "vkGetPhysicalDeviceDisplayPropertiesKHR failed: "); return VK_NULL_HANDLE; } - if (display_count == 0) - continue; // Skip planes that support no displays - - // Allocate memory to hold the supported displays - std::vector displays(display_count); - err = vkGetDisplayPlaneSupportedDisplaysKHR(physical_device, plane_index, &display_count, displays.data()); - if (err != VK_SUCCESS) + // Get the first mode of the display + uint32_t mode_count = 0; + if (VkResult err = vkGetDisplayModePropertiesKHR(physical_device, display_props.display, + &mode_count, nullptr); + err != VK_SUCCESS) { - LOG_VULKAN_ERROR(err, "vkGetDisplayPlaneSupportedDisplaysKHR (fetch displays) failed: "); + LOG_VULKAN_ERROR(err, "vkGetDisplayModePropertiesKHR failed: "); return VK_NULL_HANDLE; } - // Check if the target display is among the supported displays - for (const auto& display : displays) + if (mode_count == 0) { - if (display == display_props.display) + ERROR_LOG_FMT(VIDEO, "Cannot find any mode for the display!"); + return VK_NULL_HANDLE; + } + + VkDisplayModePropertiesKHR mode_props; + mode_count = 1; + if (VkResult err = vkGetDisplayModePropertiesKHR(physical_device, display_props.display, + &mode_count, &mode_props); + err != VK_SUCCESS && err != VK_INCOMPLETE) + { + LOG_VULKAN_ERROR(err, "vkGetDisplayModePropertiesKHR failed: "); + return VK_NULL_HANDLE; + } + + // Get the list of planes + uint32_t plane_count = 0; + if (VkResult err = + vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physical_device, &plane_count, nullptr); + err != VK_SUCCESS) + { + LOG_VULKAN_ERROR(err, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR failed: "); + return VK_NULL_HANDLE; + } + + if (plane_count == 0) + { + ERROR_LOG_FMT(VIDEO, "No display planes found!"); + return VK_NULL_HANDLE; + } + + // Find a plane compatible with the display + // Find a plane compatible with the display + uint32_t compatible_plane_index = UINT32_MAX; + + for (uint32_t plane_index = 0; plane_index < plane_count; plane_index++) + { + // Query the number of displays supported by the plane + display_count = 0; + VkResult err = vkGetDisplayPlaneSupportedDisplaysKHR(physical_device, plane_index, + &display_count, nullptr); + if (err != VK_SUCCESS) { - compatible_plane_index = plane_index; + LOG_VULKAN_ERROR(err, "vkGetDisplayPlaneSupportedDisplaysKHR (count query) failed: "); + return VK_NULL_HANDLE; + } + + if (display_count == 0) + continue; // Skip planes that support no displays + + // Allocate memory to hold the supported displays + std::vector displays(display_count); + err = vkGetDisplayPlaneSupportedDisplaysKHR(physical_device, plane_index, &display_count, + displays.data()); + if (err != VK_SUCCESS) + { + LOG_VULKAN_ERROR(err, "vkGetDisplayPlaneSupportedDisplaysKHR (fetch displays) failed: "); + return VK_NULL_HANDLE; + } + + // Check if the target display is among the supported displays + for (const auto& display : displays) + { + if (display == display_props.display) + { + compatible_plane_index = plane_index; + break; + } + } + + if (compatible_plane_index != UINT32_MAX) + break; // Exit early if a compatible plane is found + } + + if (compatible_plane_index == UINT32_MAX) + { + ERROR_LOG_FMT(VIDEO, "No compatible plane found for the display!"); + return VK_NULL_HANDLE; + } + + if (compatible_plane_index == UINT32_MAX) + { + ERROR_LOG_FMT(VIDEO, "No compatible plane found for the display!"); + return VK_NULL_HANDLE; + } + + // Get capabilities of the compatible plane + VkDisplayPlaneCapabilitiesKHR plane_capabilities; + if (VkResult err = vkGetDisplayPlaneCapabilitiesKHR( + physical_device, mode_props.displayMode, compatible_plane_index, &plane_capabilities); + err != VK_SUCCESS) + { + LOG_VULKAN_ERROR(err, "vkGetDisplayPlaneCapabilitiesKHR failed: "); + return VK_NULL_HANDLE; + } + + // Find a supported alpha mode + VkDisplayPlaneAlphaFlagBitsKHR alpha_mode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; + VkDisplayPlaneAlphaFlagBitsKHR alpha_modes[] = { + VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, + VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR, + }; + + for (auto& curr_alpha_mode : alpha_modes) + { + if (plane_capabilities.supportedAlpha & curr_alpha_mode) + { + alpha_mode = curr_alpha_mode; break; } } - if (compatible_plane_index != UINT32_MAX) - break; // Exit early if a compatible plane is found - } + // Create the display surface + VkDisplaySurfaceCreateInfoKHR surface_create_info = {}; + surface_create_info.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR; + surface_create_info.displayMode = mode_props.displayMode; + surface_create_info.planeIndex = compatible_plane_index; + surface_create_info.planeStackIndex = 0; + surface_create_info.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + surface_create_info.globalAlpha = 1.0f; + surface_create_info.alphaMode = alpha_mode; + surface_create_info.imageExtent.width = display_props.physicalResolution.width; + surface_create_info.imageExtent.height = display_props.physicalResolution.height; - if (compatible_plane_index == UINT32_MAX) - { - ERROR_LOG_FMT(VIDEO, "No compatible plane found for the display!"); - return VK_NULL_HANDLE; - } - - - if (compatible_plane_index == UINT32_MAX) - { - ERROR_LOG_FMT(VIDEO, "No compatible plane found for the display!"); - return VK_NULL_HANDLE; - } - - // Get capabilities of the compatible plane - VkDisplayPlaneCapabilitiesKHR plane_capabilities; - if (VkResult err = vkGetDisplayPlaneCapabilitiesKHR(physical_device, mode_props.displayMode, compatible_plane_index, &plane_capabilities); err != VK_SUCCESS) - { - LOG_VULKAN_ERROR(err, "vkGetDisplayPlaneCapabilitiesKHR failed: "); - return VK_NULL_HANDLE; - } - - // Find a supported alpha mode - VkDisplayPlaneAlphaFlagBitsKHR alpha_mode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; - VkDisplayPlaneAlphaFlagBitsKHR alpha_modes[] = { - VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, - VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR, - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR, - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR, - }; - - for (auto& curr_alpha_mode : alpha_modes) - { - if (plane_capabilities.supportedAlpha & curr_alpha_mode) + VkSurfaceKHR surface; + if (VkResult res = + vkCreateDisplayPlaneSurfaceKHR(instance, &surface_create_info, nullptr, &surface); + res != VK_SUCCESS) { - alpha_mode = curr_alpha_mode; - break; + LOG_VULKAN_ERROR(res, "vkCreateDisplayPlaneSurfaceKHR failed: "); + return VK_NULL_HANDLE; } + + return surface; } - // Create the display surface - VkDisplaySurfaceCreateInfoKHR surface_create_info = {}; - surface_create_info.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR; - surface_create_info.displayMode = mode_props.displayMode; - surface_create_info.planeIndex = compatible_plane_index; - surface_create_info.planeStackIndex = 0; - surface_create_info.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - surface_create_info.globalAlpha = 1.0f; - surface_create_info.alphaMode = alpha_mode; - surface_create_info.imageExtent.width = display_props.physicalResolution.width; - surface_create_info.imageExtent.height = display_props.physicalResolution.height; - - VkSurfaceKHR surface; - if (VkResult res = vkCreateDisplayPlaneSurfaceKHR(instance, &surface_create_info, nullptr, &surface); res != VK_SUCCESS) - { - LOG_VULKAN_ERROR(res, "vkCreateDisplayPlaneSurfaceKHR failed: "); - return VK_NULL_HANDLE; - } - - return surface; -} - #endif #if defined(VK_USE_PLATFORM_WIN32_KHR) @@ -329,20 +342,18 @@ bool SwapChain::SelectSurfaceFormat() // because we already apply gamma ourselves, and we might not use sRGB gamma. // Force using a linear format instead, if this is the case. VkFormat format = VKTexture::GetLinearFormat(surface_format.format); - if (surface_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) - { - if (format == VK_FORMAT_R8G8B8A8_UNORM) - surface_format_RGBA8 = &surface_format; - else if (format == VK_FORMAT_B8G8R8A8_UNORM) - surface_format_BGRA8 = &surface_format; - else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) - surface_format_RGB10_A2 = &surface_format; - } + if (format == VK_FORMAT_R8G8B8A8_UNORM) + surface_format_RGBA8 = &surface_format; + else if (format == VK_FORMAT_B8G8R8A8_UNORM) + surface_format_BGRA8 = &surface_format; + else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 && + surface_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + surface_format_RGB10_A2 = &surface_format; else if (format == VK_FORMAT_R16G16B16A16_SFLOAT && surface_format.colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT) - { surface_format_RGBA16F_scRGB = &surface_format; - } + else + continue; } const VkSurfaceFormatKHR* surface_format = nullptr; @@ -738,7 +749,8 @@ bool SwapChain::RecreateSurface(void* native_handle) // Re-create the surface with the new native handle m_wsi.render_surface = native_handle; - m_surface = CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), g_vulkan_context->GetPhysicalDevice(), m_wsi); + m_surface = CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), + g_vulkan_context->GetPhysicalDevice(), m_wsi); if (m_surface == VK_NULL_HANDLE) return false; diff --git a/Source/Core/VideoBackends/Vulkan/VKSwapChain.h b/Source/Core/VideoBackends/Vulkan/VKSwapChain.h index f86feaa3b0..f7bf31f18f 100644 --- a/Source/Core/VideoBackends/Vulkan/VKSwapChain.h +++ b/Source/Core/VideoBackends/Vulkan/VKSwapChain.h @@ -25,7 +25,8 @@ public: ~SwapChain(); // Creates a vulkan-renderable surface for the specified window handle. - static VkSurfaceKHR CreateVulkanSurface(VkInstance instance, VkPhysicalDevice physical_device, const WindowSystemInfo &wsi); + static VkSurfaceKHR CreateVulkanSurface(VkInstance instance, VkPhysicalDevice physical_device, + const WindowSystemInfo& wsi); // Create a new swap chain from a pre-existing surface. static std::unique_ptr Create(const WindowSystemInfo& wsi, VkSurfaceKHR surface, diff --git a/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl b/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl index b1557300a9..da46ece849 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl +++ b/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl @@ -50,12 +50,12 @@ VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceXlibPresentationSupportKHR, false #endif #if defined(VK_USE_PLATFORM_DISPLAY_KHR) -VULKAN_INSTANCE_ENTRY_POINT(vkCreateDisplayPlaneSurfaceKHR, true) -VULKAN_INSTANCE_ENTRY_POINT(vkGetDisplayPlaneCapabilitiesKHR, true) -VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceDisplayPlanePropertiesKHR, true) -VULKAN_INSTANCE_ENTRY_POINT(vkGetDisplayPlaneSupportedDisplaysKHR, true) -VULKAN_INSTANCE_ENTRY_POINT(vkGetDisplayModePropertiesKHR, true) -VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceDisplayPropertiesKHR, true) +VULKAN_INSTANCE_ENTRY_POINT(vkCreateDisplayPlaneSurfaceKHR, false) +VULKAN_INSTANCE_ENTRY_POINT(vkGetDisplayPlaneCapabilitiesKHR, false) +VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceDisplayPlanePropertiesKHR, false) +VULKAN_INSTANCE_ENTRY_POINT(vkGetDisplayPlaneSupportedDisplaysKHR, false) +VULKAN_INSTANCE_ENTRY_POINT(vkGetDisplayModePropertiesKHR, false) +VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceDisplayPropertiesKHR, false) #endif #if defined(VK_USE_PLATFORM_ANDROID_KHR) diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp index 46d8468960..666b3beb74 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp @@ -36,6 +36,7 @@ static void ResetVulkanLibraryFunctionPointers() #define VULKAN_INSTANCE_ENTRY_POINT(name, required) name = nullptr; #define VULKAN_DEVICE_ENTRY_POINT(name, required) name = nullptr; #include "VideoBackends/Vulkan/VulkanEntryPoints.inl" + #undef VULKAN_DEVICE_ENTRY_POINT #undef VULKAN_INSTANCE_ENTRY_POINT #undef VULKAN_MODULE_ENTRY_POINT @@ -108,6 +109,7 @@ bool LoadVulkanLibrary(bool force_system_library) return false; \ } #include "VideoBackends/Vulkan/VulkanEntryPoints.inl" + #undef VULKAN_MODULE_ENTRY_POINT return true; @@ -135,6 +137,7 @@ bool LoadVulkanInstanceFunctions(VkInstance instance) #define VULKAN_INSTANCE_ENTRY_POINT(name, required) \ LoadFunction(reinterpret_cast(&name), #name, required); #include "VideoBackends/Vulkan/VulkanEntryPoints.inl" + #undef VULKAN_INSTANCE_ENTRY_POINT return !required_functions_missing; @@ -155,6 +158,7 @@ bool LoadVulkanDeviceFunctions(VkDevice device) #define VULKAN_DEVICE_ENTRY_POINT(name, required) \ LoadFunction(reinterpret_cast(&name), #name, required); #include "VideoBackends/Vulkan/VulkanEntryPoints.inl" + #undef VULKAN_DEVICE_ENTRY_POINT return !required_functions_missing; diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h index 6dd439171c..145018f0ef 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h +++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h @@ -11,7 +11,7 @@ #if defined(HAVE_DRM) #define VK_USE_PLATFORM_DISPLAY_KHR -//#define VK_KHR_display +// #define VK_KHR_display #endif #if defined(HAVE_X11) From 32c64e4fda54183861bfe272f3d9c80de31e347d Mon Sep 17 00:00:00 2001 From: camdenorrb Date: Sun, 22 Dec 2024 23:00:41 -0600 Subject: [PATCH 2/3] Force 60fps --- .../Core/VideoBackends/Vulkan/VKSwapChain.cpp | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp index 5cf3069cae..6d962b2953 100644 --- a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp @@ -69,16 +69,34 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, VkPhysicalDevic return VK_NULL_HANDLE; } - VkDisplayModePropertiesKHR mode_props; - mode_count = 1; + auto *all_mode_props = static_cast(calloc(mode_count, sizeof(*all_mode_props))); if (VkResult err = vkGetDisplayModePropertiesKHR(physical_device, display_props.display, - &mode_count, &mode_props); + &mode_count, all_mode_props); err != VK_SUCCESS && err != VK_INCOMPLETE) { LOG_VULKAN_ERROR(err, "vkGetDisplayModePropertiesKHR failed: "); return VK_NULL_HANDLE; } + for (int i = 0; i < mode_count; ++i) + { + VkDisplayModeParametersKHR *params = &all_mode_props[i].parameters; + printf("Mode %d: %d x %d (%.2f fps)\n", i, + params->visibleRegion.width, params->visibleRegion.height, + static_cast(params->refreshRate) / 1000.0f); + + if (params->refreshRate < 60000) + { + printf("Removing mode %d\n", i); + mode_count--; + for (int j = i; j < mode_count; ++j) + all_mode_props[j] = all_mode_props[j + 1]; + i--; + } + } + + VkDisplayModePropertiesKHR mode_props = all_mode_props[0]; + // Get the list of planes uint32_t plane_count = 0; if (VkResult err = From d6df5e970b039dd8861b65e74e12a8b2f8676911 Mon Sep 17 00:00:00 2001 From: camdenorrb Date: Sun, 22 Dec 2024 23:14:06 -0600 Subject: [PATCH 3/3] User selection --- .../Core/VideoBackends/Vulkan/VKSwapChain.cpp | 54 ++++++++++++++----- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp index 6d962b2953..101a1114fb 100644 --- a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp @@ -36,6 +36,17 @@ SwapChain::~SwapChain() DestroySurface(); } +// Custom comparator to sort by resolution +bool CompareResolutions(const VkDisplayModePropertiesKHR& a, const VkDisplayModePropertiesKHR& b) +{ + const auto& params_a = a.parameters.visibleRegion; + const auto& params_b = b.parameters.visibleRegion; + + if (params_a.width != params_b.width) + return params_a.width < params_b.width; // Sort by width first + return params_a.height < params_b.height; // Then by height +} + VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, VkPhysicalDevice physical_device, const WindowSystemInfo& wsi) { @@ -69,7 +80,7 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, VkPhysicalDevic return VK_NULL_HANDLE; } - auto *all_mode_props = static_cast(calloc(mode_count, sizeof(*all_mode_props))); + auto* all_mode_props = static_cast(calloc(mode_count, sizeof(VkDisplayModePropertiesKHR))); if (VkResult err = vkGetDisplayModePropertiesKHR(physical_device, display_props.display, &mode_count, all_mode_props); err != VK_SUCCESS && err != VK_INCOMPLETE) @@ -78,24 +89,41 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, VkPhysicalDevic return VK_NULL_HANDLE; } + // Sort and display modes + std::vector all_mode_props_vector(all_mode_props, all_mode_props + mode_count); + std::ranges::sort(all_mode_props_vector, CompareResolutions); + + for (int i = 0; i < mode_count; ++i) + { + const VkDisplayModeParametersKHR* params = &all_mode_props_vector[i].parameters; + printf("Mode %d: %d x %d (%.2f fps)\n", i, + params->visibleRegion.width, params->visibleRegion.height, + static_cast(params->refreshRate) / 1000.0f); + } + for (int i = 0; i < mode_count; ++i) { VkDisplayModeParametersKHR *params = &all_mode_props[i].parameters; printf("Mode %d: %d x %d (%.2f fps)\n", i, params->visibleRegion.width, params->visibleRegion.height, static_cast(params->refreshRate) / 1000.0f); - - if (params->refreshRate < 60000) - { - printf("Removing mode %d\n", i); - mode_count--; - for (int j = i; j < mode_count; ++j) - all_mode_props[j] = all_mode_props[j + 1]; - i--; - } } - VkDisplayModePropertiesKHR mode_props = all_mode_props[0]; + int selected_mode = -1; + do + { + printf("Please select a mode (0 to %d): ", mode_count - 1); + if (scanf("%d", &selected_mode) != 1) { + // Clear invalid input + while (getchar() != '\n'); + printf("Invalid input. Please enter a number.\n"); + selected_mode = -1; + } else if (selected_mode < 0 || selected_mode >= mode_count) { + printf("Invalid selection. Please choose a valid mode.\n"); + } + } while (selected_mode < 0 || selected_mode >= mode_count); + + VkDisplayModePropertiesKHR mode_props = all_mode_props[selected_mode]; // Get the list of planes uint32_t plane_count = 0; @@ -205,8 +233,8 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, VkPhysicalDevic surface_create_info.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; surface_create_info.globalAlpha = 1.0f; surface_create_info.alphaMode = alpha_mode; - surface_create_info.imageExtent.width = display_props.physicalResolution.width; - surface_create_info.imageExtent.height = display_props.physicalResolution.height; + surface_create_info.imageExtent.width = mode_props.parameters.visibleRegion.width; + surface_create_info.imageExtent.height = mode_props.parameters.visibleRegion.height; VkSurfaceKHR surface; if (VkResult res =