Gododin Gododin Documentation

Linked repository source

examples/boid_flock/project/main.gd

This read-only view comes from the file in the Gododin repository. It retains its design, example or evidence context.

Download the original file · Return to the guide

extends Node3D

## Scene orchestration and bounded measurement. Only the selected flock runs.
## Callback timing covers producer+submission; separate monotonic frame-entry
## intervals include scene, renderer and pacing. Raw samples are saved after timing.
## Native 10,000 agents remains the original workload; --mode=native|gd at
## --count=400 is a separate matched-population implementation comparison.
##
## EX-BOID: the scene's controls initialize from the Flock's saved
## FlockSettings Resource (the authoring truth; interactive edits are per-run
## and never write back), and the predator is a visible saved Node3D actor —
## mouse mode moves that node by hand, patrol mode lets its deterministic Godot
## animation move it — whose transform feeds both simulation arms identically.
## Evaluation runs disable the actor entirely; the canonical workload is
## unchanged.

const SIMULATION_SEED := 20260911
const MAX_SPEED := 6.0
const BASELINE_CAP := 500

enum PredatorMode { OFF, MOUSE, PATROL }

var eval_mode := false
var profile_render := false
var start_on_click := false
var eval_started := false
var eval_count := 10000
var eval_frames := 600
var eval_variant := "native"
var _eval_frame := 0
var _eval_usec := 0.0
var _measured_frames := 0
var _failed := false
var _ready_done := false
var _predator_mode: int = PredatorMode.OFF
var _sim_seed := SIMULATION_SEED
var _max_speed := MAX_SPEED
var _mouse_painting := false
var _headless := false
var _finished := false
var _captured := false
var _verify_cases := 0
var _sample_intervals := PackedInt64Array()
var _previous_entry := 0
var _callback_samples := PackedInt64Array()
var unfocused_samples := 0

@onready var _field: Node = %Flock
@onready var _baseline: Node3D = %Baseline
@onready var _predator: Node3D = %Predator
@onready var _camera: Camera3D = %CameraRig.get_node("Camera3D")


const RENDER_PROFILE_WIDTH := 9
var _render_profile_samples := PackedFloat64Array()
var _render_profile_count := 0
var _render_profile_viewport: RID
var _render_profile_active := false
var _render_wall_started := 0
var _render_wall_usec := 0
var _profile_stats_usec := 0
var _profile_stats_calls := 0


