#!/usr/bin/env python3 """Generate SPIR-V blob arrays as C++ inline file. Install shaderc from https://github.com/google/shaderc/, and run: ./bin/gen-spirv-shader-arrays.py -d src/libixion/shaders -o src/libixion/vulkan_spirv_blobs.inl """ import argparse import os import shutil import sys import subprocess import tempfile from pathlib import Path def _write_cpp_byte_array(array_name, bytes, file): print("// This file has been auto-generated. DO NOT EDIT THIS FILE BY HAND!", file=file) print(file=file) print(f"uint8_t {array_name}_spirv[] = {{", file=file) bytes_per_line = 8 for i, b in enumerate(bytes): if i % bytes_per_line == 0: print(" ", end="", file=file) print(f"0x{b:02X}, ", end="", file=file) if (i + 1) % bytes_per_line == 0: print(file=file) print(file=file) print("};", file=file) print(file=file) def _scan_shader_dir(dirpath, output): # Detect glslc command. glslc_exec = shutil.which("glslc") if not glslc_exec: print("glslc command not found in your PATH.", file=sys.stderr) sys.exit(1) print(f"glslc command: {glslc_exec}") temp = tempfile.NamedTemporaryFile(delete=False) print(f"temp file name: {temp.name}") for f in os.listdir(dirpath): filepath = dirpath / f if filepath.suffix != ".comp": continue print(f"parsing {filepath}") cmd = [glslc_exec, filepath, "-o", temp.name] subprocess.run(cmd) spirv_file = Path(temp.name) bs = spirv_file.read_bytes() _write_cpp_byte_array(filepath.stem, bs, output) os.unlink(temp.name) def main(): parser = argparse.ArgumentParser( description="Generate C++ inline file containing SPIR-V representations of GLSL shaders.") parser.add_argument( "--shader-dir", "-d", type=Path, required=True, help="Path to directory where glsl shader files are.") parser.add_argument( "--output", "-o", type=Path, required=True, help="Path to output C++ inline file.") args = parser.parse_args() with args.output.open(mode="w") as output: _scan_shader_dir(args.shader_dir, output) if __name__ == "__main__": main()