1 #!/usr/bin/env python3 2 # 3 # Copyright (C) 2016 Google, Inc. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """Compile GLSL to SPIR-V. 18 19 Depends on glslangValidator. 20 """ 21 22 import os 23 import sys 24 import subprocess 25 import struct 26 import re 27 28 SPIRV_MAGIC = 0x07230203 29 COLUMNS = 4 30 INDENT = 4 31 32 in_filename = sys.argv[1] 33 out_filename = sys.argv[2] if len(sys.argv) > 2 else None 34 validator = sys.argv[3] if len(sys.argv) > 3 else \ 35 "../../../glslang/build/install/bin/glslangValidator" 36 37 def identifierize(s): 38 # translate invalid chars 39 s = re.sub("[^0-9a-zA-Z_]", "_", s) 40 # translate leading digits 41 return re.sub("^[^a-zA-Z_]+", "_", s) 42 43 def compile_glsl(filename, tmpfile): 44 # invoke glslangValidator 45 try: 46 args = [validator, "-V", "-H", "-o", tmpfile, filename] 47 output = subprocess.check_output(args, universal_newlines=True) 48 except subprocess.CalledProcessError as e: 49 print(e.output, file=sys.stderr) 50 exit(1) 51 52 # read the temp file into a list of SPIR-V words 53 words = [] 54 with open(tmpfile, "rb") as f: 55 data = f.read() 56 assert(len(data) and len(data) % 4 == 0) 57 58 # determine endianness 59 fmt = ("<" if data[0] == (SPIRV_MAGIC & 0xff) else ">") + "I" 60 for i in range(0, len(data), 4): 61 words.append(struct.unpack(fmt, data[i:(i + 4)])[0]) 62 63 assert(words[0] == SPIRV_MAGIC) 64 65 66 # remove temp file 67 os.remove(tmpfile) 68 69 return (words, output.rstrip()) 70 71 base = os.path.basename(in_filename) 72 words, comments = compile_glsl(in_filename, base + ".tmp") 73 74 literals = [] 75 for i in range(0, len(words), COLUMNS): 76 columns = ["0x%08x" % word for word in words[i:(i + COLUMNS)]] 77 literals.append(" " * INDENT + ", ".join(columns) + ",") 78 79 header = """#include <stdint.h> 80 81 #if 0 82 %s 83 #endif 84 85 static const uint32_t %s[%d] = { 86 %s 87 }; 88 """ % (comments, identifierize(base), len(words), "\n".join(literals)) 89 90 if out_filename: 91 with open(out_filename, "w") as f: 92 print(header, end="", file=f) 93 else: 94 print(header, end="") 95