blob: bc37b84e126b2e75a86b248eb74cddd3e688214d [file] [log] [blame]
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -07001#!/usr/bin/env python3
2#
3# Copyright 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070016
17"""Provide the utilities for framework generation.
18"""
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070019
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070020import os
21import subprocess
22import xml.etree.ElementTree as element_tree
Adithya Srinivasan8dce9d72019-07-11 14:26:04 -070023
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070024# Extensions unsupported on Android.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070025_BLACKLISTED_EXTENSIONS = [
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070026 'VK_EXT_acquire_xlib_display',
27 'VK_EXT_direct_mode_display',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070028 'VK_EXT_display_control',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070029 'VK_EXT_display_surface_counter',
30 'VK_EXT_full_screen_exclusive',
31 'VK_EXT_headless_surface',
32 'VK_EXT_metal_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070033 'VK_FUCHSIA_imagepipe_surface',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070034 'VK_GGP_stream_descriptor_surface',
35 'VK_KHR_display',
36 'VK_KHR_display_swapchain',
37 'VK_KHR_external_fence_win32',
38 'VK_KHR_external_memory_win32',
39 'VK_KHR_external_semaphore_win32',
40 'VK_KHR_mir_surface',
41 'VK_KHR_wayland_surface',
42 'VK_KHR_win32_keyed_mutex',
43 'VK_KHR_win32_surface',
44 'VK_KHR_xcb_surface',
45 'VK_KHR_xlib_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070046 'VK_MVK_ios_surface',
47 'VK_MVK_macos_surface',
48 'VK_NN_vi_surface',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070049 'VK_NV_cooperative_matrix',
50 'VK_NV_coverage_reduction_mode',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070051 'VK_NV_external_memory_win32',
52 'VK_NV_win32_keyed_mutex',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070053 'VK_NVX_image_view_handle',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070054]
55
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070056# Extensions having functions exported by the loader.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070057_EXPORTED_EXTENSIONS = [
Yiwei Zhangdc792f52019-10-10 16:29:42 -070058 'VK_ANDROID_external_memory_android_hardware_buffer',
59 'VK_KHR_android_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070060 'VK_KHR_surface',
61 'VK_KHR_swapchain',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070062]
63
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070064# Functions optional on Android even if extension is advertised.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070065_OPTIONAL_COMMANDS = [
Yiwei Zhangdc792f52019-10-10 16:29:42 -070066 'vkGetSwapchainGrallocUsageANDROID',
67 'vkGetSwapchainGrallocUsage2ANDROID',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070068]
69
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070070# Dict for mapping dispatch table to a type.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070071_DISPATCH_TYPE_DICT = {
72 'VkInstance ': 'Instance',
73 'VkPhysicalDevice ': 'Instance',
74 'VkDevice ': 'Device',
75 'VkQueue ': 'Device',
76 'VkCommandBuffer ': 'Device'
77}
Adithya Srinivasan8dce9d72019-07-11 14:26:04 -070078
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070079# Dict for mapping a function to its alias.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070080alias_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070081
82# List of all the Vulkan functions.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070083command_list = []
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070084
85# Dict for mapping a function to an extension.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070086extension_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070087
88# Dict for mapping a function to all its parameters.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070089param_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070090
91# Dict for mapping a function to its return type.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070092return_type_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070093
94# Dict for mapping a function to the core Vulkan API version.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070095version_dict = {}
Adithya Srinivasan01364142019-07-02 15:52:49 -070096
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070097
98def indent(num):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070099 """Returns the requested indents.
100
101 Args:
102 num: Number of the 4-space indents.
103 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700104 return ' ' * num
105
106
107def copyright_and_warning(year):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700108 """Returns the standard copyright and warning codes.
109
110 Args:
111 year: An integer year for the copyright.
112 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700113 return """\
114/*
115 * Copyright """ + str(year) + """ The Android Open Source Project
116 *
117 * Licensed under the Apache License, Version 2.0 (the "License");
118 * you may not use this file except in compliance with the License.
119 * You may obtain a copy of the License at
120 *
121 * http://www.apache.org/licenses/LICENSE-2.0
122 *
123 * Unless required by applicable law or agreed to in writing, software
124 * distributed under the License is distributed on an "AS IS" BASIS,
125 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126 * See the License for the specific language governing permissions and
127 * limitations under the License.
128 */
129
130// WARNING: This file is generated. See ../README.md for instructions.
131
132"""
133
134
135def run_clang_format(args):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700136 """Run clang format on the file.
137
138 Args:
139 args: The file to be formatted.
140 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700141 clang_call = ['clang-format', '--style', 'file', '-i', args]
142 subprocess.check_call(clang_call)
143
144
145def is_extension_internal(extension_name):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700146 """Returns true if an extension is internal to the loader and drivers.
147
148 The loader should not enumerate this extension.
149
150 Args:
151 extension_name: Vulkan extension name.
152 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700153 return extension_name == 'VK_ANDROID_native_buffer'
154
155
156def base_name(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700157 """Returns a function name without the 'vk' prefix.
158
159 Args:
160 cmd: Vulkan function name.
161 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700162 return cmd[2:]
163
164
165def is_function_supported(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700166 """Returns true if a function is core or from a supportable extension.
167
168 Args:
169 cmd: Vulkan function name.
170 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700171 if cmd not in extension_dict:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700172 return True
173 else:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700174 if extension_dict[cmd] not in _BLACKLISTED_EXTENSIONS:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700175 return True
176 return False
177
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700178
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700179def get_dispatch_table_type(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700180 """Returns the dispatch table type for a function.
181
182 Args:
183 cmd: Vulkan function name.
184 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700185 if cmd not in param_dict:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700186 return None
187
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700188 if param_dict[cmd]:
189 return _DISPATCH_TYPE_DICT.get(param_dict[cmd][0][0], 'Global')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700190 return 'Global'
191
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700192
193def is_globally_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700194 """Returns true if the function is global, which is not dispatched.
195
196 Only global functions and functions handled in the loader top without calling
197 into lower layers are not dispatched.
198
199 Args:
200 cmd: Vulkan function name.
201 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700202 return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
203
204
205def is_instance_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700206 """Returns true for functions that can have instance-specific dispatch.
207
208 Args:
209 cmd: Vulkan function name.
210 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700211 return (is_function_supported(cmd) and
212 get_dispatch_table_type(cmd) == 'Instance')
213
214
215def is_device_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700216 """Returns true for functions that can have device-specific dispatch.
217
218 Args:
219 cmd: Vulkan function name.
220 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700221 return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
222
223
224def is_extension_exported(extension_name):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700225 """Returns true if an extension has functions exported by the loader.
226
227 E.g. applications can directly link to an extension function.
228
229 Args:
230 extension_name: Vulkan extension name.
231 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700232 return extension_name in _EXPORTED_EXTENSIONS
233
234
235def is_function_exported(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700236 """Returns true if a function is exported from the Android Vulkan library.
237
238 Functions in the core API and in loader extensions are exported.
239
240 Args:
241 cmd: Vulkan function name.
242 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700243 if is_function_supported(cmd):
244 if cmd in extension_dict:
245 return is_extension_exported(extension_dict[cmd])
246 return True
247 return False
248
249
250def is_instance_dispatch_table_entry(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700251 """Returns true if a function is exported and instance-dispatched.
252
253 Args:
254 cmd: Vulkan function name.
255 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700256 if cmd == 'vkEnumerateDeviceLayerProperties':
257 # deprecated, unused internally - @dbd33bc
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700258 return False
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700259 return is_function_exported(cmd) and is_instance_dispatched(cmd)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700260
261
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700262def is_device_dispatch_table_entry(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700263 """Returns true if a function is exported and device-dispatched.
264
265 Args:
266 cmd: Vulkan function name.
267 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700268 return is_function_exported(cmd) and is_device_dispatched(cmd)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700269
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700270
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700271def init_proc(name, f):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700272 """Emits code to invoke INIT_PROC or INIT_PROC_EXT.
273
274 Args:
275 name: Vulkan function name.
276 f: Output file handle.
277 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700278 f.write(indent(1))
279 if name in extension_dict:
280 f.write('INIT_PROC_EXT(' + extension_dict[name][3:] + ', ')
281 else:
282 f.write('INIT_PROC(')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700283
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700284 if name in version_dict and version_dict[name] == 'VK_VERSION_1_1':
285 f.write('false, ')
286 elif name in _OPTIONAL_COMMANDS:
287 f.write('false, ')
288 else:
289 f.write('true, ')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700290
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700291 if is_instance_dispatched(name):
292 f.write('instance, ')
293 else:
294 f.write('dev, ')
295
296 f.write(base_name(name) + ');\n')
297
298
299def parse_vulkan_registry():
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700300 """Parses Vulkan registry into the below global variables.
301
302 alias_dict
303 command_list
304 extension_dict
305 param_dict
306 return_type_dict
307 version_dict
308 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700309 registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
310 'external', 'vulkan-headers', 'registry', 'vk.xml')
311 tree = element_tree.parse(registry)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700312 root = tree.getroot()
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700313 for commands in root.iter('commands'):
314 for command in commands:
315 if command.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700316 parameter_list = []
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700317 protoset = False
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700318 cmd_name = ''
319 cmd_type = ''
320 if command.get('alias') is not None:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700321 alias = command.get('alias')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700322 cmd_name = command.get('name')
323 alias_dict[cmd_name] = alias
324 command_list.append(cmd_name)
325 param_dict[cmd_name] = param_dict[alias].copy()
326 return_type_dict[cmd_name] = return_type_dict[alias]
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700327 for params in command:
Yiwei Zhang4bc489b2019-09-23 15:17:22 -0700328 if params.tag == 'param':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700329 param_type = ''
330 if params.text is not None and params.text.strip():
331 param_type = params.text.strip() + ' '
332 type_val = params.find('type')
333 param_type = param_type + type_val.text
334 if type_val.tail is not None:
335 param_type += type_val.tail.strip() + ' '
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700336 pname = params.find('name')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700337 param_name = pname.text
338 if pname.tail is not None and pname.tail.strip():
339 parameter_list.append(
340 (param_type, param_name, pname.tail.strip()))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700341 else:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700342 parameter_list.append((param_type, param_name))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700343 if params.tag == 'proto':
344 for c in params:
345 if c.tag == 'type':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700346 cmd_type = c.text
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700347 if c.tag == 'name':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700348 cmd_name = c.text
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700349 protoset = True
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700350 command_list.append(cmd_name)
351 return_type_dict[cmd_name] = cmd_type
352 if protoset:
353 param_dict[cmd_name] = parameter_list.copy()
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700354
355 for exts in root.iter('extensions'):
356 for extension in exts:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700357 apiversion = ''
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700358 if extension.tag == 'extension':
359 extname = extension.get('name')
360 for req in extension:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700361 if req.get('feature') is not None:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700362 apiversion = req.get('feature')
363 for commands in req:
364 if commands.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700365 cmd_name = commands.get('name')
366 if cmd_name not in extension_dict:
367 extension_dict[cmd_name] = extname
368 if apiversion:
369 version_dict[cmd_name] = apiversion
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700370
371 for feature in root.iter('feature'):
372 apiversion = feature.get('name')
373 for req in feature:
374 for command in req:
375 if command.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700376 cmd_name = command.get('name')
377 if cmd_name in command_list:
378 version_dict[cmd_name] = apiversion