Skip to content

Commit

Permalink
added code to Set/Get FPS Limit without the use of VSync
Browse files Browse the repository at this point in the history
also changed following defaults

VSync by default is now set to false.
FPSLimit by default is set to 60 FPS.

See SimpleExample to see how to get/set FPS.
  • Loading branch information
zaafar committed Jan 5, 2025
1 parent 2743223 commit bfcb06e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 5 deletions.
57 changes: 53 additions & 4 deletions ClickableTransparentOverlay/Overlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public abstract class Overlay : IDisposable
private Thread renderThread;
private volatile CancellationTokenSource cancellationTokenSource;
private volatile bool overlayIsReady;
private int fpslimit;

private Dictionary<string, (IntPtr Handle, uint Width, uint Height)> loadedTexturesPtrs;

Expand Down Expand Up @@ -150,7 +151,8 @@ public Overlay(string windowTitle, bool DPIAware, int windowWidth, int windowHei
{
this.initialWindowWidth = windowWidth;
this.initialWindowHeight = windowHeight;
this.VSync = true;
this.VSync = false;
this.FPSLimit = 60;
this._disposedValue = false;
this.overlayIsReady = false;
this.title = windowTitle;
Expand Down Expand Up @@ -311,9 +313,38 @@ public unsafe bool ReplaceFont(FontHelper.FontLoadDelegate fontLoadDelegate)

/// <summary>
/// Enable or disable the vsync on the overlay.
/// You can either use the <see cref="FPSLimit"/> or <see cref="VSync"/>.
/// VSync will be given the preference if both are set.
/// </summary>
public bool VSync;

/// <summary>
/// Gets or sets the FPS Limits of the overlay.
/// You can either use the <see cref="FPSLimit"/> or <see cref="VSync"/>.
/// VSync will be given the preference if both are set.
/// </summary>
public int FPSLimit
{
get => this.fpslimit;
set
{
if (value == 0)
{
this.fpslimit = value;
_ = Winmm.MM_EndPeriod(1);
}
else if (value > 0)
{
this.fpslimit = value;
_ = Winmm.MM_BeginPeriod(1);
}
else
{
// ignore negative values.
}
}
}

/// <summary>
/// Gets or sets the position of the overlay window.
/// </summary>
Expand Down Expand Up @@ -444,6 +475,11 @@ protected virtual void Dispose(bool disposing)

if (disposing)
{
if (this.FPSLimit > 0)
{
Winmm.MM_EndPeriod(1);
}

this.renderThread?.Join();
foreach(var key in this.loadedTexturesPtrs.Keys.ToArray())
{
Expand Down Expand Up @@ -491,22 +527,35 @@ protected virtual Task PostInitialized()
private void RunInfiniteLoop(CancellationToken token)
{
var stopwatch = Stopwatch.StartNew();
float deltaTime = 0f;
var currentTimeSec = 0f;
var clearColor = new Color4(0.0f);
var delayMs = 0f;
var sleepTimeMs = 0;
while (!token.IsCancellationRequested)
{
deltaTime = stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
currentTimeSec = stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
stopwatch.Restart();
this.window.PumpEvents();
Utils.SetOverlayClickable(this.window.Handle, this.inputhandler.Update());
this.renderer.Update(deltaTime, () => { Render(); });
this.renderer.Update(currentTimeSec, () => { Render(); });
this.deviceContext.OMSetRenderTargets(renderView);
this.deviceContext.ClearRenderTargetView(renderView, clearColor);
this.renderer.Render();
if (VSync)
{
this.swapChain.Present(1, PresentFlags.None); // Present with vsync
}
else if (this.FPSLimit > 0)
{
this.swapChain.Present(0, PresentFlags.None);
delayMs = 1000f / this.FPSLimit;
currentTimeSec = stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
sleepTimeMs = (int)(delayMs - (currentTimeSec * 1000));
if (sleepTimeMs > 0)
{
Thread.Sleep(sleepTimeMs);
}
}
else
{
this.swapChain.Present(0, PresentFlags.None); // Present without vsync
Expand Down
16 changes: 16 additions & 0 deletions ClickableTransparentOverlay/Win32/Winmm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace ClickableTransparentOverlay.Win32
{
using System;
using System.Runtime.InteropServices;

internal static class Winmm
{
public const string LibraryName = "winmm.dll";

[DllImport(LibraryName, EntryPoint = "timeBeginPeriod")]
public static extern uint MM_BeginPeriod(uint uMilliseconds);

[DllImport(LibraryName, EntryPoint = "timeEndPeriod")]
public static extern uint MM_EndPeriod(uint uMilliseconds);
}
}
14 changes: 13 additions & 1 deletion Examples/SimpleExample/SampleOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@
internal class SampleOverlay : Overlay
{
private bool wantKeepDemoWindow = true;
private int FPSHelper;

public SampleOverlay() : base(3840, 2160)
{
this.FPSHelper = this.FPSLimit;
}

protected override Task PostInitialized()
{
this.VSync = false;
return Task.CompletedTask;
}

protected override void Render()
{
ImGui.ShowDemoWindow(ref wantKeepDemoWindow);

if (ImGui.Begin("FPS Changer"))
{
if (ImGui.InputInt("Set FPS", ref FPSHelper))
{
this.FPSLimit = this.FPSHelper;
}

ImGui.End();
}

if (!this.wantKeepDemoWindow)
{
this.Close();
Expand Down

0 comments on commit bfcb06e

Please sign in to comment.