-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathperf_frame_bench.py
More file actions
122 lines (103 loc) · 3.51 KB
/
perf_frame_bench.py
File metadata and controls
122 lines (103 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
from __future__ import annotations
import argparse
import time
from pathlib import Path
import pygame
import spritePro as s
def _bench(label: str, iterations: int, func) -> None:
started = time.perf_counter()
for _ in range(iterations):
func()
elapsed_ms = (time.perf_counter() - started) * 1000.0 / max(1, iterations)
print(f"{label}: {elapsed_ms:.3f} ms")
def _clear_game(game) -> None:
for sprite in list(game.all_sprites):
sprite.kill()
def _spawn_sprites(asset_path: str, *, count: int, offscreen: bool) -> None:
columns = max(1, int(count**0.5))
for index in range(count):
x = (index % columns) * 40
y = (index // columns) * 40
if offscreen:
x += 5000
y += 5000
s.Sprite(asset_path, size=(32, 32), pos=(x, y), auto_register=True)
def main() -> None:
parser = argparse.ArgumentParser(
description="Benchmark SpritePro frame pipeline on desktop before APK checks."
)
parser.add_argument("--window-width", type=int, default=2400)
parser.add_argument("--window-height", type=int, default=1080)
parser.add_argument("--reference-width", type=int, default=1920)
parser.add_argument("--reference-height", type=int, default=1080)
parser.add_argument("--sprite-count", type=int, default=400)
parser.add_argument("--iterations", type=int, default=30)
args = parser.parse_args()
pygame.init()
screen = s.get_screen(
(args.window_width, args.window_height),
reference_size=(args.reference_width, args.reference_height),
)
ctx = s._context
game = s.get_game()
asset_path = str(
Path(__file__).resolve().parent / "spritePro" / "demoGames" / "Sprites" / "hero.png"
)
print(
f"Window: {args.window_width}x{args.window_height} | "
f"Reference: {args.reference_width}x{args.reference_height} | "
f"Viewport: {ctx._viewport_rect.size} | Sprites: {args.sprite_count}"
)
ctx._present_frame()
_bench(
"present scale only",
args.iterations * 4,
lambda: pygame.transform.scale(ctx.screen, ctx._viewport_rect.size, ctx._present_scale_surface),
)
_bench(
"present scaled blit only",
args.iterations * 4,
lambda: ctx._output_surface.blit(ctx._present_scale_surface, ctx._viewport_rect.topleft),
)
_bench(
"present whole frame blank",
args.iterations * 4,
lambda: ctx._present_frame(),
)
_clear_game(game)
_spawn_sprites(asset_path, count=args.sprite_count, offscreen=False)
game.camera.update(0, 0)
game.camera_zoom = 1.0
_bench(
"sprite update zoom=1 onscreen",
args.iterations,
lambda: game.update(screen, dt=1 / 60, wh_c=ctx.WH_C),
)
_bench(
"present after zoom=1 draw",
args.iterations,
lambda: ctx._present_frame(),
)
game.camera_zoom = 1.25
_bench(
"sprite update zoom=1.25 onscreen",
args.iterations,
lambda: game.update(screen, dt=1 / 60, wh_c=ctx.WH_C),
)
_bench(
"present after zoom=1.25 draw",
args.iterations,
lambda: ctx._present_frame(),
)
_clear_game(game)
_spawn_sprites(asset_path, count=args.sprite_count, offscreen=True)
game.camera.update(0, 0)
game.camera_zoom = 1.25
_bench(
"sprite update zoom=1.25 offscreen",
args.iterations,
lambda: game.update(screen, dt=1 / 60, wh_c=ctx.WH_C),
)
pygame.display.quit()
if __name__ == "__main__":
main()