radv: implement VK_EXT_line_rasterization
[mesa.git] / src / amd / vulkan / gfx10_format_table.py
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 """
24 Script that generates the mapping from Vulkan VK_FORMAT_xxx to gfx10
25 IMG_FORMAT_xxx enums.
26 """
27
28 from __future__ import absolute_import, division, print_function, unicode_literals
29
30 import json
31 import mako.template
32 import os
33 import re
34 import sys
35
36 AMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../registers"))
37 sys.path.extend([AMD_REGISTERS])
38
39 from regdb import Object, RegisterDatabase
40 from vk_format_parse import *
41
42 # ----------------------------------------------------------------------------
43 # Hard-coded mappings
44
45 def hardcoded_format(hw_enum):
46 return Object(img_format=hw_enum, flags=[])
47
48 HARDCODED = {
49 'VK_FORMAT_E5B9G9R9_UFLOAT_PACK32': hardcoded_format('5_9_9_9_FLOAT'),
50 'VK_FORMAT_B10G11R11_UFLOAT_PACK32': hardcoded_format('10_11_11_FLOAT'), # NOTE: full set of int/unorm/etc. exists
51
52 # BC
53 'VK_FORMAT_BC1_RGB_UNORM_BLOCK': hardcoded_format('BC1_UNORM'),
54 'VK_FORMAT_BC1_RGBA_UNORM_BLOCK': hardcoded_format('BC1_UNORM'),
55 'VK_FORMAT_BC1_RGB_SRGB_BLOCK': hardcoded_format('BC1_SRGB'),
56 'VK_FORMAT_BC1_RGBA_SRGB_BLOCK': hardcoded_format('BC1_SRGB'),
57 'VK_FORMAT_BC2_UNORM_BLOCK': hardcoded_format('BC2_UNORM'),
58 'VK_FORMAT_BC2_SRGB_BLOCK': hardcoded_format('BC2_SRGB'),
59 'VK_FORMAT_BC3_UNORM_BLOCK': hardcoded_format('BC3_UNORM'),
60 'VK_FORMAT_BC3_SRGB_BLOCK': hardcoded_format('BC3_SRGB'),
61 'VK_FORMAT_BC4_UNORM_BLOCK': hardcoded_format('BC4_UNORM'),
62 'VK_FORMAT_BC4_SNORM_BLOCK': hardcoded_format('BC4_SNORM'),
63 'VK_FORMAT_BC5_UNORM_BLOCK': hardcoded_format('BC5_UNORM'),
64 'VK_FORMAT_BC5_SNORM_BLOCK': hardcoded_format('BC5_SNORM'),
65 'VK_FORMAT_BC6H_UFLOAT_BLOCK': hardcoded_format('BC6_UFLOAT'),
66 'VK_FORMAT_BC6H_SFLOAT_BLOCK': hardcoded_format('BC6_SFLOAT'),
67 'VK_FORMAT_BC7_UNORM_BLOCK': hardcoded_format('BC7_UNORM'),
68 'VK_FORMAT_BC7_SRGB_BLOCK': hardcoded_format('BC7_SRGB'),
69
70 # DS
71 'VK_FORMAT_D16_UNORM_S8_UINT': hardcoded_format('INVALID'),
72 'VK_FORMAT_D24_UNORM_S8_UINT': hardcoded_format('8_24_UNORM'),
73 'VK_FORMAT_D32_SFLOAT_S8_UINT': hardcoded_format('X24_8_32_FLOAT'),
74 }
75
76
77 # ----------------------------------------------------------------------------
78 # Main script
79
80 header_template = mako.template.Template("""\
81 // DO NOT EDIT -- AUTOMATICALLY GENERATED
82
83 #define FMT(_img_format, ...) \
84 { .img_format = V_008F0C_IMG_FORMAT_##_img_format, \
85 ##__VA_ARGS__ }
86
87 static const struct gfx10_format gfx10_format_table[VK_FORMAT_RANGE_SIZE] = {
88 % for vk_format, args in formats:
89 % if args is not None:
90 [${vk_format}] = FMT(${args}),
91 % else:
92 /* ${vk_format} is not supported */
93 % endif
94 % endfor
95 };
96 """)
97
98 class Gfx10Format(object):
99 RE_plain_channel = re.compile(r'X?([0-9]+)')
100
101 def __init__(self, enum_entry):
102 self.img_format = enum_entry.name[11:]
103 self.flags = getattr(enum_entry, 'flags', [])
104
105 code = self.img_format.split('_')
106
107 self.plain_chan_sizes = []
108 for i, chan_code in enumerate(code):
109 m = self.RE_plain_channel.match(chan_code)
110 if m is None:
111 break
112 self.plain_chan_sizes.append(int(m.group(1)))
113 # Keep the bit sizes in little-endian order
114 self.plain_chan_sizes.reverse()
115
116 self.code = code[i:]
117
118
119 class Gfx10FormatMapping(object):
120 def __init__(self, vk_formats, gfx10_formats):
121 self.vk_formats = vk_formats
122 self.gfx10_formats = gfx10_formats
123
124 self.plain_gfx10_formats = dict(
125 (tuple(['_'.join(fmt.code)] + fmt.plain_chan_sizes), fmt)
126 for fmt in gfx10_formats if fmt.plain_chan_sizes
127 )
128
129 def map(self, fmt):
130 if fmt.layout == PLAIN:
131 chan_type = set([chan.type for chan in fmt.le_channels if chan.type != VOID])
132 chan_norm = set([chan.norm for chan in fmt.le_channels if chan.type != VOID])
133 chan_pure = set([chan.pure for chan in fmt.le_channels if chan.type != VOID])
134 if len(chan_type) > 1 or len(chan_norm) > 1 or len(chan_pure) > 1:
135 print(('Format {fmt.name} has inconsistent channel types: ' +
136 '{chan_type} {chan_norm} {chan_pure}')
137 .format(**locals()),
138 file=sys.stderr)
139 return None
140
141 chan_type = chan_type.pop()
142 chan_norm = chan_norm.pop()
143 chan_pure = chan_pure.pop()
144 chan_sizes = [chan.size for chan in fmt.le_channels if chan.size != 0]
145
146 extra_flags = []
147
148 if fmt.colorspace == SRGB:
149 assert chan_type == UNSIGNED and chan_norm
150 num_format = 'SRGB'
151 else:
152 if chan_type == UNSIGNED:
153 if chan_pure:
154 num_format = 'UINT'
155 elif chan_sizes[0] == 32:
156 # Shader-based work-around for 32-bit non-pure-integer
157 num_format = 'UINT'
158 extra_flags.append('buffers_only')
159 elif chan_norm:
160 num_format = 'UNORM'
161 else:
162 num_format = 'USCALED'
163 elif chan_type == SIGNED:
164 if chan_pure:
165 num_format = 'SINT'
166 elif chan_sizes[0] == 32:
167 # Shader-based work-around for 32-bit non-pure-integer
168 num_format = 'SINT'
169 extra_flags.append('buffers_only')
170 elif chan_norm:
171 num_format = 'SNORM'
172 else:
173 num_format = 'SSCALED'
174 elif chan_type == FLOAT:
175 num_format = 'FLOAT'
176
177 if chan_sizes[0] == 64:
178 # Shader-based work-around for doubles
179 if len(chan_sizes) % 2 == 1:
180 # 1 or 3 loads for 1 or 3 double channels
181 chan_sizes = [32, 32]
182 else:
183 # 1 or 2 loads for 2 or 4 double channels
184 chan_sizes = [32, 32, 32, 32]
185 extra_flags.append('buffers_only')
186 else:
187 # Shader-based work-around
188 assert chan_type == FIXED
189 assert chan_sizes[0] == 32
190 num_format = 'SINT'
191 extra_flags.append('buffers_only')
192
193 # These are not supported as render targets, so we don't support
194 # them as images either.
195 if (len(chan_sizes) == 3 and chan_sizes[0] in (8, 16, 32) and
196 chan_sizes[0] == chan_sizes[1]):
197 extra_flags.append('buffers_only')
198 if chan_sizes[0] in (8, 16):
199 # Shader-based work-around: one load per channel
200 chan_sizes = [chan_sizes[0]]
201
202 # Don't expose SRGB buffer formats
203 if 'buffers_only' in extra_flags and fmt.colorspace == SRGB:
204 return None
205
206 # Don't support 4_4 because it's not supported as render targets
207 # and it's useless in other cases.
208 if len(chan_sizes) == 2 and chan_sizes[0] == 4:
209 return None
210
211 key = tuple([num_format] + chan_sizes)
212 if key not in self.plain_gfx10_formats:
213 return None
214
215 gfx10_fmt = self.plain_gfx10_formats[key]
216 return Object(
217 img_format=gfx10_fmt.img_format,
218 flags=gfx10_fmt.flags + extra_flags,
219 )
220
221 return None
222
223
224 if __name__ == '__main__':
225 vk_formats = parse(sys.argv[1])
226
227 with open(sys.argv[2], 'r') as filp:
228 db = RegisterDatabase.from_json(json.load(filp))
229
230 gfx10_formats = [Gfx10Format(entry) for entry in db.enum('IMG_FORMAT').entries]
231
232 mapping = Gfx10FormatMapping(vk_formats, gfx10_formats)
233
234 formats = []
235 for fmt in vk_formats:
236 if fmt.name in HARDCODED:
237 obj = HARDCODED[fmt.name]
238 else:
239 obj = mapping.map(fmt)
240
241 if obj is not None:
242 args = obj.img_format
243 if 'buffers_only' in obj.flags:
244 args += ', .buffers_only = 1'
245 else:
246 args = None
247 formats.append((fmt.name, args))
248
249 print(header_template.render(formats=formats))