| #!/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_format_table.py: |
| # Code generation for Metal format map. |
| # NOTE: don't run this script directly. Run scripts/run_code_generation.py. |
| # |
| |
| from datetime import date |
| import json |
| import math |
| import pprint |
| import re |
| import sys |
| |
| sys.path.append('..') |
| import angle_format |
| |
| template_autogen_inl = """// GENERATED FILE - DO NOT EDIT. |
| // Generated by {script_name} using data from {data_source_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. |
| // |
| // Metal Format table: |
| // Conversion from ANGLE format to Metal format. |
| |
| #import <Metal/Metal.h> |
| #include <TargetConditionals.h> |
| |
| #include "libANGLE/renderer/Format.h" |
| #include "libANGLE/renderer/metal/DisplayMtl.h" |
| #include "libANGLE/renderer/metal/mtl_format_utils.h" |
| |
| namespace rx |
| {{ |
| namespace mtl |
| {{ |
| |
| void Format::init(const DisplayMtl *display, angle::FormatID intendedFormatId_) |
| {{ |
| this->intendedFormatId = intendedFormatId_; |
| |
| id<MTLDevice> metalDevice = display->getMetalDevice(); |
| |
| // Actual conversion |
| switch (this->intendedFormatId) |
| {{ |
| {angle_image_format_switch} |
| }} |
| }} |
| |
| void VertexFormat::init(angle::FormatID angleFormatId, bool tightlyPacked) |
| {{ |
| this->intendedFormatId = angleFormatId; |
| |
| // Actual conversion |
| switch (this->intendedFormatId) |
| {{ |
| {angle_vertex_format_switch} |
| }} |
| }} |
| |
| }} // namespace mtl |
| }} // namespace rx |
| """ |
| |
| case_image_format_template1 = """ case angle::FormatID::{angle_format}: |
| this->metalFormat = {mtl_format}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format}; |
| break; |
| |
| """ |
| |
| case_image_format_template2 = """ case angle::FormatID::{angle_format}: |
| if (metalDevice.depth24Stencil8PixelFormatSupported) |
| {{ |
| this->metalFormat = {mtl_format}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format}; |
| }} |
| else |
| {{ |
| this->metalFormat = {mtl_format_fallback}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format_fallback}; |
| }} |
| break; |
| |
| """ |
| |
| case_vertex_format_template1 = """ case angle::FormatID::{angle_format}: |
| this->metalFormat = {mtl_format}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format}; |
| this->vertexLoadFunction = {vertex_copy_function}; |
| break; |
| |
| """ |
| |
| case_vertex_format_template2 = """ case angle::FormatID::{angle_format}: |
| if (tightlyPacked) |
| {{ |
| this->metalFormat = {mtl_format_packed}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format_packed}; |
| this->vertexLoadFunction = {vertex_copy_function_packed}; |
| }} |
| else |
| {{ |
| this->metalFormat = {mtl_format}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format}; |
| this->vertexLoadFunction = {vertex_copy_function}; |
| }} |
| break; |
| |
| """ |
| |
| |
| def gen_image_map_switch_simple_case(angle_format, actual_angle_format, angle_to_mtl_map): |
| mtl_format = angle_to_mtl_map[actual_angle_format] |
| return case_image_format_template1.format( |
| angle_format=angle_format, actual_angle_format=actual_angle_format, mtl_format=mtl_format) |
| |
| |
| def gen_image_map_switch_mac_case(angle_format, actual_angle_format, angle_to_mtl_map, |
| mac_specific_map, mac_fallbacks): |
| if actual_angle_format in mac_specific_map: |
| # look for the metal format in mac specific table |
| mtl_format = mac_specific_map[actual_angle_format] |
| else: |
| # look for the metal format in common table |
| mtl_format = angle_to_mtl_map[actual_angle_format] |
| |
| if actual_angle_format in mac_fallbacks: |
| # This format requires fallback when depth24Stencil8PixelFormatSupported flag is false. |
| # Fallback format: |
| actual_angle_format_fallback = mac_fallbacks[actual_angle_format] |
| if actual_angle_format_fallback in mac_specific_map: |
| # look for the metal format in mac specific table |
| mtl_format_fallback = mac_specific_map[actual_angle_format_fallback] |
| else: |
| # look for the metal format in common table |
| mtl_format_fallback = angle_to_mtl_map[actual_angle_format_fallback] |
| # return if else block: |
| return case_image_format_template2.format( |
| angle_format=angle_format, |
| actual_angle_format=actual_angle_format, |
| mtl_format=mtl_format, |
| actual_angle_format_fallback=actual_angle_format_fallback, |
| mtl_format_fallback=mtl_format_fallback) |
| else: |
| # return ordinary block: |
| return case_image_format_template1.format( |
| angle_format=angle_format, |
| actual_angle_format=actual_angle_format, |
| mtl_format=mtl_format) |
| |
| |
| def gen_image_map_switch_string(image_table): |
| angle_override = image_table["override"] |
| mac_override = image_table["override_mac"] |
| ios_override = image_table["override_ios"] |
| mac_fallbacks = image_table["fallbacks_mac"] |
| angle_to_mtl = image_table["map"] |
| mac_specific_map = image_table["map_mac"] |
| ios_specific_map = image_table["map_ios"] |
| |
| switch_data = '' |
| |
| def gen_image_map_switch_common_case(angle_format, actual_angle_format): |
| mac_case = gen_image_map_switch_mac_case(angle_format, actual_angle_format, angle_to_mtl, |
| mac_specific_map, mac_fallbacks) |
| non_mac_case = gen_image_map_switch_simple_case(angle_format, actual_angle_format, |
| angle_to_mtl) |
| if mac_case == non_mac_case: |
| return mac_case |
| |
| re = '' |
| re += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" |
| re += mac_case |
| re += "#else // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" |
| re += non_mac_case |
| re += "#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" |
| return re |
| |
| # Common case |
| for angle_format in sorted(angle_to_mtl.keys()): |
| switch_data += gen_image_map_switch_common_case(angle_format, angle_format) |
| for angle_format in sorted(angle_override.keys()): |
| switch_data += gen_image_map_switch_common_case(angle_format, angle_override[angle_format]) |
| |
| # Mac specific |
| switch_data += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" |
| for angle_format in sorted(mac_specific_map.keys()): |
| switch_data += gen_image_map_switch_mac_case(angle_format, angle_format, angle_to_mtl, |
| mac_specific_map, mac_fallbacks) |
| for angle_format in sorted(mac_override.keys()): |
| # overide case will always map to a format in common table, i.e. angle_to_mtl |
| switch_data += gen_image_map_switch_mac_case(angle_format, mac_override[angle_format], |
| angle_to_mtl, mac_specific_map, mac_fallbacks) |
| |
| # iOS specific |
| switch_data += "#elif TARGET_OS_IOS // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" |
| for angle_format in sorted(ios_specific_map.keys()): |
| switch_data += gen_image_map_switch_simple_case(angle_format, angle_format, |
| ios_specific_map) |
| for angle_format in sorted(ios_override.keys()): |
| # overide case will always map to a format in common table, i.e. angle_to_mtl |
| switch_data += gen_image_map_switch_simple_case(angle_format, ios_override[angle_format], |
| angle_to_mtl) |
| switch_data += "#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" |
| switch_data += " default:\n" |
| switch_data += " this->metalFormat = MTLPixelFormatInvalid;\n" |
| switch_data += " this->actualFormatId = angle::FormatID::NONE;" |
| return switch_data |
| |
| |
| def gen_vertex_map_switch_case(angle_fmt, actual_angle_fmt, angle_to_mtl_map, override_packed_map): |
| mtl_format = angle_to_mtl_map[actual_angle_fmt] |
| copy_function = angle_format.get_vertex_copy_function(angle_fmt, actual_angle_fmt) |
| if actual_angle_fmt in override_packed_map: |
| # This format has an override when used in tightly packed buffer, |
| # Return if else block |
| angle_fmt_packed = override_packed_map[actual_angle_fmt] |
| mtl_format_packed = angle_to_mtl_map[angle_fmt_packed] |
| copy_function_packed = angle_format.get_vertex_copy_function(angle_fmt, angle_fmt_packed) |
| return case_vertex_format_template2.format( |
| angle_format=angle_fmt, |
| mtl_format_packed=mtl_format_packed, |
| actual_angle_format_packed=angle_fmt_packed, |
| vertex_copy_function_packed=copy_function_packed, |
| mtl_format=mtl_format, |
| actual_angle_format=actual_angle_fmt, |
| vertex_copy_function=copy_function) |
| else: |
| # This format has no packed buffer's override, return ordinary block. |
| return case_vertex_format_template1.format( |
| angle_format=angle_fmt, |
| mtl_format=mtl_format, |
| actual_angle_format=actual_angle_fmt, |
| vertex_copy_function=copy_function) |
| |
| |
| def gen_vertex_map_switch_string(vertex_table): |
| angle_to_mtl = vertex_table["map"] |
| angle_override = vertex_table["override"] |
| override_packed = vertex_table["override_tightly_packed"] |
| |
| switch_data = '' |
| for angle_fmt in sorted(angle_to_mtl.keys()): |
| switch_data += gen_vertex_map_switch_case(angle_fmt, angle_fmt, angle_to_mtl, |
| override_packed) |
| |
| for angle_fmt in sorted(angle_override.keys()): |
| switch_data += gen_vertex_map_switch_case(angle_fmt, angle_override[angle_fmt], |
| angle_to_mtl, override_packed) |
| |
| switch_data += " default:\n" |
| switch_data += " this->metalFormat = MTLVertexFormatInvalid;\n" |
| switch_data += " this->actualFormatId = angle::FormatID::NONE;\n" |
| switch_data += " this->vertexLoadFunction = nullptr;" |
| return switch_data |
| |
| |
| def main(): |
| # auto_script parameters. |
| if len(sys.argv) > 1: |
| inputs = ['mtl_format_map.json'] |
| outputs = ['mtl_format_table_autogen.mm'] |
| |
| 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 |
| |
| data_source_name = 'mtl_format_map.json' |
| map_json = angle_format.load_json(data_source_name) |
| map_image = map_json["image"] |
| map_vertex = map_json["vertex"] |
| |
| image_switch_data = gen_image_map_switch_string(map_image) |
| |
| vertex_switch_data = gen_vertex_map_switch_string(map_vertex) |
| |
| output_cpp = template_autogen_inl.format( |
| script_name=sys.argv[0], |
| copyright_year=date.today().year, |
| data_source_name=data_source_name, |
| angle_image_format_switch=image_switch_data, |
| angle_vertex_format_switch=vertex_switch_data) |
| with open('mtl_format_table_autogen.mm', 'wt') as out_file: |
| out_file.write(output_cpp) |
| out_file.close() |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |