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