#!/usr/bin/python3 # 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. # # Information on Simulator formats: # According to https://developer.apple.com/documentation/metal/developing_metal_apps_that_run_in_simulator?language=objc, # Metal sim does not support several formats. The format table explicitly avoids enabling format support # for MTLPixelFormatR8Unorm_sRGB, MTLPixelFormatR8G8Unorm_sRGB, # and packed 16 bit formats when building for a Simulator target. import json import math import pprint import re import sys sys.path.append('..') import angle_format as angle_format_utils template_autogen_inl = """// GENERATED FILE - DO NOT EDIT. // Generated by {script_name} using data from {data_source_name} // // Copyright 2020 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 #include #include "image_util/copyimage.h" #include "image_util/generatemip.h" #include "image_util/loadimage.h" #include "libANGLE/renderer/Format.h" #include "libANGLE/renderer/metal/DisplayMtl.h" #include "libANGLE/renderer/metal/mtl_format_utils.h" #include "libANGLE/renderer/metal/mtl_utils.h" using namespace angle; namespace rx {{ namespace mtl {{ angle::FormatID Format::MetalToAngleFormatID(MTLPixelFormat formatMtl) {{ // Actual conversion switch (formatMtl) {{ {mtl_pixel_format_switch} }} }} void Format::init(const DisplayMtl *display, angle::FormatID intendedFormatId_) {{ this->intendedFormatId = intendedFormatId_; #if TARGET_OS_OSX || TARGET_OS_MACCATALYST id metalDevice = display->getMetalDevice(); #endif // 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} }} }} void FormatTable::initNativeFormatCapsAutogen(const DisplayMtl *display) {{ const angle::FeaturesMtl &featuresMtl = display->getFeatures(); // Skip auto resolve if either hasDepth/StencilAutoResolve or allowMultisampleStoreAndResolve // feature are disabled. bool supportDepthAutoResolve = featuresMtl.hasDepthAutoResolve.enabled && featuresMtl.allowMultisampleStoreAndResolve.enabled; bool supportStencilAutoResolve = featuresMtl.hasStencilAutoResolve.enabled && featuresMtl.allowMultisampleStoreAndResolve.enabled; bool supportDepthStencilAutoResolve = supportDepthAutoResolve && supportStencilAutoResolve; // Source: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf {metal_format_caps} }} }} // namespace mtl }} // namespace rx """ image_format_assign_template1 = """ this->metalFormat = {mtl_format}; this->actualFormatId = angle::FormatID::{actual_angle_format};{init_function}""" image_format_assign_template2 = """ if ({fallback_condition}) {{ this->metalFormat = {mtl_format}; this->actualFormatId = angle::FormatID::{actual_angle_format};{init_function} }} else {{ this->metalFormat = {mtl_format_fallback}; this->actualFormatId = angle::FormatID::{actual_angle_format_fallback};{init_function_fallback} }}""" #D16 is fully supported on Apple3+. However, on #previous versions of Apple hardware, some operations can cause #undefined behavior. image_format_assign_template3 = """ if (mtl::SupportsIOSGPUFamily(metalDevice, 3)) {{ this->metalFormat = {mtl_format}; this->actualFormatId = angle::FormatID::{actual_angle_format};{init_function} }} else {{ this->metalFormat = {mtl_format_fallback}; this->actualFormatId = angle::FormatID::{actual_angle_format_fallback};{init_function_fallback} }}""" case_image_format_template1 = """ case angle::FormatID::{angle_format}: {image_format_assign} break; """ case_image_format_template2 = """ case angle::FormatID::{angle_format}: #if defined(__IPHONE_13_0) || defined(__MAC_10_15) if (display->getFeatures().hasTextureSwizzle.enabled) {{ {image_format_assign_swizzled} this->swizzled = true; this->swizzle = {mtl_swizzle}; }} else #endif // #if defined(__IPHONE_13_0) || defined(__MAC_10_15) {{ {image_format_assign_default} }} break; """ case_image_mtl_to_angle_template = """ case {mtl_format}: return angle::FormatID::{angle_format}; """ 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}; this->defaultAlpha = {default_alpha};{same_gl_type} 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}; this->defaultAlpha = {default_alpha_packed};{same_gl_type_packed} }} else {{ this->metalFormat = {mtl_format}; this->actualFormatId = angle::FormatID::{actual_angle_format}; this->vertexLoadFunction = {vertex_copy_function}; this->defaultAlpha = {default_alpha};{same_gl_type} }} break; """ def wrap_init_function(str): return '' if str == 'nullptr' else f'this->initFunction = {str};' def wrap_actual_same_gl_type(str): return '' if str == 'true' else f'this->actualSameGLType = {str};' # NOTE(hqle): This is a modified version of the get_vertex_copy_function() function in # src/libANGLE/renderer/angle_format.py # - Return value is a tuple {copy_function, default_alpha_value, have_same_gl_type}. def get_vertex_copy_function_and_default_alpha(src_format, dst_format): if dst_format == "NONE": return "nullptr", 0, "false" num_channel = len(angle_format_utils.get_channel_tokens(src_format)) if num_channel < 1 or num_channel > 4: return "nullptr", 0, "false" src_gl_type = angle_format_utils.get_format_gl_type(src_format) dst_gl_type = angle_format_utils.get_format_gl_type(dst_format) if src_gl_type == dst_gl_type: if src_format.startswith('R10G10B10A2'): return 'CopyNativeVertexData', 0, "true" if src_gl_type == None: return 'nullptr', 0, "true" dst_num_channel = len(angle_format_utils.get_channel_tokens(dst_format)) default_alpha = '1' if num_channel == dst_num_channel or dst_num_channel < 4: default_alpha = '0' elif 'A16_FLOAT' in dst_format: default_alpha = 'gl::Float16One' elif 'A32_FLOAT' in dst_format: default_alpha = 'gl::Float32One' elif 'NORM' in dst_format: default_alpha = 'std::numeric_limits<%s>::max()' % (src_gl_type) return 'CopyNativeVertexData<%s, %d, %d, %s>' % (src_gl_type, num_channel, dst_num_channel, default_alpha), default_alpha, "true" if src_format.startswith('R10G10B10A2'): assert 'FLOAT' in dst_format, ('get_vertex_copy_function: can only convert to float,' + ' not to ' + dst_format) is_signed = 'true' if 'SINT' in src_format or 'SNORM' in src_format or 'SSCALED' in src_format else 'false' is_normal = 'true' if 'NORM' in src_format else 'false' return 'CopyXYZ10W2ToXYZWFloatVertexData<%s, %s, true, false>' % (is_signed, is_normal), 0, "false" return angle_format_utils.get_vertex_copy_function(src_format, dst_format), 0, "false" # Generate format conversion switch case (generic case) def gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, assign_gen_func): if isinstance(actual_angle_format_info, dict): default_actual_angle_format = actual_angle_format_info['default'] # Check if the format can be override with swizzle feature if 'swizzle' in actual_angle_format_info: swizzle_info = actual_angle_format_info['swizzle'] swizzle_channels = swizzle_info[0] swizzled_actual_angle_format = swizzle_info[1] swizzle_map = { 'R': 'GL_RED', 'G': 'GL_GREEN', 'B': 'GL_BLUE', 'A': 'GL_ALPHA', '1': 'GL_ONE', '0': 'GL_ZERO', } mtl_swizzle_make = '{{{r}, {g}, {b}, {a}}}'.format( r=swizzle_map[swizzle_channels[0:1]], g=swizzle_map[swizzle_channels[1:2]], b=swizzle_map[swizzle_channels[2:3]], a=swizzle_map[swizzle_channels[3:]]) return case_image_format_template2.format( angle_format=angle_format, image_format_assign_default=assign_gen_func(default_actual_angle_format, angle_to_mtl_map), image_format_assign_swizzled=assign_gen_func(swizzled_actual_angle_format, angle_to_mtl_map), mtl_swizzle=mtl_swizzle_make) else: # Only default case return gen_image_map_switch_case(angle_format, default_actual_angle_format, angle_to_mtl_map, assign_gen_func) else: # Default case return case_image_format_template1.format( angle_format=angle_format, image_format_assign=assign_gen_func(actual_angle_format_info, angle_to_mtl_map)) # Generate format conversion switch case (simple case) def gen_image_map_switch_simple_case(angle_format, actual_angle_format_info, angle_to_gl, angle_to_mtl_map): def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): return image_format_assign_template1.format( actual_angle_format=actual_angle_format, mtl_format=angle_to_mtl_map[actual_angle_format], init_function=wrap_init_function( angle_format_utils.get_internal_format_initializer(angle_to_gl[angle_format], actual_angle_format))) return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, gen_format_assign_code) # Generate format conversion switch case (Mac case) def gen_image_map_switch_mac_case(angle_format, actual_angle_format_info, angle_to_gl, angle_to_mtl_map, mac_fallbacks): gl_format = angle_to_gl[angle_format] def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): 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] fallback_condition = "metalDevice.depth24Stencil8PixelFormatSupported && \ !display->getFeatures().forceD24S8AsUnsupported.enabled" # return if else block: return image_format_assign_template2.format( actual_angle_format=actual_angle_format, mtl_format=angle_to_mtl_map[actual_angle_format], init_function=wrap_init_function( angle_format_utils.get_internal_format_initializer( gl_format, actual_angle_format)), actual_angle_format_fallback=actual_angle_format_fallback, mtl_format_fallback=angle_to_mtl_map[actual_angle_format_fallback], init_function_fallback=wrap_init_function( angle_format_utils.get_internal_format_initializer( gl_format, actual_angle_format_fallback)), fallback_condition=fallback_condition) else: # return ordinary block: return image_format_assign_template1.format( actual_angle_format=actual_angle_format, mtl_format=angle_to_mtl_map[actual_angle_format], init_function=wrap_init_function( angle_format_utils.get_internal_format_initializer( gl_format, actual_angle_format))) return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, gen_format_assign_code) # Generate format conversion switch case (non-desktop ES 3.0 case) def gen_image_map_switch_es3_case(angle_format, actual_angle_format_info, angle_to_gl, angle_to_mtl_map, mac_fallbacks): gl_format = angle_to_gl[angle_format] def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): actual_angle_format_fallback = mac_fallbacks[actual_angle_format] return image_format_assign_template2.format( actual_angle_format=actual_angle_format, mtl_format=angle_to_mtl_map[actual_angle_format], init_function=wrap_init_function( angle_format_utils.get_internal_format_initializer(gl_format, actual_angle_format)), actual_angle_format_fallback=actual_angle_format_fallback, mtl_format_fallback=angle_to_mtl_map[actual_angle_format_fallback], init_function_fallback=wrap_init_function( angle_format_utils.get_internal_format_initializer(gl_format, actual_angle_format_fallback)), fallback_condition="display->supportsAppleGPUFamily(1)") return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, gen_format_assign_code) # Generate format conversion switch case (ASTC LDR/HDR case) def gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, angle_to_mtl_map): gl_format = angle_to_gl[angle_format] def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): return image_format_assign_template2.format( actual_angle_format=actual_angle_format, mtl_format=angle_to_mtl_map[actual_angle_format] + "HDR", init_function=wrap_init_function( angle_format_utils.get_internal_format_initializer(gl_format, actual_angle_format)), actual_angle_format_fallback=actual_angle_format, mtl_format_fallback=angle_to_mtl_map[actual_angle_format] + "LDR", init_function_fallback=wrap_init_function( angle_format_utils.get_internal_format_initializer(gl_format, actual_angle_format)), fallback_condition="display->supportsAppleGPUFamily(6)") return gen_image_map_switch_case(angle_format, angle_format, angle_to_mtl_map, gen_format_assign_code) def gen_image_map_switch_astc_case_tv_watchos(angle_format, angle_to_gl, angle_to_mtl_map): gl_format = angle_to_gl[angle_format] def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): return image_format_assign_template1.format( actual_angle_format=actual_angle_format, mtl_format=angle_to_mtl_map[actual_angle_format] + "LDR", init_function=wrap_init_function( angle_format_utils.get_internal_format_initializer(gl_format, actual_angle_format))) return gen_image_map_switch_case(angle_format, angle_format, angle_to_mtl_map, gen_format_assign_code) def gen_image_map_switch_string(image_table, angle_to_gl): angle_override = image_table["override"] mac_override = image_table["override_mac"] mac_override_es3 = image_table["override_mac_es3"] mac_override_bc1 = image_table["override_mac_bc1"] ios_override = image_table["override_ios"] mac_d24s8_fallbacks = image_table["d24s8_fallbacks_mac"] angle_to_mtl = image_table["map"] mac_specific_map = image_table["map_mac"] ios_specific_map = image_table["map_ios"] astc_tpl_map = image_table["map_astc_tpl"] sim_specific_map = image_table["map_sim"] sim_override = image_table["override_sim"] # mac_specific_map + angle_to_mtl: mac_angle_to_mtl = mac_specific_map.copy() mac_angle_to_mtl.update(angle_to_mtl) # ios_specific_map + angle_to_mtl ios_angle_to_mtl = ios_specific_map.copy() ios_angle_to_mtl.update(angle_to_mtl) # sim_specific_map + angle_to_mtl sim_angle_to_mtl = sim_specific_map.copy() sim_angle_to_mtl.update(angle_to_mtl) switch_data = '' def gen_image_map_switch_common_case(angle_format, actual_angle_format): return gen_image_map_switch_simple_case(angle_format, actual_angle_format, angle_to_gl, angle_to_mtl) # Common case: universally-supported formats + universal overrides 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 GPU case: macOS + Catalyst targets 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_gl, mac_angle_to_mtl, mac_d24s8_fallbacks) for angle_format in sorted(mac_override.keys()): switch_data += gen_image_map_switch_simple_case(angle_format, mac_override[angle_format], angle_to_gl, mac_angle_to_mtl) for angle_format in sorted(mac_override_bc1.keys()): switch_data += gen_image_map_switch_simple_case(angle_format, mac_override_bc1[angle_format], angle_to_gl, mac_angle_to_mtl) switch_data += "#endif\n" # Override missing ES 3.0 formats for older macOS SDK or Catalyst switch_data += "#if (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED < 110000)) || \\\n" switch_data += "TARGET_OS_MACCATALYST\n" for angle_format in sorted(mac_override_es3.keys()): switch_data += gen_image_map_switch_simple_case(angle_format, mac_override_es3[angle_format], angle_to_gl, mac_angle_to_mtl) switch_data += "#endif\n" switch_data += "#if TARGET_OS_SIMULATOR\n" for angle_format in sorted(sim_specific_map.keys()): switch_data += gen_image_map_switch_simple_case(angle_format, angle_format, angle_to_gl, sim_specific_map) for angle_format in sorted(sim_override.keys()): switch_data += gen_image_map_switch_simple_case(angle_format, sim_override[angle_format], angle_to_gl, sim_angle_to_mtl) switch_data += "#if TARGET_OS_IOS\n" for angle_format in sorted(astc_tpl_map.keys()): switch_data += gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, astc_tpl_map) switch_data += "#elif TARGET_OS_TV ||TARGET_OS_WATCH\n" for angle_format in sorted(astc_tpl_map.keys()): switch_data += gen_image_map_switch_astc_case_tv_watchos(angle_format, angle_to_gl, astc_tpl_map) switch_data += "#endif // TARGET_OS_IOS\n " # iOS specific switch_data += "#elif TARGET_OS_IPHONE && !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, angle_to_gl, ios_specific_map) for angle_format in sorted(ios_override.keys()): switch_data += gen_image_map_switch_simple_case(angle_format, ios_override[angle_format], angle_to_gl, ios_angle_to_mtl) switch_data += "#if TARGET_OS_IOS\n" for angle_format in sorted(astc_tpl_map.keys()): switch_data += gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, astc_tpl_map) switch_data += "#elif TARGET_OS_TV ||TARGET_OS_WATCH\n" for angle_format in sorted(astc_tpl_map.keys()): switch_data += gen_image_map_switch_astc_case_tv_watchos(angle_format, angle_to_gl, astc_tpl_map) switch_data += "#endif // TARGET_OS_IOS || TARGET_OS_TV\n" switch_data += "#endif // TARGET_OS_IPHONE\n" # Try to support all iOS formats on newer macOS with Apple GPU. switch_data += "#if (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000))\n" for angle_format in sorted(ios_specific_map.keys()): if (angle_format in mac_override_es3.keys()): # ETC/EAC or packed 16-bit switch_data += gen_image_map_switch_es3_case(angle_format, angle_format, angle_to_gl, ios_angle_to_mtl, mac_override_es3) else: # ASTC sRGB or PVRTC1 switch_data += gen_image_map_switch_simple_case(angle_format, angle_format, angle_to_gl, ios_specific_map) # ASTC LDR or HDR for angle_format in sorted(astc_tpl_map.keys()): switch_data += gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, astc_tpl_map) switch_data += "#endif // TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000)) \n" switch_data += " default:\n" switch_data += " this->metalFormat = MTLPixelFormatInvalid;\n" switch_data += " this->actualFormatId = angle::FormatID::NONE;" return switch_data def gen_image_mtl_to_angle_switch_string(image_table): angle_to_mtl = image_table["map"] mac_specific_map = image_table["map_mac"] ios_specific_map = image_table["map_ios"] astc_tpl_map = image_table["map_astc_tpl"] switch_data = '' # Common case for angle_format in sorted(angle_to_mtl.keys()): switch_data += case_image_mtl_to_angle_template.format( mtl_format=angle_to_mtl[angle_format], angle_format=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 += case_image_mtl_to_angle_template.format( mtl_format=mac_specific_map[angle_format], angle_format=angle_format) switch_data += "#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" # iOS + macOS 11.0+ specific switch_data += "#if TARGET_OS_IPHONE || (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000))\n" for angle_format in sorted(ios_specific_map.keys()): # ETC1_R8G8B8_UNORM_BLOCK is a duplicated of ETC2_R8G8B8_UNORM_BLOCK if angle_format == 'ETC1_R8G8B8_UNORM_BLOCK': continue switch_data += case_image_mtl_to_angle_template.format( mtl_format=ios_specific_map[angle_format], angle_format=angle_format) for angle_format in sorted(astc_tpl_map.keys()): switch_data += case_image_mtl_to_angle_template.format( mtl_format=astc_tpl_map[angle_format] + "LDR", angle_format=angle_format) switch_data += "#if TARGET_OS_IOS || TARGET_OS_OSX \n" for angle_format in sorted(astc_tpl_map.keys()): switch_data += case_image_mtl_to_angle_template.format( mtl_format=astc_tpl_map[angle_format] + "HDR", angle_format=angle_format) switch_data += "#endif // TARGET_OS_IOS || TARGET_OS_OSX\n" switch_data += "#endif // TARGET_OS_IPHONE || mac 11.0+\n" switch_data += " default:\n" switch_data += " return angle::FormatID::NONE;\n" 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, default_alpha, same_gl_type = get_vertex_copy_function_and_default_alpha( 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, default_alpha_packed, same_gl_type_packed = get_vertex_copy_function_and_default_alpha( 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, default_alpha_packed=default_alpha_packed, same_gl_type_packed=wrap_actual_same_gl_type(same_gl_type_packed), mtl_format=mtl_format, actual_angle_format=actual_angle_fmt, vertex_copy_function=copy_function, default_alpha=default_alpha, same_gl_type=wrap_actual_same_gl_type(same_gl_type)) 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, default_alpha=default_alpha, same_gl_type=wrap_actual_same_gl_type(same_gl_type)) 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;" switch_data += " this->defaultAlpha = 0;" switch_data += " this->actualSameGLType = false;" return switch_data def gen_mtl_format_caps_init_string(map_image): caps = map_image['caps'] mac_caps = map_image['caps_mac'] ios_platform_caps = map_image['caps_ios_platform'] ios_specific_caps = map_image['caps_ios_specific'] caps_init_str = '' def cap_to_param(caps, key): return '/** ' + key + '*/ ' + caps.get(key, 'false') def caps_to_cpp(caps_table): init_str = '' for mtl_format in sorted(caps_table.keys()): caps = caps_table[mtl_format] filterable = cap_to_param(caps, 'filterable') writable = cap_to_param(caps, 'writable') colorRenderable = cap_to_param(caps, 'colorRenderable') depthRenderable = cap_to_param(caps, 'depthRenderable') blendable = cap_to_param(caps, 'blendable') multisample = cap_to_param(caps, 'multisample') resolve = cap_to_param(caps, 'resolve') init_str += " setFormatCaps({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7});\n\n".format( mtl_format, filterable, writable, blendable, multisample, resolve, colorRenderable, depthRenderable) return init_str caps_init_str += caps_to_cpp(caps) caps_init_str += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" caps_init_str += caps_to_cpp(mac_caps) caps_init_str += "#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" caps_init_str += "#if (TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST) || \\\n" caps_init_str += " (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000))\n" caps_init_str += caps_to_cpp(ios_platform_caps) caps_init_str += "#if TARGET_OS_IOS || TARGET_OS_OSX\n" caps_init_str += caps_to_cpp(ios_specific_caps) caps_init_str += "#endif // TARGET_OS_IOS || mac 11.0+ \n" caps_init_str += "#endif // TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST || mac 11.0+ \n" return caps_init_str def main(): data_source_name = 'mtl_format_map.json' # auto_script parameters. if len(sys.argv) > 1: inputs = ['../angle_format.py', '../angle_format_map.json', data_source_name] 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 angle_to_gl = angle_format_utils.load_inverse_table('../angle_format_map.json') map_json = angle_format_utils.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, angle_to_gl) image_mtl_to_angle_switch_data = gen_image_mtl_to_angle_switch_string(map_image) vertex_switch_data = gen_vertex_map_switch_string(map_vertex) caps_init_str = gen_mtl_format_caps_init_string(map_image) output_cpp = template_autogen_inl.format( script_name=sys.argv[0], data_source_name=data_source_name, angle_image_format_switch=image_switch_data, mtl_pixel_format_switch=image_mtl_to_angle_switch_data, angle_vertex_format_switch=vertex_switch_data, metal_format_caps=caps_init_str) 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())