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 19Depends on glslangValidator. 20""" 21 22import os 23import sys 24import subprocess 25import struct 26import re 27 28SPIRV_MAGIC = 0x07230203 29COLUMNS = 4 30INDENT = 4 31 32in_filename = sys.argv[1] 33out_filename = sys.argv[2] if len(sys.argv) > 2 else None 34validator = sys.argv[3] if len(sys.argv) > 3 else \ 35 "../../../glslang/build/install/bin/glslangValidator" 36 37def 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 43def 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 71base = os.path.basename(in_filename) 72words, comments = compile_glsl(in_filename, base + ".tmp") 73 74literals = [] 75for 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 79header = """#include <stdint.h> 80 81#if 0 82%s 83#endif 84 85static const uint32_t %s[%d] = { 86%s 87}; 88""" % (comments, identifierize(base), len(words), "\n".join(literals)) 89 90if out_filename: 91 with open(out_filename, "w") as f: 92 print(header, end="", file=f) 93else: 94 print(header, end="") 95