| #!/usr/bin/python3 |
| # Copyright 2015 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_texture_format_table.py: |
| # Code generation for texture format map |
| # NOTE: don't run this script directly. Run scripts/run_code_generation.py. |
| # |
| |
| import json |
| import math |
| import pprint |
| import os |
| import sys |
| |
| sys.path.append('../..') |
| import angle_format |
| |
| template_texture_format_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT. |
| // Generated by {script_name} using data from {data_source_name} |
| // |
| // Copyright 2015 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. |
| // |
| // texture_format_table: |
| // Queries for full textureFormat information based in internalFormat |
| // |
| |
| #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" |
| |
| #include "image_util/copyimage.h" |
| #include "image_util/generatemip.h" |
| #include "image_util/loadimage.h" |
| |
| #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" |
| #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" |
| #include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h" |
| |
| using namespace angle; |
| |
| namespace rx |
| {{ |
| |
| namespace d3d11 |
| {{ |
| |
| // static |
| const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps) |
| {{ |
| // clang-format off |
| switch (internalFormat) |
| {{ |
| {angle_format_info_cases} |
| default: |
| break; |
| }} |
| // clang-format on |
| |
| UNREACHABLE(); |
| static constexpr Format defaultInfo; |
| return defaultInfo; |
| }} |
| |
| }} // namespace d3d11 |
| |
| }} // namespace rx |
| """ |
| |
| |
| def get_swizzle_format_id(internal_format, angle_format): |
| angle_format_id = angle_format["formatName"] |
| if (internal_format == 'GL_NONE') or (angle_format_id == 'NONE'): |
| return 'GL_NONE' |
| |
| elif 'swizzleFormat' in angle_format: |
| # For some special formats like compressed formats that don't have a clearly defined number |
| # of bits per channel, swizzle format needs to be specified manually. |
| return angle_format['swizzleFormat'] |
| |
| if 'bits' not in angle_format: |
| raise ValueError('no bits information for determining swizzleformat for format: ' + |
| internal_format) |
| |
| bits = angle_format['bits'] |
| max_component_bits = max(bits.values()) |
| bits_iter = iter(list(sorted(bits.values()))) |
| channels_different = not all( |
| [component_bits == next(bits_iter) for component_bits in bits.values()]) |
| |
| # The format itself can be used for swizzles if it can be accessed as a render target and |
| # sampled and the bit count for all 4 channels is the same. |
| if "rtvFormat" in angle_format and "srvFormat" in angle_format and "uavFormat" in angle_format and not channels_different and len( |
| angle_format['channels']) == 4: |
| return angle_format[ |
| "glInternalFormat"] if "glInternalFormat" in angle_format else internal_format |
| |
| b = int(math.ceil(float(max_component_bits) / 8) * 8) |
| |
| # Depth formats need special handling, since combined depth/stencil formats don't have a clearly |
| # defined component type. |
| if angle_format['channels'].find('d') >= 0: |
| if b == 24 or b == 32: |
| return 'GL_RGBA32F' |
| if b == 16: |
| return 'GL_RGBA16_EXT' |
| |
| if b == 24: |
| raise ValueError('unexpected 24-bit format when determining swizzleformat for format: ' + |
| internal_format) |
| |
| if 'componentType' not in angle_format: |
| raise ValueError('no component type information for determining swizzleformat for format: ' |
| + internal_format) |
| |
| component_type = angle_format['componentType'] |
| |
| swizzle = "GL_RGBA" + str(b) |
| |
| if component_type == 'uint': |
| swizzle += "I" |
| elif component_type == 'int': |
| swizzle += "I" |
| elif component_type == 'unorm': |
| if (b == 16): |
| swizzle += "_EXT" |
| elif component_type == 'snorm': |
| swizzle += "_SNORM" |
| if (b == 16): |
| swizzle += "_EXT" |
| elif component_type == 'float': |
| swizzle += "F" |
| if (b == 16): |
| swizzle += "_EXT" |
| else: |
| raise ValueError('could not determine swizzleformat based on componentType for format: ' + |
| internal_format) |
| |
| return swizzle |
| |
| |
| def get_blit_srv_format(angle_format): |
| if 'channels' not in angle_format: |
| return 'DXGI_FORMAT_UNKNOWN' |
| if 'r' in angle_format['channels'] and angle_format['componentType'] in ['int', 'uint']: |
| return angle_format['rtvFormat'] |
| |
| return angle_format["srvFormat"] if "srvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN" |
| |
| |
| format_entry_template = """{space}{{ |
| {space} static constexpr Format info({internalFormat}, |
| {space} angle::FormatID::{formatName}, |
| {space} {texFormat}, |
| {space} {srvFormat}, |
| {space} {uavFormat}, |
| {space} {rtvFormat}, |
| {space} {dsvFormat}, |
| {space} {blitSRVFormat}, |
| {space} {swizzleFormat}, |
| {space} {initializer}); |
| {space} return info; |
| {space}}} |
| """ |
| |
| split_format_entry_template = """{space} {condition} |
| {space} {{ |
| {space} static constexpr Format info({internalFormat}, |
| {space} angle::FormatID::{formatName}, |
| {space} {texFormat}, |
| {space} {srvFormat}, |
| {space} {uavFormat}, |
| {space} {rtvFormat}, |
| {space} {dsvFormat}, |
| {space} {blitSRVFormat}, |
| {space} {swizzleFormat}, |
| {space} {initializer}); |
| {space} return info; |
| {space} }} |
| """ |
| |
| |
| def json_to_table_data(internal_format, format_name, prefix, json): |
| |
| table_data = "" |
| |
| parsed = { |
| "space": " ", |
| "internalFormat": internal_format, |
| "formatName": format_name, |
| "texFormat": "DXGI_FORMAT_UNKNOWN", |
| "srvFormat": "DXGI_FORMAT_UNKNOWN", |
| "uavFormat": "DXGI_FORMAT_UNKNOWN", |
| "rtvFormat": "DXGI_FORMAT_UNKNOWN", |
| "dsvFormat": "DXGI_FORMAT_UNKNOWN", |
| "condition": prefix, |
| } |
| |
| for k, v in sorted(json.items()): |
| parsed[k] = v |
| |
| # Derived values. |
| parsed["blitSRVFormat"] = get_blit_srv_format(parsed) |
| parsed["swizzleFormat"] = get_swizzle_format_id(internal_format, parsed) |
| parsed["initializer"] = angle_format.get_internal_format_initializer( |
| internal_format, parsed["formatName"]) |
| |
| if len(prefix) > 0: |
| return split_format_entry_template.format(**parsed) |
| else: |
| return format_entry_template.format(**parsed) |
| |
| |
| def parse_json_angle_format_case(format_name, angle_format, json_data): |
| supported_case = {} |
| unsupported_case = {} |
| support_test = None |
| fallback = None |
| |
| for k, v in sorted(angle_format.items()): |
| if k == "FL10Plus": |
| assert support_test is None |
| support_test = "OnlyFL10Plus(deviceCaps)" |
| for k2, v2 in sorted(v.items()): |
| supported_case[k2] = v2 |
| elif k == "FL9_3": |
| split = True |
| for k2, v2 in sorted(v.items()): |
| unsupported_case[k2] = v2 |
| elif k == "supportTest": |
| assert support_test is None |
| support_test = v |
| elif k == "fallbackFormat": |
| fallback = v |
| else: |
| supported_case[k] = v |
| unsupported_case[k] = v |
| |
| if fallback != None: |
| unsupported_case, _, _ = parse_json_angle_format_case(fallback, json_data[fallback], |
| json_data) |
| unsupported_case["formatName"] = fallback |
| |
| if support_test != None: |
| return supported_case, unsupported_case, support_test |
| else: |
| return supported_case, None, None |
| |
| |
| def parse_json_into_switch_angle_format_string(json_map, json_data): |
| table_data = '' |
| |
| for internal_format, format_name in sorted(json_map.items()): |
| |
| if format_name not in json_data: |
| continue |
| |
| # Typeless internal formats are fake formats just used to fit support |
| # for typeless D3D textures into the format system. Their properties |
| # should not be queried. |
| if 'TYPELESS' in internal_format: |
| continue |
| |
| angle_format = json_data[format_name] |
| |
| supported_case, unsupported_case, support_test = parse_json_angle_format_case( |
| format_name, angle_format, json_data) |
| |
| table_data += ' case ' + internal_format + ':\n' |
| |
| if support_test != None: |
| table_data += " {\n" |
| table_data += json_to_table_data(internal_format, format_name, |
| "if (" + support_test + ")", supported_case) |
| table_data += json_to_table_data(internal_format, format_name, "else", |
| unsupported_case) |
| table_data += " }\n" |
| else: |
| table_data += json_to_table_data(internal_format, format_name, "", supported_case) |
| |
| return table_data |
| |
| |
| def main(): |
| |
| map_file_name = 'texture_format_map.json' |
| data_source_name = 'texture_format_data.json' |
| |
| # auto_script parameters. |
| if len(sys.argv) > 1: |
| inputs = ['../../angle_format.py', data_source_name, map_file_name] |
| outputs = ['texture_format_table_autogen.cpp'] |
| |
| 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 |
| |
| json_map = angle_format.load_with_override(os.path.abspath(map_file_name)) |
| json_data = angle_format.load_json(data_source_name) |
| |
| angle_format_cases = parse_json_into_switch_angle_format_string(json_map, json_data) |
| output_cpp = template_texture_format_table_autogen_cpp.format( |
| script_name=sys.argv[0], |
| angle_format_info_cases=angle_format_cases, |
| data_source_name=data_source_name) |
| with open('texture_format_table_autogen.cpp', 'wt') as out_file: |
| out_file.write(output_cpp) |
| out_file.close() |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |