ADD: shader compile script

This commit is contained in:
2025-12-21 01:10:45 +09:00
parent 249c78b2aa
commit a3c0029723
4 changed files with 158 additions and 12 deletions

145
compile_shaders.py Normal file
View File

@@ -0,0 +1,145 @@
#!/usr/bin/env python3
import argparse, os, subprocess, sys
from pathlib import Path
from shutil import which
SHADER_EXTS = {
".frag", ".vert", ".comp", ".geom", ".tesc", ".tese",
".mesh", ".task",
".rgen", ".rint", ".rahit", ".rchit", ".rmiss", ".rcall",
}
PROFILE_FLAGS = {
"Debug": ["-g"],
"Release": ["-O"],
# Matches the old `compile_shaders.ps1` defaults (-O + -g).
"RelWithDebInfo": ["-O", "-g"],
}
STAGE_FLAGS_BY_EXT = {
".mesh": ["-fshader-stage=mesh"],
".task": ["-fshader-stage=task"],
}
def find_glslc(user_path):
if user_path:
return user_path
env_glslc = os.environ.get("GLSLC")
if env_glslc:
return env_glslc
vulkan_sdk = os.environ.get("VULKAN_SDK")
if vulkan_sdk:
sdk = Path(vulkan_sdk)
candidates = [
sdk / "Bin" / "glslc.exe",
sdk / "Bin" / "glslc",
sdk / "bin" / "glslc.exe",
sdk / "bin" / "glslc",
]
for c in candidates:
if c.exists():
return str(c)
for name in ("glslc", "glslc.exe"):
p = which(name)
if p:
return p
sys.exit(
"ERROR: `glslc` not found. Install the Vulkan SDK and ensure `glslc` is on PATH,\n"
" or set `VULKAN_SDK`, `GLSLC`, or pass `--glslc /path/to/glslc`."
)
def parse_args():
p = argparse.ArgumentParser(description="Compile GLSL shaders under shaders/ to .spv next to sources.")
cfg = p.add_mutually_exclusive_group()
cfg.add_argument("--debug", action="store_true", help="Debug profile (adds -g, no -O).")
cfg.add_argument("--release", action="store_true", help="Release profile (adds -O, no -g).")
p.add_argument(
"--config",
choices=list(PROFILE_FLAGS.keys()),
default="RelWithDebInfo",
help="Compilation profile (default: RelWithDebInfo).",
)
p.add_argument("--shader-dir", default="shaders", help="Shader source directory (default: shaders).")
p.add_argument("--glslc", default=None, help="Path to glslc (default: auto-detect).")
p.add_argument("--target-env", default="vulkan1.3", help="Vulkan target env for glslc (default: vulkan1.3).")
p.add_argument("--no-werror", action="store_true", help="Do not pass -Werror.")
p.add_argument("--quiet", action="store_true", help="Only print errors.")
return p.parse_args()
def collect_sources(shader_dir: Path):
return sorted([p for p in shader_dir.rglob("*") if p.is_file() and p.suffix.lower() in SHADER_EXTS])
def compile_one(glslc: str, src: Path, shader_dir: Path, args) -> int:
out_path = src.parent / f"{src.name}.spv"
stage_flags = STAGE_FLAGS_BY_EXT.get(src.suffix.lower(), [])
cmd = [
glslc,
str(src),
f"--target-env={args.target_env}",
"-I", str(shader_dir),
*PROFILE_FLAGS[args.config],
*stage_flags,
]
if not args.no_werror:
cmd.append("-Werror")
cmd += ["-o", str(out_path)]
if not args.quiet:
print(subprocess.list2cmdline(cmd))
proc = subprocess.run(cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if proc.stdout and not args.quiet:
sys.stdout.write(proc.stdout)
if proc.returncode != 0:
if proc.stderr:
sys.stderr.write(proc.stderr)
elif proc.stderr and not args.quiet:
sys.stderr.write(proc.stderr)
return proc.returncode
def main() -> int:
args = parse_args()
if args.debug:
args.config = "Debug"
elif args.release:
args.config = "Release"
repo_root = Path(__file__).resolve().parent
shader_dir = (repo_root / args.shader_dir).resolve()
if not shader_dir.exists():
sys.stderr.write(f"ERROR: shader dir not found: {shader_dir}\n")
return 2
glslc = find_glslc(args.glslc)
sources = collect_sources(shader_dir)
if not sources:
if not args.quiet:
print(f"No shaders found under {shader_dir}")
return 0
failed = 0
for src in sources:
rc = compile_one(glslc, src, shader_dir, args)
if rc != 0:
failed += 1
if failed:
sys.stderr.write(f"ERROR: {failed} shader(s) failed to compile.\n")
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())