func _ready() -> void:
	if not RenderingServer.is_on_render_thread():
		_fail("separate_render_thread_unsupported")
		return
	_baseline.set_process(false)
	%Mode.add_item("Native staged")
	%Mode.add_item("GDScript per instance (≤500)")
	%Mode.item_selected.connect(_on_mode_selected)
	%Count.value_changed.connect(_on_count_slider)
	%UI.get_node("CountApplyTimer").timeout.connect(_apply_count)
	for slider in [%Separation, %Alignment, %Cohesion, %Perception]:
		slider.value_changed.connect(_on_steering_changed)
	%PredatorMode.add_item("Predator: off")
	%PredatorMode.add_item("Predator: mouse")
	%PredatorMode.add_item("Predator: patrol")
	%PredatorMode.item_selected.connect(_on_predator_mode_selected)
	%UI.get_node("StatsTimer").timeout.connect(_on_stats_tick)
	var seen := {}
	for arg in OS.get_cmdline_user_args():
		var key: String = arg.split("=")[0]
		if seen.has(key):
			_fail("duplicate_argument=" + key)
			return
		seen[key] = true
		if arg == "--eval":
			eval_mode = true
		elif arg == "--eval-profile-render":
			profile_render = true
		elif arg == "--eval-start-on-click":
			start_on_click = true
		elif arg.begins_with("--count=") and arg.trim_prefix("--count=").is_valid_int():
			eval_count = int(arg.trim_prefix("--count="))
		elif arg.begins_with("--frames=") and arg.trim_prefix("--frames=").is_valid_int():
			eval_frames = int(arg.trim_prefix("--frames="))
		elif arg.begins_with("--mode="):
			eval_variant = arg.trim_prefix("--mode=")
		else:
			_fail("unknown_or_invalid_argument=" + arg)
			return
	if eval_count < 1 or eval_count > 1000000 or eval_frames < 2 or eval_frames > 100000 or eval_variant not in ["native", "gd"]:
		_fail("bad_arguments")
		return
	if eval_variant == "gd" and eval_count > BASELINE_CAP:
		_fail("gd_count_exceeds_500")
		return
	# EX-BOID: initialize the interactive controls from the saved settings
	# Resource — the authoring truth — before anything consumes them.
	if not eval_mode:
		var settings: Resource = _field.get("settings")
		if settings != null:
			_sim_seed = int(settings.population_seed)
			_max_speed = float(settings.max_speed)
			%Count.value = clampf(float(int(settings.count)), %Count.min_value, %Count.max_value)
			%Separation.value = float(settings.separation)
			%Alignment.value = float(settings.alignment)
			%Cohesion.value = float(settings.cohesion)
			%Perception.value = float(settings.perception)
			%CountValue.text = str(int(%Count.value))
	var count := eval_count if eval_mode else int(%Count.value)
	var setup_error: int = _field.call("setup", count, _sim_seed)
	if setup_error != 0:
		_fail("setup code=%d" % setup_error)
		return
	if profile_render and not eval_mode:
		_fail("render_profile_requires_eval")
		return
	# Mark readiness before the initial apply: assigning the authored settings
	# to the sliders above fires their value_changed signals, and a reopened
	# scene's saved values differ from the scene defaults, so those signals may
	# arrive before setup has configured the field.
	_ready_done = not _failed
	if eval_mode:
		_predator.visible = false
		_start_eval()
	elif _ready_done:
		_apply_params()


func _process(_delta: float) -> void:
	if not _ready_done or _failed or _finished:
		return
	if eval_mode:
		_eval_process()
		return
	var code: int = _field.call("error")
	if code != 0:
		_fail("autonomous_submit=%d" % code)
		return
	if _predator_mode == PredatorMode.PATROL:
		# The Godot animation moves the actor; its transform feeds both arms.
		_feed_predator(true)


func _unhandled_input(event: InputEvent) -> void:
	if not eval_mode and event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE:
		_quit(0)
	if eval_mode or not _ready_done or _failed:
		return
	if _predator_mode != PredatorMode.MOUSE:
		return
	# Mouse mode moves the saved actor over the ground plane; a click sets it,
	# a drag carries it, and the actor's transform feeds both simulation arms.
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		_mouse_painting = event.pressed
		if event.pressed:
			_move_predator_to_mouse()
	elif _mouse_painting and event is InputEventMouseMotion:
		_move_predator_to_mouse()


func _move_predator_to_mouse() -> void:
	var mouse := get_viewport().get_mouse_position()
	var origin := _camera.project_ray_origin(mouse)
	var normal := _camera.project_ray_normal(mouse)
	if absf(normal.y) < 0.0001:
		return
	var t := -origin.y / normal.y
	if t <= 0.0:
		return
	_predator.position = origin + normal * t
	_feed_predator(true)


## The one place the predator reaches the simulations: the saved actor's
## transform feeds the native arm and the GDScript arm with identical values.
func _feed_predator(active: bool) -> void:
	var p := _predator.position
	if _field.call("set_predator", p.x, p.y, p.z, active) != 0:
		_fail("set_predator")
		return
	_baseline.predator = p
	_baseline.predator_active = active
	_predator.visible = active


