From 2bc323b2ed045e38089eca9a9d34d3853e608d3e Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 5 Feb 2024 22:17:00 +0100 Subject: [PATCH] param: present_mode This parameter displays the current present mode being used in vulkan or the vsync status in opengl --- README.md | 1 + src/hud_elements.cpp | 19 ++++++++++++++++++- src/hud_elements.h | 29 ++++++++++++++++++++++++++++- src/overlay_params.h | 1 + src/vulkan.cpp | 38 +++++++++++++++++++++++++++++++++----- 5 files changed, 81 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fa177f43..2f50b431 100644 --- a/README.md +++ b/README.md @@ -426,6 +426,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `wine_color` | Change color of the wine/proton text | | `wine` | Show current Wine or Proton version in use | | `winesync` | Show wine sync method in use | +| `present_mode` | Shows current vulkan [present mode](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPresentModeKHR.html) or vsync status in opengl | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` Because comma is also used as option delimiter and needs to be escaped for values with a backslash, you can use `+` like `MANGOHUD_CONFIG=fps_limit=60+30+0` instead. diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 9af1d7f0..c2752837 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -1430,6 +1430,18 @@ void HudElements::winesync() { } } +void HudElements::present_mode() { + ImguiNextColumnFirstItem(); + ImGui::PushFont(HUDElements.sw_stats->font1); + if (HUDElements.is_vulkan) + HUDElements.TextColored(HUDElements.colors.engine, "%s", "Present Mode"); + else + HUDElements.TextColored(HUDElements.colors.engine, "%s", "VSYNC"); + ImguiNextColumnOrNewRow(); + HUDElements.TextColored(HUDElements.colors.text, "%s\n", HUDElements.get_present_mode().c_str()); + ImGui::PopFont(); +} + void HudElements::sort_elements(const std::pair& option) { const auto& param = option.first; const auto& value = option.second; @@ -1475,7 +1487,9 @@ void HudElements::sort_elements(const std::pair& optio {"fps_metrics", {fps_metrics}}, {"hdr", {hdr}}, {"refresh_rate", {refresh_rate}}, - {"winesync", {winesync}} + {"winesync", {winesync}}, + {"present_mode", {present_mode}} + }; auto check_param = display_params.find(param); @@ -1598,6 +1612,9 @@ void HudElements::legacy_elements(){ ordered_functions.push_back({duration, "duration", value}); if (params->enabled[OVERLAY_PARAM_ENABLED_winesync]) ordered_functions.push_back({winesync, "winesync", value}); + if (params->enabled[OVERLAY_PARAM_ENABLED_present_mode]) + ordered_functions.push_back({present_mode, "present_mode", value}); + } void HudElements::update_exec(){ diff --git a/src/hud_elements.h b/src/hud_elements.h index 69cc8383..29035b52 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -6,6 +6,8 @@ #include "timing.hpp" #include #include "winesync.h" +#include "vulkan/vulkan.h" +#include struct Function { std::function run; // Using std::function instead of a raw function pointer for more flexibility @@ -26,7 +28,7 @@ class HudElements{ float ralign_width; float old_scale; float res_width, res_height; - bool is_vulkan, gamemode_bol = false, vkbasalt_bol = false; + bool is_vulkan = true, gamemode_bol = false, vkbasalt_bol = false; int place; int text_column = 1; int table_columns_count = 0; @@ -92,6 +94,7 @@ class HudElements{ static void hdr(); static void refresh_rate(); static void winesync(); + static void present_mode(); void convert_colors(const struct overlay_params& params); void convert_colors(bool do_conv, const struct overlay_params& params); @@ -123,6 +126,30 @@ class HudElements{ } colors {}; void TextColored(ImVec4 col, const char *fmt, ...); + + std::array presentModes = { + VK_PRESENT_MODE_FIFO_RELAXED_KHR, + VK_PRESENT_MODE_IMMEDIATE_KHR, + VK_PRESENT_MODE_MAILBOX_KHR, + VK_PRESENT_MODE_FIFO_KHR, + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR}; + + std::map presentModeMap = { + {VK_PRESENT_MODE_IMMEDIATE_KHR, "IMMEDIATE"}, + {VK_PRESENT_MODE_MAILBOX_KHR, "MAILBOX"}, + {VK_PRESENT_MODE_FIFO_KHR, "FIFO"}, + {VK_PRESENT_MODE_FIFO_RELAXED_KHR, "FIFO Relaxed"}, + {VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, "DEMAND"}, + {VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, "ONTINUOUS"} + }; + + std::string get_present_mode(){ + if (is_vulkan) + return presentModeMap[presentModes[params->vsync]]; + else + return params->gl_vsync == 0 ? "OFF" : "ON"; + } }; extern HudElements HUDElements; diff --git a/src/overlay_params.h b/src/overlay_params.h index 825aece5..a3d8774e 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -110,6 +110,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(refresh_rate) \ OVERLAY_PARAM_BOOL(frame_timing_detailed) \ OVERLAY_PARAM_BOOL(winesync) \ + OVERLAY_PARAM_BOOL(present_mode) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 6a2e8ac9..3de63034 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -1497,6 +1497,14 @@ static struct overlay_draw *before_present(struct swapchain_data *swapchain_data return draw; } +static bool IsPresentModeSupported(VkPresentModeKHR targetPresentMode, const std::vector& supportedPresentModes) { + for (const auto& mode : supportedPresentModes) + if (mode == targetPresentMode) + return true; + + return false; // Not found +} + static VkResult overlay_CreateSwapchainKHR( VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, @@ -1508,12 +1516,31 @@ static VkResult overlay_CreateSwapchainKHR( createInfo.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; struct device_data *device_data = FIND(struct device_data, device); - array modes = {VK_PRESENT_MODE_FIFO_RELAXED_KHR, - VK_PRESENT_MODE_IMMEDIATE_KHR, - VK_PRESENT_MODE_MAILBOX_KHR, - VK_PRESENT_MODE_FIFO_KHR}; + + VkPresentModeKHR presentMode = HUDElements.presentModes[device_data->instance->params.vsync]; if (device_data->instance->params.vsync < 4) - createInfo.presentMode = modes[device_data->instance->params.vsync]; + createInfo.presentMode = presentMode; + + struct instance_data *instance_data = + FIND(struct instance_data, device_data->physical_device); + + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR = + (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) instance_data->vtable.GetInstanceProcAddr(instance_data->instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + + if (fpGetPhysicalDeviceSurfacePresentModesKHR != NULL) { + uint32_t presentModeCount; + std::vector presentModes(6); + VkResult result = fpGetPhysicalDeviceSurfacePresentModesKHR(device_data->physical_device, pCreateInfo->surface, &presentModeCount, presentModes.data()); + + if (result == VK_SUCCESS) { + if (IsPresentModeSupported(HUDElements.presentModes[device_data->instance->params.vsync], presentModes)) + SPDLOG_DEBUG("Present mode: {}", HUDElements.get_present_mode()); + else { + SPDLOG_DEBUG("Present mode is not supported: {}", HUDElements.get_present_mode()); + device_data->instance->params.vsync = 3; + } + } + } VkResult result = device_data->vtable.CreateSwapchainKHR(device, &createInfo, pAllocator, pSwapchain); if (result != VK_SUCCESS) return result; @@ -1769,6 +1796,7 @@ static VkResult overlay_CreateDevice( pCreateInfo->enabledExtensionCount); uint32_t extension_count; + instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extension_count, nullptr); std::vector available_extensions(extension_count);