Skip to content

Conversation

@Mosch0512
Copy link
Contributor

This pull request significantly enhances the in-game performance monitoring capabilities by introducing both a basic FPS counter and a comprehensive debug overlay. The detailed overlay provides crucial metrics like 1% low FPS and a visual frame time graph, offering a much deeper understanding of performance consistency beyond just average frame rates. These new tools are easily accessible and controllable via chat commands, enabling developers and users to quickly diagnose and analyze performance characteristics.

Highlights

  • New Performance Overlays: Introduced a simple FPS counter ('$fpscounter') and a detailed performance overlay ('$details') displaying average FPS, 1% low, slowest frame, and a visual frame time graph.
  • Detailed Frame Statistics: Implemented a frame statistics tracker to record frame times, calculate average FPS, 1% low, and the slowest frame over a history of recent frames.
  • Visual Frame Time Graph: Added a graphical representation of recent frame times, color-coded to indicate performance thresholds (e.g., 60 FPS, 40 FPS).
  • Console Command Integration: New console commands ('$fpscounter on/off', '$details on/off') allow dynamic toggling of the performance overlays. 'ResetFrameStats()' is now called when VSync settings are changed.

RenderDebugInfo (FPS, mouse position, camera angles) is now:
- Always on in Debug builds
- Off by default in Release builds, toggle with $fpscounter on/off

The $fpscounter command is checked before the $fps prefix to avoid
a crash from trying to parse "ounter on" as a float.
Show avg FPS, max FPS, 1% low, 0.1% low, frame time in ms.
Render a color-coded frame time bar graph (green/yellow/red)
with a 60fps reference line.
… overlay

Address PR review feedback: replace extern declarations with header
include, extract magic numbers to named constants, use std::accumulate,
fix highest FPS to track instantaneous values, rename misleading 0.1%
low to slowest frame, fix frame time consistency.
Move glBegin/glEnd outside the frame bar loop to reduce draw calls.
Use else-if chain in CheckCommand to skip unnecessary comparisons.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Mosch0512, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the in-game performance monitoring by introducing robust tools for analyzing frame rates and consistency. It provides both a basic FPS display and a comprehensive debug overlay, offering critical metrics like 1% low FPS and a visual frame time graph. These additions empower users and developers to gain a deeper understanding of performance characteristics and diagnose issues more effectively.

Highlights

  • New Performance Overlays: Introduced a simple FPS counter ('$fpscounter') and a detailed performance overlay ('$details') displaying average FPS, 1% low, slowest frame, and a visual frame time graph.
  • Detailed Frame Statistics: Implemented a frame statistics tracker to record frame times, calculate average FPS, 1% low, and the slowest frame over a history of recent frames.
  • Visual Frame Time Graph: Added a graphical representation of recent frame times, color-coded to indicate performance thresholds (e.g., 60 FPS, 40 FPS).
  • Console Command Integration: New console commands ('$fpscounter on/off', '$details on/off') allow dynamic toggling of the performance overlays. 'ResetFrameStats()' is now called when VSync settings are changed.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • README.md
    • Updated chat command documentation to include new $fpscounter and $details commands.
  • src/source/Scenes/SceneManager.cpp
    • Added necessary includes for <algorithm> and <numeric> for statistical calculations.
    • Introduced global flags g_bShowDebugInfo and g_bShowFpsCounter with corresponding setter functions to control overlay visibility.
    • Implemented a Frame Statistics Tracker with constants defining history size, update intervals, and display parameters.
    • Added static variables to store frame times, frame count, and calculated statistics like average FPS, 1% low, and slowest frame.
    • Created ResetFrameStats() function to clear all collected frame data.
    • Developed UpdateFrameStats() to continuously record frame times, calculate instantaneous FPS, and periodically compute percentile statistics.
    • Implemented RenderFrameGraph() to draw a dynamic, color-coded bar graph of recent frame times using OpenGL primitives.
    • Modified RenderDebugInfo() to incorporate the new frame statistics (average, 1% low, slowest frame) and integrate the RenderFrameGraph.
    • Created RenderFpsCounter() to display a simple, current FPS value.
    • Integrated calls to RenderDebugInfo() and RenderFpsCounter() within the MainScene() rendering loop.
  • src/source/Scenes/SceneManager.h
    • Added declarations for SetShowDebugInfo(bool enabled), SetShowFpsCounter(bool enabled), and ResetFrameStats() to expose control over the new overlays and statistics.
  • src/source/Utilities/Log/muConsoleDebug.cpp
    • Included SceneManager.h to access new overlay control functions.
    • Extended CheckCommand() to parse and handle new console commands: $fpscounter on/off and $details on/off, which toggle the respective overlays.
    • Added calls to ResetFrameStats() when VSync settings are changed via $vsync on/off commands, ensuring statistics are reset for new display modes.