func _apply_params() -> void:
	# Slider value_changed signals fire while _ready is still assigning the
	# authored settings; before the field is set up there is nothing to apply.
	if not _ready_done or _failed:
		return
	if _field.call("set_params", %Separation.value, %Alignment.value, %Cohesion.value, %Perception.value, _max_speed) != 0:
		_fail("set_params")
		return
	_baseline.separation = %Separation.value
	_baseline.alignment = %Alignment.value
	_baseline.cohesion = %Cohesion.value
	_baseline.perception = %Perception.value
	_baseline.max_speed = _max_speed
	%SeparationValue.text = "%.2f" % %Separation.value
	%AlignmentValue.text = "%.2f" % %Alignment.value
	%CohesionValue.text = "%.2f" % %Cohesion.value
	%PerceptionValue.text = "%.2f" % %Perception.value


func _on_mode_selected(index: int) -> void:
	var native := index == 0
	_field.visible = native
	_field.set_process(native)
	_baseline.visible = not native
	_baseline.set_process(not native)
	%PredatorHint.visible = true
	_apply_count()


func _on_count_slider(value: float) -> void:
	%CountValue.text = "%d pending" % int(value)
	%UI.get_node("CountApplyTimer").start()


func _apply_count() -> void:
	if eval_mode or _failed:
		return
	var native: bool = %Mode.selected == 0
	var requested := int(%Count.value)
	var actual := requested if native else mini(requested, BASELINE_CAP)
	if _field.call("set_count", actual) != 0:
		_fail("set_count")
		return
	if not native and not _baseline.set_count(actual, _field.call("state_bytes")):
		_fail("baseline_setup")
		return
	%CountValue.text = str(actual) if actual == requested else "%d (cap)" % actual


func _on_steering_changed(_value: float) -> void:
	_apply_params()


func _on_predator_mode_selected(index: int) -> void:
	_predator_mode = index
	if not eval_mode and _ready_done and not _failed:
		if index == PredatorMode.OFF:
			_feed_predator(false)
			%PredatorHint.text = "predator off — the flock flies free"
		elif index == PredatorMode.MOUSE:
			# The actor appears at its saved (or last placed) position; the
			# next click or drag over the ground carries it.
			_feed_predator(true)
			%PredatorHint.text = "mouse: click or drag over the ground"
		else:
			%Predator.seek_patrol(0.0)
			_feed_predator(true)
			%PredatorHint.text = "patrol: the saved trajectory flies itself"


func _on_stats_tick() -> void:
	if not profile_render:
		_on_stats_tick_display()
		return
	var entered := Time.get_ticks_usec()
	_on_stats_tick_display()
	_profile_stats_usec += Time.get_ticks_usec() - entered
	_profile_stats_calls += 1


func _on_stats_tick_display() -> void:
	if eval_mode and start_on_click and not eval_started:
		%Stats.text = "Click the scene to start the focused evaluation"
		return
	if not _ready_done:
		return
	var native: bool = eval_variant == "native" if eval_mode else %Mode.selected == 0
	var agents: int = _field.call("count") if native else _baseline.count
	var neighbors: int = _field.call("max_neighbors") if native else _baseline.max_neighbors
	%Stats.text = "FPS %d | agents %d | max neighbors/agent %d" % [Engine.get_frames_per_second(), agents, neighbors]


