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