| #!/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. |
| # |
| |
| 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 <Metal/Metal.h> |
| #include <TargetConditionals.h> |
| |
| #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<MTLDevice> 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}; |
| this->initFunction = {init_function}; |
| """ |
| |
| image_format_assign_template2 = """ |
| if ({fallback_condition}) |
| {{ |
| this->metalFormat = {mtl_format}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format}; |
| this->initFunction = {init_function}; |
| }} |
| else |
| {{ |
| this->metalFormat = {mtl_format_fallback}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format_fallback}; |
| this->initFunction = {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}; |
| this->initFunction = {init_function}; |
| }} |
| else |
| {{ |
| this->metalFormat = {mtl_format_fallback}; |
| this->actualFormatId = angle::FormatID::{actual_angle_format_fallback}; |
| this->initFunction = {init_function_fallback}; |
| }} |
| """ |
| |
| case_image_format_template1 = """ case angle::FormatID::{angle_format}: |
| {image_format_assign} |
| this->swizzled = false; |
| 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} |
| this->swizzled = false; |
| }} |
| 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}; |
| this->actualSameGLType = {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}; |
| this->actualSameGLType = {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}; |
| this->actualSameGLType = {same_gl_type}; |
| }} |
| break; |
| |
| """ |
| |
| |
| # 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<GLuint, 1, 1, 0>', 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=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=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=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=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=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=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=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=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=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_WATCH || TARGET_OS_TV\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_WATCH || TARGET_OS_TV\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" |
| 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 >= 101600)) \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 >= 101600))\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=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=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=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_spcific'] |
| 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()) |