1#!/usr/bin/python
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_dxgi_support_tables.py:
7#  Code generation for the DXGI support tables. Determines which formats
8#  are natively support in D3D10+.
9#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
10#
11#  NOTE: The "never supported" formats should not be combined with the
12#  "supported" and "optional" ones. At the moment, this does not cause
13#  any issues as ANGLE does not internally check for "never supported".
14#
15# MSDN links:
16#  10Level9 9_3: https://msdn.microsoft.com/en-us/library/windows/desktop/mt790740.aspx
17#  10_0: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627090.aspx
18#  10_1: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627091.aspx
19#  11_0: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471325.aspx
20#  11_1: https://msdn.microsoft.com/en-us/library/windows/desktop/hh404483.aspx
21
22import sys
23import json
24
25macro_prefix = 'F_'
26
27template = """// GENERATED FILE - DO NOT EDIT. See dxgi_support_data.json.
28//
29// Copyright 2015 The ANGLE Project Authors. All rights reserved.
30// Use of this source code is governed by a BSD-style license that can be
31// found in the LICENSE file.
32//
33// dxgi_support_table:
34//   Queries for DXGI support of various texture formats. Depends on DXGI
35//   version, D3D feature level, and is sometimes guaranteed or optional.
36//
37
38#include "libANGLE/renderer/dxgi_support_table.h"
39
40#include "common/debug.h"
41
42namespace rx
43{{
44
45namespace d3d11
46{{
47
48#define {prefix}2D D3D11_FORMAT_SUPPORT_TEXTURE2D
49#define {prefix}3D D3D11_FORMAT_SUPPORT_TEXTURE3D
50#define {prefix}CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE
51#define {prefix}SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
52#define {prefix}RT D3D11_FORMAT_SUPPORT_RENDER_TARGET
53#define {prefix}MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
54#define {prefix}DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
55#define {prefix}MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN
56
57namespace
58{{
59
60const DXGISupport &GetDefaultSupport()
61{{
62    static UINT AllSupportFlags =
63        D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D |
64        D3D11_FORMAT_SUPPORT_TEXTURECUBE | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
65        D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET |
66        D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
67    static const DXGISupport defaultSupport(0, 0, AllSupportFlags);
68    return defaultSupport;
69}}
70
71const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat)
72{{
73    // clang-format off
74    switch (dxgiFormat)
75    {{
76{table_data_9_3}
77        default:
78            UNREACHABLE();
79            return GetDefaultSupport();
80    }}
81    // clang-format on
82}}
83
84const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
85{{
86    // clang-format off
87    switch (dxgiFormat)
88    {{
89{table_data_10_0}
90        default:
91            UNREACHABLE();
92            return GetDefaultSupport();
93    }}
94    // clang-format on
95}}
96
97const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
98{{
99    // clang-format off
100    switch (dxgiFormat)
101    {{
102{table_data_10_1}
103        default:
104            UNREACHABLE();
105            return GetDefaultSupport();
106    }}
107    // clang-format on
108}}
109
110const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
111{{
112    // clang-format off
113    switch (dxgiFormat)
114    {{
115{table_data_11_0}
116        default:
117            UNREACHABLE();
118            return GetDefaultSupport();
119    }}
120    // clang-format on
121}}
122
123const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat)
124{{
125    // clang-format off
126    switch (dxgiFormat)
127    {{
128{table_data_11_1}
129        default:
130            UNREACHABLE();
131            return GetDefaultSupport();
132    }}
133    // clang-format on
134}}
135
136}}
137
138#undef {prefix}2D
139#undef {prefix}3D
140#undef {prefix}CUBE
141#undef {prefix}SAMPLE
142#undef {prefix}RT
143#undef {prefix}MS
144#undef {prefix}DS
145#undef {prefix}MIPGEN
146
147const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
148{{
149    switch (featureLevel)
150    {{
151        case D3D_FEATURE_LEVEL_9_3:
152            return GetDXGISupport_9_3(dxgiFormat);
153        case D3D_FEATURE_LEVEL_10_0:
154            return GetDXGISupport_10_0(dxgiFormat);
155        case D3D_FEATURE_LEVEL_10_1:
156            return GetDXGISupport_10_1(dxgiFormat);
157        case D3D_FEATURE_LEVEL_11_0:
158            return GetDXGISupport_11_0(dxgiFormat);
159        case D3D_FEATURE_LEVEL_11_1:
160            return GetDXGISupport_11_1(dxgiFormat);
161        default:
162            return GetDefaultSupport();
163    }}
164}}
165
166}} // namespace d3d11
167
168}} // namespace rx
169"""
170
171
172def do_format(format_data):
173    table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': '', '11_1': ''}
174
175    json_flag_to_d3d = {
176        'texture2D': macro_prefix + '2D',
177        'texture3D': macro_prefix + '3D',
178        'textureCube': macro_prefix + 'CUBE',
179        'shaderSample': macro_prefix + 'SAMPLE',
180        'renderTarget': macro_prefix + 'RT',
181        'multisampleRT': macro_prefix + 'MS',
182        'depthStencil': macro_prefix + 'DS',
183        'mipAutoGen': macro_prefix + 'MIPGEN'
184    }
185
186    for format_name, format_support in sorted(format_data.iteritems()):
187
188        always_supported = set()
189        never_supported = set()
190        optionally_supported = set()
191        fl_9_3_supported = set()
192        fl_9_3_check = set()
193        fl_10_0_supported = set()
194        fl_10_1_supported = set()
195        fl_11_0_supported = set()
196        fl_11_0_check = set()
197        fl_11_1_supported = set()
198        fl_10_0_check_10_1_supported = set()
199        fl_10_0_check_11_0_supported = set()
200
201        for json_flag, support in format_support.iteritems():
202
203            d3d_flag = [json_flag_to_d3d[json_flag]]
204
205            if support == 'check':
206                optionally_supported.update(d3d_flag)
207            elif support == 'always':
208                always_supported.update(d3d_flag)
209            elif support == 'never':
210                never_supported.update(d3d_flag)
211            elif support == '10_0':
212                fl_10_0_supported.update(d3d_flag)
213            elif support == '10_1':
214                fl_10_1_supported.update(d3d_flag)
215            elif support == '11_0':
216                fl_11_0_supported.update(d3d_flag)
217            elif support == '11_1':
218                fl_11_1_supported.update(d3d_flag)
219            elif support == 'dxgi1_2':
220                # TODO(jmadill): DXGI 1.2 handling.
221                always_supported.update(d3d_flag)
222            elif support == '10_0check10_1always':
223                fl_10_0_check_10_1_supported.update(d3d_flag)
224            elif support == '10_0check11_0always':
225                fl_10_0_check_11_0_supported.update(d3d_flag)
226            elif support == '11_0check':
227                fl_11_0_check.update(d3d_flag)
228            elif support == '9_3always_10_0check11_0always':
229                fl_9_3_supported.update(d3d_flag)
230                fl_10_0_check_11_0_supported.update(d3d_flag)
231            elif support == '9_3check_10_0always':
232                fl_9_3_check.update(d3d_flag)
233                fl_10_0_supported.update(d3d_flag)
234            elif support == '9_3check11_0always':
235                fl_9_3_check.update(d3d_flag)
236                fl_10_0_check_11_0_supported.update(d3d_flag)
237            else:
238                print("Data specification error: " + support)
239                sys.exit(1)
240
241        for feature_level in ['9_3', '10_0', '10_1', '11_0', '11_1']:
242            always_for_fl = always_supported
243            optional_for_fl = optionally_supported
244            if feature_level == '9_3':
245                always_for_fl = fl_9_3_supported.union(always_for_fl)
246                optional_for_fl = fl_9_3_check.union(optional_for_fl)
247            elif feature_level == '10_0':
248                always_for_fl = fl_10_0_supported.union(always_for_fl)
249                optional_for_fl = fl_10_0_check_10_1_supported.union(optional_for_fl)
250                optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl)
251            elif feature_level == '10_1':
252                always_for_fl = fl_10_0_supported.union(always_for_fl)
253                always_for_fl = fl_10_1_supported.union(always_for_fl)
254                always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl)
255                optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl)
256            elif feature_level == '11_0':
257                always_for_fl = fl_10_0_supported.union(always_for_fl)
258                always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl)
259                always_for_fl = fl_10_0_check_11_0_supported.union(always_for_fl)
260                always_for_fl = fl_10_1_supported.union(always_for_fl)
261                always_for_fl = fl_11_0_supported.union(always_for_fl)
262            elif feature_level == '11_1':
263                always_for_fl = fl_10_0_supported.union(always_for_fl)
264                always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl)
265                always_for_fl = fl_10_0_check_11_0_supported.union(always_for_fl)
266                always_for_fl = fl_10_1_supported.union(always_for_fl)
267                always_for_fl = fl_11_0_supported.union(always_for_fl)
268                always_for_fl = fl_11_1_supported.union(always_for_fl)
269
270            always = ' | '.join(sorted(always_for_fl))
271            never = ' | '.join(sorted(never_supported))
272            optional = ' | '.join(sorted(optional_for_fl))
273
274            if not always:
275                always = '0'
276            if not never:
277                never = '0'
278            if not optional:
279                optional = '0'
280
281            table_data[feature_level] += '        case ' + format_name + ':\n'
282            table_data[feature_level] += '        {\n'
283            table_data[
284                feature_level] += '            static const DXGISupport info(' + always + ', ' + never + ', ' + optional + ');\n'
285            table_data[feature_level] += '            return info;\n'
286            table_data[feature_level] += '        }\n'
287
288    return table_data
289
290
291def join_table_data(table_data_1, table_data_2):
292    return {
293        '9_3': table_data_1['9_3'] + table_data_2['9_3'],
294        '10_0': table_data_1['10_0'] + table_data_2['10_0'],
295        '10_1': table_data_1['10_1'] + table_data_2['10_1'],
296        '11_0': table_data_1['11_0'] + table_data_2['11_0'],
297        '11_1': table_data_1['11_1'] + table_data_2['11_1']
298    }
299
300
301def main():
302
303    # auto_script parameters.
304    if len(sys.argv) > 1:
305        inputs = ['dxgi_support_data.json']
306        outputs = ['dxgi_support_table_autogen.cpp']
307
308        if sys.argv[1] == 'inputs':
309            print ','.join(inputs)
310        elif sys.argv[1] == 'outputs':
311            print ','.join(outputs)
312        else:
313            print('Invalid script parameters')
314            return 1
315        return 0
316
317    with open('dxgi_support_data.json') as dxgi_file:
318        file_data = dxgi_file.read()
319        dxgi_file.close()
320        json_data = json.loads(file_data)
321
322        table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': '', '11_1': ''}
323
324        for format_data in json_data:
325            table_data = join_table_data(table_data, do_format(format_data))
326
327        out_data = template.format(
328            prefix=macro_prefix,
329            table_data_9_3=table_data['9_3'],
330            table_data_10_0=table_data['10_0'],
331            table_data_10_1=table_data['10_1'],
332            table_data_11_0=table_data['11_0'],
333            table_data_11_1=table_data['11_1'])
334
335        with open('dxgi_support_table_autogen.cpp', 'wt') as out_file:
336            out_file.write(out_data)
337            out_file.close()
338    return 0
339
340
341if __name__ == '__main__':
342    sys.exit(main())
343