blob: ef021f246254cb630a6a535ef67ec68005dbebb8 [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 Zhang95924222020-06-15 09:39:03 -070025_BLOCKED_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
Yiwei Zhang7cc36a52019-10-11 19:02:09 -070094# List of the sorted Vulkan version codes. e.g. '1_0', '1_1'.
95version_code_list = []
96
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070097# Dict for mapping a function to the core Vulkan API version.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070098version_dict = {}
Adithya Srinivasan01364142019-07-02 15:52:49 -070099
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700100# Dict for mapping a promoted instance extension to the core Vulkan API version.
101promoted_inst_ext_dict = {}
102
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700103
104def indent(num):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700105 """Returns the requested indents.
106
107 Args:
108 num: Number of the 4-space indents.
109 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700110 return ' ' * num
111
112
113def copyright_and_warning(year):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700114 """Returns the standard copyright and warning codes.
115
116 Args:
117 year: An integer year for the copyright.
118 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700119 return """\
120/*
121 * Copyright """ + str(year) + """ The Android Open Source Project
122 *
123 * Licensed under the Apache License, Version 2.0 (the "License");
124 * you may not use this file except in compliance with the License.
125 * You may obtain a copy of the License at
126 *
127 * http://www.apache.org/licenses/LICENSE-2.0
128 *
129 * Unless required by applicable law or agreed to in writing, software
130 * distributed under the License is distributed on an "AS IS" BASIS,
131 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132 * See the License for the specific language governing permissions and
133 * limitations under the License.
134 */
135
136// WARNING: This file is generated. See ../README.md for instructions.
137
138"""
139
140
141def run_clang_format(args):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700142 """Run clang format on the file.
143
144 Args:
145 args: The file to be formatted.
146 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700147 clang_call = ['clang-format', '--style', 'file', '-i', args]
148 subprocess.check_call(clang_call)
149
150
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700151def is_extension_internal(ext):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700152 """Returns true if an extension is internal to the loader and drivers.
153
154 The loader should not enumerate this extension.
155
156 Args:
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700157 ext: Vulkan extension name.
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700158 """
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700159 return ext == 'VK_ANDROID_native_buffer'
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700160
161
162def base_name(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700163 """Returns a function name without the 'vk' prefix.
164
165 Args:
166 cmd: Vulkan function name.
167 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700168 return cmd[2:]
169
170
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700171def base_ext_name(ext):
172 """Returns an extension name without the 'VK_' prefix.
173
174 Args:
175 ext: Vulkan extension name.
176 """
177 return ext[3:]
178
179
Yiwei Zhang7cc36a52019-10-11 19:02:09 -0700180def version_code(version):
181 """Returns the version code from a version string.
182
183 Args:
184 version: Vulkan version string.
185 """
186 return version[11:]
187
188
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700189def version_2_api_version(version):
190 """Returns the api version from a version string.
191
192 Args:
193 version: Vulkan version string.
194 """
195 return 'VK_API' + version[2:]
196
197
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700198def is_function_supported(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700199 """Returns true if a function is core or from a supportable extension.
200
201 Args:
202 cmd: Vulkan function name.
203 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700204 if cmd not in extension_dict:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700205 return True
206 else:
Yiwei Zhang95924222020-06-15 09:39:03 -0700207 if extension_dict[cmd] not in _BLOCKED_EXTENSIONS:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700208 return True
209 return False
210
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700211
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700212def get_dispatch_table_type(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700213 """Returns the dispatch table type for a function.
214
215 Args:
216 cmd: Vulkan function name.
217 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700218 if cmd not in param_dict:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700219 return None
220
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700221 if param_dict[cmd]:
222 return _DISPATCH_TYPE_DICT.get(param_dict[cmd][0][0], 'Global')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700223 return 'Global'
224
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700225
226def is_globally_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700227 """Returns true if the function is global, which is not dispatched.
228
229 Only global functions and functions handled in the loader top without calling
230 into lower layers are not dispatched.
231
232 Args:
233 cmd: Vulkan function name.
234 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700235 return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
236
237
238def is_instance_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700239 """Returns true for functions that can have instance-specific dispatch.
240
241 Args:
242 cmd: Vulkan function name.
243 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700244 return (is_function_supported(cmd) and
245 get_dispatch_table_type(cmd) == 'Instance')
246
247
248def is_device_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700249 """Returns true for functions that can have device-specific dispatch.
250
251 Args:
252 cmd: Vulkan function name.
253 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700254 return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
255
256
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700257def is_extension_exported(ext):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700258 """Returns true if an extension has functions exported by the loader.
259
260 E.g. applications can directly link to an extension function.
261
262 Args:
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700263 ext: Vulkan extension name.
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700264 """
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700265 return ext in _EXPORTED_EXTENSIONS
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700266
267
268def is_function_exported(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700269 """Returns true if a function is exported from the Android Vulkan library.
270
271 Functions in the core API and in loader extensions are exported.
272
273 Args:
274 cmd: Vulkan function name.
275 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700276 if is_function_supported(cmd):
277 if cmd in extension_dict:
278 return is_extension_exported(extension_dict[cmd])
279 return True
280 return False
281
282
283def is_instance_dispatch_table_entry(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700284 """Returns true if a function is exported and instance-dispatched.
285
286 Args:
287 cmd: Vulkan function name.
288 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700289 if cmd == 'vkEnumerateDeviceLayerProperties':
290 # deprecated, unused internally - @dbd33bc
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700291 return False
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700292 return is_function_exported(cmd) and is_instance_dispatched(cmd)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700293
294
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700295def is_device_dispatch_table_entry(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700296 """Returns true if a function is exported and device-dispatched.
297
298 Args:
299 cmd: Vulkan function name.
300 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700301 return is_function_exported(cmd) and is_device_dispatched(cmd)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700302
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700303
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700304def init_proc(name, f):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700305 """Emits code to invoke INIT_PROC or INIT_PROC_EXT.
306
307 Args:
308 name: Vulkan function name.
309 f: Output file handle.
310 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700311 f.write(indent(1))
312 if name in extension_dict:
Yiwei Zhangaeaa8672019-10-16 18:59:41 -0700313 f.write('INIT_PROC_EXT(' + base_ext_name(extension_dict[name]) + ', ')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700314 else:
315 f.write('INIT_PROC(')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700316
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700317 if name in version_dict and version_dict[name] == 'VK_VERSION_1_1':
318 f.write('false, ')
319 elif name in _OPTIONAL_COMMANDS:
320 f.write('false, ')
321 else:
322 f.write('true, ')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700323
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700324 if is_instance_dispatched(name):
325 f.write('instance, ')
326 else:
327 f.write('dev, ')
328
329 f.write(base_name(name) + ');\n')
330
331
332def parse_vulkan_registry():
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700333 """Parses Vulkan registry into the below global variables.
334
335 alias_dict
336 command_list
337 extension_dict
338 param_dict
339 return_type_dict
Yiwei Zhang7cc36a52019-10-11 19:02:09 -0700340 version_code_list
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700341 version_dict
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700342 promoted_inst_ext_dict
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700343 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700344 registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
345 'external', 'vulkan-headers', 'registry', 'vk.xml')
346 tree = element_tree.parse(registry)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700347 root = tree.getroot()
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700348 for commands in root.iter('commands'):
349 for command in commands:
350 if command.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700351 parameter_list = []
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700352 protoset = False
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700353 cmd_name = ''
354 cmd_type = ''
355 if command.get('alias') is not None:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700356 alias = command.get('alias')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700357 cmd_name = command.get('name')
358 alias_dict[cmd_name] = alias
359 command_list.append(cmd_name)
360 param_dict[cmd_name] = param_dict[alias].copy()
361 return_type_dict[cmd_name] = return_type_dict[alias]
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700362 for params in command:
Yiwei Zhang4bc489b2019-09-23 15:17:22 -0700363 if params.tag == 'param':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700364 param_type = ''
365 if params.text is not None and params.text.strip():
366 param_type = params.text.strip() + ' '
367 type_val = params.find('type')
368 param_type = param_type + type_val.text
369 if type_val.tail is not None:
370 param_type += type_val.tail.strip() + ' '
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700371 pname = params.find('name')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700372 param_name = pname.text
373 if pname.tail is not None and pname.tail.strip():
374 parameter_list.append(
375 (param_type, param_name, pname.tail.strip()))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700376 else:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700377 parameter_list.append((param_type, param_name))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700378 if params.tag == 'proto':
379 for c in params:
380 if c.tag == 'type':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700381 cmd_type = c.text
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700382 if c.tag == 'name':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700383 cmd_name = c.text
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700384 protoset = True
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700385 command_list.append(cmd_name)
386 return_type_dict[cmd_name] = cmd_type
387 if protoset:
388 param_dict[cmd_name] = parameter_list.copy()
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700389
390 for exts in root.iter('extensions'):
391 for extension in exts:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700392 apiversion = ''
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700393 if extension.tag == 'extension':
394 extname = extension.get('name')
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700395 if (extension.get('type') == 'instance' and
396 extension.get('promotedto') is not None):
397 promoted_inst_ext_dict[extname] = \
398 version_2_api_version(extension.get('promotedto'))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700399 for req in extension:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700400 if req.get('feature') is not None:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700401 apiversion = req.get('feature')
402 for commands in req:
403 if commands.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700404 cmd_name = commands.get('name')
405 if cmd_name not in extension_dict:
406 extension_dict[cmd_name] = extname
407 if apiversion:
408 version_dict[cmd_name] = apiversion
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700409
410 for feature in root.iter('feature'):
411 apiversion = feature.get('name')
412 for req in feature:
413 for command in req:
414 if command.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700415 cmd_name = command.get('name')
416 if cmd_name in command_list:
417 version_dict[cmd_name] = apiversion
Yiwei Zhang7cc36a52019-10-11 19:02:09 -0700418
419 version_code_set = set()
420 for version in version_dict.values():
421 version_code_set.add(version_code(version))
422 for code in sorted(version_code_set):
423 version_code_list.append(code)