[CmdletBinding()] param( [string]$GodotPath, [string]$Output = "user://render_baseline", [string]$CacheState = "existing", [double]$WaitSeconds = 8.0, [double]$MeasureSeconds = 3.0, [string]$ReferenceCheckpointDirectory, [string]$VisualComparisonReport = "user://render_baseline/visual_comparison.json", [int]$VisualComparisonWidth = 2560, [int]$VisualComparisonHeight = 1440, [switch]$DryRun ) $ErrorActionPreference = "Stop" $repoRoot = Split-Path -Parent $PSScriptRoot if (-not $GodotPath) { $command = Get-Command godot -ErrorAction SilentlyContinue if ($command) { $GodotPath = $command.Source } else { $GodotPath = Join-Path $env:TEMP "godot-4.6.1-openwc\Godot_v4.6.1-stable_win64.exe" } } if (-not (Test-Path -LiteralPath $GodotPath)) { throw "Godot executable not found: $GodotPath" } $revision = (& git -C $repoRoot rev-parse --short HEAD).Trim() if (-not $revision) { $revision = "worktree" } function Invoke-GodotStep { param([string]$Name, [string[]]$Arguments) Write-Host "[$Name] $GodotPath $($Arguments -join ' ')" $process = Start-Process -FilePath $GodotPath -ArgumentList $Arguments -NoNewWindow -Wait -PassThru if ($process.ExitCode -ne 0) { throw "$Name failed with exit code $($process.ExitCode)" } } function Invoke-GodotComparisonStep { param([string]$Name, [string[]]$Arguments) Write-Host "[$Name] $GodotPath $($Arguments -join ' ')" $process = Start-Process -FilePath $GodotPath -ArgumentList $Arguments -NoNewWindow -Wait -PassThru if ($process.ExitCode -notin @(0, 1)) { throw "$Name failed with exit code $($process.ExitCode)" } } Push-Location $repoRoot try { Invoke-GodotStep "project-load" @("--headless", "--path", ".", "--quit") Invoke-GodotStep "render-materials" @("--headless", "--path", ".", "--script", "res://src/tools/verify_render_materials.gd") Invoke-GodotStep "m2-unique-dedupe" @("--headless", "--path", ".", "--script", "res://src/tools/verify_m2_unique_dedupe.gd") Invoke-GodotStep "runtime-cache-shutdown" @("--headless", "--path", ".", "--script", "res://src/tools/verify_render_runtime_cache_shutdown.gd") Invoke-GodotStep "baseline-manifest" @("--headless", "--path", ".", "--script", "res://src/tools/verify_render_baseline_manifest.gd") Invoke-GodotStep "coordinate-calibration" @("--headless", "--path", ".", "--script", "res://src/tools/verify_render_coordinate_calibration.gd") Invoke-GodotStep "coordinate-boundaries" @("--headless", "--path", ".", "--script", "res://src/tools/verify_coordinate_conversion_boundaries.gd") $captureArgs = @( "--path", ".", "--script", "res://src/tools/capture_render_checkpoints.gd", "--", "--output", $Output, "--cache-state", $CacheState, "--revision", $revision, "--wait", $WaitSeconds.ToString([Globalization.CultureInfo]::InvariantCulture), "--measure", $MeasureSeconds.ToString([Globalization.CultureInfo]::InvariantCulture) ) if ($DryRun) { $captureArgs = @("--headless") + $captureArgs + @("--dry-run") } Invoke-GodotStep "capture" $captureArgs if ($ReferenceCheckpointDirectory) { if ($DryRun) { throw "Reference checkpoint comparison requires PNG capture; remove -DryRun" } $visualCandidateOutput = "$Output/visual_comparison_candidates" $visualCaptureArgs = @( "--path", ".", "--script", "res://src/tools/capture_render_checkpoints.gd", "--", "--output", $visualCandidateOutput, "--cache-state", $CacheState, "--revision", $revision, "--wait", $WaitSeconds.ToString([Globalization.CultureInfo]::InvariantCulture), "--measure", $MeasureSeconds.ToString([Globalization.CultureInfo]::InvariantCulture), "--viewport-width", $VisualComparisonWidth.ToString(), "--viewport-height", $VisualComparisonHeight.ToString() ) Invoke-GodotStep "visual-capture" $visualCaptureArgs Invoke-GodotComparisonStep "visual-comparison" @( "--headless", "--path", ".", "--script", "res://src/tools/compare_render_checkpoints.gd", "--", "--reference", $ReferenceCheckpointDirectory, "--candidate", $visualCandidateOutput, "--output", $VisualComparisonReport ) } Write-Host "Renderer baseline completed. Report: $Output/report.json" } finally { Pop-Location }