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