1bf215546Sopenharmony_ciCOPYRIGHT=u""" 2bf215546Sopenharmony_ci/* Copyright © 2021 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci""" 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ciimport argparse 26bf215546Sopenharmony_ciimport os 27bf215546Sopenharmony_cifrom collections import OrderedDict, namedtuple 28bf215546Sopenharmony_ciimport xml.etree.ElementTree as et 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_cifrom mako.template import Template 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ciTEMPLATE_C = Template(COPYRIGHT + """ 33bf215546Sopenharmony_ci/* This file generated from ${filename}, don't edit directly. */ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "vk_log.h" 36bf215546Sopenharmony_ci#include "vk_physical_device.h" 37bf215546Sopenharmony_ci#include "vk_util.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_cistatic VkResult 40bf215546Sopenharmony_cicheck_physical_device_features(struct vk_physical_device *physical_device, 41bf215546Sopenharmony_ci const VkPhysicalDeviceFeatures *supported, 42bf215546Sopenharmony_ci const VkPhysicalDeviceFeatures *enabled, 43bf215546Sopenharmony_ci const char *struct_name) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci% for flag in pdev_features: 46bf215546Sopenharmony_ci if (enabled->${flag} && !supported->${flag}) 47bf215546Sopenharmony_ci return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT, 48bf215546Sopenharmony_ci "%s.%s not supported", struct_name, "${flag}"); 49bf215546Sopenharmony_ci% endfor 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci return VK_SUCCESS; 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ciVkResult 55bf215546Sopenharmony_civk_physical_device_check_device_features(struct vk_physical_device *physical_device, 56bf215546Sopenharmony_ci const VkDeviceCreateInfo *pCreateInfo) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci VkPhysicalDevice vk_physical_device = 59bf215546Sopenharmony_ci vk_physical_device_to_handle(physical_device); 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci /* Query the device what kind of features are supported. */ 62bf215546Sopenharmony_ci VkPhysicalDeviceFeatures2 supported_features2 = { 63bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, 64bf215546Sopenharmony_ci }; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci% for f in features: 67bf215546Sopenharmony_ci ${f.name} supported_${f.name} = { .pNext = NULL }; 68bf215546Sopenharmony_ci% endfor 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci vk_foreach_struct_const(feat, pCreateInfo->pNext) { 71bf215546Sopenharmony_ci VkBaseOutStructure *supported = NULL; 72bf215546Sopenharmony_ci switch (feat->sType) { 73bf215546Sopenharmony_ci% for f in features: 74bf215546Sopenharmony_ci case ${f.vk_type}: 75bf215546Sopenharmony_ci supported = (VkBaseOutStructure *) &supported_${f.name}; 76bf215546Sopenharmony_ci break; 77bf215546Sopenharmony_ci% endfor 78bf215546Sopenharmony_ci default: 79bf215546Sopenharmony_ci break; 80bf215546Sopenharmony_ci } 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci /* Not a feature struct. */ 83bf215546Sopenharmony_ci if (!supported) 84bf215546Sopenharmony_ci continue; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci /* Check for cycles in the list */ 87bf215546Sopenharmony_ci if (supported->pNext != NULL || supported->sType != 0) 88bf215546Sopenharmony_ci return VK_ERROR_UNKNOWN; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci supported->sType = feat->sType; 91bf215546Sopenharmony_ci __vk_append_struct(&supported_features2, supported); 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci physical_device->dispatch_table.GetPhysicalDeviceFeatures2( 95bf215546Sopenharmony_ci vk_physical_device, &supported_features2); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci if (pCreateInfo->pEnabledFeatures) { 98bf215546Sopenharmony_ci VkResult result = 99bf215546Sopenharmony_ci check_physical_device_features(physical_device, 100bf215546Sopenharmony_ci &supported_features2.features, 101bf215546Sopenharmony_ci pCreateInfo->pEnabledFeatures, 102bf215546Sopenharmony_ci "VkPhysicalDeviceFeatures"); 103bf215546Sopenharmony_ci if (result != VK_SUCCESS) 104bf215546Sopenharmony_ci return result; 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci /* Iterate through additional feature structs */ 108bf215546Sopenharmony_ci vk_foreach_struct_const(feat, pCreateInfo->pNext) { 109bf215546Sopenharmony_ci /* Check each feature boolean for given structure. */ 110bf215546Sopenharmony_ci switch (feat->sType) { 111bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: { 112bf215546Sopenharmony_ci const VkPhysicalDeviceFeatures2 *features2 = (const void *)feat; 113bf215546Sopenharmony_ci VkResult result = 114bf215546Sopenharmony_ci check_physical_device_features(physical_device, 115bf215546Sopenharmony_ci &supported_features2.features, 116bf215546Sopenharmony_ci &features2->features, 117bf215546Sopenharmony_ci "VkPhysicalDeviceFeatures2.features"); 118bf215546Sopenharmony_ci if (result != VK_SUCCESS) 119bf215546Sopenharmony_ci return result; 120bf215546Sopenharmony_ci break; 121bf215546Sopenharmony_ci } 122bf215546Sopenharmony_ci% for f in features: 123bf215546Sopenharmony_ci case ${f.vk_type} : { 124bf215546Sopenharmony_ci ${f.name} *a = &supported_${f.name}; 125bf215546Sopenharmony_ci ${f.name} *b = (${f.name} *) feat; 126bf215546Sopenharmony_ci% for flag in f.vk_flags: 127bf215546Sopenharmony_ci if (b->${flag} && !a->${flag}) 128bf215546Sopenharmony_ci return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT, 129bf215546Sopenharmony_ci "%s.%s not supported", "${f.name}", "${flag}"); 130bf215546Sopenharmony_ci% endfor 131bf215546Sopenharmony_ci break; 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci% endfor 134bf215546Sopenharmony_ci default: 135bf215546Sopenharmony_ci break; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci } // for each extension structure 138bf215546Sopenharmony_ci return VK_SUCCESS; 139bf215546Sopenharmony_ci} 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci""", output_encoding='utf-8') 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ciFeature = namedtuple('Feature', 'name vk_type vk_flags') 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_cidef get_pdev_features(doc): 146bf215546Sopenharmony_ci for _type in doc.findall('./types/type'): 147bf215546Sopenharmony_ci if _type.attrib.get('name') != 'VkPhysicalDeviceFeatures': 148bf215546Sopenharmony_ci continue 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci flags = [] 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci for p in _type.findall('./member'): 153bf215546Sopenharmony_ci assert p.find('./type').text == 'VkBool32' 154bf215546Sopenharmony_ci flags.append(p.find('./name').text) 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci return flags 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci return None 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_cidef get_features(doc): 161bf215546Sopenharmony_ci features = OrderedDict() 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci provisional_structs = set() 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci # we want to ignore struct types that are part of provisional extensions 166bf215546Sopenharmony_ci for _extension in doc.findall('./extensions/extension'): 167bf215546Sopenharmony_ci if _extension.attrib.get('provisional') != 'true': 168bf215546Sopenharmony_ci continue 169bf215546Sopenharmony_ci for p in _extension.findall('./require/type'): 170bf215546Sopenharmony_ci provisional_structs.add(p.attrib.get('name')) 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci # parse all struct types where structextends VkPhysicalDeviceFeatures2 173bf215546Sopenharmony_ci for _type in doc.findall('./types/type'): 174bf215546Sopenharmony_ci if _type.attrib.get('category') != 'struct': 175bf215546Sopenharmony_ci continue 176bf215546Sopenharmony_ci if _type.attrib.get('structextends') != 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo': 177bf215546Sopenharmony_ci continue 178bf215546Sopenharmony_ci if _type.attrib.get('name') in provisional_structs: 179bf215546Sopenharmony_ci continue 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci # find Vulkan structure type 182bf215546Sopenharmony_ci for elem in _type: 183bf215546Sopenharmony_ci if "STRUCTURE_TYPE" in str(elem.attrib): 184bf215546Sopenharmony_ci s_type = elem.attrib.get('values') 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci # collect a list of feature flags 187bf215546Sopenharmony_ci flags = [] 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci for p in _type.findall('./member'): 190bf215546Sopenharmony_ci m_name = p.find('./name').text 191bf215546Sopenharmony_ci if m_name == 'pNext': 192bf215546Sopenharmony_ci pass 193bf215546Sopenharmony_ci elif m_name == 'sType': 194bf215546Sopenharmony_ci s_type = p.attrib.get('values') 195bf215546Sopenharmony_ci else: 196bf215546Sopenharmony_ci assert p.find('./type').text == 'VkBool32' 197bf215546Sopenharmony_ci flags.append(m_name) 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci feat = Feature(name=_type.attrib.get('name'), vk_type=s_type, vk_flags=flags) 200bf215546Sopenharmony_ci features[_type.attrib.get('name')] = feat 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci return features.values() 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_cidef get_features_from_xml(xml_files): 205bf215546Sopenharmony_ci pdev_features = None 206bf215546Sopenharmony_ci features = [] 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci for filename in xml_files: 209bf215546Sopenharmony_ci doc = et.parse(filename) 210bf215546Sopenharmony_ci features += get_features(doc) 211bf215546Sopenharmony_ci if not pdev_features: 212bf215546Sopenharmony_ci pdev_features = get_pdev_features(doc) 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci return pdev_features, features 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_cidef main(): 218bf215546Sopenharmony_ci parser = argparse.ArgumentParser() 219bf215546Sopenharmony_ci parser.add_argument('--out-c', required=True, help='Output C file.') 220bf215546Sopenharmony_ci parser.add_argument('--xml', 221bf215546Sopenharmony_ci help='Vulkan API XML file.', 222bf215546Sopenharmony_ci required=True, action='append', dest='xml_files') 223bf215546Sopenharmony_ci args = parser.parse_args() 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci pdev_features, features = get_features_from_xml(args.xml_files) 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci environment = { 228bf215546Sopenharmony_ci 'filename': os.path.basename(__file__), 229bf215546Sopenharmony_ci 'pdev_features': pdev_features, 230bf215546Sopenharmony_ci 'features': features, 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci try: 234bf215546Sopenharmony_ci with open(args.out_c, 'wb') as f: 235bf215546Sopenharmony_ci f.write(TEMPLATE_C.render(**environment)) 236bf215546Sopenharmony_ci except Exception: 237bf215546Sopenharmony_ci # In the event there's an error, this imports some helpers from mako 238bf215546Sopenharmony_ci # to print a useful stack trace and prints it, then exits with 239bf215546Sopenharmony_ci # status 1, if python is run with debug; otherwise it just raises 240bf215546Sopenharmony_ci # the exception 241bf215546Sopenharmony_ci import sys 242bf215546Sopenharmony_ci from mako import exceptions 243bf215546Sopenharmony_ci print(exceptions.text_error_template().render(), file=sys.stderr) 244bf215546Sopenharmony_ci sys.exit(1) 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ciif __name__ == '__main__': 247bf215546Sopenharmony_ci main() 248