| #!/usr/bin/python |
| # Copyright 2019 The ANGLE Project Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| # |
| # gen_mtl_internal_shaders.py: |
| # Code generation for Metal backend's default shaders. |
| # NOTE: don't run this script directly. Run scripts/run_code_generation.py. |
| |
| import os |
| import sys |
| import json |
| from datetime import datetime |
| |
| sys.path.append('../..') |
| import angle_format |
| import gen_angle_format_table |
| |
| template_header_boilerplate = """// GENERATED FILE - DO NOT EDIT. |
| // Generated by {script_name} |
| // |
| // Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| """ |
| |
| def gen_shader_enums_code(angle_formats): |
| |
| code = """// This file is similar to src/libANGLE/renderer/FormatID_autogen.h but is used by Metal default |
| // shaders instead of C++ code. |
| // |
| """ |
| |
| code += "namespace rx\n" |
| code += "{\n" |
| code += "namespace mtl_shader\n" |
| code += "{\n" |
| code += "\n" |
| code += "namespace FormatID\n" |
| code += "{\n" |
| code += "enum\n" |
| code += "{\n" |
| code += gen_angle_format_table.gen_enum_string(angle_formats) + '\n' |
| code += "};\n\n" |
| code += "}\n" |
| code += "\n" |
| code += "}\n" |
| code += "}\n" |
| |
| return code |
| |
| |
| def main(): |
| angle_format_script_files = [ |
| '../../angle_format_map.json', '../../angle_format.py', '../../gen_angle_format_table.py' |
| ] |
| src_files = [ |
| 'blit.metal', 'clear.metal', 'gen_indices.metal', 'gen_mipmap.metal', 'copy_buffer.metal', |
| 'visibility.metal' |
| ] |
| |
| # auto_script parameters. |
| if len(sys.argv) > 1: |
| inputs = angle_format_script_files + src_files + ['common.h', 'constants.h'] |
| outputs = ['format_autogen.h', 'mtl_default_shaders_src_autogen.inc'] |
| |
| if sys.argv[1] == 'inputs': |
| print ','.join(inputs) |
| elif sys.argv[1] == 'outputs': |
| print ','.join(outputs) |
| else: |
| print('Invalid script parameters') |
| return 1 |
| return 0 |
| |
| os.chdir(sys.path[0]) |
| |
| boilerplate_code = template_header_boilerplate.format( |
| script_name=sys.argv[0], copyright_year=datetime.today().year) |
| |
| # -------- Generate shader constants ----------- |
| angle_to_gl = angle_format.load_inverse_table('../../angle_format_map.json') |
| shader_formats_autogen = gen_shader_enums_code(angle_to_gl.keys()) |
| shader_autogen_header = boilerplate_code + shader_formats_autogen |
| |
| with open('format_autogen.h', 'wt') as out_file: |
| out_file.write(shader_autogen_header) |
| out_file.close() |
| |
| # -------- Combine and create shader source string ----------- |
| # Generate a combination source |
| os.system('mkdir -p temp && rm -f temp/master_source.metal && touch temp/master_source.metal') |
| for src_file in src_files: |
| os.system('echo "#include \\"../{0}\\"" >> temp/master_source.metal'.format(src_file)) |
| |
| # Use clang/gcc to preprocess the combination source. "@@" token is used to prevent clang from |
| # expanding the preprocessor directive |
| if os.system('which gcc') == 0: |
| print('combining source files using gcc -E') |
| os.system('gcc -xc++ -E temp/master_source.metal > temp/master_source.metal.pp') |
| else: |
| print('combining source files using clang -E') |
| os.system('clang -xc++ -E temp/master_source.metal > temp/master_source.metal.pp') |
| |
| # Remove '@@' tokens |
| final_combined_src_string = '' |
| with open('temp/master_source.metal.pp', 'rt') as in_file: |
| final_combined_src_string = in_file.read().replace('@@', '') |
| in_file.close() |
| |
| # Generate final file: |
| with open('mtl_default_shaders_src_autogen.inc', 'wt') as out_file: |
| out_file.write(boilerplate_code) |
| out_file.write('\n') |
| out_file.write('// C++ string version of combined Metal default shaders.\n\n') |
| out_file.write('\n\nstatic char gDefaultMetallibSrc[] = R"(\n') |
| out_file.write(final_combined_src_string) |
| out_file.write('\n') |
| out_file.write(')";\n') |
| out_file.close() |
| |
| # Clean up |
| os.system('rm -rf temp') |
| |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |