mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
04691aaa48
Lands the non-networked Phase 0 tasks from multiplayer-todo.md (ship/camera/ arena refactors, sim constants, background FPS handling) plus a first pass at exposing graphics/performance settings (presets, resolution scaling, vsync, FPS cap, perf overlay) and a GPU profiling harness for the real-hardware follow-up in task 0.15b.
63 lines
2.3 KiB
GDScript
63 lines
2.3 KiB
GDScript
extends CanvasLayer
|
|
|
|
# Autoload: toggleable frame-time/bottleneck overlay (F3 by default — see
|
|
# toggle_perf_overlay in project.godot's [input]). Read-only against
|
|
# Performance monitors; never touches rendering or gameplay state. Exists so
|
|
# 0.17/0.17b's graphics presets and resolution scaling are self-diagnosing —
|
|
# TIME_PROCESS vs total frame time tells the player whether they're CPU- or
|
|
# GPU-bound. See multiplayer-todo.md task 0.20.
|
|
|
|
# ~2s of history at 60 fps; enough to make p50/p99 meaningful without the
|
|
# history itself being a rate-dependent quantity.
|
|
const HISTORY_SIZE := 120
|
|
|
|
var _label: Label
|
|
var _frame_times_ms: PackedFloat32Array = PackedFloat32Array()
|
|
var _history_index := 0
|
|
var _history_filled := 0
|
|
|
|
|
|
func _ready() -> void:
|
|
# A headless server never renders and has no input to toggle this with.
|
|
if DisplayServer.get_name() == "headless":
|
|
set_process(false)
|
|
return
|
|
layer = 100
|
|
_label = Label.new()
|
|
_label.add_theme_font_size_override("font_size", 14)
|
|
_label.add_theme_color_override("font_color", Color(0.4, 1.0, 0.5))
|
|
_label.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.85))
|
|
_label.add_theme_constant_override("shadow_offset_x", 1)
|
|
_label.add_theme_constant_override("shadow_offset_y", 1)
|
|
_label.position = Vector2(12, 12)
|
|
_label.visible = false
|
|
add_child(_label)
|
|
_frame_times_ms.resize(HISTORY_SIZE)
|
|
_frame_times_ms.fill(0.0)
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event.is_action_pressed("toggle_perf_overlay") and _label:
|
|
_label.visible = not _label.visible
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
if not _label or not _label.visible:
|
|
return
|
|
var frame_ms := Performance.get_monitor(Performance.TIME_PROCESS) * 1000.0
|
|
var physics_ms := Performance.get_monitor(Performance.TIME_PHYSICS_PROCESS) * 1000.0
|
|
_frame_times_ms[_history_index] = frame_ms
|
|
_history_index = (_history_index + 1) % HISTORY_SIZE
|
|
_history_filled = mini(_history_filled + 1, HISTORY_SIZE)
|
|
|
|
var sorted := _frame_times_ms.slice(0, _history_filled)
|
|
sorted.sort()
|
|
var p50 := sorted[sorted.size() / 2]
|
|
var p99 := sorted[int(sorted.size() * 0.99)]
|
|
|
|
_label.text = "FPS %d (p50 %.2fms p99 %.2fms)\nprocess %.2fms physics %.2fms\ndraw calls %d" % [
|
|
Performance.get_monitor(Performance.TIME_FPS),
|
|
p50, p99, frame_ms, physics_ms,
|
|
Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME),
|
|
]
|