Automatically validate GLSL shaders after build

This commit is contained in:
Kovid Goyal
2026-07-01 10:23:27 +05:30
parent c2924944f0
commit 4f144a2147
2 changed files with 71 additions and 1 deletions

View File

@@ -291,7 +291,8 @@ def commands_to_compile_to_glsl(sources: dict[str, SlangFile], build_dir: str, d
extra_cmd = ['-line-directive-mode', 'none', '-target', 'glsl', '-profile', 'glsl_330']
for ep in sfile.entry_points:
for sp in sfile.specializations:
dest = f'{base_dest}.{ep.stage.name}.glsl'
v = {Stage.vertex: 'vert', Stage.fragment: 'frag'}[ep.stage]
dest = f'{base_dest}.{v}.glsl'
c = list(cmd)
if sp.name:
dest = f'{base_dest}{sp.filename_insert}.{ep.stage.name}.glsl'
@@ -461,6 +462,9 @@ def main() -> None:
needed.append(Command(desc, cmd, lambda: True))
parallel_run(needed)
compile_builtin_shaders(sys.argv[-2], sys.argv[-1], prun)
if shutil.which('glslangValidator'):
from kitty.shaders.validate_shaders import validate_glsl
validate_glsl('shaders')
def test_slang_build() -> None:

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import subprocess
import sys
from pathlib import Path
def validate_glsl(directory_path: str = '.', verbose: bool = False) -> None:
'''
Validates all GLSL shaders in the specified directory with names matching
name.vert.glsl or name.frag.glsl using glslangValidator.
'''
target_dir = Path(directory_path)
if not target_dir.is_dir():
raise SystemExit(f"Error: Directory '{directory_path}' does not exist.")
# Map the custom extensions to the required glslangValidator stage strings
stage_mapping = {
'.vert.glsl': 'vert',
'.frag.glsl': 'frag'
}
# Find all files matching the patterns
shader_files: list[Path] = []
for ext in stage_mapping.keys():
shader_files.extend(target_dir.glob(f'*{ext}'))
if not shader_files:
if verbose:
print(f"No matching shaders (*.vert.glsl or *.frag.glsl) found in '{target_dir}'.")
return
error_count = 0
print(f"Scanning directory: {target_dir.resolve()}\n" + "-" * 50)
# Process each shader file
for file_path in sorted(shader_files):
# Identify extension matching suffix
matched_ext = next(ext for ext in stage_mapping if file_path.name.endswith(ext))
stage = stage_mapping[matched_ext]
if verbose:
print(f'Validating: {file_path.name}')
result = subprocess.run(['glslangValidator', '-S', stage, str(file_path)],)
# Check exit code
if result.returncode != 0:
error_count += 1
print(f'❌ Failed: {file_path.name}', file=sys.stderr)
else:
if verbose:
print(f'✅ Passed: {file_path.name}')
if verbose:
print('-' * 50)
# Print execution summary
if error_count == 0:
if verbose:
print("Success: All shaders validated successfully!")
else:
raise SystemExit(f"Failure: {error_count} shader(s) failed validation.")
if __name__ == "__main__":
dir_to_scan = sys.argv[1] if len(sys.argv) > 1 else 'shaders'
validate_glsl(dir_to_scan, verbose=True)