• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2# Copyright 2019 The ANGLE Project Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# gen_mtl_internal_shaders.py:
7#   Code generation for Metal backend's default shaders.
8#   NOTE: don't run this script directly. Run scripts/run_code_generation.py.
9
10import json
11import os
12import subprocess
13import sys
14
15sys.path.append('../..')
16import angle_format
17import gen_angle_format_table
18
19template_header_boilerplate = """// GENERATED FILE - DO NOT EDIT.
20// Generated by {script_name}
21//
22// Copyright 2020 The ANGLE Project Authors. All rights reserved.
23// Use of this source code is governed by a BSD-style license that can be
24// found in the LICENSE file.
25//
26"""
27
28def gen_shader_enums_code(angle_formats):
29
30    code = """// This file is similar to src/libANGLE/renderer/FormatID_autogen.h but is used by Metal default
31// shaders instead of C++ code.
32//
33"""
34
35    code += "namespace rx\n"
36    code += "{\n"
37    code += "namespace mtl_shader\n"
38    code += "{\n"
39    code += "\n"
40    code += "namespace FormatID\n"
41    code += "{\n"
42    code += "enum\n"
43    code += "{\n"
44    code += gen_angle_format_table.gen_enum_string(angle_formats) + '\n'
45    code += "};\n\n"
46    code += "}\n"
47    code += "\n"
48    code += "}\n"
49    code += "}\n"
50
51    return code
52
53
54def find_clang():
55    if os.name == 'nt':
56        binary = 'clang-cl.exe'
57    else:
58        binary = 'clang++'
59
60    clang = os.path.join('..', '..', '..', '..', '..', 'third_party', 'llvm-build',
61                         'Release+Asserts', 'bin', binary)
62
63    if not os.path.isfile(clang):
64        xcrun_clang = subprocess.run(["xcrun", "-f", binary], stdout=subprocess.PIPE, text=True)
65        if xcrun_clang.returncode == 0:
66            clang = xcrun_clang.stdout.strip()
67    if (not os.path.isfile(clang)):
68        raise Exception('Cannot find clang')
69
70    return clang
71
72
73def main():
74    angle_format_script_files = [
75        '../../angle_format_map.json', '../../angle_format.py', '../../gen_angle_format_table.py'
76    ]
77    src_files = [
78        'blit.metal', 'clear.metal', 'gen_indices.metal', 'gen_mipmap.metal', 'copy_buffer.metal',
79        'visibility.metal', 'rewrite_indices.metal'
80    ]
81
82    # auto_script parameters.
83    if len(sys.argv) > 1:
84        inputs = angle_format_script_files + src_files + ['common.h', 'constants.h']
85        outputs = ['format_autogen.h', 'mtl_default_shaders_src_autogen.inc']
86
87        if sys.argv[1] == 'inputs':
88            print(','.join(inputs))
89        elif sys.argv[1] == 'outputs':
90            print(','.join(outputs))
91        else:
92            print('Invalid script parameters')
93            return 1
94        return 0
95
96    os.chdir(sys.path[0])
97
98    boilerplate_code = template_header_boilerplate.format(script_name=sys.argv[0])
99
100    # -------- Generate shader constants -----------
101    angle_to_gl = angle_format.load_inverse_table('../../angle_format_map.json')
102    shader_formats_autogen = gen_shader_enums_code(angle_to_gl.keys())
103    shader_autogen_header = boilerplate_code + shader_formats_autogen
104
105    with open('format_autogen.h', 'wt') as out_file:
106        out_file.write(shader_autogen_header)
107        out_file.close()
108
109    # -------- Combine and create shader source string -----------
110    # Generate combined source
111    clang = find_clang()
112
113    # Use clang to preprocess the combination source. "@@" token is used to prevent clang from
114    # expanding the preprocessor directive
115    temp_fname = 'temp_master_source.metal'
116    with open(temp_fname, 'wb') as temp_file:
117        for src_file in src_files:
118            include_str = '#include "' + src_file + '" \n'
119            temp_file.write(include_str.encode('utf-8'))
120
121    args = [clang]
122    if not os.name == 'nt':
123        args += ['-xc++']
124    args += ['-E', temp_fname]
125
126    combined_source = subprocess.check_output(args)
127
128    # Remove '@@' tokens
129    final_combined_src_string = combined_source.replace('@@'.encode('utf-8'), ''.encode('utf-8'))
130
131    # Generate final file:
132    with open('mtl_default_shaders_src_autogen.inc', 'wt') as out_file:
133        out_file.write(boilerplate_code)
134        out_file.write('\n')
135        out_file.write('// C++ string version of combined Metal default shaders.\n\n')
136        out_file.write('\n\nstatic char gDefaultMetallibSrc[] = R"(\n')
137        out_file.write(final_combined_src_string.decode("utf-8"))
138        out_file.write('\n')
139        out_file.write(')";\n')
140        out_file.close()
141
142    with open('mtl_default_shaders_src_autogen.metal', 'wt') as out_file:
143        out_file.write(boilerplate_code)
144        out_file.write('\n')
145        out_file.write('// Metal version of combined Metal default shaders.\n\n')
146        out_file.write(final_combined_src_string.decode("utf-8"))
147        out_file.close()
148
149    os.remove(temp_fname)
150
151
152if __name__ == '__main__':
153    sys.exit(main())
154