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