func _start_eval() -> void:
	_start_render_profile()
	Engine.max_fps = 0
	if DisplayServer.get_name() != "headless":
		DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED, get_window().get_window_id())
	if not _eval_pacing_ok():
		return
	_sample_intervals.resize(eval_frames - int(eval_frames / 2))
	_callback_samples.resize(_sample_intervals.size())
	_headless = DisplayServer.get_name() == "headless"
	_field.set_process(false)
	_baseline.set_process(false)
	if _field.call("set_driver_driven", true) != 0:
		_fail("driver_handoff")
		return
	for control in [%Mode, %PredatorMode]:
		control.disabled = true
	for slider in [%Count, %Separation, %Alignment, %Cohesion, %Perception]:
		slider.editable = false
	%CameraRig.set_process_unhandled_input(false)
	# Independent runtime implementation check, outside every measured window.
	# Reset GD from exact old native state before each single step, so this
	# tolerance tests one-step rules rather than long chaotic divergence.
	if _field.call("set_count", 64) != 0:
		_fail("comparison_setup")
		return
	if not _baseline.set_count(64, _field.call("state_bytes")):
		_fail("comparison_snapshot")
		return
	if _field.call("verify") != -3:
		_fail("verify_before_submit")
		return
	for bad in [NAN, INF, -1.0, 1.0e300]:
		if _field.call("set_params", bad, 1.0, 0.9, 3.5, MAX_SPEED) == 0:
			_fail("invalid_params_accepted")
			return
	if _field.call("set_predator", NAN, 0.0, 0.0, true) == 0:
		_fail("invalid_predator_accepted")
		return
	for radius in [0.5, 3.5, 8.0]:
		if _field.call("set_params", 1.5, 1.0, 0.9, radius, MAX_SPEED) != 0 or _field.call("set_predator", 0.0, 0.0, 0.0, true) != 0:
			_fail("comparison_params")
			return
		_baseline.perception = radius
		_baseline.predator_active = true
		for step in 4:
			if not _baseline.load_state(_field.call("state_bytes")):
				_fail("comparison_load")
				return
			_baseline._step()
			if _field.call("submit_frame") != 0 or _field.call("verify_state", _baseline.state_values(), 0.0001) != 0:
				_fail("comparison_state radius=%s step=%s" % [radius, step])
				return
			_verify_cases += 1
	if not _headless:
		# Reading transforms must not make a later retained write detach.
		for probe in 3:
			if _field.call("verify") != 0 or _field.call("submit_frame") != 0:
				_fail("retained_readback_reuse=%d" % probe)
				return
		print("GODODIN_BOID_FLOCK_RETAINED_REUSE_PASS cycles=3")
	if _field.call("set_params", 1.5, 1.0, 0.9, 3.5, MAX_SPEED) != 0 or _field.call("set_predator", 0.0, 0.0, 0.0, false) != 0 or _field.call("set_count", eval_count) != 0:
		_fail("measurement_reset")
		return
	_baseline.perception = 3.5
	_baseline.predator_active = false
	if eval_variant == "gd" and not _baseline.set_count(eval_count, _field.call("state_bytes")):
		_fail("gd_measurement_setup")
		return
	_field.visible = eval_variant == "native"
	_baseline.visible = eval_variant == "gd"
	%Mode.select(0 if eval_variant == "native" else 1)
	%CountValue.text = str(eval_count)
	print("GODODIN_BOID_FLOCK_COMPARISON_PASS one_step_cases=%d count=64 tolerance=0.0001" % _verify_cases)


func _eval_process() -> void:
	if start_on_click and not eval_started:
		return
	# Windowed campaigns start only after the operator brings the window forward.
	# This leaves the seed, warm-up steps and measured workload unchanged.
	if _eval_frame == 0 and DisplayServer.get_name() != "headless" and not get_window().has_focus():
		return
	if _field.is_processing() or _baseline.is_processing():
		_fail("unowned_background_processing")
		return
	var entry := Time.get_ticks_usec()
	if _previous_entry != 0 and _eval_frame >= eval_frames / 2:
		_sample_intervals[_measured_frames] = entry - _previous_entry
		if not get_window().has_focus():
			unfocused_samples += 1
	_previous_entry = entry
	if profile_render:
		if _eval_frame >= eval_frames / 2:
			_sample_render_profile(_measured_frames)
		_profile_stats_usec = 0
		_profile_stats_calls = 0
	var t0 := Time.get_ticks_usec()
	var code: int = 0
	if eval_variant == "native":
		code = _field.call("submit_frame")
	else:
		_baseline._step()
	var elapsed := Time.get_ticks_usec() - t0
	if code != 0:
		_fail("submit=%d" % code)
		return
	_eval_frame += 1
	if _eval_frame > eval_frames / 2:
		_callback_samples[_measured_frames] = elapsed
		_eval_usec += elapsed
		_measured_frames += 1
	if _eval_frame < eval_frames:
		return
	_finished = true
	_finish_eval()


