• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2# Copyright 2017 Advanced Micro Devices, Inc.
3#
4# Permission is hereby granted, free of charge, to any person obtaining a
5# copy of this software and associated documentation files (the "Software"),
6# to deal in the Software without restriction, including without limitation
7# on the rights to use, copy, modify, merge, publish, distribute, sub
8# license, and/or sell copies of the Software, and to permit persons to whom
9# the Software is furnished to do so, subject to the following conditions:
10#
11# The above copyright notice and this permission notice (including the next
12# paragraph) shall be included in all copies or substantial portions of the
13# Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21# USE OR OTHER DEALINGS IN THE SOFTWARE.
22#
23"""
24Script that generates the mapping from Gallium PIPE_FORMAT_xxx to GFX10_FORMAT_xxx enums.
25"""
26
27import json
28import mako.template
29import os
30import re
31import sys
32
33AMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../registers"))
34UTIL_FORMAT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../../util/format"))
35sys.path.extend([AMD_REGISTERS, UTIL_FORMAT])
36
37from regdb import Object, RegisterDatabase
38from u_format_parse import *
39
40# ----------------------------------------------------------------------------
41# Hard-coded mappings
42
43def hardcoded_format(hw_enum):
44    return Object(img_format=hw_enum, flags=[])
45
46HARDCODED = {
47    'PIPE_FORMAT_Z32_FLOAT_S8X24_UINT': hardcoded_format('X24_8_32_FLOAT'),
48    'PIPE_FORMAT_Z24_UNORM_S8_UINT': hardcoded_format('8_24_UNORM'),
49    'PIPE_FORMAT_S8_UINT_Z24_UNORM': hardcoded_format('24_8_UNORM'),
50    'PIPE_FORMAT_Z32_UNORM': None,
51    'PIPE_FORMAT_Z16_UNORM_S8_UINT': None,
52
53    'PIPE_FORMAT_R9G9B9E5_FLOAT': hardcoded_format('5_9_9_9_FLOAT'),
54    'PIPE_FORMAT_R11G11B10_FLOAT': hardcoded_format('10_11_11_FLOAT'), # NOTE: full set of int/unorm/etc. exists
55
56    'PIPE_FORMAT_R8G8_B8G8_UNORM': hardcoded_format('GB_GR_UNORM'),
57    'PIPE_FORMAT_G8R8_B8R8_UNORM': hardcoded_format('GB_GR_UNORM'),
58
59    'PIPE_FORMAT_R8G8_R8B8_UNORM': hardcoded_format('BG_RG_UNORM'),
60    'PIPE_FORMAT_G8R8_G8B8_UNORM': hardcoded_format('BG_RG_UNORM'),
61
62    # These mixed channel types are not supported natively
63    'PIPE_FORMAT_R8SG8SB8UX8U_NORM': None,
64    'PIPE_FORMAT_R10SG10SB10SA2U_NORM': None,
65    'PIPE_FORMAT_R5SG5SB6U_NORM': None,
66
67    # Only R8G8_SRGB is supported, not L8A8_SRGB
68    'PIPE_FORMAT_L8A8_SRGB': None,
69
70    # S3TC
71    'PIPE_FORMAT_DXT1_RGB': hardcoded_format('BC1_UNORM'),
72    'PIPE_FORMAT_DXT1_RGBA': hardcoded_format('BC1_UNORM'),
73    'PIPE_FORMAT_DXT1_SRGB': hardcoded_format('BC1_SRGB'),
74    'PIPE_FORMAT_DXT1_SRGBA': hardcoded_format('BC1_SRGB'),
75    'PIPE_FORMAT_DXT3_RGBA': hardcoded_format('BC2_UNORM'),
76    'PIPE_FORMAT_DXT3_SRGBA': hardcoded_format('BC2_SRGB'),
77    'PIPE_FORMAT_DXT5_RGBA': hardcoded_format('BC3_UNORM'),
78    'PIPE_FORMAT_DXT5_SRGBA': hardcoded_format('BC3_SRGB'),
79
80    # RGTC
81    'PIPE_FORMAT_RGTC1_UNORM': hardcoded_format('BC4_UNORM'),
82    'PIPE_FORMAT_RGTC1_SNORM': hardcoded_format('BC4_SNORM'),
83    'PIPE_FORMAT_RGTC2_UNORM': hardcoded_format('BC5_UNORM'),
84    'PIPE_FORMAT_RGTC2_SNORM': hardcoded_format('BC5_SNORM'),
85    'PIPE_FORMAT_LATC1_UNORM': hardcoded_format('BC4_UNORM'),
86    'PIPE_FORMAT_LATC1_SNORM': hardcoded_format('BC4_SNORM'),
87    'PIPE_FORMAT_LATC2_UNORM': hardcoded_format('BC5_UNORM'),
88    'PIPE_FORMAT_LATC2_SNORM': hardcoded_format('BC5_SNORM'),
89
90    # BPTC
91    'PIPE_FORMAT_BPTC_RGB_UFLOAT': hardcoded_format('BC6_UFLOAT'),
92    'PIPE_FORMAT_BPTC_RGB_FLOAT': hardcoded_format('BC6_SFLOAT'),
93
94    'PIPE_FORMAT_BPTC_RGBA_UNORM': hardcoded_format('BC7_UNORM'),
95    'PIPE_FORMAT_BPTC_SRGBA': hardcoded_format('BC7_SRGB'),
96
97    'PIPE_FORMAT_R64_UINT': hardcoded_format('32_32_UINT'),
98    'PIPE_FORMAT_R64_SINT': hardcoded_format('32_32_SINT'),
99}
100
101
102# ----------------------------------------------------------------------------
103# Main script
104
105header_template = mako.template.Template("""\
106% if header:
107// DO NOT EDIT -- AUTOMATICALLY GENERATED
108
109#include "gfx10_format_table.h"
110#include "amdgfxregs.h"
111
112% endif
113
114#define FMT(_img_format, ...) \
115   { .img_format = V_008F0C_${gfx.upper()}_FORMAT_##_img_format, \
116     ##__VA_ARGS__ }
117
118const struct gfx10_format ${gfx}_format_table[PIPE_FORMAT_COUNT] = {
119% for pipe_format, args in formats:
120 % if args is not None:
121  [${pipe_format}] = FMT(${args}),
122 % else:
123/* ${pipe_format} is not supported */
124 % endif
125% endfor
126
127#undef FMT
128};
129""")
130
131class Gfx10Format(object):
132    RE_plain_channel = re.compile(r'X?([0-9]+)')
133
134    def __init__(self, enum_entry):
135        self.img_format = enum_entry.name[13:]
136        self.flags = getattr(enum_entry, 'flags', [])
137
138        code = self.img_format.split('_')
139
140        self.plain_chan_sizes = []
141        for i, chan_code in enumerate(code):
142            m = self.RE_plain_channel.match(chan_code)
143            if m is None:
144                break
145            self.plain_chan_sizes.append(int(m.group(1)))
146        # Keep the bit sizes in little-endian order
147        self.plain_chan_sizes.reverse()
148
149        self.code = code[i:]
150
151
152class Gfx10FormatMapping(object):
153    def __init__(self, pipe_formats, gfx10_formats):
154        self.pipe_formats = pipe_formats
155        self.gfx10_formats = gfx10_formats
156
157        self.plain_gfx10_formats = dict(
158            (tuple(['_'.join(fmt.code)] + fmt.plain_chan_sizes), fmt)
159            for fmt in gfx10_formats if fmt.plain_chan_sizes
160        )
161
162    def map(self, fmt):
163        if fmt.layout == PLAIN:
164            chan_type = set([chan.type for chan in fmt.le_channels if chan.type != VOID])
165            chan_norm = set([chan.norm for chan in fmt.le_channels if chan.type != VOID])
166            chan_pure = set([chan.pure for chan in fmt.le_channels if chan.type != VOID])
167            if len(chan_type) > 1 or len(chan_norm) > 1 or len(chan_pure) > 1:
168                print(('Format {fmt.name} has inconsistent channel types: ' +
169                        '{chan_type} {chan_norm} {chan_pure}')
170                      .format(**locals()),
171                      file=sys.stderr)
172                return None
173
174            chan_type = chan_type.pop()
175            chan_norm = chan_norm.pop()
176            chan_pure = chan_pure.pop()
177            chan_sizes = [chan.size for chan in fmt.le_channels if chan.size != 0]
178
179            extra_flags = []
180
181            if fmt.colorspace == SRGB:
182                assert chan_type == UNSIGNED and chan_norm
183                num_format = 'SRGB'
184            else:
185                if chan_type == UNSIGNED:
186                    if chan_pure:
187                        num_format = 'UINT'
188                    elif chan_sizes[0] == 32:
189                        # Shader-based work-around for 32-bit non-pure-integer
190                        num_format = 'UINT'
191                        extra_flags.append('buffers_only')
192                    elif chan_norm:
193                        num_format = 'UNORM'
194                    else:
195                        num_format = 'USCALED'
196                        extra_flags.append('buffers_only')
197                elif chan_type == SIGNED:
198                    if chan_pure:
199                        num_format = 'SINT'
200                    elif chan_sizes[0] == 32:
201                        # Shader-based work-around for 32-bit non-pure-integer
202                        num_format = 'SINT'
203                        extra_flags.append('buffers_only')
204                    elif chan_norm:
205                        num_format = 'SNORM'
206                    else:
207                        num_format = 'SSCALED'
208                        extra_flags.append('buffers_only')
209                elif chan_type == FLOAT:
210                    num_format = 'FLOAT'
211
212                    if chan_sizes[0] == 64:
213                        # Shader-based work-around for doubles
214                        if len(chan_sizes) % 2 == 1:
215                            # 1 or 3 loads for 1 or 3 double channels
216                            chan_sizes = [32, 32]
217                        else:
218                            # 1 or 2 loads for 2 or 4 double channels
219                            chan_sizes = [32, 32, 32, 32]
220                        extra_flags.append('buffers_only')
221                else:
222                    # Shader-based work-around
223                    assert chan_type == FIXED
224                    assert chan_sizes[0] == 32
225                    num_format = 'SINT'
226                    extra_flags.append('buffers_only')
227
228            # These are not supported as render targets, so we don't support
229            # them as images either.
230            if (len(chan_sizes) == 3 and chan_sizes[0] in (8, 16, 32) and
231                chan_sizes[0] == chan_sizes[1]):
232                extra_flags.append('buffers_only')
233                if chan_sizes[0] in (8, 16):
234                    # Shader-based work-around: one load per channel
235                    chan_sizes = [chan_sizes[0]]
236
237            # Don't expose SRGB buffer formats
238            if 'buffers_only' in extra_flags and fmt.colorspace == SRGB:
239                return None
240
241            # Don't support 4_4 because it's not supported as render targets
242            # and it's useless in other cases.
243            if len(chan_sizes) == 2 and chan_sizes[0] == 4:
244                return None
245
246            key = tuple([num_format] + chan_sizes)
247            if key not in self.plain_gfx10_formats:
248                return None
249
250            gfx10_fmt = self.plain_gfx10_formats[key]
251            return Object(
252                img_format=gfx10_fmt.img_format,
253                flags=gfx10_fmt.flags + extra_flags,
254            )
255
256        return None
257
258def pipe_formats_to_formats(pipe_formats, mapping):
259    formats = []
260    for fmt in pipe_formats:
261        if fmt.name in HARDCODED:
262            obj = HARDCODED[fmt.name]
263        else:
264            obj = mapping.map(fmt)
265
266        if obj is not None:
267            args = obj.img_format
268            if 'buffers_only' in obj.flags:
269                args += ', .buffers_only = 1'
270        else:
271            args = None
272        formats.append((fmt.name, args))
273
274    return formats
275
276if __name__ == '__main__':
277    pipe_formats = parse(sys.argv[1])
278
279    # gfx10
280    with open(sys.argv[2], 'r') as filp:
281        db = RegisterDatabase.from_json(json.load(filp))
282
283    gfx10_formats = [Gfx10Format(entry) for entry in db.enum('GFX10_FORMAT').entries]
284    mapping = Gfx10FormatMapping(pipe_formats, gfx10_formats)
285    formats = pipe_formats_to_formats(pipe_formats, mapping)
286    print(header_template.render(header=True, gfx='gfx10', formats=formats))
287
288    # gfx11
289    with open(sys.argv[3], 'r') as filp:
290        db = RegisterDatabase.from_json(json.load(filp))
291
292    gfx11_formats = [Gfx10Format(entry) for entry in db.enum('GFX11_FORMAT').entries]
293    mapping = Gfx10FormatMapping(pipe_formats, gfx11_formats)
294    formats = pipe_formats_to_formats(pipe_formats, mapping)
295    print(header_template.render(header=False, gfx='gfx11', formats=formats))
296