15db71995Sopenharmony_ci#!/usr/bin/python3 -i 25db71995Sopenharmony_ci# 35db71995Sopenharmony_ci# Copyright (c) 2015-2017 The Khronos Group Inc. 45db71995Sopenharmony_ci# Copyright (c) 2015-2017 Valve Corporation 55db71995Sopenharmony_ci# Copyright (c) 2015-2017 LunarG, Inc. 65db71995Sopenharmony_ci# Copyright (c) 2015-2017 Google Inc. 75db71995Sopenharmony_ci# 85db71995Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 95db71995Sopenharmony_ci# you may not use this file except in compliance with the License. 105db71995Sopenharmony_ci# You may obtain a copy of the License at 115db71995Sopenharmony_ci# 125db71995Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 135db71995Sopenharmony_ci# 145db71995Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 155db71995Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 165db71995Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 175db71995Sopenharmony_ci# See the License for the specific language governing permissions and 185db71995Sopenharmony_ci# limitations under the License. 195db71995Sopenharmony_ci# 205db71995Sopenharmony_ci# Author: Mark Lobodzinski <mark@lunarg.com> 215db71995Sopenharmony_ci# Author: Tobin Ehlis <tobine@google.com> 225db71995Sopenharmony_ci# Author: John Zulauf <jzulauf@lunarg.com> 235db71995Sopenharmony_ci 245db71995Sopenharmony_ciimport os,re,sys 255db71995Sopenharmony_ciimport xml.etree.ElementTree as etree 265db71995Sopenharmony_cifrom generator import * 275db71995Sopenharmony_cifrom collections import namedtuple 285db71995Sopenharmony_cifrom common_codegen import * 295db71995Sopenharmony_ci 305db71995Sopenharmony_ci# 315db71995Sopenharmony_ci# HelperFileOutputGeneratorOptions - subclass of GeneratorOptions. 325db71995Sopenharmony_ciclass HelperFileOutputGeneratorOptions(GeneratorOptions): 335db71995Sopenharmony_ci def __init__(self, 345db71995Sopenharmony_ci conventions = None, 355db71995Sopenharmony_ci filename = None, 365db71995Sopenharmony_ci directory = '.', 375db71995Sopenharmony_ci genpath = None, 385db71995Sopenharmony_ci apiname = None, 395db71995Sopenharmony_ci profile = None, 405db71995Sopenharmony_ci versions = '.*', 415db71995Sopenharmony_ci emitversions = '.*', 425db71995Sopenharmony_ci defaultExtensions = None, 435db71995Sopenharmony_ci addExtensions = None, 445db71995Sopenharmony_ci removeExtensions = None, 455db71995Sopenharmony_ci emitExtensions = None, 465db71995Sopenharmony_ci sortProcedure = regSortFeatures, 475db71995Sopenharmony_ci prefixText = "", 485db71995Sopenharmony_ci genFuncPointers = True, 495db71995Sopenharmony_ci protectFile = True, 505db71995Sopenharmony_ci protectFeature = True, 515db71995Sopenharmony_ci apicall = '', 525db71995Sopenharmony_ci apientry = '', 535db71995Sopenharmony_ci apientryp = '', 545db71995Sopenharmony_ci alignFuncParam = 0, 555db71995Sopenharmony_ci library_name = '', 565db71995Sopenharmony_ci expandEnumerants = True, 575db71995Sopenharmony_ci helper_file_type = ''): 585db71995Sopenharmony_ci GeneratorOptions.__init__(self, 595db71995Sopenharmony_ci conventions = conventions, 605db71995Sopenharmony_ci filename = filename, 615db71995Sopenharmony_ci directory = directory, 625db71995Sopenharmony_ci genpath = genpath, 635db71995Sopenharmony_ci apiname = apiname, 645db71995Sopenharmony_ci profile = profile, 655db71995Sopenharmony_ci versions = versions, 665db71995Sopenharmony_ci emitversions = emitversions, 675db71995Sopenharmony_ci defaultExtensions = defaultExtensions, 685db71995Sopenharmony_ci addExtensions = addExtensions, 695db71995Sopenharmony_ci removeExtensions = removeExtensions, 705db71995Sopenharmony_ci emitExtensions = emitExtensions, 715db71995Sopenharmony_ci sortProcedure = sortProcedure) 725db71995Sopenharmony_ci self.prefixText = prefixText 735db71995Sopenharmony_ci self.genFuncPointers = genFuncPointers 745db71995Sopenharmony_ci self.protectFile = protectFile 755db71995Sopenharmony_ci self.protectFeature = protectFeature 765db71995Sopenharmony_ci self.apicall = apicall 775db71995Sopenharmony_ci self.apientry = apientry 785db71995Sopenharmony_ci self.apientryp = apientryp 795db71995Sopenharmony_ci self.alignFuncParam = alignFuncParam 805db71995Sopenharmony_ci self.library_name = library_name 815db71995Sopenharmony_ci self.helper_file_type = helper_file_type 825db71995Sopenharmony_ci# 835db71995Sopenharmony_ci# HelperFileOutputGenerator - subclass of OutputGenerator. Outputs Vulkan helper files 845db71995Sopenharmony_ciclass HelperFileOutputGenerator(OutputGenerator): 855db71995Sopenharmony_ci """Generate helper file based on XML element attributes""" 865db71995Sopenharmony_ci def __init__(self, 875db71995Sopenharmony_ci errFile = sys.stderr, 885db71995Sopenharmony_ci warnFile = sys.stderr, 895db71995Sopenharmony_ci diagFile = sys.stdout): 905db71995Sopenharmony_ci OutputGenerator.__init__(self, errFile, warnFile, diagFile) 915db71995Sopenharmony_ci # Internal state - accumulators for different inner block text 925db71995Sopenharmony_ci self.enum_output = '' # string built up of enum string routines 935db71995Sopenharmony_ci # Internal state - accumulators for different inner block text 945db71995Sopenharmony_ci self.structNames = [] # List of Vulkan struct typenames 955db71995Sopenharmony_ci self.structTypes = dict() # Map of Vulkan struct typename to required VkStructureType 965db71995Sopenharmony_ci self.structMembers = [] # List of StructMemberData records for all Vulkan structs 975db71995Sopenharmony_ci self.object_types = [] # List of all handle types 985db71995Sopenharmony_ci self.object_type_aliases = [] # Aliases to handles types (for handles that were extensions) 995db71995Sopenharmony_ci self.debug_report_object_types = [] # Handy copy of debug_report_object_type enum data 1005db71995Sopenharmony_ci self.core_object_types = [] # Handy copy of core_object_type enum data 1015db71995Sopenharmony_ci self.device_extension_info = dict() # Dict of device extension name defines and ifdef values 1025db71995Sopenharmony_ci self.instance_extension_info = dict() # Dict of instance extension name defines and ifdef values 1035db71995Sopenharmony_ci 1045db71995Sopenharmony_ci # Named tuples to store struct and command data 1055db71995Sopenharmony_ci self.StructType = namedtuple('StructType', ['name', 'value']) 1065db71995Sopenharmony_ci self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isstaticarray', 'isconst', 'iscount', 'len', 'extstructs', 'cdecl']) 1075db71995Sopenharmony_ci self.StructMemberData = namedtuple('StructMemberData', ['name', 'members', 'ifdef_protect']) 1085db71995Sopenharmony_ci 1095db71995Sopenharmony_ci self.custom_construct_params = { 1105db71995Sopenharmony_ci # safe_VkGraphicsPipelineCreateInfo needs to know if subpass has color and\or depth\stencil attachments to use its pointers 1115db71995Sopenharmony_ci 'VkGraphicsPipelineCreateInfo' : 1125db71995Sopenharmony_ci ', const bool uses_color_attachment, const bool uses_depthstencil_attachment', 1135db71995Sopenharmony_ci # safe_VkPipelineViewportStateCreateInfo needs to know if viewport and scissor is dynamic to use its pointers 1145db71995Sopenharmony_ci 'VkPipelineViewportStateCreateInfo' : 1155db71995Sopenharmony_ci ', const bool is_dynamic_viewports, const bool is_dynamic_scissors', 1165db71995Sopenharmony_ci } 1175db71995Sopenharmony_ci # 1185db71995Sopenharmony_ci # Called once at the beginning of each run 1195db71995Sopenharmony_ci def beginFile(self, genOpts): 1205db71995Sopenharmony_ci OutputGenerator.beginFile(self, genOpts) 1215db71995Sopenharmony_ci # User-supplied prefix text, if any (list of strings) 1225db71995Sopenharmony_ci self.helper_file_type = genOpts.helper_file_type 1235db71995Sopenharmony_ci self.library_name = genOpts.library_name 1245db71995Sopenharmony_ci 1255db71995Sopenharmony_ci write("// clang-format off", file=self.outFile) 1265db71995Sopenharmony_ci 1275db71995Sopenharmony_ci # File Comment 1285db71995Sopenharmony_ci file_comment = '// *** THIS FILE IS GENERATED - DO NOT EDIT ***\n' 1295db71995Sopenharmony_ci file_comment += '// See helper_file_generator.py for modifications\n' 1305db71995Sopenharmony_ci write(file_comment, file=self.outFile) 1315db71995Sopenharmony_ci # Copyright Notice 1325db71995Sopenharmony_ci copyright = '' 1335db71995Sopenharmony_ci copyright += '\n' 1345db71995Sopenharmony_ci copyright += '/***************************************************************************\n' 1355db71995Sopenharmony_ci copyright += ' *\n' 1365db71995Sopenharmony_ci copyright += ' * Copyright (c) 2015-2017 The Khronos Group Inc.\n' 1375db71995Sopenharmony_ci copyright += ' * Copyright (c) 2015-2017 Valve Corporation\n' 1385db71995Sopenharmony_ci copyright += ' * Copyright (c) 2015-2017 LunarG, Inc.\n' 1395db71995Sopenharmony_ci copyright += ' * Copyright (c) 2015-2017 Google Inc.\n' 1405db71995Sopenharmony_ci copyright += ' *\n' 1415db71995Sopenharmony_ci copyright += ' * Licensed under the Apache License, Version 2.0 (the "License");\n' 1425db71995Sopenharmony_ci copyright += ' * you may not use this file except in compliance with the License.\n' 1435db71995Sopenharmony_ci copyright += ' * You may obtain a copy of the License at\n' 1445db71995Sopenharmony_ci copyright += ' *\n' 1455db71995Sopenharmony_ci copyright += ' * http://www.apache.org/licenses/LICENSE-2.0\n' 1465db71995Sopenharmony_ci copyright += ' *\n' 1475db71995Sopenharmony_ci copyright += ' * Unless required by applicable law or agreed to in writing, software\n' 1485db71995Sopenharmony_ci copyright += ' * distributed under the License is distributed on an "AS IS" BASIS,\n' 1495db71995Sopenharmony_ci copyright += ' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n' 1505db71995Sopenharmony_ci copyright += ' * See the License for the specific language governing permissions and\n' 1515db71995Sopenharmony_ci copyright += ' * limitations under the License.\n' 1525db71995Sopenharmony_ci copyright += ' *\n' 1535db71995Sopenharmony_ci copyright += ' * Author: Mark Lobodzinski <mark@lunarg.com>\n' 1545db71995Sopenharmony_ci copyright += ' * Author: Courtney Goeltzenleuchter <courtneygo@google.com>\n' 1555db71995Sopenharmony_ci copyright += ' * Author: Tobin Ehlis <tobine@google.com>\n' 1565db71995Sopenharmony_ci copyright += ' * Author: Chris Forbes <chrisforbes@google.com>\n' 1575db71995Sopenharmony_ci copyright += ' * Author: John Zulauf<jzulauf@lunarg.com>\n' 1585db71995Sopenharmony_ci copyright += ' *\n' 1595db71995Sopenharmony_ci copyright += ' ****************************************************************************/\n' 1605db71995Sopenharmony_ci write(copyright, file=self.outFile) 1615db71995Sopenharmony_ci # 1625db71995Sopenharmony_ci # Write generated file content to output file 1635db71995Sopenharmony_ci def endFile(self): 1645db71995Sopenharmony_ci dest_file = '' 1655db71995Sopenharmony_ci dest_file += self.OutputDestFile() 1665db71995Sopenharmony_ci # Remove blank lines at EOF 1675db71995Sopenharmony_ci if dest_file.endswith('\n'): 1685db71995Sopenharmony_ci dest_file = dest_file[:-1] 1695db71995Sopenharmony_ci write(dest_file, file=self.outFile) 1705db71995Sopenharmony_ci write("// clang-format on", file=self.outFile) 1715db71995Sopenharmony_ci # Finish processing in superclass 1725db71995Sopenharmony_ci OutputGenerator.endFile(self) 1735db71995Sopenharmony_ci # 1745db71995Sopenharmony_ci # Override parent class to be notified of the beginning of an extension 1755db71995Sopenharmony_ci def beginFeature(self, interface, emit): 1765db71995Sopenharmony_ci # Start processing in superclass 1775db71995Sopenharmony_ci OutputGenerator.beginFeature(self, interface, emit) 1785db71995Sopenharmony_ci self.featureExtraProtect = GetFeatureProtect(interface) 1795db71995Sopenharmony_ci 1805db71995Sopenharmony_ci if interface.tag != 'extension': 1815db71995Sopenharmony_ci return 1825db71995Sopenharmony_ci name = self.featureName 1835db71995Sopenharmony_ci name_define = next(enum.get('name') for enum in interface.findall('require/enum') if enum.get('name').endswith('_EXTENSION_NAME')) 1845db71995Sopenharmony_ci requires = interface.get('requires') 1855db71995Sopenharmony_ci if requires is not None: 1865db71995Sopenharmony_ci required_extensions = requires.split(',') 1875db71995Sopenharmony_ci else: 1885db71995Sopenharmony_ci required_extensions = list() 1895db71995Sopenharmony_ci info = { 'define': name_define, 'ifdef':self.featureExtraProtect, 'reqs':required_extensions } 1905db71995Sopenharmony_ci if interface.get('type') == 'instance': 1915db71995Sopenharmony_ci self.instance_extension_info[name] = info 1925db71995Sopenharmony_ci else: 1935db71995Sopenharmony_ci self.device_extension_info[name] = info 1945db71995Sopenharmony_ci 1955db71995Sopenharmony_ci # 1965db71995Sopenharmony_ci # Override parent class to be notified of the end of an extension 1975db71995Sopenharmony_ci def endFeature(self): 1985db71995Sopenharmony_ci # Finish processing in superclass 1995db71995Sopenharmony_ci OutputGenerator.endFeature(self) 2005db71995Sopenharmony_ci # 2015db71995Sopenharmony_ci # Grab group (e.g. C "enum" type) info to output for enum-string conversion helper 2025db71995Sopenharmony_ci def genGroup(self, groupinfo, groupName, alias): 2035db71995Sopenharmony_ci OutputGenerator.genGroup(self, groupinfo, groupName, alias) 2045db71995Sopenharmony_ci groupElem = groupinfo.elem 2055db71995Sopenharmony_ci # For enum_string_header 2065db71995Sopenharmony_ci if self.helper_file_type == 'enum_string_header': 2075db71995Sopenharmony_ci value_set = set() 2085db71995Sopenharmony_ci for elem in groupElem.findall('enum'): 2095db71995Sopenharmony_ci if elem.get('supported') != 'disabled' and elem.get('alias') is None: 2105db71995Sopenharmony_ci value_set.add(elem.get('name')) 2115db71995Sopenharmony_ci self.enum_output += self.GenerateEnumStringConversion(groupName, value_set) 2125db71995Sopenharmony_ci elif self.helper_file_type == 'object_types_header': 2135db71995Sopenharmony_ci if groupName == 'VkDebugReportObjectTypeEXT': 2145db71995Sopenharmony_ci for elem in groupElem.findall('enum'): 2155db71995Sopenharmony_ci if elem.get('supported') != 'disabled': 2165db71995Sopenharmony_ci item_name = elem.get('name') 2175db71995Sopenharmony_ci self.debug_report_object_types.append(item_name) 2185db71995Sopenharmony_ci elif groupName == 'VkObjectType': 2195db71995Sopenharmony_ci for elem in groupElem.findall('enum'): 2205db71995Sopenharmony_ci if elem.get('supported') != 'disabled': 2215db71995Sopenharmony_ci item_name = elem.get('name') 2225db71995Sopenharmony_ci self.core_object_types.append(item_name) 2235db71995Sopenharmony_ci 2245db71995Sopenharmony_ci # 2255db71995Sopenharmony_ci # Called for each type -- if the type is a struct/union, grab the metadata 2265db71995Sopenharmony_ci def genType(self, typeinfo, name, alias): 2275db71995Sopenharmony_ci OutputGenerator.genType(self, typeinfo, name, alias) 2285db71995Sopenharmony_ci typeElem = typeinfo.elem 2295db71995Sopenharmony_ci # If the type is a struct type, traverse the imbedded <member> tags generating a structure. 2305db71995Sopenharmony_ci # Otherwise, emit the tag text. 2315db71995Sopenharmony_ci category = typeElem.get('category') 2325db71995Sopenharmony_ci if category == 'handle': 2335db71995Sopenharmony_ci if alias: 2345db71995Sopenharmony_ci self.object_type_aliases.append((name,alias)) 2355db71995Sopenharmony_ci else: 2365db71995Sopenharmony_ci self.object_types.append(name) 2375db71995Sopenharmony_ci elif (category == 'struct' or category == 'union'): 2385db71995Sopenharmony_ci self.structNames.append(name) 2395db71995Sopenharmony_ci self.genStruct(typeinfo, name, alias) 2405db71995Sopenharmony_ci # 2415db71995Sopenharmony_ci # Generate a VkStructureType based on a structure typename 2425db71995Sopenharmony_ci def genVkStructureType(self, typename): 2435db71995Sopenharmony_ci # Add underscore between lowercase then uppercase 2445db71995Sopenharmony_ci value = re.sub('([a-z0-9])([A-Z])', r'\1_\2', typename) 2455db71995Sopenharmony_ci # Change to uppercase 2465db71995Sopenharmony_ci value = value.upper() 2475db71995Sopenharmony_ci # Add STRUCTURE_TYPE_ 2485db71995Sopenharmony_ci return re.sub('VK_', 'VK_STRUCTURE_TYPE_', value) 2495db71995Sopenharmony_ci # 2505db71995Sopenharmony_ci # Check if the parameter passed in is a pointer 2515db71995Sopenharmony_ci def paramIsPointer(self, param): 2525db71995Sopenharmony_ci ispointer = False 2535db71995Sopenharmony_ci for elem in param: 2545db71995Sopenharmony_ci if ((elem.tag != 'type') and (elem.tail is not None)) and '*' in elem.tail: 2555db71995Sopenharmony_ci ispointer = True 2565db71995Sopenharmony_ci return ispointer 2575db71995Sopenharmony_ci # 2585db71995Sopenharmony_ci # Check if the parameter passed in is a static array 2595db71995Sopenharmony_ci def paramIsStaticArray(self, param): 2605db71995Sopenharmony_ci isstaticarray = 0 2615db71995Sopenharmony_ci paramname = param.find('name') 2625db71995Sopenharmony_ci if (paramname.tail is not None) and ('[' in paramname.tail): 2635db71995Sopenharmony_ci isstaticarray = paramname.tail.count('[') 2645db71995Sopenharmony_ci return isstaticarray 2655db71995Sopenharmony_ci # 2665db71995Sopenharmony_ci # Retrieve the type and name for a parameter 2675db71995Sopenharmony_ci def getTypeNameTuple(self, param): 2685db71995Sopenharmony_ci type = '' 2695db71995Sopenharmony_ci name = '' 2705db71995Sopenharmony_ci for elem in param: 2715db71995Sopenharmony_ci if elem.tag == 'type': 2725db71995Sopenharmony_ci type = noneStr(elem.text) 2735db71995Sopenharmony_ci elif elem.tag == 'name': 2745db71995Sopenharmony_ci name = noneStr(elem.text) 2755db71995Sopenharmony_ci return (type, name) 2765db71995Sopenharmony_ci # 2775db71995Sopenharmony_ci # Retrieve the value of the len tag 2785db71995Sopenharmony_ci def getLen(self, param): 2795db71995Sopenharmony_ci result = None 2805db71995Sopenharmony_ci len = param.attrib.get('len') 2815db71995Sopenharmony_ci if len and len != 'null-terminated': 2825db71995Sopenharmony_ci # For string arrays, 'len' can look like 'count,null-terminated', indicating that we 2835db71995Sopenharmony_ci # have a null terminated array of strings. We strip the null-terminated from the 2845db71995Sopenharmony_ci # 'len' field and only return the parameter specifying the string count 2855db71995Sopenharmony_ci if 'null-terminated' in len: 2865db71995Sopenharmony_ci result = len.split(',')[0] 2875db71995Sopenharmony_ci else: 2885db71995Sopenharmony_ci result = len 2895db71995Sopenharmony_ci if 'altlen' in param.attrib: 2905db71995Sopenharmony_ci # Elements with latexmath 'len' also contain a C equivalent 'altlen' attribute 2915db71995Sopenharmony_ci # Use indexing operator instead of get() so we fail if the attribute is missing 2925db71995Sopenharmony_ci result = param.attrib['altlen'] 2935db71995Sopenharmony_ci # Spec has now notation for len attributes, using :: instead of platform specific pointer symbol 2945db71995Sopenharmony_ci result = str(result).replace('::', '->') 2955db71995Sopenharmony_ci return result 2965db71995Sopenharmony_ci # 2975db71995Sopenharmony_ci # Check if a structure is or contains a dispatchable (dispatchable = True) or 2985db71995Sopenharmony_ci # non-dispatchable (dispatchable = False) handle 2995db71995Sopenharmony_ci def TypeContainsObjectHandle(self, handle_type, dispatchable): 3005db71995Sopenharmony_ci if dispatchable: 3015db71995Sopenharmony_ci type_key = 'VK_DEFINE_HANDLE' 3025db71995Sopenharmony_ci else: 3035db71995Sopenharmony_ci type_key = 'VK_DEFINE_NON_DISPATCHABLE_HANDLE' 3045db71995Sopenharmony_ci handle = self.registry.tree.find("types/type/[name='" + handle_type + "'][@category='handle']") 3055db71995Sopenharmony_ci if handle is not None and handle.find('type').text == type_key: 3065db71995Sopenharmony_ci return True 3075db71995Sopenharmony_ci # if handle_type is a struct, search its members 3085db71995Sopenharmony_ci if handle_type in self.structNames: 3095db71995Sopenharmony_ci member_index = next((i for i, v in enumerate(self.structMembers) if v[0] == handle_type), None) 3105db71995Sopenharmony_ci if member_index is not None: 3115db71995Sopenharmony_ci for item in self.structMembers[member_index].members: 3125db71995Sopenharmony_ci handle = self.registry.tree.find("types/type/[name='" + item.type + "'][@category='handle']") 3135db71995Sopenharmony_ci if handle is not None and handle.find('type').text == type_key: 3145db71995Sopenharmony_ci return True 3155db71995Sopenharmony_ci return False 3165db71995Sopenharmony_ci # 3175db71995Sopenharmony_ci # Generate local ready-access data describing Vulkan structures and unions from the XML metadata 3185db71995Sopenharmony_ci def genStruct(self, typeinfo, typeName, alias): 3195db71995Sopenharmony_ci OutputGenerator.genStruct(self, typeinfo, typeName, alias) 3205db71995Sopenharmony_ci members = typeinfo.elem.findall('.//member') 3215db71995Sopenharmony_ci # Iterate over members once to get length parameters for arrays 3225db71995Sopenharmony_ci lens = set() 3235db71995Sopenharmony_ci for member in members: 3245db71995Sopenharmony_ci len = self.getLen(member) 3255db71995Sopenharmony_ci if len: 3265db71995Sopenharmony_ci lens.add(len) 3275db71995Sopenharmony_ci # Generate member info 3285db71995Sopenharmony_ci membersInfo = [] 3295db71995Sopenharmony_ci for member in members: 3305db71995Sopenharmony_ci # Get the member's type and name 3315db71995Sopenharmony_ci info = self.getTypeNameTuple(member) 3325db71995Sopenharmony_ci type = info[0] 3335db71995Sopenharmony_ci name = info[1] 3345db71995Sopenharmony_ci cdecl = self.makeCParamDecl(member, 1) 3355db71995Sopenharmony_ci # Process VkStructureType 3365db71995Sopenharmony_ci if type == 'VkStructureType': 3375db71995Sopenharmony_ci # Extract the required struct type value from the comments 3385db71995Sopenharmony_ci # embedded in the original text defining the 'typeinfo' element 3395db71995Sopenharmony_ci rawXml = etree.tostring(typeinfo.elem).decode('ascii') 3405db71995Sopenharmony_ci result = re.search(r'VK_STRUCTURE_TYPE_\w+', rawXml) 3415db71995Sopenharmony_ci if result: 3425db71995Sopenharmony_ci value = result.group(0) 3435db71995Sopenharmony_ci else: 3445db71995Sopenharmony_ci value = self.genVkStructureType(typeName) 3455db71995Sopenharmony_ci # Store the required type value 3465db71995Sopenharmony_ci self.structTypes[typeName] = self.StructType(name=name, value=value) 3475db71995Sopenharmony_ci # Store pointer/array/string info 3485db71995Sopenharmony_ci isstaticarray = self.paramIsStaticArray(member) 3495db71995Sopenharmony_ci membersInfo.append(self.CommandParam(type=type, 3505db71995Sopenharmony_ci name=name, 3515db71995Sopenharmony_ci ispointer=self.paramIsPointer(member), 3525db71995Sopenharmony_ci isstaticarray=isstaticarray, 3535db71995Sopenharmony_ci isconst=True if 'const' in cdecl else False, 3545db71995Sopenharmony_ci iscount=True if name in lens else False, 3555db71995Sopenharmony_ci len=self.getLen(member), 3565db71995Sopenharmony_ci extstructs=self.registry.validextensionstructs[typeName] if name == 'pNext' else None, 3575db71995Sopenharmony_ci cdecl=cdecl)) 3585db71995Sopenharmony_ci self.structMembers.append(self.StructMemberData(name=typeName, members=membersInfo, ifdef_protect=self.featureExtraProtect)) 3595db71995Sopenharmony_ci # 3605db71995Sopenharmony_ci # Enum_string_header: Create a routine to convert an enumerated value into a string 3615db71995Sopenharmony_ci def GenerateEnumStringConversion(self, groupName, value_list): 3625db71995Sopenharmony_ci outstring = '\n' 3635db71995Sopenharmony_ci outstring += 'static inline const char* string_%s(%s input_value)\n' % (groupName, groupName) 3645db71995Sopenharmony_ci outstring += '{\n' 3655db71995Sopenharmony_ci outstring += ' switch ((%s)input_value)\n' % groupName 3665db71995Sopenharmony_ci outstring += ' {\n' 3675db71995Sopenharmony_ci for item in value_list: 3685db71995Sopenharmony_ci outstring += ' case %s:\n' % item 3695db71995Sopenharmony_ci outstring += ' return "%s";\n' % item 3705db71995Sopenharmony_ci outstring += ' default:\n' 3715db71995Sopenharmony_ci outstring += ' return "Unhandled %s";\n' % groupName 3725db71995Sopenharmony_ci outstring += ' }\n' 3735db71995Sopenharmony_ci outstring += '}\n' 3745db71995Sopenharmony_ci return outstring 3755db71995Sopenharmony_ci # 3765db71995Sopenharmony_ci # Combine object types helper header file preamble with body text and return 3775db71995Sopenharmony_ci def GenerateObjectTypesHelperHeader(self): 3785db71995Sopenharmony_ci object_types_helper_header = '\n' 3795db71995Sopenharmony_ci object_types_helper_header += '#pragma once\n' 3805db71995Sopenharmony_ci object_types_helper_header += '\n' 3815db71995Sopenharmony_ci object_types_helper_header += '#include <vulkan/vulkan.h>\n\n' 3825db71995Sopenharmony_ci object_types_helper_header += self.GenerateObjectTypesHeader() 3835db71995Sopenharmony_ci return object_types_helper_header 3845db71995Sopenharmony_ci # 3855db71995Sopenharmony_ci # Object types header: create object enum type header file 3865db71995Sopenharmony_ci def GenerateObjectTypesHeader(self): 3875db71995Sopenharmony_ci object_types_header = '' 3885db71995Sopenharmony_ci object_types_header += '// Object Type enum for validation layer internal object handling\n' 3895db71995Sopenharmony_ci object_types_header += 'typedef enum VulkanObjectType {\n' 3905db71995Sopenharmony_ci object_types_header += ' kVulkanObjectTypeUnknown = 0,\n' 3915db71995Sopenharmony_ci enum_num = 1 3925db71995Sopenharmony_ci type_list = []; 3935db71995Sopenharmony_ci enum_entry_map = {} 3945db71995Sopenharmony_ci 3955db71995Sopenharmony_ci # Output enum definition as each handle is processed, saving the names to use for the conversion routine 3965db71995Sopenharmony_ci for item in self.object_types: 3975db71995Sopenharmony_ci fixup_name = item[2:] 3985db71995Sopenharmony_ci enum_entry = 'kVulkanObjectType%s' % fixup_name 3995db71995Sopenharmony_ci enum_entry_map[item] = enum_entry 4005db71995Sopenharmony_ci object_types_header += ' ' + enum_entry 4015db71995Sopenharmony_ci object_types_header += ' = %d,\n' % enum_num 4025db71995Sopenharmony_ci enum_num += 1 4035db71995Sopenharmony_ci type_list.append(enum_entry) 4045db71995Sopenharmony_ci object_types_header += ' kVulkanObjectTypeMax = %d,\n' % enum_num 4055db71995Sopenharmony_ci object_types_header += ' // Aliases for backwards compatibilty of "promoted" types\n' 4065db71995Sopenharmony_ci for (name, alias) in self.object_type_aliases: 4075db71995Sopenharmony_ci fixup_name = name[2:] 4085db71995Sopenharmony_ci object_types_header += ' kVulkanObjectType{} = {},\n'.format(fixup_name, enum_entry_map[alias]) 4095db71995Sopenharmony_ci object_types_header += '} VulkanObjectType;\n\n' 4105db71995Sopenharmony_ci 4115db71995Sopenharmony_ci # Output name string helper 4125db71995Sopenharmony_ci object_types_header += '// Array of object name strings for OBJECT_TYPE enum conversion\n' 4135db71995Sopenharmony_ci object_types_header += 'static const char * const object_string[kVulkanObjectTypeMax] = {\n' 4145db71995Sopenharmony_ci object_types_header += ' "Unknown",\n' 4155db71995Sopenharmony_ci for item in self.object_types: 4165db71995Sopenharmony_ci fixup_name = item[2:] 4175db71995Sopenharmony_ci object_types_header += ' "%s",\n' % fixup_name 4185db71995Sopenharmony_ci object_types_header += '};\n' 4195db71995Sopenharmony_ci 4205db71995Sopenharmony_ci # Key creation helper for map comprehensions that convert between k<Name> and VK<Name> symbols 4215db71995Sopenharmony_ci def to_key(regex, raw_key): return re.search(regex, raw_key).group(1).lower().replace("_","") 4225db71995Sopenharmony_ci 4235db71995Sopenharmony_ci # Output a conversion routine from the layer object definitions to the debug report definitions 4245db71995Sopenharmony_ci # As the VK_DEBUG_REPORT types are not being updated, specify UNKNOWN for unmatched types 4255db71995Sopenharmony_ci object_types_header += '\n' 4265db71995Sopenharmony_ci object_types_header += '// Helper array to get Vulkan VK_EXT_debug_report object type enum from the internal layers version\n' 4275db71995Sopenharmony_ci object_types_header += 'const VkDebugReportObjectTypeEXT get_debug_report_enum[] = {\n' 4285db71995Sopenharmony_ci object_types_header += ' VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeUnknown\n' 4295db71995Sopenharmony_ci 4305db71995Sopenharmony_ci dbg_re = '^VK_DEBUG_REPORT_OBJECT_TYPE_(.*?)(_EXT)?$' 4315db71995Sopenharmony_ci dbg_map = {to_key(dbg_re, dbg) : dbg for dbg in self.debug_report_object_types} 4325db71995Sopenharmony_ci dbg_default = 'VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT' 4335db71995Sopenharmony_ci for object_type in type_list: 4345db71995Sopenharmony_ci vk_object_type = dbg_map.get(object_type.replace("kVulkanObjectType", "").lower(), dbg_default) 4355db71995Sopenharmony_ci object_types_header += ' %s, // %s\n' % (vk_object_type, object_type) 4365db71995Sopenharmony_ci object_types_header += '};\n' 4375db71995Sopenharmony_ci 4385db71995Sopenharmony_ci # Output a conversion routine from the layer object definitions to the core object type definitions 4395db71995Sopenharmony_ci # This will intentionally *fail* for unmatched types as the VK_OBJECT_TYPE list should match the kVulkanObjectType list 4405db71995Sopenharmony_ci object_types_header += '\n' 4415db71995Sopenharmony_ci object_types_header += '// Helper array to get Official Vulkan VkObjectType enum from the internal layers version\n' 4425db71995Sopenharmony_ci object_types_header += 'const VkObjectType get_object_type_enum[] = {\n' 4435db71995Sopenharmony_ci object_types_header += ' VK_OBJECT_TYPE_UNKNOWN, // kVulkanObjectTypeUnknown\n' 4445db71995Sopenharmony_ci 4455db71995Sopenharmony_ci vko_re = '^VK_OBJECT_TYPE_(.*)' 4465db71995Sopenharmony_ci vko_map = {to_key(vko_re, vko) : vko for vko in self.core_object_types} 4475db71995Sopenharmony_ci for object_type in type_list: 4485db71995Sopenharmony_ci vk_object_type = vko_map[object_type.replace("kVulkanObjectType", "").lower()] 4495db71995Sopenharmony_ci object_types_header += ' %s, // %s\n' % (vk_object_type, object_type) 4505db71995Sopenharmony_ci object_types_header += '};\n' 4515db71995Sopenharmony_ci 4525db71995Sopenharmony_ci # Create a function to convert from VkDebugReportObjectTypeEXT to VkObjectType 4535db71995Sopenharmony_ci object_types_header += '\n' 4545db71995Sopenharmony_ci object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n' 4555db71995Sopenharmony_ci object_types_header += 'static inline VkObjectType convertDebugReportObjectToCoreObject(VkDebugReportObjectTypeEXT debug_report_obj){\n' 4565db71995Sopenharmony_ci object_types_header += ' if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) {\n' 4575db71995Sopenharmony_ci object_types_header += ' return VK_OBJECT_TYPE_UNKNOWN;\n' 4585db71995Sopenharmony_ci for core_object_type in self.core_object_types: 4595db71995Sopenharmony_ci core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower() 4605db71995Sopenharmony_ci core_target_type = core_target_type.replace("_", "") 4615db71995Sopenharmony_ci for dr_object_type in self.debug_report_object_types: 4625db71995Sopenharmony_ci dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower() 4635db71995Sopenharmony_ci dr_target_type = dr_target_type[:-4] 4645db71995Sopenharmony_ci dr_target_type = dr_target_type.replace("_", "") 4655db71995Sopenharmony_ci if core_target_type == dr_target_type: 4665db71995Sopenharmony_ci object_types_header += ' } else if (debug_report_obj == %s) {\n' % dr_object_type 4675db71995Sopenharmony_ci object_types_header += ' return %s;\n' % core_object_type 4685db71995Sopenharmony_ci break 4695db71995Sopenharmony_ci object_types_header += ' }\n' 4705db71995Sopenharmony_ci object_types_header += ' return VK_OBJECT_TYPE_UNKNOWN;\n' 4715db71995Sopenharmony_ci object_types_header += '}\n' 4725db71995Sopenharmony_ci 4735db71995Sopenharmony_ci # Create a function to convert from VkObjectType to VkDebugReportObjectTypeEXT 4745db71995Sopenharmony_ci object_types_header += '\n' 4755db71995Sopenharmony_ci object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n' 4765db71995Sopenharmony_ci object_types_header += 'static inline VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj){\n' 4775db71995Sopenharmony_ci object_types_header += ' if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {\n' 4785db71995Sopenharmony_ci object_types_header += ' return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n' 4795db71995Sopenharmony_ci for core_object_type in self.core_object_types: 4805db71995Sopenharmony_ci core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower() 4815db71995Sopenharmony_ci core_target_type = core_target_type.replace("_", "") 4825db71995Sopenharmony_ci for dr_object_type in self.debug_report_object_types: 4835db71995Sopenharmony_ci dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower() 4845db71995Sopenharmony_ci dr_target_type = dr_target_type[:-4] 4855db71995Sopenharmony_ci dr_target_type = dr_target_type.replace("_", "") 4865db71995Sopenharmony_ci if core_target_type == dr_target_type: 4875db71995Sopenharmony_ci object_types_header += ' } else if (core_report_obj == %s) {\n' % core_object_type 4885db71995Sopenharmony_ci object_types_header += ' return %s;\n' % dr_object_type 4895db71995Sopenharmony_ci break 4905db71995Sopenharmony_ci object_types_header += ' }\n' 4915db71995Sopenharmony_ci object_types_header += ' return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n' 4925db71995Sopenharmony_ci object_types_header += '}\n' 4935db71995Sopenharmony_ci return object_types_header 4945db71995Sopenharmony_ci 4955db71995Sopenharmony_ci # 4965db71995Sopenharmony_ci # Create a helper file and return it as a string 4975db71995Sopenharmony_ci def OutputDestFile(self): 4985db71995Sopenharmony_ci if self.helper_file_type == 'object_types_header': 4995db71995Sopenharmony_ci return self.GenerateObjectTypesHelperHeader() 5005db71995Sopenharmony_ci else: 5015db71995Sopenharmony_ci return 'Bad Helper File Generator Option %s' % self.helper_file_type 502