func _finish_eval() -> void:
	_stop_render_profile()
	if not _eval_pacing_ok():
		return
	var verify_note := "skipped-headless-dummy-renderer" if _headless else "ok"
	if not _headless:
		if eval_variant == "native" and _field.call("verify") != 0:
			_fail("native_readback")
			return
		if eval_variant == "gd" and not _baseline.verify_readback():
			_fail("gd_readback")
			return
		await RenderingServer.frame_post_draw
		var image := get_viewport().get_texture().get_image()
		if image == null or image.save_png("user://boids.png") != OK:
			_fail("screenshot")
			return
		_captured = true
	if _measured_frames < 1 or _verify_cases != 12:
		_fail("missing_measurements")
		return
	if not _save_profile_samples() or not _save_render_profile():
		return
	var frame_avg := 0.0
	for interval in _sample_intervals:
		frame_avg += interval
	frame_avg /= maxi(1, _sample_intervals.size())
	_sample_intervals.sort()
	var p95: int = _sample_intervals[mini(_sample_intervals.size()-1, ceili(_sample_intervals.size()*0.95)-1)] if not _sample_intervals.is_empty() else 0
	print("GODODIN_BOID_FLOCK_PASS mode=%s count=%d frames=%d measured_frames=%d avg_usec=%.3f frame_avg_usec=%.3f frame_p95_usec=%d verify=%s" % [eval_variant, eval_count, _eval_frame, _measured_frames, _eval_usec / _measured_frames, frame_avg, p95, verify_note])
	if _field.call("shutdown") != 0 or _field.call("staging_live") or _field.call("count") != 0:
		_fail("shutdown")
		return
	print("GODODIN_BOID_FLOCK_TEARDOWN_PASS frames=%d" % _eval_frame)
	_quit(0)


func _quit(code: int) -> void:
	if is_instance_valid(_field) and _field.call("shutdown") != 0:
		print("GODODIN_BOID_FLOCK_FAIL shutdown")
		code = 1
	get_tree().quit(code)


func _exit_tree() -> void:
	_stop_render_profile()
	# Normal window close/scene removal uses the same explicit owner cleanup.
	if is_instance_valid(_field) and _field.call("shutdown") != 0:
		push_error("GODODIN_BOID_FLOCK_FAIL exit_shutdown")


func _fail(reason: String) -> void:
	if _failed:
		return
	_failed = true
	print("GODODIN_BOID_FLOCK_FAIL ", reason)
	_quit(1)


# Arrival N's interval covers entry N-1 to entry N; its callback is step N.
# Buffers are allocated before simulation; file I/O occurs after measurement.
func _save_profile_samples() -> bool:
	var file := FileAccess.open("user://boid-profile.csv", FileAccess.WRITE)
	if file == null:
		_fail("profile_samples_open")
		return false
	file.store_line("arrival_frame,callback_usec,previous_frame_interval_usec")
	for index in range(_measured_frames):
		file.store_line("%d,%d,%d" % [int(eval_frames / 2) + 1 + index, _callback_samples[index], _sample_intervals[index]])
	file.flush()
	if file.get_error() != OK:
		_fail("profile_samples_write")
		return false
	print("GODODIN_BOID_FLOCK_PROFILE_FOCUS samples=%d unfocused=%d headless=%s" % [_measured_frames, unfocused_samples, DisplayServer.get_name() == "headless"])
	if DisplayServer.get_name() != "headless" and unfocused_samples != 0:
		_fail("profile_window_not_focused")
		return false
	print("GODODIN_BOID_FLOCK_PROFILE_SAMPLES count=%d path=user://boid-profile.csv" % _measured_frames)
	return true


