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_format_table.py: 7# Code generation for Metal format map. 8# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 9# 10 11# Information on Simulator formats: 12# According to https://developer.apple.com/documentation/metal/developing_metal_apps_that_run_in_simulator?language=objc, 13# Metal sim does not support several formats. The format table explicitly avoids enabling format support 14# for MTLPixelFormatR8Unorm_sRGB, MTLPixelFormatR8G8Unorm_sRGB, 15# and packed 16 bit formats when building for a Simulator target. 16 17import json 18import math 19import pprint 20import re 21import sys 22 23sys.path.append('..') 24import angle_format as angle_format_utils 25 26template_autogen_inl = """// GENERATED FILE - DO NOT EDIT. 27// Generated by {script_name} using data from {data_source_name} 28// 29// Copyright 2020 The ANGLE Project Authors. All rights reserved. 30// Use of this source code is governed by a BSD-style license that can be 31// found in the LICENSE file. 32// 33// Metal Format table: 34// Conversion from ANGLE format to Metal format. 35 36#import <Metal/Metal.h> 37#include <TargetConditionals.h> 38 39#include "image_util/copyimage.h" 40#include "image_util/generatemip.h" 41#include "image_util/loadimage.h" 42#include "libANGLE/renderer/Format.h" 43#include "libANGLE/renderer/metal/DisplayMtl.h" 44#include "libANGLE/renderer/metal/mtl_format_utils.h" 45#include "libANGLE/renderer/metal/mtl_utils.h" 46 47using namespace angle; 48 49namespace rx 50{{ 51namespace mtl 52{{ 53 54angle::FormatID Format::MetalToAngleFormatID(MTLPixelFormat formatMtl) 55{{ 56 // Actual conversion 57 switch (formatMtl) 58 {{ 59{mtl_pixel_format_switch} 60 }} 61}} 62 63void Format::init(const DisplayMtl *display, angle::FormatID intendedFormatId_) 64{{ 65 this->intendedFormatId = intendedFormatId_; 66#if TARGET_OS_OSX || TARGET_OS_MACCATALYST 67 id<MTLDevice> metalDevice = display->getMetalDevice(); 68#endif 69 70 // Actual conversion 71 switch (this->intendedFormatId) 72 {{ 73{angle_image_format_switch} 74 }} 75}} 76 77void VertexFormat::init(angle::FormatID angleFormatId, bool tightlyPacked) 78{{ 79 this->intendedFormatId = angleFormatId; 80 81 // Actual conversion 82 switch (this->intendedFormatId) 83 {{ 84{angle_vertex_format_switch} 85 }} 86}} 87 88void FormatTable::initNativeFormatCapsAutogen(const DisplayMtl *display) 89{{ 90 const angle::FeaturesMtl &featuresMtl = display->getFeatures(); 91 // Skip auto resolve if either hasDepth/StencilAutoResolve or allowMultisampleStoreAndResolve 92 // feature are disabled. 93 bool supportDepthAutoResolve = featuresMtl.hasDepthAutoResolve.enabled && 94 featuresMtl.allowMultisampleStoreAndResolve.enabled; 95 bool supportStencilAutoResolve = featuresMtl.hasStencilAutoResolve.enabled && 96 featuresMtl.allowMultisampleStoreAndResolve.enabled; 97 bool supportDepthStencilAutoResolve = supportDepthAutoResolve && supportStencilAutoResolve; 98 99 // Source: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf 100 {metal_format_caps} 101}} 102 103}} // namespace mtl 104}} // namespace rx 105""" 106 107image_format_assign_template1 = """ 108 this->metalFormat = {mtl_format}; 109 this->actualFormatId = angle::FormatID::{actual_angle_format};{init_function}""" 110 111image_format_assign_template2 = """ 112 if ({fallback_condition}) 113 {{ 114 this->metalFormat = {mtl_format}; 115 this->actualFormatId = angle::FormatID::{actual_angle_format};{init_function} 116 }} 117 else 118 {{ 119 this->metalFormat = {mtl_format_fallback}; 120 this->actualFormatId = angle::FormatID::{actual_angle_format_fallback};{init_function_fallback} 121 }}""" 122 123#D16 is fully supported on Apple3+. However, on 124#previous versions of Apple hardware, some operations can cause 125#undefined behavior. 126image_format_assign_template3 = """ 127 if (mtl::SupportsIOSGPUFamily(metalDevice, 3)) 128 {{ 129 this->metalFormat = {mtl_format}; 130 this->actualFormatId = angle::FormatID::{actual_angle_format};{init_function} 131 }} 132 else 133 {{ 134 this->metalFormat = {mtl_format_fallback}; 135 this->actualFormatId = angle::FormatID::{actual_angle_format_fallback};{init_function_fallback} 136 }}""" 137 138case_image_format_template1 = """ case angle::FormatID::{angle_format}: 139 {image_format_assign} 140 break; 141 142""" 143 144case_image_format_template2 = """ case angle::FormatID::{angle_format}: 145#if defined(__IPHONE_13_0) || defined(__MAC_10_15) 146 if (display->getFeatures().hasTextureSwizzle.enabled) 147 {{ 148 {image_format_assign_swizzled} 149 this->swizzled = true; 150 this->swizzle = {mtl_swizzle}; 151 }} 152 else 153#endif // #if defined(__IPHONE_13_0) || defined(__MAC_10_15) 154 {{ 155 {image_format_assign_default} 156 }} 157 break; 158 159""" 160 161case_image_mtl_to_angle_template = """ case {mtl_format}: 162 return angle::FormatID::{angle_format}; 163""" 164 165case_vertex_format_template1 = """ case angle::FormatID::{angle_format}: 166 this->metalFormat = {mtl_format}; 167 this->actualFormatId = angle::FormatID::{actual_angle_format}; 168 this->vertexLoadFunction = {vertex_copy_function}; 169 this->defaultAlpha = {default_alpha};{same_gl_type} 170 break; 171 172""" 173 174case_vertex_format_template2 = """ case angle::FormatID::{angle_format}: 175 if (tightlyPacked) 176 {{ 177 this->metalFormat = {mtl_format_packed}; 178 this->actualFormatId = angle::FormatID::{actual_angle_format_packed}; 179 this->vertexLoadFunction = {vertex_copy_function_packed}; 180 this->defaultAlpha = {default_alpha_packed};{same_gl_type_packed} 181 }} 182 else 183 {{ 184 this->metalFormat = {mtl_format}; 185 this->actualFormatId = angle::FormatID::{actual_angle_format}; 186 this->vertexLoadFunction = {vertex_copy_function}; 187 this->defaultAlpha = {default_alpha};{same_gl_type} 188 }} 189 break; 190 191""" 192 193 194def wrap_init_function(str): 195 return '' if str == 'nullptr' else f'this->initFunction = {str};' 196 197 198def wrap_actual_same_gl_type(str): 199 return '' if str == 'true' else f'this->actualSameGLType = {str};' 200 201 202# NOTE(hqle): This is a modified version of the get_vertex_copy_function() function in 203# src/libANGLE/renderer/angle_format.py 204# - Return value is a tuple {copy_function, default_alpha_value, have_same_gl_type}. 205def get_vertex_copy_function_and_default_alpha(src_format, dst_format): 206 if dst_format == "NONE": 207 return "nullptr", 0, "false" 208 209 num_channel = len(angle_format_utils.get_channel_tokens(src_format)) 210 if num_channel < 1 or num_channel > 4: 211 return "nullptr", 0, "false" 212 213 src_gl_type = angle_format_utils.get_format_gl_type(src_format) 214 dst_gl_type = angle_format_utils.get_format_gl_type(dst_format) 215 216 if src_gl_type == dst_gl_type: 217 if src_format.startswith('R10G10B10A2'): 218 return 'CopyNativeVertexData<GLuint, 1, 1, 0>', 0, "true" 219 220 if src_gl_type == None: 221 return 'nullptr', 0, "true" 222 dst_num_channel = len(angle_format_utils.get_channel_tokens(dst_format)) 223 default_alpha = '1' 224 225 if num_channel == dst_num_channel or dst_num_channel < 4: 226 default_alpha = '0' 227 elif 'A16_FLOAT' in dst_format: 228 default_alpha = 'gl::Float16One' 229 elif 'A32_FLOAT' in dst_format: 230 default_alpha = 'gl::Float32One' 231 elif 'NORM' in dst_format: 232 default_alpha = 'std::numeric_limits<%s>::max()' % (src_gl_type) 233 234 return 'CopyNativeVertexData<%s, %d, %d, %s>' % (src_gl_type, num_channel, dst_num_channel, 235 default_alpha), default_alpha, "true" 236 237 if src_format.startswith('R10G10B10A2'): 238 assert 'FLOAT' in dst_format, ('get_vertex_copy_function: can only convert to float,' + 239 ' not to ' + dst_format) 240 is_signed = 'true' if 'SINT' in src_format or 'SNORM' in src_format or 'SSCALED' in src_format else 'false' 241 is_normal = 'true' if 'NORM' in src_format else 'false' 242 return 'CopyXYZ10W2ToXYZWFloatVertexData<%s, %s, true, false>' % (is_signed, 243 is_normal), 0, "false" 244 245 return angle_format_utils.get_vertex_copy_function(src_format, dst_format), 0, "false" 246 247 248# Generate format conversion switch case (generic case) 249 250 251def gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, 252 assign_gen_func): 253 if isinstance(actual_angle_format_info, dict): 254 default_actual_angle_format = actual_angle_format_info['default'] 255 # Check if the format can be override with swizzle feature 256 if 'swizzle' in actual_angle_format_info: 257 swizzle_info = actual_angle_format_info['swizzle'] 258 swizzle_channels = swizzle_info[0] 259 swizzled_actual_angle_format = swizzle_info[1] 260 swizzle_map = { 261 'R': 'GL_RED', 262 'G': 'GL_GREEN', 263 'B': 'GL_BLUE', 264 'A': 'GL_ALPHA', 265 '1': 'GL_ONE', 266 '0': 'GL_ZERO', 267 } 268 269 mtl_swizzle_make = '{{{r}, {g}, {b}, {a}}}'.format( 270 r=swizzle_map[swizzle_channels[0:1]], 271 g=swizzle_map[swizzle_channels[1:2]], 272 b=swizzle_map[swizzle_channels[2:3]], 273 a=swizzle_map[swizzle_channels[3:]]) 274 return case_image_format_template2.format( 275 angle_format=angle_format, 276 image_format_assign_default=assign_gen_func(default_actual_angle_format, 277 angle_to_mtl_map), 278 image_format_assign_swizzled=assign_gen_func(swizzled_actual_angle_format, 279 angle_to_mtl_map), 280 mtl_swizzle=mtl_swizzle_make) 281 else: 282 # Only default case 283 return gen_image_map_switch_case(angle_format, default_actual_angle_format, 284 angle_to_mtl_map, assign_gen_func) 285 else: 286 # Default case 287 return case_image_format_template1.format( 288 angle_format=angle_format, 289 image_format_assign=assign_gen_func(actual_angle_format_info, angle_to_mtl_map)) 290 291 292# Generate format conversion switch case (simple case) 293 294 295def gen_image_map_switch_simple_case(angle_format, actual_angle_format_info, angle_to_gl, 296 angle_to_mtl_map): 297 298 def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): 299 return image_format_assign_template1.format( 300 actual_angle_format=actual_angle_format, 301 mtl_format=angle_to_mtl_map[actual_angle_format], 302 init_function=wrap_init_function( 303 angle_format_utils.get_internal_format_initializer(angle_to_gl[angle_format], 304 actual_angle_format))) 305 306 return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, 307 gen_format_assign_code) 308 309 310# Generate format conversion switch case (Mac case) 311 312 313def gen_image_map_switch_mac_case(angle_format, actual_angle_format_info, angle_to_gl, 314 angle_to_mtl_map, mac_fallbacks): 315 gl_format = angle_to_gl[angle_format] 316 317 def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): 318 if actual_angle_format in mac_fallbacks: 319 # This format requires fallback when depth24Stencil8PixelFormatSupported flag is false. 320 # Fallback format: 321 actual_angle_format_fallback = mac_fallbacks[actual_angle_format] 322 fallback_condition = "metalDevice.depth24Stencil8PixelFormatSupported && \ 323 !display->getFeatures().forceD24S8AsUnsupported.enabled" 324 # return if else block: 325 return image_format_assign_template2.format( 326 actual_angle_format=actual_angle_format, 327 mtl_format=angle_to_mtl_map[actual_angle_format], 328 init_function=wrap_init_function( 329 angle_format_utils.get_internal_format_initializer( 330 gl_format, actual_angle_format)), 331 actual_angle_format_fallback=actual_angle_format_fallback, 332 mtl_format_fallback=angle_to_mtl_map[actual_angle_format_fallback], 333 init_function_fallback=wrap_init_function( 334 angle_format_utils.get_internal_format_initializer( 335 gl_format, actual_angle_format_fallback)), 336 fallback_condition=fallback_condition) 337 else: 338 # return ordinary block: 339 return image_format_assign_template1.format( 340 actual_angle_format=actual_angle_format, 341 mtl_format=angle_to_mtl_map[actual_angle_format], 342 init_function=wrap_init_function( 343 angle_format_utils.get_internal_format_initializer( 344 gl_format, actual_angle_format))) 345 346 return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, 347 gen_format_assign_code) 348 349 350# Generate format conversion switch case (non-desktop ES 3.0 case) 351def gen_image_map_switch_es3_case(angle_format, actual_angle_format_info, angle_to_gl, 352 angle_to_mtl_map, mac_fallbacks): 353 gl_format = angle_to_gl[angle_format] 354 355 def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): 356 actual_angle_format_fallback = mac_fallbacks[actual_angle_format] 357 return image_format_assign_template2.format( 358 actual_angle_format=actual_angle_format, 359 mtl_format=angle_to_mtl_map[actual_angle_format], 360 init_function=wrap_init_function( 361 angle_format_utils.get_internal_format_initializer(gl_format, 362 actual_angle_format)), 363 actual_angle_format_fallback=actual_angle_format_fallback, 364 mtl_format_fallback=angle_to_mtl_map[actual_angle_format_fallback], 365 init_function_fallback=wrap_init_function( 366 angle_format_utils.get_internal_format_initializer(gl_format, 367 actual_angle_format_fallback)), 368 fallback_condition="display->supportsAppleGPUFamily(1)") 369 370 return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map, 371 gen_format_assign_code) 372 373 374# Generate format conversion switch case (ASTC LDR/HDR case) 375def gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, angle_to_mtl_map): 376 gl_format = angle_to_gl[angle_format] 377 378 def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): 379 return image_format_assign_template2.format( 380 actual_angle_format=actual_angle_format, 381 mtl_format=angle_to_mtl_map[actual_angle_format] + "HDR", 382 init_function=wrap_init_function( 383 angle_format_utils.get_internal_format_initializer(gl_format, 384 actual_angle_format)), 385 actual_angle_format_fallback=actual_angle_format, 386 mtl_format_fallback=angle_to_mtl_map[actual_angle_format] + "LDR", 387 init_function_fallback=wrap_init_function( 388 angle_format_utils.get_internal_format_initializer(gl_format, 389 actual_angle_format)), 390 fallback_condition="display->supportsAppleGPUFamily(6)") 391 392 return gen_image_map_switch_case(angle_format, angle_format, angle_to_mtl_map, 393 gen_format_assign_code) 394 395 396def gen_image_map_switch_astc_case_tv_watchos(angle_format, angle_to_gl, angle_to_mtl_map): 397 gl_format = angle_to_gl[angle_format] 398 399 def gen_format_assign_code(actual_angle_format, angle_to_mtl_map): 400 return image_format_assign_template1.format( 401 actual_angle_format=actual_angle_format, 402 mtl_format=angle_to_mtl_map[actual_angle_format] + "LDR", 403 init_function=wrap_init_function( 404 angle_format_utils.get_internal_format_initializer(gl_format, 405 actual_angle_format))) 406 407 return gen_image_map_switch_case(angle_format, angle_format, angle_to_mtl_map, 408 gen_format_assign_code) 409 410 411def gen_image_map_switch_string(image_table, angle_to_gl): 412 angle_override = image_table["override"] 413 mac_override = image_table["override_mac"] 414 mac_override_es3 = image_table["override_mac_es3"] 415 mac_override_bc1 = image_table["override_mac_bc1"] 416 ios_override = image_table["override_ios"] 417 mac_d24s8_fallbacks = image_table["d24s8_fallbacks_mac"] 418 angle_to_mtl = image_table["map"] 419 mac_specific_map = image_table["map_mac"] 420 ios_specific_map = image_table["map_ios"] 421 astc_tpl_map = image_table["map_astc_tpl"] 422 sim_specific_map = image_table["map_sim"] 423 sim_override = image_table["override_sim"] 424 425 # mac_specific_map + angle_to_mtl: 426 mac_angle_to_mtl = mac_specific_map.copy() 427 mac_angle_to_mtl.update(angle_to_mtl) 428 # ios_specific_map + angle_to_mtl 429 ios_angle_to_mtl = ios_specific_map.copy() 430 ios_angle_to_mtl.update(angle_to_mtl) 431 # sim_specific_map + angle_to_mtl 432 sim_angle_to_mtl = sim_specific_map.copy() 433 sim_angle_to_mtl.update(angle_to_mtl) 434 switch_data = '' 435 436 def gen_image_map_switch_common_case(angle_format, actual_angle_format): 437 return gen_image_map_switch_simple_case(angle_format, actual_angle_format, angle_to_gl, 438 angle_to_mtl) 439 440 # Common case: universally-supported formats + universal overrides 441 for angle_format in sorted(angle_to_mtl.keys()): 442 switch_data += gen_image_map_switch_common_case(angle_format, angle_format) 443 for angle_format in sorted(angle_override.keys()): 444 switch_data += gen_image_map_switch_common_case(angle_format, angle_override[angle_format]) 445 446 # Mac GPU case: macOS + Catalyst targets 447 switch_data += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" 448 for angle_format in sorted(mac_specific_map.keys()): 449 switch_data += gen_image_map_switch_mac_case(angle_format, angle_format, angle_to_gl, 450 mac_angle_to_mtl, mac_d24s8_fallbacks) 451 for angle_format in sorted(mac_override.keys()): 452 switch_data += gen_image_map_switch_simple_case(angle_format, mac_override[angle_format], 453 angle_to_gl, mac_angle_to_mtl) 454 for angle_format in sorted(mac_override_bc1.keys()): 455 switch_data += gen_image_map_switch_simple_case(angle_format, 456 mac_override_bc1[angle_format], 457 angle_to_gl, mac_angle_to_mtl) 458 switch_data += "#endif\n" 459 460 # Override missing ES 3.0 formats for older macOS SDK or Catalyst 461 switch_data += "#if (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED < 110000)) || \\\n" 462 switch_data += "TARGET_OS_MACCATALYST\n" 463 for angle_format in sorted(mac_override_es3.keys()): 464 switch_data += gen_image_map_switch_simple_case(angle_format, 465 mac_override_es3[angle_format], 466 angle_to_gl, mac_angle_to_mtl) 467 switch_data += "#endif\n" 468 469 switch_data += "#if TARGET_OS_SIMULATOR\n" 470 for angle_format in sorted(sim_specific_map.keys()): 471 switch_data += gen_image_map_switch_simple_case(angle_format, angle_format, angle_to_gl, 472 sim_specific_map) 473 for angle_format in sorted(sim_override.keys()): 474 switch_data += gen_image_map_switch_simple_case(angle_format, sim_override[angle_format], 475 angle_to_gl, sim_angle_to_mtl) 476 switch_data += "#if TARGET_OS_IOS\n" 477 for angle_format in sorted(astc_tpl_map.keys()): 478 switch_data += gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, 479 astc_tpl_map) 480 switch_data += "#elif TARGET_OS_TV ||TARGET_OS_WATCH\n" 481 482 for angle_format in sorted(astc_tpl_map.keys()): 483 switch_data += gen_image_map_switch_astc_case_tv_watchos(angle_format, angle_to_gl, 484 astc_tpl_map) 485 switch_data += "#endif // TARGET_OS_IOS\n " 486 # iOS specific 487 switch_data += "#elif TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST\n" 488 for angle_format in sorted(ios_specific_map.keys()): 489 switch_data += gen_image_map_switch_simple_case(angle_format, angle_format, angle_to_gl, 490 ios_specific_map) 491 for angle_format in sorted(ios_override.keys()): 492 switch_data += gen_image_map_switch_simple_case(angle_format, ios_override[angle_format], 493 angle_to_gl, ios_angle_to_mtl) 494 switch_data += "#if TARGET_OS_IOS\n" 495 for angle_format in sorted(astc_tpl_map.keys()): 496 switch_data += gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, 497 astc_tpl_map) 498 499 switch_data += "#elif TARGET_OS_TV ||TARGET_OS_WATCH\n" 500 501 for angle_format in sorted(astc_tpl_map.keys()): 502 switch_data += gen_image_map_switch_astc_case_tv_watchos(angle_format, angle_to_gl, 503 astc_tpl_map) 504 switch_data += "#endif // TARGET_OS_IOS || TARGET_OS_TV\n" 505 switch_data += "#endif // TARGET_OS_IPHONE\n" 506 507 # Try to support all iOS formats on newer macOS with Apple GPU. 508 switch_data += "#if (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000))\n" 509 for angle_format in sorted(ios_specific_map.keys()): 510 if (angle_format in mac_override_es3.keys()): 511 # ETC/EAC or packed 16-bit 512 switch_data += gen_image_map_switch_es3_case(angle_format, angle_format, angle_to_gl, 513 ios_angle_to_mtl, mac_override_es3) 514 else: 515 # ASTC sRGB or PVRTC1 516 switch_data += gen_image_map_switch_simple_case(angle_format, angle_format, 517 angle_to_gl, ios_specific_map) 518 # ASTC LDR or HDR 519 for angle_format in sorted(astc_tpl_map.keys()): 520 switch_data += gen_image_map_switch_astc_case_iosmac(angle_format, angle_to_gl, 521 astc_tpl_map) 522 switch_data += "#endif // TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000)) \n" 523 524 switch_data += " default:\n" 525 switch_data += " this->metalFormat = MTLPixelFormatInvalid;\n" 526 switch_data += " this->actualFormatId = angle::FormatID::NONE;" 527 return switch_data 528 529 530def gen_image_mtl_to_angle_switch_string(image_table): 531 angle_to_mtl = image_table["map"] 532 mac_specific_map = image_table["map_mac"] 533 ios_specific_map = image_table["map_ios"] 534 astc_tpl_map = image_table["map_astc_tpl"] 535 536 switch_data = '' 537 538 # Common case 539 for angle_format in sorted(angle_to_mtl.keys()): 540 switch_data += case_image_mtl_to_angle_template.format( 541 mtl_format=angle_to_mtl[angle_format], angle_format=angle_format) 542 543 # Mac specific 544 switch_data += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" 545 for angle_format in sorted(mac_specific_map.keys()): 546 switch_data += case_image_mtl_to_angle_template.format( 547 mtl_format=mac_specific_map[angle_format], angle_format=angle_format) 548 switch_data += "#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" 549 550 # iOS + macOS 11.0+ specific 551 switch_data += "#if TARGET_OS_IPHONE || (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000))\n" 552 for angle_format in sorted(ios_specific_map.keys()): 553 # ETC1_R8G8B8_UNORM_BLOCK is a duplicated of ETC2_R8G8B8_UNORM_BLOCK 554 if angle_format == 'ETC1_R8G8B8_UNORM_BLOCK': 555 continue 556 switch_data += case_image_mtl_to_angle_template.format( 557 mtl_format=ios_specific_map[angle_format], angle_format=angle_format) 558 for angle_format in sorted(astc_tpl_map.keys()): 559 switch_data += case_image_mtl_to_angle_template.format( 560 mtl_format=astc_tpl_map[angle_format] + "LDR", angle_format=angle_format) 561 switch_data += "#if TARGET_OS_IOS || TARGET_OS_OSX \n" 562 for angle_format in sorted(astc_tpl_map.keys()): 563 switch_data += case_image_mtl_to_angle_template.format( 564 mtl_format=astc_tpl_map[angle_format] + "HDR", angle_format=angle_format) 565 switch_data += "#endif // TARGET_OS_IOS || TARGET_OS_OSX\n" 566 switch_data += "#endif // TARGET_OS_IPHONE || mac 11.0+\n" 567 568 switch_data += " default:\n" 569 switch_data += " return angle::FormatID::NONE;\n" 570 return switch_data 571 572 573def gen_vertex_map_switch_case(angle_fmt, actual_angle_fmt, angle_to_mtl_map, override_packed_map): 574 mtl_format = angle_to_mtl_map[actual_angle_fmt] 575 copy_function, default_alpha, same_gl_type = get_vertex_copy_function_and_default_alpha( 576 angle_fmt, actual_angle_fmt) 577 578 if actual_angle_fmt in override_packed_map: 579 # This format has an override when used in tightly packed buffer, 580 # Return if else block 581 angle_fmt_packed = override_packed_map[actual_angle_fmt] 582 mtl_format_packed = angle_to_mtl_map[angle_fmt_packed] 583 copy_function_packed, default_alpha_packed, same_gl_type_packed = get_vertex_copy_function_and_default_alpha( 584 angle_fmt, angle_fmt_packed) 585 586 return case_vertex_format_template2.format( 587 angle_format=angle_fmt, 588 mtl_format_packed=mtl_format_packed, 589 actual_angle_format_packed=angle_fmt_packed, 590 vertex_copy_function_packed=copy_function_packed, 591 default_alpha_packed=default_alpha_packed, 592 same_gl_type_packed=wrap_actual_same_gl_type(same_gl_type_packed), 593 mtl_format=mtl_format, 594 actual_angle_format=actual_angle_fmt, 595 vertex_copy_function=copy_function, 596 default_alpha=default_alpha, 597 same_gl_type=wrap_actual_same_gl_type(same_gl_type)) 598 else: 599 # This format has no packed buffer's override, return ordinary block. 600 return case_vertex_format_template1.format( 601 angle_format=angle_fmt, 602 mtl_format=mtl_format, 603 actual_angle_format=actual_angle_fmt, 604 vertex_copy_function=copy_function, 605 default_alpha=default_alpha, 606 same_gl_type=wrap_actual_same_gl_type(same_gl_type)) 607 608 609def gen_vertex_map_switch_string(vertex_table): 610 angle_to_mtl = vertex_table["map"] 611 angle_override = vertex_table["override"] 612 override_packed = vertex_table["override_tightly_packed"] 613 614 switch_data = '' 615 for angle_fmt in sorted(angle_to_mtl.keys()): 616 switch_data += gen_vertex_map_switch_case(angle_fmt, angle_fmt, angle_to_mtl, 617 override_packed) 618 619 for angle_fmt in sorted(angle_override.keys()): 620 switch_data += gen_vertex_map_switch_case(angle_fmt, angle_override[angle_fmt], 621 angle_to_mtl, override_packed) 622 623 switch_data += " default:\n" 624 switch_data += " this->metalFormat = MTLVertexFormatInvalid;\n" 625 switch_data += " this->actualFormatId = angle::FormatID::NONE;\n" 626 switch_data += " this->vertexLoadFunction = nullptr;" 627 switch_data += " this->defaultAlpha = 0;" 628 switch_data += " this->actualSameGLType = false;" 629 return switch_data 630 631 632def gen_mtl_format_caps_init_string(map_image): 633 caps = map_image['caps'] 634 mac_caps = map_image['caps_mac'] 635 ios_platform_caps = map_image['caps_ios_platform'] 636 ios_specific_caps = map_image['caps_ios_specific'] 637 caps_init_str = '' 638 639 def cap_to_param(caps, key): 640 return '/** ' + key + '*/ ' + caps.get(key, 'false') 641 642 def caps_to_cpp(caps_table): 643 init_str = '' 644 for mtl_format in sorted(caps_table.keys()): 645 caps = caps_table[mtl_format] 646 filterable = cap_to_param(caps, 'filterable') 647 writable = cap_to_param(caps, 'writable') 648 colorRenderable = cap_to_param(caps, 'colorRenderable') 649 depthRenderable = cap_to_param(caps, 'depthRenderable') 650 blendable = cap_to_param(caps, 'blendable') 651 multisample = cap_to_param(caps, 'multisample') 652 resolve = cap_to_param(caps, 'resolve') 653 654 init_str += " setFormatCaps({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7});\n\n".format( 655 mtl_format, filterable, writable, blendable, multisample, resolve, colorRenderable, 656 depthRenderable) 657 658 return init_str 659 660 caps_init_str += caps_to_cpp(caps) 661 662 caps_init_str += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" 663 caps_init_str += caps_to_cpp(mac_caps) 664 caps_init_str += "#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n" 665 666 caps_init_str += "#if (TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST) || \\\n" 667 caps_init_str += " (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000))\n" 668 669 caps_init_str += caps_to_cpp(ios_platform_caps) 670 671 caps_init_str += "#if TARGET_OS_IOS || TARGET_OS_OSX\n" 672 caps_init_str += caps_to_cpp(ios_specific_caps) 673 caps_init_str += "#endif // TARGET_OS_IOS || mac 11.0+ \n" 674 caps_init_str += "#endif // TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST || mac 11.0+ \n" 675 676 return caps_init_str 677 678 679def main(): 680 data_source_name = 'mtl_format_map.json' 681 # auto_script parameters. 682 if len(sys.argv) > 1: 683 inputs = ['../angle_format.py', '../angle_format_map.json', data_source_name] 684 outputs = ['mtl_format_table_autogen.mm'] 685 686 if sys.argv[1] == 'inputs': 687 print(','.join(inputs)) 688 elif sys.argv[1] == 'outputs': 689 print(','.join(outputs)) 690 else: 691 print('Invalid script parameters') 692 return 1 693 return 0 694 695 angle_to_gl = angle_format_utils.load_inverse_table('../angle_format_map.json') 696 697 map_json = angle_format_utils.load_json(data_source_name) 698 map_image = map_json["image"] 699 map_vertex = map_json["vertex"] 700 701 image_switch_data = gen_image_map_switch_string(map_image, angle_to_gl) 702 image_mtl_to_angle_switch_data = gen_image_mtl_to_angle_switch_string(map_image) 703 704 vertex_switch_data = gen_vertex_map_switch_string(map_vertex) 705 706 caps_init_str = gen_mtl_format_caps_init_string(map_image) 707 708 output_cpp = template_autogen_inl.format( 709 script_name=sys.argv[0], 710 data_source_name=data_source_name, 711 angle_image_format_switch=image_switch_data, 712 mtl_pixel_format_switch=image_mtl_to_angle_switch_data, 713 angle_vertex_format_switch=vertex_switch_data, 714 metal_format_caps=caps_init_str) 715 with open('mtl_format_table_autogen.mm', 'wt') as out_file: 716 out_file.write(output_cpp) 717 out_file.close() 718 719 720if __name__ == '__main__': 721 sys.exit(main()) 722