frame pacing fix
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user