frame pacing fix

This commit is contained in:
Dmitry Sergeev
2026-09-02 00:39:30 +03:00
parent da5ff8ea4a
commit b8cb750fb4
5 changed files with 118 additions and 1 deletions
+24
View File
@@ -0,0 +1,24 @@
package main
import "time"
const guiFrameInterval = time.Second / 60
// videoPollInterval bounds GUI latency when no video producer is waiting.
// It is not a video-rate cap: Next returns immediately whenever a frame
// arrives, including for sources faster than this interval.
const videoPollInterval = 8 * time.Millisecond
func remainingFrameTime(start, now time.Time, interval time.Duration) time.Duration {
remaining := interval - now.Sub(start)
if remaining < 0 {
return 0
}
return remaining
}
func paceFrame(start time.Time) {
if remaining := remainingFrameTime(start, time.Now(), guiFrameInterval); remaining > 0 {
time.Sleep(remaining)
}
}
+29
View File
@@ -0,0 +1,29 @@
package main
import (
"testing"
"time"
)
func TestRemainingFrameTime(t *testing.T) {
start := time.Date(2026, time.September, 2, 0, 0, 0, 0, time.UTC)
interval := 16 * time.Millisecond
tests := []struct {
name string
elapsed time.Duration
want time.Duration
}{
{name: "no work", want: interval},
{name: "partial budget", elapsed: 5 * time.Millisecond, want: 11 * time.Millisecond},
{name: "exact budget", elapsed: interval},
{name: "over budget", elapsed: 20 * time.Millisecond},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got := remainingFrameTime(start, start.Add(test.elapsed), interval)
if got != test.want {
t.Fatalf("remainingFrameTime() = %v, want %v", got, test.want)
}
})
}
}
+3 -1
View File
@@ -532,6 +532,7 @@ func main() {
if err := r.RecreateSwapchain(); err != nil {
if errors.Is(err, renderer.ErrMinimized) {
resized = true
paceFrame(frameStart)
continue
}
panic(err)
@@ -543,7 +544,7 @@ func main() {
var shownSource playback.FeedConfig
hasFrame := false
frameCtx, frameCancel := context.WithTimeout(ctx, 100*time.Millisecond)
frameCtx, frameCancel := context.WithTimeout(ctx, videoPollInterval)
pendingFrame, frameErr := videoBridge.Next(frameCtx)
frameCancel()
@@ -1094,6 +1095,7 @@ func main() {
if rerr := r.RecreateSwapchain(); rerr != nil {
if errors.Is(rerr, renderer.ErrMinimized) {
resized = true
paceFrame(frameStart)
continue
}
panic(rerr)