# The windowed runner uses an explicit input event to establish foreground
# readiness before any simulation steps. Ordinary play and headless runs bypass it.
func _input(event: InputEvent) -> void:
	if eval_mode and start_on_click and not eval_started and event is InputEventMouseButton and event.pressed and get_window().has_focus():
		eval_started = true


func _eval_pacing_ok() -> bool:
	var headless := DisplayServer.get_name() == "headless"
	if Engine.max_fps != 0 or (not headless and DisplayServer.window_get_vsync_mode(get_window().get_window_id()) != DisplayServer.VSYNC_DISABLED):
		_fail("eval_pacing_changed")
		return false
	print("GODODIN_BOID_FLOCK_EVAL_PACING vsync=%s max_fps=%d" % ["not_applicable" if headless else "disabled", Engine.max_fps])
	return true


# Opt-in instrumentation, outside the native callback timer. Dev5's GL query
# results use a three-frame ring (drivers/gles3/storage/utilities.cpp:351).
# These are buffered viewport observations, not timings for arrival_frame's
# callback. Their distributions may be compared; they cannot be added rowwise.
# Viewport spans exclude screen blit/swap (renderer_viewport.cpp:954). Engine
# timer queries and these reads add overhead included in whole-frame intervals.
func _start_render_profile() -> void:
	if not profile_render:
		return
	_render_profile_samples.resize((eval_frames - int(eval_frames / 2)) * RENDER_PROFILE_WIDTH)
	_render_profile_viewport = get_viewport().get_viewport_rid()
	if DisplayServer.get_name() != "headless":
		RenderingServer.viewport_set_measure_render_time(_render_profile_viewport, true)
		_render_profile_active = true
		RenderingServer.frame_pre_draw.connect(_render_profile_pre_draw)
		RenderingServer.frame_post_draw.connect(_render_profile_post_draw)


func _sample_render_profile(index: int) -> void:
	var offset := index * RENDER_PROFILE_WIDTH
	if _render_profile_active:
		_render_profile_samples[offset] = RenderingServer.viewport_get_measured_render_time_cpu(_render_profile_viewport)
		_render_profile_samples[offset + 1] = RenderingServer.viewport_get_measured_render_time_gpu(_render_profile_viewport)
		_render_profile_samples[offset + 2] = RenderingServer.get_frame_setup_time_cpu()
		_render_profile_samples[offset + 3] = RenderingServer.viewport_get_render_info(_render_profile_viewport, RenderingServer.VIEWPORT_RENDER_INFO_TYPE_VISIBLE, RenderingServer.VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME)
		_render_profile_samples[offset + 4] = RenderingServer.viewport_get_render_info(_render_profile_viewport, RenderingServer.VIEWPORT_RENDER_INFO_TYPE_SHADOW, RenderingServer.VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME)
		_render_profile_samples[offset + 5] = RenderingServer.viewport_get_render_info(_render_profile_viewport, RenderingServer.VIEWPORT_RENDER_INFO_TYPE_CANVAS, RenderingServer.VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME)
	# Stats callbacks occur between frame entries; this cost does correspond to
	# arrival_frame's previous_frame_interval_usec, unlike buffered GL queries.
	_render_profile_samples[offset + 6] = _profile_stats_usec
	_render_profile_samples[offset + 7] = _profile_stats_calls
	_render_profile_samples[offset + 8] = _render_wall_usec
	_render_wall_usec = 0
	_render_profile_count += 1


# On the synchronous render path this wall bracket includes viewport work,
# blit/swap waiting, and earlier frame-drawn callbacks. It is not GPU execution
# time. Signal callbacks add overhead. The latest completed draw belongs to
# the previous frame interval; buffered viewport timestamps have a different lag.
func _render_profile_pre_draw() -> void:
	_render_wall_started = Time.get_ticks_usec()


