blob: 4176509447e093643723aa2804e5bd30ca81a224 [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',
Yiwei Zhang6be097b2020-10-19 20:22:05 -070028 'VK_EXT_directfb_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070029 'VK_EXT_display_control',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070030 'VK_EXT_display_surface_counter',
31 'VK_EXT_full_screen_exclusive',
32 'VK_EXT_headless_surface',
33 'VK_EXT_metal_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070034 'VK_FUCHSIA_imagepipe_surface',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070035 'VK_GGP_stream_descriptor_surface',
Trevor David Black4c622a02021-06-28 22:46:14 +000036 'VK_HUAWEI_subpass_shading',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070037 'VK_KHR_display',
38 'VK_KHR_display_swapchain',
39 'VK_KHR_external_fence_win32',
40 'VK_KHR_external_memory_win32',
41 'VK_KHR_external_semaphore_win32',
42 'VK_KHR_mir_surface',
43 'VK_KHR_wayland_surface',
44 'VK_KHR_win32_keyed_mutex',
45 'VK_KHR_win32_surface',
46 'VK_KHR_xcb_surface',
47 'VK_KHR_xlib_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070048 'VK_MVK_ios_surface',
49 'VK_MVK_macos_surface',
50 'VK_NN_vi_surface',
Trevor David Black4c622a02021-06-28 22:46:14 +000051 'VK_NV_acquire_winrt_display',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070052 'VK_NV_cooperative_matrix',
53 'VK_NV_coverage_reduction_mode',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070054 'VK_NV_external_memory_win32',
55 'VK_NV_win32_keyed_mutex',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070056 'VK_NVX_image_view_handle',
Trevor David Black4c622a02021-06-28 22:46:14 +000057 'VK_QNX_screen_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070058]
59
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070060# Extensions having functions exported by the loader.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070061_EXPORTED_EXTENSIONS = [
Yiwei Zhangdc792f52019-10-10 16:29:42 -070062 'VK_ANDROID_external_memory_android_hardware_buffer',
63 'VK_KHR_android_surface',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070064 'VK_KHR_surface',
65 'VK_KHR_swapchain',
Yiwei Zhangdc792f52019-10-10 16:29:42 -070066]
67
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070068# Functions optional on Android even if extension is advertised.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070069_OPTIONAL_COMMANDS = [
Yiwei Zhangdc792f52019-10-10 16:29:42 -070070 'vkGetSwapchainGrallocUsageANDROID',
71 'vkGetSwapchainGrallocUsage2ANDROID',
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -070072]
73
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070074# Dict for mapping dispatch table to a type.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070075_DISPATCH_TYPE_DICT = {
76 'VkInstance ': 'Instance',
77 'VkPhysicalDevice ': 'Instance',
78 'VkDevice ': 'Device',
79 'VkQueue ': 'Device',
80 'VkCommandBuffer ': 'Device'
81}
Adithya Srinivasan8dce9d72019-07-11 14:26:04 -070082
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070083# Dict for mapping a function to its alias.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070084alias_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070085
86# List of all the Vulkan functions.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070087command_list = []
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070088
89# Dict for mapping a function to an extension.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070090extension_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070091
92# Dict for mapping a function to all its parameters.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070093param_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070094
95# Dict for mapping a function to its return type.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -070096return_type_dict = {}
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -070097
Yiwei Zhang7cc36a52019-10-11 19:02:09 -070098# List of the sorted Vulkan version codes. e.g. '1_0', '1_1'.
99version_code_list = []
100
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700101# Dict for mapping a function to the core Vulkan API version.
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700102version_dict = {}
Adithya Srinivasan01364142019-07-02 15:52:49 -0700103
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700104# Dict for mapping a promoted instance extension to the core Vulkan API version.
105promoted_inst_ext_dict = {}
106
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700107
108def indent(num):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700109 """Returns the requested indents.
110
111 Args:
112 num: Number of the 4-space indents.
113 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700114 return ' ' * num
115
116
117def copyright_and_warning(year):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700118 """Returns the standard copyright and warning codes.
119
120 Args:
121 year: An integer year for the copyright.
122 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700123 return """\
124/*
125 * Copyright """ + str(year) + """ The Android Open Source Project
126 *
127 * Licensed under the Apache License, Version 2.0 (the "License");
128 * you may not use this file except in compliance with the License.
129 * You may obtain a copy of the License at
130 *
131 * http://www.apache.org/licenses/LICENSE-2.0
132 *
133 * Unless required by applicable law or agreed to in writing, software
134 * distributed under the License is distributed on an "AS IS" BASIS,
135 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136 * See the License for the specific language governing permissions and
137 * limitations under the License.
138 */
139
140// WARNING: This file is generated. See ../README.md for instructions.
141
142"""
143
144
145def run_clang_format(args):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700146 """Run clang format on the file.
147
148 Args:
149 args: The file to be formatted.
150 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700151 clang_call = ['clang-format', '--style', 'file', '-i', args]
152 subprocess.check_call(clang_call)
153
154
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700155def is_extension_internal(ext):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700156 """Returns true if an extension is internal to the loader and drivers.
157
158 The loader should not enumerate this extension.
159
160 Args:
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700161 ext: Vulkan extension name.
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700162 """
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700163 return ext == 'VK_ANDROID_native_buffer'
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700164
165
166def base_name(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700167 """Returns a function name without the 'vk' prefix.
168
169 Args:
170 cmd: Vulkan function name.
171 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700172 return cmd[2:]
173
174
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700175def base_ext_name(ext):
176 """Returns an extension name without the 'VK_' prefix.
177
178 Args:
179 ext: Vulkan extension name.
180 """
181 return ext[3:]
182
183
Yiwei Zhang7cc36a52019-10-11 19:02:09 -0700184def version_code(version):
185 """Returns the version code from a version string.
186
187 Args:
188 version: Vulkan version string.
189 """
190 return version[11:]
191
192
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700193def version_2_api_version(version):
194 """Returns the api version from a version string.
195
196 Args:
197 version: Vulkan version string.
198 """
199 return 'VK_API' + version[2:]
200
201
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700202def is_function_supported(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700203 """Returns true if a function is core or from a supportable extension.
204
205 Args:
206 cmd: Vulkan function name.
207 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700208 if cmd not in extension_dict:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700209 return True
210 else:
Yiwei Zhang95924222020-06-15 09:39:03 -0700211 if extension_dict[cmd] not in _BLOCKED_EXTENSIONS:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700212 return True
213 return False
214
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700215
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700216def get_dispatch_table_type(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700217 """Returns the dispatch table type for a function.
218
219 Args:
220 cmd: Vulkan function name.
221 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700222 if cmd not in param_dict:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700223 return None
224
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700225 if param_dict[cmd]:
226 return _DISPATCH_TYPE_DICT.get(param_dict[cmd][0][0], 'Global')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700227 return 'Global'
228
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700229
230def is_globally_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700231 """Returns true if the function is global, which is not dispatched.
232
233 Only global functions and functions handled in the loader top without calling
234 into lower layers are not dispatched.
235
236 Args:
237 cmd: Vulkan function name.
238 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700239 return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
240
241
242def is_instance_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700243 """Returns true for functions that can have instance-specific dispatch.
244
245 Args:
246 cmd: Vulkan function name.
247 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700248 return (is_function_supported(cmd) and
249 get_dispatch_table_type(cmd) == 'Instance')
250
251
252def is_device_dispatched(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700253 """Returns true for functions that can have device-specific dispatch.
254
255 Args:
256 cmd: Vulkan function name.
257 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700258 return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
259
260
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700261def is_extension_exported(ext):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700262 """Returns true if an extension has functions exported by the loader.
263
264 E.g. applications can directly link to an extension function.
265
266 Args:
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700267 ext: Vulkan extension name.
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700268 """
Yiwei Zhang5365a7b2019-10-11 17:26:44 -0700269 return ext in _EXPORTED_EXTENSIONS
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700270
271
272def is_function_exported(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700273 """Returns true if a function is exported from the Android Vulkan library.
274
275 Functions in the core API and in loader extensions are exported.
276
277 Args:
278 cmd: Vulkan function name.
279 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700280 if is_function_supported(cmd):
281 if cmd in extension_dict:
282 return is_extension_exported(extension_dict[cmd])
283 return True
284 return False
285
286
287def is_instance_dispatch_table_entry(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700288 """Returns true if a function is exported and instance-dispatched.
289
290 Args:
291 cmd: Vulkan function name.
292 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700293 if cmd == 'vkEnumerateDeviceLayerProperties':
294 # deprecated, unused internally - @dbd33bc
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700295 return False
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700296 return is_function_exported(cmd) and is_instance_dispatched(cmd)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700297
298
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700299def is_device_dispatch_table_entry(cmd):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700300 """Returns true if a function is exported and device-dispatched.
301
302 Args:
303 cmd: Vulkan function name.
304 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700305 return is_function_exported(cmd) and is_device_dispatched(cmd)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700306
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700307
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700308def init_proc(name, f):
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700309 """Emits code to invoke INIT_PROC or INIT_PROC_EXT.
310
311 Args:
312 name: Vulkan function name.
313 f: Output file handle.
314 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700315 f.write(indent(1))
316 if name in extension_dict:
Yiwei Zhangaeaa8672019-10-16 18:59:41 -0700317 f.write('INIT_PROC_EXT(' + base_ext_name(extension_dict[name]) + ', ')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700318 else:
319 f.write('INIT_PROC(')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700320
Yiwei Zhang6be097b2020-10-19 20:22:05 -0700321 if name in _OPTIONAL_COMMANDS:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700322 f.write('false, ')
Yiwei Zhang6be097b2020-10-19 20:22:05 -0700323 elif version_dict[name] == 'VK_VERSION_1_0':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700324 f.write('true, ')
Yiwei Zhang6be097b2020-10-19 20:22:05 -0700325 else:
326 f.write('false, ')
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700327
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700328 if is_instance_dispatched(name):
329 f.write('instance, ')
330 else:
331 f.write('dev, ')
332
333 f.write(base_name(name) + ');\n')
334
335
336def parse_vulkan_registry():
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700337 """Parses Vulkan registry into the below global variables.
338
339 alias_dict
340 command_list
341 extension_dict
342 param_dict
343 return_type_dict
Yiwei Zhang7cc36a52019-10-11 19:02:09 -0700344 version_code_list
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700345 version_dict
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700346 promoted_inst_ext_dict
Yiwei Zhang6ca5d0c2019-10-11 17:15:02 -0700347 """
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700348 registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
349 'external', 'vulkan-headers', 'registry', 'vk.xml')
350 tree = element_tree.parse(registry)
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700351 root = tree.getroot()
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700352 for commands in root.iter('commands'):
353 for command in commands:
354 if command.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700355 parameter_list = []
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700356 protoset = False
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700357 cmd_name = ''
358 cmd_type = ''
359 if command.get('alias') is not None:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700360 alias = command.get('alias')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700361 cmd_name = command.get('name')
362 alias_dict[cmd_name] = alias
363 command_list.append(cmd_name)
364 param_dict[cmd_name] = param_dict[alias].copy()
365 return_type_dict[cmd_name] = return_type_dict[alias]
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700366 for params in command:
Yiwei Zhang4bc489b2019-09-23 15:17:22 -0700367 if params.tag == 'param':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700368 param_type = ''
369 if params.text is not None and params.text.strip():
370 param_type = params.text.strip() + ' '
371 type_val = params.find('type')
372 param_type = param_type + type_val.text
373 if type_val.tail is not None:
374 param_type += type_val.tail.strip() + ' '
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700375 pname = params.find('name')
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700376 param_name = pname.text
377 if pname.tail is not None and pname.tail.strip():
378 parameter_list.append(
379 (param_type, param_name, pname.tail.strip()))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700380 else:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700381 parameter_list.append((param_type, param_name))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700382 if params.tag == 'proto':
383 for c in params:
384 if c.tag == 'type':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700385 cmd_type = c.text
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700386 if c.tag == 'name':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700387 cmd_name = c.text
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700388 protoset = True
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700389 command_list.append(cmd_name)
390 return_type_dict[cmd_name] = cmd_type
391 if protoset:
392 param_dict[cmd_name] = parameter_list.copy()
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700393
394 for exts in root.iter('extensions'):
395 for extension in exts:
Yiwei Zhang6be097b2020-10-19 20:22:05 -0700396 apiversion = 'VK_VERSION_1_0'
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700397 if extension.tag == 'extension':
398 extname = extension.get('name')
Yiwei Zhang7c0c07c2020-07-04 23:49:47 -0700399 if (extension.get('type') == 'instance' and
400 extension.get('promotedto') is not None):
401 promoted_inst_ext_dict[extname] = \
402 version_2_api_version(extension.get('promotedto'))
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700403 for req in extension:
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700404 if req.get('feature') is not None:
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700405 apiversion = req.get('feature')
406 for commands in req:
407 if commands.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700408 cmd_name = commands.get('name')
409 if cmd_name not in extension_dict:
410 extension_dict[cmd_name] = extname
Yiwei Zhang6be097b2020-10-19 20:22:05 -0700411 version_dict[cmd_name] = apiversion
Adithya Srinivasan751a7dc2019-07-02 17:17:25 -0700412
413 for feature in root.iter('feature'):
414 apiversion = feature.get('name')
415 for req in feature:
416 for command in req:
417 if command.tag == 'command':
Yiwei Zhang1ca59c12019-10-10 12:54:42 -0700418 cmd_name = command.get('name')
419 if cmd_name in command_list:
420 version_dict[cmd_name] = apiversion
Yiwei Zhang7cc36a52019-10-11 19:02:09 -0700421
422 version_code_set = set()
423 for version in version_dict.values():
424 version_code_set.add(version_code(version))
425 for code in sorted(version_code_set):
426 version_code_list.append(code)