radv/meta: don't need vertex info for resolve shader.
[mesa.git] / src / amd / vulkan / radv_entrypoints_gen.py
1 # coding=utf-8
2 #
3 # Copyright © 2015 Intel Corporation
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 # and/or sell copies of the Software, and to permit persons to whom the
10 # Software is furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
14 # Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 # IN THE SOFTWARE.
23 #
24
25 import sys
26 import xml.etree.ElementTree as ET
27
28 max_api_version = 1.0
29
30 supported_extensions = [
31 'VK_AMD_draw_indirect_count',
32 'VK_NV_dedicated_allocation',
33 'VK_KHR_descriptor_update_template',
34 'VK_KHR_get_physical_device_properties2',
35 'VK_KHR_incremental_present',
36 'VK_KHR_maintenance1',
37 'VK_KHR_push_descriptor',
38 'VK_KHR_sampler_mirror_clamp_to_edge',
39 'VK_KHR_shader_draw_parameters',
40 'VK_KHR_surface',
41 'VK_KHR_swapchain',
42 'VK_KHR_wayland_surface',
43 'VK_KHR_xcb_surface',
44 'VK_KHR_xlib_surface',
45 'VK_KHX_external_memory_capabilities',
46 'VK_KHX_external_memory',
47 'VK_KHX_external_memory_fd',
48 ]
49
50 # We generate a static hash table for entry point lookup
51 # (vkGetProcAddress). We use a linear congruential generator for our hash
52 # function and a power-of-two size table. The prime numbers are determined
53 # experimentally.
54
55 none = 0xffff
56 hash_size = 256
57 u32_mask = 2**32 - 1
58 hash_mask = hash_size - 1
59
60 prime_factor = 5024183
61 prime_step = 19
62
63 def hash(name):
64 h = 0;
65 for c in name:
66 h = (h * prime_factor + ord(c)) & u32_mask
67
68 return h
69
70 def print_guard_start(guard):
71 if guard is not None:
72 print "#ifdef {0}".format(guard)
73
74 def print_guard_end(guard):
75 if guard is not None:
76 print "#endif // {0}".format(guard)
77
78 opt_header = False
79 opt_code = False
80
81 if (sys.argv[1] == "header"):
82 opt_header = True
83 sys.argv.pop()
84 elif (sys.argv[1] == "code"):
85 opt_code = True
86 sys.argv.pop()
87
88 # Extract the entry points from the registry
89 def get_entrypoints(doc, entrypoints_to_defines):
90 entrypoints = []
91
92 enabled_commands = set()
93 for feature in doc.findall('./feature'):
94 assert feature.attrib['api'] == 'vulkan'
95 if float(feature.attrib['number']) > max_api_version:
96 continue
97
98 for command in feature.findall('./require/command'):
99 enabled_commands.add(command.attrib['name'])
100
101 for extension in doc.findall('.extensions/extension'):
102 if extension.attrib['name'] not in supported_extensions:
103 continue
104
105 assert extension.attrib['supported'] == 'vulkan'
106 for command in extension.findall('./require/command'):
107 enabled_commands.add(command.attrib['name'])
108
109 index = 0
110 for command in doc.findall('./commands/command'):
111 type = command.find('./proto/type').text
112 fullname = command.find('./proto/name').text
113
114 if fullname not in enabled_commands:
115 continue
116
117 shortname = fullname[2:]
118 params = map(lambda p: "".join(p.itertext()), command.findall('./param'))
119 params = ', '.join(params)
120 if fullname in entrypoints_to_defines:
121 guard = entrypoints_to_defines[fullname]
122 else:
123 guard = None
124 entrypoints.append((type, shortname, params, index, hash(fullname), guard))
125 index += 1
126
127 return entrypoints
128
129 # Maps entry points to extension defines
130 def get_entrypoints_defines(doc):
131 entrypoints_to_defines = {}
132 extensions = doc.findall('./extensions/extension')
133 for extension in extensions:
134 define = extension.get('protect')
135 entrypoints = extension.findall('./require/command')
136 for entrypoint in entrypoints:
137 fullname = entrypoint.get('name')
138 entrypoints_to_defines[fullname] = define
139 return entrypoints_to_defines
140
141 doc = ET.parse(sys.stdin)
142 entrypoints = get_entrypoints(doc, get_entrypoints_defines(doc))
143
144 # For outputting entrypoints.h we generate a radv_EntryPoint() prototype
145 # per entry point.
146
147 if opt_header:
148 print "/* This file generated from vk_gen.py, don't edit directly. */\n"
149
150 print "struct radv_dispatch_table {"
151 print " union {"
152 print " void *entrypoints[%d];" % len(entrypoints)
153 print " struct {"
154
155 for type, name, args, num, h, guard in entrypoints:
156 if guard is not None:
157 print "#ifdef {0}".format(guard)
158 print " PFN_vk{0} {0};".format(name)
159 print "#else"
160 print " void *{0};".format(name)
161 print "#endif"
162 else:
163 print " PFN_vk{0} {0};".format(name)
164 print " };\n"
165 print " };\n"
166 print "};\n"
167
168 for type, name, args, num, h, guard in entrypoints:
169 print_guard_start(guard)
170 print "%s radv_%s(%s);" % (type, name, args)
171 print_guard_end(guard)
172 exit()
173
174
175
176 print """/*
177 * Copyright © 2015 Intel Corporation
178 *
179 * Permission is hereby granted, free of charge, to any person obtaining a
180 * copy of this software and associated documentation files (the "Software"),
181 * to deal in the Software without restriction, including without limitation
182 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
183 * and/or sell copies of the Software, and to permit persons to whom the
184 * Software is furnished to do so, subject to the following conditions:
185 *
186 * The above copyright notice and this permission notice (including the next
187 * paragraph) shall be included in all copies or substantial portions of the
188 * Software.
189 *
190 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
191 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
192 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
193 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
194 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
195 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
196 * IN THE SOFTWARE.
197 */
198
199 /* DO NOT EDIT! This is a generated file. */
200
201 #include "radv_private.h"
202
203 struct radv_entrypoint {
204 uint32_t name;
205 uint32_t hash;
206 };
207
208 /* We use a big string constant to avoid lots of reloctions from the entry
209 * point table to lots of little strings. The entries in the entry point table
210 * store the index into this big string.
211 */
212
213 static const char strings[] ="""
214
215 offsets = []
216 i = 0;
217 for type, name, args, num, h, guard in entrypoints:
218 print " \"vk%s\\0\"" % name
219 offsets.append(i)
220 i += 2 + len(name) + 1
221 print " ;"
222
223 # Now generate the table of all entry points
224
225 print "\nstatic const struct radv_entrypoint entrypoints[] = {"
226 for type, name, args, num, h, guard in entrypoints:
227 print " { %5d, 0x%08x }," % (offsets[num], h)
228 print "};\n"
229
230 print """
231
232 /* Weak aliases for all potential implementations. These will resolve to
233 * NULL if they're not defined, which lets the resolve_entrypoint() function
234 * either pick the correct entry point.
235 */
236 """
237
238 for layer in [ "radv" ]:
239 for type, name, args, num, h, guard in entrypoints:
240 print_guard_start(guard)
241 print "%s %s_%s(%s) __attribute__ ((weak));" % (type, layer, name, args)
242 print_guard_end(guard)
243 print "\nconst struct radv_dispatch_table %s_layer = {" % layer
244 for type, name, args, num, h, guard in entrypoints:
245 print_guard_start(guard)
246 print " .%s = %s_%s," % (name, layer, name)
247 print_guard_end(guard)
248 print "};\n"
249
250 print """
251
252 static void * __attribute__ ((noinline))
253 radv_resolve_entrypoint(uint32_t index)
254 {
255 return radv_layer.entrypoints[index];
256 }
257 """
258
259 # Now generate the hash table used for entry point look up. This is a
260 # uint16_t table of entry point indices. We use 0xffff to indicate an entry
261 # in the hash table is empty.
262
263 map = [none for f in xrange(hash_size)]
264 collisions = [0 for f in xrange(10)]
265 for type, name, args, num, h, guard in entrypoints:
266 level = 0
267 while map[h & hash_mask] != none:
268 h = h + prime_step
269 level = level + 1
270 if level > 9:
271 collisions[9] += 1
272 else:
273 collisions[level] += 1
274 map[h & hash_mask] = num
275
276 print "/* Hash table stats:"
277 print " * size %d entries" % hash_size
278 print " * collisions entries"
279 for i in xrange(10):
280 if (i == 9):
281 plus = "+"
282 else:
283 plus = " "
284
285 print " * %2d%s %4d" % (i, plus, collisions[i])
286 print " */\n"
287
288 print "#define none 0x%04x\n" % none
289
290 print "static const uint16_t map[] = {"
291 for i in xrange(0, hash_size, 8):
292 print " ",
293 for j in xrange(i, i + 8):
294 if map[j] & 0xffff == 0xffff:
295 print " none,",
296 else:
297 print "0x%04x," % (map[j] & 0xffff),
298 print
299
300 print "};"
301
302 # Finally we generate the hash table lookup function. The hash function and
303 # linear probing algorithm matches the hash table generated above.
304
305 print """
306 void *
307 radv_lookup_entrypoint(const char *name)
308 {
309 static const uint32_t prime_factor = %d;
310 static const uint32_t prime_step = %d;
311 const struct radv_entrypoint *e;
312 uint32_t hash, h, i;
313 const char *p;
314
315 hash = 0;
316 for (p = name; *p; p++)
317 hash = hash * prime_factor + *p;
318
319 h = hash;
320 do {
321 i = map[h & %d];
322 if (i == none)
323 return NULL;
324 e = &entrypoints[i];
325 h += prime_step;
326 } while (e->hash != hash);
327
328 if (strcmp(name, strings + e->name) != 0)
329 return NULL;
330
331 return radv_resolve_entrypoint(i);
332 }
333 """ % (prime_factor, prime_step, hash_mask)