freedreno/ir3: Fix assertion failures dumping CS high full regs.
[mesa.git] / src / freedreno / vulkan / vk_format_parse.py
1
2 '''
3 /**************************************************************************
4 *
5 * Copyright 2009 VMware, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29 '''
30
31
32 VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
33
34 SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
35
36 PLAIN = 'plain'
37 SCALED = 'scaled'
38
39 RGB = 'rgb'
40 SRGB = 'srgb'
41 YUV = 'yuv'
42 ZS = 'zs'
43
44
45 def is_pot(x):
46 return (x & (x - 1)) == 0
47
48
49 VERY_LARGE = 99999999999999999999999
50
51
52 class Channel:
53 '''Describe the channel of a color channel.'''
54
55 def __init__(self, type, norm, pure, scaled, size, name = ''):
56 self.type = type
57 self.norm = norm
58 self.pure = pure
59 self.size = size
60 self.scaled = scaled
61 self.sign = type in (SIGNED, FIXED, FLOAT)
62 self.name = name
63
64 def __str__(self):
65 s = str(self.type)
66 if self.norm:
67 s += 'n'
68 if self.pure:
69 s += 'p'
70 if self.scaled:
71 s += 's'
72 s += str(self.size)
73 return s
74
75 def __eq__(self, other):
76 return (other is not None and
77 self.type == other.type and
78 self.norm == other.norm and
79 self.pure == other.pure and
80 self.size == other.size and
81 self.scaled == other.scaled)
82
83 def max(self):
84 '''Maximum representable number.'''
85 if self.type == FLOAT:
86 return VERY_LARGE
87 if self.type == FIXED:
88 return (1 << (self.size/2)) - 1
89 if self.norm:
90 return 1
91 if self.type == UNSIGNED:
92 return (1 << self.size) - 1
93 if self.type == SIGNED:
94 return (1 << (self.size - 1)) - 1
95 assert False
96
97 def min(self):
98 '''Minimum representable number.'''
99 if self.type == FLOAT:
100 return -VERY_LARGE
101 if self.type == FIXED:
102 return -(1 << (self.size/2))
103 if self.type == UNSIGNED:
104 return 0
105 if self.norm:
106 return -1
107 if self.type == SIGNED:
108 return -(1 << (self.size - 1))
109 assert False
110
111
112 class Format:
113 '''Describe a pixel format.'''
114
115 def __init__(self, name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace):
116 self.name = name
117 self.layout = layout
118 self.block_width = block_width
119 self.block_height = block_height
120 self.le_channels = le_channels
121 self.le_swizzles = le_swizzles
122 self.be_channels = be_channels
123 self.be_swizzles = be_swizzles
124 self.name = name
125 self.colorspace = colorspace
126
127 def __str__(self):
128 return self.name
129
130 def short_name(self):
131 '''Make up a short norm for a format, suitable to be used as suffix in
132 function names.'''
133
134 name = self.name
135 if name.startswith('VK_FORMAT_'):
136 name = name[len('VK_FORMAT_'):]
137 name = name.lower()
138 return name
139
140 def block_size(self):
141 size = 0
142 for channel in self.le_channels:
143 size += channel.size
144 return size
145
146 def nr_channels(self):
147 nr_channels = 0
148 for channel in self.le_channels:
149 if channel.size:
150 nr_channels += 1
151 return nr_channels
152
153 def array_element(self):
154 if self.layout != PLAIN:
155 return None
156 ref_channel = self.le_channels[0]
157 if ref_channel.type == VOID:
158 ref_channel = self.le_channels[1]
159 for channel in self.le_channels:
160 if channel.size and (channel.size != ref_channel.size or channel.size % 8):
161 return None
162 if channel.type != VOID:
163 if channel.type != ref_channel.type:
164 return None
165 if channel.norm != ref_channel.norm:
166 return None
167 if channel.pure != ref_channel.pure:
168 return None
169 if channel.scaled != ref_channel.scaled:
170 return None
171 return ref_channel
172
173 def is_array(self):
174 return self.array_element() != None
175
176 def is_mixed(self):
177 if self.layout != PLAIN:
178 return False
179 ref_channel = self.le_channels[0]
180 if ref_channel.type == VOID:
181 ref_channel = self.le_channels[1]
182 for channel in self.le_channels[1:]:
183 if channel.type != VOID:
184 if channel.type != ref_channel.type:
185 return True
186 if channel.norm != ref_channel.norm:
187 return True
188 if channel.pure != ref_channel.pure:
189 return True
190 if channel.scaled != ref_channel.scaled:
191 return True
192 return False
193
194 def is_pot(self):
195 return is_pot(self.block_size())
196
197 def is_int(self):
198 if self.layout != PLAIN:
199 return False
200 for channel in self.le_channels:
201 if channel.type not in (VOID, UNSIGNED, SIGNED):
202 return False
203 return True
204
205 def is_float(self):
206 if self.layout != PLAIN:
207 return False
208 for channel in self.le_channels:
209 if channel.type not in (VOID, FLOAT):
210 return False
211 return True
212
213 def is_bitmask(self):
214 if self.layout != PLAIN:
215 return False
216 if self.block_size() not in (8, 16, 32):
217 return False
218 for channel in self.le_channels:
219 if channel.type not in (VOID, UNSIGNED, SIGNED):
220 return False
221 return True
222
223 def is_pure_color(self):
224 if self.layout != PLAIN or self.colorspace == ZS:
225 return False
226 pures = [channel.pure
227 for channel in self.le_channels
228 if channel.type != VOID]
229 for x in pures:
230 assert x == pures[0]
231 return pures[0]
232
233 def channel_type(self):
234 types = [channel.type
235 for channel in self.le_channels
236 if channel.type != VOID]
237 for x in types:
238 assert x == types[0]
239 return types[0]
240
241 def is_pure_signed(self):
242 return self.is_pure_color() and self.channel_type() == SIGNED
243
244 def is_pure_unsigned(self):
245 return self.is_pure_color() and self.channel_type() == UNSIGNED
246
247 def has_channel(self, id):
248 return self.le_swizzles[id] != SWIZZLE_NONE
249
250 def has_depth(self):
251 return self.colorspace == ZS and self.has_channel(0)
252
253 def has_stencil(self):
254 return self.colorspace == ZS and self.has_channel(1)
255
256 def stride(self):
257 return self.block_size()/8
258
259
260 _type_parse_map = {
261 '': VOID,
262 'x': VOID,
263 'u': UNSIGNED,
264 's': SIGNED,
265 'h': FIXED,
266 'f': FLOAT,
267 }
268
269 _swizzle_parse_map = {
270 'x': SWIZZLE_X,
271 'y': SWIZZLE_Y,
272 'z': SWIZZLE_Z,
273 'w': SWIZZLE_W,
274 '0': SWIZZLE_0,
275 '1': SWIZZLE_1,
276 '_': SWIZZLE_NONE,
277 }
278
279 def _parse_channels(fields, layout, colorspace, swizzles):
280 if layout == PLAIN:
281 names = ['']*4
282 if colorspace in (RGB, SRGB):
283 for i in range(4):
284 swizzle = swizzles[i]
285 if swizzle < 4:
286 names[swizzle] += 'rgba'[i]
287 elif colorspace == ZS:
288 for i in range(4):
289 swizzle = swizzles[i]
290 if swizzle < 4:
291 names[swizzle] += 'zs'[i]
292 else:
293 assert False
294 for i in range(4):
295 if names[i] == '':
296 names[i] = 'x'
297 else:
298 names = ['x', 'y', 'z', 'w']
299
300 channels = []
301 for i in range(0, 4):
302 field = fields[i]
303 if field:
304 type = _type_parse_map[field[0]]
305 if field[1] == 'n':
306 norm = True
307 pure = False
308 scaled = False
309 size = int(field[2:])
310 elif field[1] == 'p':
311 pure = True
312 norm = False
313 scaled = False
314 size = int(field[2:])
315 elif field[1] == 's':
316 pure = False
317 norm = False
318 scaled = True
319 size = int(field[2:])
320 else:
321 norm = False
322 pure = False
323 scaled = False
324 size = int(field[1:])
325 else:
326 type = VOID
327 norm = False
328 pure = False
329 scaled = False
330 size = 0
331 channel = Channel(type, norm, pure, scaled, size, names[i])
332 channels.append(channel)
333
334 return channels
335
336 def parse(filename):
337 '''Parse the format description in CSV format in terms of the
338 Channel and Format classes above.'''
339
340 stream = open(filename)
341 formats = []
342 for line in stream:
343 try:
344 comment = line.index('#')
345 except ValueError:
346 pass
347 else:
348 line = line[:comment]
349 line = line.strip()
350 if not line:
351 continue
352
353 fields = [field.strip() for field in line.split(',')]
354 if len (fields) < 10:
355 continue
356 if len (fields) == 10:
357 fields += fields[4:9]
358 assert len (fields) == 15
359
360 name = fields[0]
361 layout = fields[1]
362 block_width, block_height = map(int, fields[2:4])
363 colorspace = fields[9]
364
365 le_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
366 le_channels = _parse_channels(fields[4:8], layout, colorspace, le_swizzles)
367
368 be_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[14]]
369 be_channels = _parse_channels(fields[10:14], layout, colorspace, be_swizzles)
370
371 le_shift = 0
372 for channel in le_channels:
373 channel.shift = le_shift
374 le_shift += channel.size
375
376 be_shift = 0
377 for channel in be_channels[3::-1]:
378 channel.shift = be_shift
379 be_shift += channel.size
380
381 assert le_shift == be_shift
382 for i in range(4):
383 assert (le_swizzles[i] != SWIZZLE_NONE) == (be_swizzles[i] != SWIZZLE_NONE)
384
385 format = Format(name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace)
386 formats.append(format)
387 return formats
388