• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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