OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_hitch_log_gpu.gd

64 lines · gd ref:
extends Node
## GATE: the hitch logger's 10 s summaries carry dc-terrain's GPU-thread submit
## timing (DCTerrain.get_frame_stats gpu_submit_* -> "[HITCH] summary gpu"), so an
## ashatron log can tie a draw-phase hitch to the GPU job behind it (hyper-games #88).
##
##   "$G" --path . --rendering-driver vulkan --resolution 1280x720 res://scenes/test/gate_hitch_log_gpu.tscn
##
## Loads the mountain (streaming = GPU jobs) with a HitchLog on a scratch file and
## passes when a summary record has gpu_submits > 0, gpu_max_ms > 0 and a worst-job
## line naming its kind. ⛔ NOT HEADLESS (the mountain's field is GPU-only).

const HitchLog := preload("res://scenes/game/hitch_log.gd")
const MAP := "res://scenes/maps/map_mountain.tscn"
const MAP_ID := "map_mountain"
const LOG := "user://gate_hitch_log_gpu.jsonl"
const WAIT_S := 25.0


func _ready() -> void:
	_run.call_deferred()


func _run() -> void:
	if DisplayServer.get_name() == "headless":
		print("RESULT: SKIP (needs a display)")
		get_tree().quit(2)
		return
	var hl := HitchLog.new()
	hl.set("log_path", LOG)
	get_tree().root.add_child(hl)
	GameState.enter_map(MAP_ID)
	var cam := Camera3D.new()
	cam.far = 20000.0
	add_child(cam)
	cam.current = true
	var map := (load(MAP) as PackedScene).instantiate()
	add_child(map)
	var spawn := Vector3(0, 250, 0)
	var sp := get_tree().get_nodes_in_group("spawn_points")
	if not sp.is_empty():
		spawn = (sp[0] as Node3D).global_position
	cam.global_position = spawn + Vector3(0, 2, 0)
	cam.look_at(spawn + Vector3(20, 0, 0))
	var t0 := Time.get_ticks_msec()
	while (Time.get_ticks_msec() - t0) / 1000.0 < WAIT_S:
		await get_tree().process_frame

	var best := {}
	var f := FileAccess.open(LOG, FileAccess.READ)
	while f != null and not f.eof_reached():
		var rec: Variant = JSON.parse_string(f.get_line())
		if rec is Dictionary and rec.get("type", "") == "summary" and int(rec.get("gpu_submits", 0)) > 0:
			if best.is_empty() or float(rec["gpu_max_ms"]) > float(best["gpu_max_ms"]):
				best = rec
	var worst := str(best.get("gpu_worst", ""))
	var kind_ok := false
	for k in ["stream ", "edit-group ", "solo ", "brick "]:
		kind_ok = kind_ok or worst.begins_with(k)
	var ok := not best.is_empty() and float(best["gpu_max_ms"]) > 0.0 and kind_ok
	print("[GATE-HITCH-GPU] %s: submits %d, max %.1f ms, worst '%s'" % [
			"PASS" if ok else "FAIL", int(best.get("gpu_submits", 0)), float(best.get("gpu_max_ms", 0.0)), worst])
	print("RESULT: %s" % ("PASS" if ok else "FAIL"))
	get_tree().quit(0 if ok else 1)