fd817e8a
Add grep gate that forbids unbounded Vulkan waits outside vk_sync
a73x 2026-04-18 15:22
Commit message
build.zig
| Old | New | ||
|---|---|---|---|
| @@ -341,6 +341,9 @@ pub fn build(b: *std.Build) void { | |||
| 341 | const vk_sync_tests = b.addTest(.{ .root_module = vk_sync_test_mod }); | 341 | const vk_sync_tests = b.addTest(.{ .root_module = vk_sync_test_mod }); |
| 342 | test_step.dependOn(&b.addRunArtifact(vk_sync_tests).step); | 342 | test_step.dependOn(&b.addRunArtifact(vk_sync_tests).step); |
| 343 | 343 | ||
| 344 | const check_unbounded_vk = b.addSystemCommand(&.{ "tests/check_unbounded_vk.sh" }); | ||
| 345 | test_step.dependOn(&check_unbounded_vk.step); | ||
| 346 | |||
| 344 | // capture module — --capture mode (render a VT script to PNG) | 347 | // capture module — --capture mode (render a VT script to PNG) |
| 345 | const capture_mod = b.createModule(.{ | 348 | const capture_mod = b.createModule(.{ |
| 346 | .root_source_file = b.path("src/capture.zig"), | 349 | .root_source_file = b.path("src/capture.zig"), |
tests/check_unbounded_vk.sh
| Old | New | ||
|---|---|---|---|
| @@ -0,0 +1,47 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # Grep gate: fail if any source file outside src/vk_sync.zig calls | ||
| 3 | # Vulkan blocking primitives directly. All such calls must go through | ||
| 4 | # src/vk_sync.zig helpers (waitFenceBounded, acquireImageBounded, | ||
| 5 | # waitIdleForShutdown, etc.). | ||
| 6 | |||
| 7 | set -euo pipefail | ||
| 8 | |||
| 9 | REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" | ||
| 10 | cd "$REPO_ROOT" | ||
| 11 | |||
| 12 | PATTERNS=( | ||
| 13 | 'vkd\.waitForFences' | ||
| 14 | 'vkd\.acquireNextImageKHR' | ||
| 15 | 'vkd\.deviceWaitIdle' | ||
| 16 | 'vkd\.queueWaitIdle' | ||
| 17 | ) | ||
| 18 | |||
| 19 | # Find all .zig files in src/ except vk_sync.zig | ||
| 20 | mapfile -t files < <(find src -name '*.zig' ! -path 'src/vk_sync.zig' | sort) | ||
| 21 | |||
| 22 | violations=0 | ||
| 23 | violation_lines=() | ||
| 24 | |||
| 25 | for file in "${files[@]}"; do | ||
| 26 | for pat in "${PATTERNS[@]}"; do | ||
| 27 | while IFS= read -r hit; do | ||
| 28 | violation_lines+=("$file:$hit") | ||
| 29 | violations=$((violations + 1)) | ||
| 30 | done < <(grep -nE "$pat" "$file" || true) | ||
| 31 | done | ||
| 32 | done | ||
| 33 | |||
| 34 | if [[ $violations -gt 0 ]]; then | ||
| 35 | echo "ERROR: $violations unbounded Vulkan wait call(s) found outside src/vk_sync.zig:" >&2 | ||
| 36 | for line in "${violation_lines[@]}"; do | ||
| 37 | echo " $line" >&2 | ||
| 38 | done | ||
| 39 | echo "" >&2 | ||
| 40 | echo "Use src/vk_sync.zig helpers instead:" >&2 | ||
| 41 | echo " waitFenceBounded — replace vkd.waitForFences" >&2 | ||
| 42 | echo " acquireImageBounded — replace vkd.acquireNextImageKHR" >&2 | ||
| 43 | echo " waitIdleForShutdown — replace vkd.deviceWaitIdle / queueWaitIdle" >&2 | ||
| 44 | exit 1 | ||
| 45 | fi | ||
| 46 | |||
| 47 | echo "vk grep gate: ok (${#files[@]} files, no violations)" | ||