Activity
  • The author, Mosch0512, created this pull request to introduce new performance monitoring features.
  • The pull request description details the new performance overlays, frame statistics, visual frame time graph, and console command integration.
  • No human activity (comments, reviews) has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a great addition, providing valuable performance monitoring tools. The implementation of the FPS counter and the detailed debug overlay with frame statistics is well-structured and fits within the existing architecture. The new chat commands make these features easily accessible. My review includes a few suggestions to improve maintainability and safety, such as using safer string formatting functions, refactoring command handling for better scalability, and using named constants for UI colors. Overall, this is a solid contribution.

Comment on lines +149 to +151
static float sorted[FRAME_HISTORY_SIZE];
memcpy(sorted, s_frameTimesMs, sizeof(float) * s_frameCount);
std::sort(sorted, sorted + s_frameCount, std::greater<float>());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of a C-style static array sorted and memcpy is functional but less idiomatic and safe than modern C++ alternatives. Consider using std::vector for the sorted data. A static std::vector would prevent reallocations on every call, and you could use std::copy or its constructor for safer data transfer. This would align better with the use of other <algorithm> features in this function and improve type safety.

        static std::vector<float> sorted;
        sorted.assign(s_frameTimesMs, s_frameTimesMs + s_frameCount);
        std::sort(sorted.begin(), sorted.end(), std::greater<float>());

Comment on lines +428 to +434
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
glBegin(GL_QUADS);
glVertex2f(gx, glBottom);
glVertex2f(gx + gw, glBottom);
glVertex2f(gx + gw, glTop);
glVertex2f(gx, glTop);
glEnd();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The colors for the frame graph background, lines, and bars are hardcoded directly in the rendering calls (e.g., glColor4f(0.0f, 0.0f, 0.0f, 0.5f)). To improve readability and make it easier to tweak the UI theme later, it's better to define these colors as named constexpr constants at the top of the file, alongside the other DEBUG_* constants.

For example:
static constexpr float GRAPH_BG_COLOR[] = {0.0f, 0.0f, 0.0f, 0.5f};
and then use it like glColor4fv(GRAPH_BG_COLOR);.

Comment on lines +496 to +497
swprintf(szLine, L"FPS: %.1f Avg: %.1f Max: %.1f Vsync: %d CPU: %.1f%%",
FPS_AVG, s_avgFps, s_highestFps, IsVSyncEnabled(), CPU_AVG);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of swprintf with fixed-size buffers (e.g., szLine) is unsafe and can lead to buffer overflows. It's recommended to use the safer swprintf_s function throughout this file (in RenderDebugInfo and RenderFpsCounter) to prevent such vulnerabilities. This requires passing the buffer size as an argument.

    swprintf_s(szLine, L"FPS: %.1f  Avg: %.1f  Max: %.1f  Vsync: %d  CPU: %.1f%%",
        FPS_AVG, s_avgFps, s_highestFps, IsVSyncEnabled(), CPU_AVG);

Comment on lines 81 to 122
bool CmuConsoleDebug::CheckCommand(const std::wstring& strCommand)
{
if (strCommand.compare(0, 4, L"$fps") == 0)
if (strCommand.compare(L"$fpscounter on") == 0)
{
SetShowFpsCounter(true);
return true;
}
else if (strCommand.compare(L"$fpscounter off") == 0)
{
SetShowFpsCounter(false);
return true;
}
else if (strCommand.compare(L"$details on") == 0)
{
SetShowDebugInfo(true);
return true;
}
else if (strCommand.compare(L"$details off") == 0)
{
SetShowDebugInfo(false);
return true;
}
else if (strCommand.compare(0, 4, L"$fps") == 0)
{
auto fps_str = strCommand.substr(5);
auto target_fps = std::stof(fps_str);
SetTargetFps(target_fps);
return true;
}

if (strCommand.compare(L"$vsync on") == 0)
else if (strCommand.compare(L"$vsync on") == 0)
{
EnableVSync();
SetTargetFps(-1); // unlimited
ResetFrameStats();
return true;
}

if (strCommand.compare(L"$vsync off") == 0)
else if (strCommand.compare(L"$vsync off") == 0)
{
DisableVSync();
ResetFrameStats();
return true;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current command handling uses a long if-else if chain. This pattern can become difficult to manage and extend as more commands are added. Consider refactoring this into a more scalable approach, such as using a std::map to map command strings to their handler functions.

For example:

// In your class definition
std::map<std::wstring, std::function<void(const std::wstring&)>> m_commandHandlers;

// In constructor, register commands:
m_commandHandlers[L"$fpscounter on"] = [](const auto&){ SetShowFpsCounter(true); };
m_commandHandlers[L"$fps"] = [](const std::wstring& cmd) {
    auto fps_str = cmd.substr(5);
    auto target_fps = std::stof(fps_str);
    SetTargetFps(target_fps);
};
// ... other commands

// In CheckCommand:
for(const auto& pair : m_commandHandlers)
{
    // Use rfind for prefix matching
    if (strCommand.rfind(pair.first, 0) == 0) 
    {
        pair.second(strCommand);
        return true;
    }
}

@sven-n sven-n merged commit d98b7bf into sven-n:main Feb 8, 2026
1 check passed
@Mosch0512 Mosch0512 deleted the fpscounter branch February 9, 2026 12:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants