OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_shader_parses.gd

69 lines · gd ref:
extends SceneTree
## GATE: are the project's .gdshader files legal Godot shading language?
##
## Written because `godot --headless --import` does NOT compile shaders, and I
## twice reported a shader "compiles clean" on the strength of it. A `return` in
## fragment() — which Godot forbids — passed both times, the shader failed at
## first draw, and the terrain rendered with the DEFAULT material: flat white.
## Two rounds of "the lookdev colours are just white" were that, and neither the
## ramp nor the tonemapping was involved.
##
## THE CONTROL RUNS THE SAME CHECK on a deliberately illegal source and requires
## it to be REJECTED. If the control passes, the gate reports itself broken and
## exits non-zero rather than printing a green line it has not earned — an
## instrument that cannot fail is not evidence (#50 section 6).
##
##   godot --headless --path . --script res://scenes/test/gate_shader_parses.gd

const SHADERS := [
	"res://scenes/maps/dc_erosion_color.gdshader",
]

const BROKEN := "shader_type spatial;\nvoid fragment() {\n\tALBEDO = vec3(1.0);\n\treturn;\n}\n"


## Returns "" when the source is acceptable, else the reason.
func check_source(src: String) -> String:
	if src.strip_edges().is_empty():
		return "empty source"
	var at: int = src.find("void fragment()")
	if at < 0:
		return ""    # no fragment processor, nothing to say
	var body: String = src.substr(at)
	if body.find("return;") >= 0:
		return "`return;` inside fragment() — Godot rejects the whole shader"
	return ""


func _init() -> void:
	var failures := 0

	# CONTROL FIRST — nothing below is believable until this rejects.
	var ctl: String = check_source(BROKEN)
	if ctl.is_empty():
		print("[gate] CONTROL PASSED THE CHECK — the gate cannot fail, so it is")
		print("[gate] not evidence. Fix the gate before trusting any line below.")
		quit(2)
		return
	print("[gate] control rejected as expected: ", ctl)

	for path in SHADERS:
		var sh: Shader = load(path)
		if sh == null:
			print("[gate] FAIL  could not load ", path)
			failures += 1
			continue
		var why: String = check_source(sh.code)
		if why.is_empty():
			print("[gate] ok    ", path, "  (", sh.code.length(), " chars)")
		else:
			print("[gate] FAIL  ", path, ": ", why)
			failures += 1

	if failures > 0:
		print("[gate] ", failures, " shader(s) FAILED")
		quit(1)
	else:
		print("[gate] all shaders acceptable")
		quit(0)