1COPYRIGHT = """\ 2/* 3 * Copyright 2017 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 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25""" 26 27import argparse 28import copy 29import re 30import xml.etree.cElementTree as et 31 32from mako.template import Template 33 34MAX_API_VERSION = '1.1.90' 35 36class Extension: 37 def __init__(self, name, ext_version, enable): 38 self.name = name 39 self.ext_version = int(ext_version) 40 if enable is True: 41 self.enable = 'true'; 42 elif enable is False: 43 self.enable = 'false'; 44 else: 45 self.enable = enable; 46 47# On Android, we disable all surface and swapchain extensions. Android's Vulkan 48# loader implements VK_KHR_surface and VK_KHR_swapchain, and applications 49# cannot access the driver's implementation. Moreoever, if the driver exposes 50# the those extension strings, then tests dEQP-VK.api.info.instance.extensions 51# and dEQP-VK.api.info.device fail due to the duplicated strings. 52EXTENSIONS = [ 53 Extension('VK_ANDROID_native_buffer', 5, 'ANDROID && device->rad_info.has_syncobj_wait_for_submit'), 54 Extension('VK_KHR_16bit_storage', 1, True), 55 Extension('VK_KHR_bind_memory2', 1, True), 56 Extension('VK_KHR_create_renderpass2', 1, True), 57 Extension('VK_KHR_dedicated_allocation', 1, True), 58 Extension('VK_KHR_descriptor_update_template', 1, True), 59 Extension('VK_KHR_device_group', 1, True), 60 Extension('VK_KHR_device_group_creation', 1, True), 61 Extension('VK_KHR_draw_indirect_count', 1, True), 62 Extension('VK_KHR_driver_properties', 1, True), 63 Extension('VK_KHR_external_fence', 1, 'device->rad_info.has_syncobj_wait_for_submit'), 64 Extension('VK_KHR_external_fence_capabilities', 1, True), 65 Extension('VK_KHR_external_fence_fd', 1, 'device->rad_info.has_syncobj_wait_for_submit'), 66 Extension('VK_KHR_external_memory', 1, True), 67 Extension('VK_KHR_external_memory_capabilities', 1, True), 68 Extension('VK_KHR_external_memory_fd', 1, True), 69 Extension('VK_KHR_external_semaphore', 1, 'device->rad_info.has_syncobj'), 70 Extension('VK_KHR_external_semaphore_capabilities', 1, True), 71 Extension('VK_KHR_external_semaphore_fd', 1, 'device->rad_info.has_syncobj'), 72 Extension('VK_KHR_get_display_properties2', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), 73 Extension('VK_KHR_get_memory_requirements2', 1, True), 74 Extension('VK_KHR_get_physical_device_properties2', 1, True), 75 Extension('VK_KHR_get_surface_capabilities2', 1, 'RADV_HAS_SURFACE'), 76 Extension('VK_KHR_image_format_list', 1, True), 77 Extension('VK_KHR_incremental_present', 1, 'RADV_HAS_SURFACE'), 78 Extension('VK_KHR_maintenance1', 1, True), 79 Extension('VK_KHR_maintenance2', 1, True), 80 Extension('VK_KHR_maintenance3', 1, True), 81 Extension('VK_KHR_push_descriptor', 1, True), 82 Extension('VK_KHR_relaxed_block_layout', 1, True), 83 Extension('VK_KHR_sampler_mirror_clamp_to_edge', 1, True), 84 Extension('VK_KHR_sampler_ycbcr_conversion', 1, True), 85 Extension('VK_KHR_shader_atomic_int64', 1, False), 86 Extension('VK_KHR_shader_draw_parameters', 1, True), 87 Extension('VK_KHR_shader_float16_int8', 1, True), 88 Extension('VK_KHR_storage_buffer_storage_class', 1, True), 89 Extension('VK_KHR_surface', 25, 'RADV_HAS_SURFACE'), 90 Extension('VK_KHR_surface_protected_capabilities', 1, 'RADV_HAS_SURFACE'), 91 Extension('VK_KHR_swapchain', 68, 'RADV_HAS_SURFACE'), 92 Extension('VK_KHR_variable_pointers', 1, True), 93 Extension('VK_KHR_wayland_surface', 6, 'VK_USE_PLATFORM_WAYLAND_KHR'), 94 Extension('VK_KHR_xcb_surface', 6, 'VK_USE_PLATFORM_XCB_KHR'), 95 Extension('VK_KHR_xlib_surface', 6, 'VK_USE_PLATFORM_XLIB_KHR'), 96 Extension('VK_KHR_multiview', 1, True), 97 Extension('VK_KHR_display', 23, 'VK_USE_PLATFORM_DISPLAY_KHR'), 98 Extension('VK_KHR_8bit_storage', 1, 'device->rad_info.chip_class >= VI'), 99 Extension('VK_EXT_direct_mode_display', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), 100 Extension('VK_EXT_acquire_xlib_display', 1, 'VK_USE_PLATFORM_XLIB_XRANDR_EXT'), 101 Extension('VK_EXT_buffer_device_address', 1, True), 102 Extension('VK_EXT_calibrated_timestamps', 1, True), 103 Extension('VK_EXT_conditional_rendering', 1, True), 104 Extension('VK_EXT_conservative_rasterization', 1, 'device->rad_info.chip_class >= GFX9'), 105 Extension('VK_EXT_display_surface_counter', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), 106 Extension('VK_EXT_display_control', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), 107 Extension('VK_EXT_debug_report', 9, True), 108 Extension('VK_EXT_depth_clip_enable', 1, True), 109 Extension('VK_EXT_depth_range_unrestricted', 1, True), 110 Extension('VK_EXT_descriptor_indexing', 2, True), 111 Extension('VK_EXT_discard_rectangles', 1, True), 112 Extension('VK_EXT_external_memory_dma_buf', 1, True), 113 Extension('VK_EXT_external_memory_host', 1, 'device->rad_info.has_userptr'), 114 Extension('VK_EXT_global_priority', 1, 'device->rad_info.has_ctx_priority'), 115 Extension('VK_EXT_host_query_reset', 1, True), 116 Extension('VK_EXT_inline_uniform_block', 1, True), 117 Extension('VK_EXT_memory_budget', 1, True), 118 Extension('VK_EXT_memory_priority', 1, True), 119 Extension('VK_EXT_pci_bus_info', 2, True), 120 Extension('VK_EXT_pipeline_creation_feedback', 1, True), 121 Extension('VK_EXT_sampler_filter_minmax', 1, 'device->rad_info.chip_class >= CIK'), 122 Extension('VK_EXT_scalar_block_layout', 1, 'device->rad_info.chip_class >= CIK'), 123 Extension('VK_EXT_shader_viewport_index_layer', 1, True), 124 Extension('VK_EXT_shader_stencil_export', 1, True), 125 Extension('VK_EXT_transform_feedback', 1, True), 126 Extension('VK_EXT_vertex_attribute_divisor', 3, True), 127 Extension('VK_EXT_ycbcr_image_arrays', 1, True), 128 Extension('VK_AMD_draw_indirect_count', 1, True), 129 Extension('VK_AMD_gcn_shader', 1, True), 130 Extension('VK_AMD_gpu_shader_half_float', 1, 'device->rad_info.chip_class >= GFX9 && HAVE_LLVM >= 0x0800'), 131 Extension('VK_AMD_gpu_shader_int16', 1, 'device->rad_info.chip_class >= GFX9'), 132 Extension('VK_AMD_rasterization_order', 1, 'device->has_out_of_order_rast'), 133 Extension('VK_AMD_shader_core_properties', 1, True), 134 Extension('VK_AMD_shader_info', 1, True), 135 Extension('VK_AMD_shader_trinary_minmax', 1, True), 136 Extension('VK_GOOGLE_decorate_string', 1, True), 137 Extension('VK_GOOGLE_hlsl_functionality1', 1, True), 138 Extension('VK_NV_compute_shader_derivatives', 1, 'device->rad_info.chip_class >= VI'), 139] 140 141class VkVersion: 142 def __init__(self, string): 143 split = string.split('.') 144 self.major = int(split[0]) 145 self.minor = int(split[1]) 146 if len(split) > 2: 147 assert len(split) == 3 148 self.patch = int(split[2]) 149 else: 150 self.patch = None 151 152 # Sanity check. The range bits are required by the definition of the 153 # VK_MAKE_VERSION macro 154 assert self.major < 1024 and self.minor < 1024 155 assert self.patch is None or self.patch < 4096 156 assert(str(self) == string) 157 158 def __str__(self): 159 ver_list = [str(self.major), str(self.minor)] 160 if self.patch is not None: 161 ver_list.append(str(self.patch)) 162 return '.'.join(ver_list) 163 164 def c_vk_version(self): 165 patch = self.patch if self.patch is not None else 0 166 ver_list = [str(self.major), str(self.minor), str(patch)] 167 return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')' 168 169 def __int_ver(self): 170 # This is just an expansion of VK_VERSION 171 patch = self.patch if self.patch is not None else 0 172 return (self.major << 22) | (self.minor << 12) | patch 173 174 def __gt__(self, other): 175 # If only one of them has a patch version, "ignore" it by making 176 # other's patch version match self. 177 if (self.patch is None) != (other.patch is None): 178 other = copy.copy(other) 179 other.patch = self.patch 180 181 return self.__int_ver() > other.__int_ver() 182 183 184MAX_API_VERSION = VkVersion(MAX_API_VERSION) 185 186def _init_exts_from_xml(xml): 187 """ Walk the Vulkan XML and fill out extra extension information. """ 188 189 xml = et.parse(xml) 190 191 ext_name_map = {} 192 for ext in EXTENSIONS: 193 ext_name_map[ext.name] = ext 194 195 for ext_elem in xml.findall('.extensions/extension'): 196 ext_name = ext_elem.attrib['name'] 197 if ext_name not in ext_name_map: 198 continue 199 200 ext = ext_name_map[ext_name] 201 ext.type = ext_elem.attrib['type'] 202 ext.promotedto = ext_elem.attrib.get('promotedto', None) 203 try: 204 ext.requires = ext_elem.attrib['requires'].split(',') 205 except KeyError: 206 ext.requires = [] 207 208 def extra_deps(ext): 209 if ext.type == 'instance': 210 check = 'instance->enabled_extensions.{}'.format(ext.name[3:]) 211 if ext.promotedto is not None: 212 # the xml contains values like VK_VERSION_1_1, but we need to 213 # translate them to VK_API_VERSION_1_1 for the apiVersion check 214 api_ver = ext.promotedto.replace('VK_VER', 'VK_API_VER') 215 check = '({} || instance->apiVersion >= {})'.format(check, api_ver) 216 return set([check]) 217 218 deps = set() 219 for dep in ext.requires: 220 deps |= extra_deps(ext_name_map[dep]) 221 222 return deps 223 224 for ext in EXTENSIONS: 225 if ext.type == 'device': 226 for dep in extra_deps(ext): 227 ext.enable += ' && ' + dep 228 229_TEMPLATE_H = Template(COPYRIGHT + """ 230#ifndef RADV_EXTENSIONS_H 231#define RADV_EXTENSIONS_H 232 233enum { 234 RADV_INSTANCE_EXTENSION_COUNT = ${len(instance_extensions)}, 235 RADV_DEVICE_EXTENSION_COUNT = ${len(device_extensions)}, 236}; 237 238struct radv_instance_extension_table { 239 union { 240 bool extensions[RADV_INSTANCE_EXTENSION_COUNT]; 241 struct { 242%for ext in instance_extensions: 243 bool ${ext.name[3:]}; 244%endfor 245 }; 246 }; 247}; 248 249struct radv_device_extension_table { 250 union { 251 bool extensions[RADV_DEVICE_EXTENSION_COUNT]; 252 struct { 253%for ext in device_extensions: 254 bool ${ext.name[3:]}; 255%endfor 256 }; 257 }; 258}; 259 260extern const VkExtensionProperties radv_instance_extensions[RADV_INSTANCE_EXTENSION_COUNT]; 261extern const VkExtensionProperties radv_device_extensions[RADV_DEVICE_EXTENSION_COUNT]; 262extern const struct radv_instance_extension_table radv_supported_instance_extensions; 263 264 265struct radv_physical_device; 266 267void radv_fill_device_extension_table(const struct radv_physical_device *device, 268 struct radv_device_extension_table* table); 269#endif 270""") 271 272_TEMPLATE_C = Template(COPYRIGHT + """ 273#include "radv_private.h" 274 275#include "vk_util.h" 276 277/* Convert the VK_USE_PLATFORM_* defines to booleans */ 278%for platform in ['ANDROID_KHR', 'WAYLAND_KHR', 'XCB_KHR', 'XLIB_KHR', 'DISPLAY_KHR', 'XLIB_XRANDR_EXT']: 279#ifdef VK_USE_PLATFORM_${platform} 280# undef VK_USE_PLATFORM_${platform} 281# define VK_USE_PLATFORM_${platform} true 282#else 283# define VK_USE_PLATFORM_${platform} false 284#endif 285%endfor 286 287/* And ANDROID too */ 288#ifdef ANDROID 289# undef ANDROID 290# define ANDROID true 291#else 292# define ANDROID false 293#endif 294 295#define RADV_HAS_SURFACE (VK_USE_PLATFORM_WAYLAND_KHR || \\ 296 VK_USE_PLATFORM_XCB_KHR || \\ 297 VK_USE_PLATFORM_XLIB_KHR || \\ 298 VK_USE_PLATFORM_DISPLAY_KHR) 299 300 301const VkExtensionProperties radv_instance_extensions[RADV_INSTANCE_EXTENSION_COUNT] = { 302%for ext in instance_extensions: 303 {"${ext.name}", ${ext.ext_version}}, 304%endfor 305}; 306 307const VkExtensionProperties radv_device_extensions[RADV_DEVICE_EXTENSION_COUNT] = { 308%for ext in device_extensions: 309 {"${ext.name}", ${ext.ext_version}}, 310%endfor 311}; 312 313const struct radv_instance_extension_table radv_supported_instance_extensions = { 314%for ext in instance_extensions: 315 .${ext.name[3:]} = ${ext.enable}, 316%endfor 317}; 318 319void radv_fill_device_extension_table(const struct radv_physical_device *device, 320 struct radv_device_extension_table* table) 321{ 322 const struct radv_instance *instance = device->instance; 323%for ext in device_extensions: 324 table->${ext.name[3:]} = ${ext.enable}; 325%endfor 326} 327 328VkResult radv_EnumerateInstanceVersion( 329 uint32_t* pApiVersion) 330{ 331 *pApiVersion = ${MAX_API_VERSION.c_vk_version()}; 332 return VK_SUCCESS; 333} 334 335uint32_t 336radv_physical_device_api_version(struct radv_physical_device *dev) 337{ 338 uint32_t override = vk_get_version_override(); 339 uint32_t version = VK_MAKE_VERSION(1, 0, 68); 340 if (dev->rad_info.has_syncobj_wait_for_submit) 341 version = ${MAX_API_VERSION.c_vk_version()}; 342 343 return override ? MIN2(override, version) : version; 344} 345""") 346 347if __name__ == '__main__': 348 parser = argparse.ArgumentParser() 349 parser.add_argument('--out-c', help='Output C file.', required=True) 350 parser.add_argument('--out-h', help='Output H file.', required=True) 351 parser.add_argument('--xml', 352 help='Vulkan API XML file.', 353 required=True, 354 action='append', 355 dest='xml_files') 356 args = parser.parse_args() 357 358 for filename in args.xml_files: 359 _init_exts_from_xml(filename) 360 361 for ext in EXTENSIONS: 362 assert ext.type == 'instance' or ext.type == 'device' 363 364 template_env = { 365 'MAX_API_VERSION': MAX_API_VERSION, 366 'instance_extensions': [e for e in EXTENSIONS if e.type == 'instance'], 367 'device_extensions': [e for e in EXTENSIONS if e.type == 'device'], 368 } 369 370 with open(args.out_c, 'w') as f: 371 f.write(_TEMPLATE_C.render(**template_env)) 372 with open(args.out_h, 'w') as f: 373 f.write(_TEMPLATE_H.render(**template_env)) 374