func _render_profile_post_draw() -> void:
	_render_wall_usec = Time.get_ticks_usec() - _render_wall_started


func _stop_render_profile() -> void:
	if _render_profile_active:
		RenderingServer.viewport_set_measure_render_time(_render_profile_viewport, false)
		_render_profile_active = false
		RenderingServer.frame_pre_draw.disconnect(_render_profile_pre_draw)
		RenderingServer.frame_post_draw.disconnect(_render_profile_post_draw)


func _save_render_profile() -> bool:
	if not profile_render:
		return true
	if _render_profile_count != _measured_frames or _render_profile_count == 0:
		_fail("render_profile_sample_count")
		return false
	var file := FileAccess.open("user://boid-render-profile.csv", FileAccess.WRITE)
	if file == null:
		_fail("render_profile_open")
		return false
	file.store_line("arrival_frame,viewport_cpu_ms,viewport_gpu_ms,setup_cpu_ms,visible_draw_calls,shadow_draw_calls,canvas_draw_calls,stats_usec,stats_calls,render_wall_usec")
	var totals := PackedFloat64Array()
	totals.resize(RENDER_PROFILE_WIDTH)
	var cpu_positive := 0
	var gpu_positive := 0
	var wall_positive := 0
	for index in range(_render_profile_count):
		var offset := index * RENDER_PROFILE_WIDTH
		for column in range(RENDER_PROFILE_WIDTH):
			var value := _render_profile_samples[offset + column]
			if not is_finite(value) or value < 0.0:
				_fail("invalid_render_profile_sample")
				return false
			totals[column] += value
		if _render_profile_samples[offset] > 0.0:
			cpu_positive += 1
		if _render_profile_samples[offset + 1] > 0.0:
			gpu_positive += 1
		if _render_profile_samples[offset + 8] > 0.0:
			wall_positive += 1
		file.store_line("%d,%.6f,%.6f,%.6f,%.0f,%.0f,%.0f,%.0f,%.0f,%.0f" % [int(eval_frames / 2) + 1 + index, _render_profile_samples[offset], _render_profile_samples[offset + 1], _render_profile_samples[offset + 2], _render_profile_samples[offset + 3], _render_profile_samples[offset + 4], _render_profile_samples[offset + 5], _render_profile_samples[offset + 6], _render_profile_samples[offset + 7], _render_profile_samples[offset + 8]])
	file.flush()
	if file.get_error() != OK:
		_fail("render_profile_write")
		return false
	var headless := DisplayServer.get_name() == "headless"
	# Preserve zeros in the CSV. An all-zero series is unavailable/unproven,
	# never proof of free rendering; headless has no rendering observation.
	var cpu_status := "unavailable" if headless or cpu_positive == 0 else "observed"
	var gpu_status := "unavailable" if headless or gpu_positive == 0 else "observed"
	var wall_status := "unavailable" if headless or wall_positive == 0 else "observed"
	print("GODODIN_BOID_FLOCK_RENDER_PROFILE samples=%d cpu_status=%s gpu_status=%s cpu_positive=%d gpu_positive=%d viewport_cpu_ms=%.6f viewport_gpu_ms=%.6f setup_cpu_ms=%.6f stats_avg_usec=%.6f stats_calls=%d render_wall_usec=%.6f wall_status=%s wall_positive=%d render_wall_scope=pre_to_post_draw render_wall_swap_included=true lag=renderer_buffered viewport_swap_included=false overhead=included headless=%s path=user://boid-render-profile.csv" % [_render_profile_count, cpu_status, gpu_status, cpu_positive, gpu_positive, totals[0] / _render_profile_count, totals[1] / _render_profile_count, totals[2] / _render_profile_count, totals[6] / _render_profile_count, int(totals[7]), totals[8] / _render_profile_count, wall_status, wall_positive, headless])
	return true