1#!/usr/bin/python3 2# Copyright 2015 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_texture_format_table.py: 7# Code generation for texture format map 8# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 9# 10 11import json 12import math 13import pprint 14import os 15import sys 16 17sys.path.append('../..') 18import angle_format 19 20template_texture_format_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT. 21// Generated by {script_name} using data from {data_source_name} 22// 23// Copyright 2015 The ANGLE Project Authors. All rights reserved. 24// Use of this source code is governed by a BSD-style license that can be 25// found in the LICENSE file. 26// 27// texture_format_table: 28// Queries for full textureFormat information based in internalFormat 29// 30 31#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" 32 33#include "image_util/copyimage.h" 34#include "image_util/generatemip.h" 35#include "image_util/loadimage.h" 36 37#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" 38#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" 39#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h" 40 41using namespace angle; 42 43namespace rx 44{{ 45 46namespace d3d11 47{{ 48 49// static 50const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps) 51{{ 52 // clang-format off 53 switch (internalFormat) 54 {{ 55{angle_format_info_cases} 56 default: 57 break; 58 }} 59 // clang-format on 60 61 UNREACHABLE(); 62 static constexpr Format defaultInfo; 63 return defaultInfo; 64}} 65 66}} // namespace d3d11 67 68}} // namespace rx 69""" 70 71 72def get_swizzle_format_id(internal_format, angle_format): 73 angle_format_id = angle_format["formatName"] 74 if (internal_format == 'GL_NONE') or (angle_format_id == 'NONE'): 75 return 'GL_NONE' 76 77 elif 'swizzleFormat' in angle_format: 78 # For some special formats like compressed formats that don't have a clearly defined number 79 # of bits per channel, swizzle format needs to be specified manually. 80 return angle_format['swizzleFormat'] 81 82 if 'bits' not in angle_format: 83 raise ValueError('no bits information for determining swizzleformat for format: ' + 84 internal_format) 85 86 bits = angle_format['bits'] 87 max_component_bits = max(bits.values()) 88 bits_iter = iter(list(sorted(bits.values()))) 89 channels_different = not all( 90 [component_bits == next(bits_iter) for component_bits in bits.values()]) 91 92 # The format itself can be used for swizzles if it can be accessed as a render target and 93 # sampled and the bit count for all 4 channels is the same. 94 if "rtvFormat" in angle_format and "srvFormat" in angle_format and "uavFormat" in angle_format and not channels_different and len( 95 angle_format['channels']) == 4: 96 return angle_format[ 97 "glInternalFormat"] if "glInternalFormat" in angle_format else internal_format 98 99 b = int(math.ceil(float(max_component_bits) / 8) * 8) 100 101 # Depth formats need special handling, since combined depth/stencil formats don't have a clearly 102 # defined component type. 103 if angle_format['channels'].find('d') >= 0: 104 if b == 24 or b == 32: 105 return 'GL_RGBA32F' 106 if b == 16: 107 return 'GL_RGBA16_EXT' 108 109 if b == 24: 110 raise ValueError('unexpected 24-bit format when determining swizzleformat for format: ' + 111 internal_format) 112 113 if 'componentType' not in angle_format: 114 raise ValueError('no component type information for determining swizzleformat for format: ' 115 + internal_format) 116 117 component_type = angle_format['componentType'] 118 119 swizzle = "GL_RGBA" + str(b) 120 121 if component_type == 'uint': 122 swizzle += "I" 123 elif component_type == 'int': 124 swizzle += "I" 125 elif component_type == 'unorm': 126 if (b == 16): 127 swizzle += "_EXT" 128 elif component_type == 'snorm': 129 swizzle += "_SNORM" 130 if (b == 16): 131 swizzle += "_EXT" 132 elif component_type == 'float': 133 swizzle += "F" 134 if (b == 16): 135 swizzle += "_EXT" 136 else: 137 raise ValueError('could not determine swizzleformat based on componentType for format: ' + 138 internal_format) 139 140 return swizzle 141 142 143def get_blit_srv_format(angle_format): 144 if 'channels' not in angle_format: 145 return 'DXGI_FORMAT_UNKNOWN' 146 if 'r' in angle_format['channels'] and angle_format['componentType'] in ['int', 'uint']: 147 return angle_format['rtvFormat'] 148 149 return angle_format["srvFormat"] if "srvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN" 150 151 152def get_stencil_srv_format(angle_format): 153 return angle_format[ 154 "stencilSRVFormat"] if "stencilSRVFormat" in angle_format else "DXGI_FORMAT_UNKNOWN" 155 156 157def get_typeless_format(angle_format): 158 return angle_format[ 159 "typelessFormat"] if "typelessFormat" in angle_format else "DXGI_FORMAT_UNKNOWN" 160 161 162format_entry_template = """{space}{{ 163{space} static constexpr Format info({internalFormat}, 164{space} angle::FormatID::{formatName}, 165{space} {texFormat}, 166{space} {srvFormat}, 167{space} {uavFormat}, 168{space} {rtvFormat}, 169{space} {dsvFormat}, 170{space} {blitSRVFormat}, 171{space} {stencilSRVFormat}, 172{space} {typelessFormat}, 173{space} {swizzleFormat}, 174{space} {initializer}); 175{space} return info; 176{space}}} 177""" 178 179split_format_entry_template = """{space} {condition} 180{space} {{ 181{space} static constexpr Format info({internalFormat}, 182{space} angle::FormatID::{formatName}, 183{space} {texFormat}, 184{space} {srvFormat}, 185{space} {uavFormat}, 186{space} {rtvFormat}, 187{space} {dsvFormat}, 188{space} {blitSRVFormat}, 189{space} {stencilSRVFormat}, 190{space} {typelessFormat}, 191{space} {swizzleFormat}, 192{space} {initializer}); 193{space} return info; 194{space} }} 195""" 196 197 198def json_to_table_data(internal_format, format_name, prefix, json): 199 200 table_data = "" 201 202 parsed = { 203 "space": " ", 204 "internalFormat": internal_format, 205 "formatName": format_name, 206 "texFormat": "DXGI_FORMAT_UNKNOWN", 207 "srvFormat": "DXGI_FORMAT_UNKNOWN", 208 "uavFormat": "DXGI_FORMAT_UNKNOWN", 209 "rtvFormat": "DXGI_FORMAT_UNKNOWN", 210 "dsvFormat": "DXGI_FORMAT_UNKNOWN", 211 "condition": prefix, 212 } 213 214 for k, v in sorted(json.items()): 215 parsed[k] = v 216 217 # Derived values. 218 parsed["blitSRVFormat"] = get_blit_srv_format(parsed) 219 parsed["stencilSRVFormat"] = get_stencil_srv_format(parsed) 220 parsed["typelessFormat"] = get_typeless_format(parsed) 221 parsed["swizzleFormat"] = get_swizzle_format_id(internal_format, parsed) 222 parsed["initializer"] = angle_format.get_internal_format_initializer( 223 internal_format, parsed["formatName"]) 224 225 if len(prefix) > 0: 226 return split_format_entry_template.format(**parsed) 227 else: 228 return format_entry_template.format(**parsed) 229 230 231def parse_json_angle_format_case(format_name, angle_format, json_data): 232 supported_case = {} 233 unsupported_case = {} 234 support_test = None 235 fallback = None 236 237 for k, v in sorted(angle_format.items()): 238 if k == "FL10Plus": 239 assert support_test is None 240 support_test = "OnlyFL10Plus(deviceCaps)" 241 for k2, v2 in sorted(v.items()): 242 supported_case[k2] = v2 243 elif k == "FL9_3": 244 split = True 245 for k2, v2 in sorted(v.items()): 246 unsupported_case[k2] = v2 247 elif k == "supportTest": 248 assert support_test is None 249 support_test = v 250 elif k == "fallbackFormat": 251 fallback = v 252 else: 253 supported_case[k] = v 254 unsupported_case[k] = v 255 256 if fallback != None: 257 unsupported_case, _, _ = parse_json_angle_format_case(fallback, json_data[fallback], 258 json_data) 259 unsupported_case["formatName"] = fallback 260 261 if support_test != None: 262 return supported_case, unsupported_case, support_test 263 else: 264 return supported_case, None, None 265 266 267def parse_json_into_switch_angle_format_string(json_map, json_data): 268 table_data = '' 269 270 for internal_format, format_name in sorted(json_map.items()): 271 272 if format_name not in json_data: 273 continue 274 275 # Typeless internal formats are fake formats just used to fit support 276 # for typeless D3D textures into the format system. Their properties 277 # should not be queried. 278 if 'TYPELESS' in internal_format: 279 continue 280 281 angle_format = json_data[format_name] 282 283 supported_case, unsupported_case, support_test = parse_json_angle_format_case( 284 format_name, angle_format, json_data) 285 286 table_data += ' case ' + internal_format + ':\n' 287 288 if support_test != None: 289 table_data += " {\n" 290 table_data += json_to_table_data(internal_format, format_name, 291 "if (" + support_test + ")", supported_case) 292 table_data += json_to_table_data(internal_format, format_name, "else", 293 unsupported_case) 294 table_data += " }\n" 295 else: 296 table_data += json_to_table_data(internal_format, format_name, "", supported_case) 297 298 return table_data 299 300 301def main(): 302 303 map_file_name = 'texture_format_map.json' 304 data_source_name = 'texture_format_data.json' 305 306 # auto_script parameters. 307 if len(sys.argv) > 1: 308 inputs = ['../../angle_format.py', data_source_name, map_file_name] 309 outputs = ['texture_format_table_autogen.cpp'] 310 311 if sys.argv[1] == 'inputs': 312 print(','.join(inputs)) 313 elif sys.argv[1] == 'outputs': 314 print(','.join(outputs)) 315 else: 316 print('Invalid script parameters') 317 return 1 318 return 0 319 320 json_map = angle_format.load_with_override(os.path.abspath(map_file_name)) 321 json_data = angle_format.load_json(data_source_name) 322 323 angle_format_cases = parse_json_into_switch_angle_format_string(json_map, json_data) 324 output_cpp = template_texture_format_table_autogen_cpp.format( 325 script_name=os.path.basename(sys.argv[0]), 326 angle_format_info_cases=angle_format_cases, 327 data_source_name=data_source_name) 328 with open('texture_format_table_autogen.cpp', 'wt') as out_file: 329 out_file.write(output_cpp) 330 out_file.close() 331 return 0 332 333 334if __name__ == '__main__': 335 sys.exit(main()) 336