Home | History | Annotate | Download | only in smoke
      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