blob: d19d99ea1853c85eafa3ae4578db0485fff6f240 [file] [log] [blame]
#!/usr/bin/python
# 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
#
from datetime import date
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 {copyright_year} 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.itervalues())
channels_different = not all([component_bits == bits.itervalues().next() for component_bits in bits.itervalues()])
# 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 json.iteritems():
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 angle_format.iteritems():
if k == "FL10Plus":
assert support_test is None
support_test = "OnlyFL10Plus(deviceCaps)"
for k2, v2 in v.iteritems():
supported_case[k2] = v2
elif k == "FL9_3":
split = True
for k2, v2 in v.iteritems():
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.iteritems()):
if format_name not in json_data:
continue
# Typeless internal formats are dummy 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
json_map = angle_format.load_with_override(os.path.abspath('texture_format_map.json'))
data_source_name = 'texture_format_data.json'
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],
copyright_year = date.today().year,
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()