diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
index 8fa2790565..b24a94db66 100644
--- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
+++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
@@ -35,6 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
         private long _1msTicks;
 
         private int _swapInterval;
+        private int _swapIntervalDelay;
 
         private readonly object Lock = new object();
 
@@ -91,7 +92,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
             }
             else
             {
-                _ticksPerFrame = Stopwatch.Frequency / (TargetFps / _swapInterval);
+                _ticksPerFrame = Stopwatch.Frequency / TargetFps;
             }
         }
 
@@ -322,7 +323,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
 
                     if (_ticks >= _ticksPerFrame)
                     {
-                        Compose();
+                        if (_swapIntervalDelay-- == 0)
+                        {
+                            Compose();
+
+                            // When a frame is presented, delay the next one by its swap interval value.
+                            _swapIntervalDelay = Math.Max(0, _swapInterval - 1);
+                        }
 
                         _device.System?.SignalVsync();