1*b7893ccfSSadaf Ebrahimi#!/usr/bin/python3 -i 2*b7893ccfSSadaf Ebrahimi# 3*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 The Khronos Group Inc. 4*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 Valve Corporation 5*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 LunarG, Inc. 6*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 Google Inc. 7*b7893ccfSSadaf Ebrahimi# 8*b7893ccfSSadaf Ebrahimi# Licensed under the Apache License, Version 2.0 (the "License"); 9*b7893ccfSSadaf Ebrahimi# you may not use this file except in compliance with the License. 10*b7893ccfSSadaf Ebrahimi# You may obtain a copy of the License at 11*b7893ccfSSadaf Ebrahimi# 12*b7893ccfSSadaf Ebrahimi# http://www.apache.org/licenses/LICENSE-2.0 13*b7893ccfSSadaf Ebrahimi# 14*b7893ccfSSadaf Ebrahimi# Unless required by applicable law or agreed to in writing, software 15*b7893ccfSSadaf Ebrahimi# distributed under the License is distributed on an "AS IS" BASIS, 16*b7893ccfSSadaf Ebrahimi# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17*b7893ccfSSadaf Ebrahimi# See the License for the specific language governing permissions and 18*b7893ccfSSadaf Ebrahimi# limitations under the License. 19*b7893ccfSSadaf Ebrahimi# 20*b7893ccfSSadaf Ebrahimi# Author: Mark Lobodzinski <[email protected]> 21*b7893ccfSSadaf Ebrahimi# Author: Tobin Ehlis <[email protected]> 22*b7893ccfSSadaf Ebrahimi# Author: John Zulauf <[email protected]> 23*b7893ccfSSadaf Ebrahimi 24*b7893ccfSSadaf Ebrahimiimport os,re,sys 25*b7893ccfSSadaf Ebrahimiimport xml.etree.ElementTree as etree 26*b7893ccfSSadaf Ebrahimifrom generator import * 27*b7893ccfSSadaf Ebrahimifrom collections import namedtuple 28*b7893ccfSSadaf Ebrahimifrom common_codegen import * 29*b7893ccfSSadaf Ebrahimi 30*b7893ccfSSadaf Ebrahimi# 31*b7893ccfSSadaf Ebrahimi# HelperFileOutputGeneratorOptions - subclass of GeneratorOptions. 32*b7893ccfSSadaf Ebrahimiclass HelperFileOutputGeneratorOptions(GeneratorOptions): 33*b7893ccfSSadaf Ebrahimi def __init__(self, 34*b7893ccfSSadaf Ebrahimi conventions = None, 35*b7893ccfSSadaf Ebrahimi filename = None, 36*b7893ccfSSadaf Ebrahimi directory = '.', 37*b7893ccfSSadaf Ebrahimi apiname = None, 38*b7893ccfSSadaf Ebrahimi profile = None, 39*b7893ccfSSadaf Ebrahimi versions = '.*', 40*b7893ccfSSadaf Ebrahimi emitversions = '.*', 41*b7893ccfSSadaf Ebrahimi defaultExtensions = None, 42*b7893ccfSSadaf Ebrahimi addExtensions = None, 43*b7893ccfSSadaf Ebrahimi removeExtensions = None, 44*b7893ccfSSadaf Ebrahimi emitExtensions = None, 45*b7893ccfSSadaf Ebrahimi sortProcedure = regSortFeatures, 46*b7893ccfSSadaf Ebrahimi prefixText = "", 47*b7893ccfSSadaf Ebrahimi genFuncPointers = True, 48*b7893ccfSSadaf Ebrahimi protectFile = True, 49*b7893ccfSSadaf Ebrahimi protectFeature = True, 50*b7893ccfSSadaf Ebrahimi apicall = '', 51*b7893ccfSSadaf Ebrahimi apientry = '', 52*b7893ccfSSadaf Ebrahimi apientryp = '', 53*b7893ccfSSadaf Ebrahimi alignFuncParam = 0, 54*b7893ccfSSadaf Ebrahimi library_name = '', 55*b7893ccfSSadaf Ebrahimi expandEnumerants = True, 56*b7893ccfSSadaf Ebrahimi helper_file_type = ''): 57*b7893ccfSSadaf Ebrahimi GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile, 58*b7893ccfSSadaf Ebrahimi versions, emitversions, defaultExtensions, 59*b7893ccfSSadaf Ebrahimi addExtensions, removeExtensions, emitExtensions, sortProcedure) 60*b7893ccfSSadaf Ebrahimi self.prefixText = prefixText 61*b7893ccfSSadaf Ebrahimi self.genFuncPointers = genFuncPointers 62*b7893ccfSSadaf Ebrahimi self.protectFile = protectFile 63*b7893ccfSSadaf Ebrahimi self.protectFeature = protectFeature 64*b7893ccfSSadaf Ebrahimi self.apicall = apicall 65*b7893ccfSSadaf Ebrahimi self.apientry = apientry 66*b7893ccfSSadaf Ebrahimi self.apientryp = apientryp 67*b7893ccfSSadaf Ebrahimi self.alignFuncParam = alignFuncParam 68*b7893ccfSSadaf Ebrahimi self.library_name = library_name 69*b7893ccfSSadaf Ebrahimi self.helper_file_type = helper_file_type 70*b7893ccfSSadaf Ebrahimi# 71*b7893ccfSSadaf Ebrahimi# HelperFileOutputGenerator - subclass of OutputGenerator. Outputs Vulkan helper files 72*b7893ccfSSadaf Ebrahimiclass HelperFileOutputGenerator(OutputGenerator): 73*b7893ccfSSadaf Ebrahimi """Generate helper file based on XML element attributes""" 74*b7893ccfSSadaf Ebrahimi def __init__(self, 75*b7893ccfSSadaf Ebrahimi errFile = sys.stderr, 76*b7893ccfSSadaf Ebrahimi warnFile = sys.stderr, 77*b7893ccfSSadaf Ebrahimi diagFile = sys.stdout): 78*b7893ccfSSadaf Ebrahimi OutputGenerator.__init__(self, errFile, warnFile, diagFile) 79*b7893ccfSSadaf Ebrahimi # Internal state - accumulators for different inner block text 80*b7893ccfSSadaf Ebrahimi self.enum_output = '' # string built up of enum string routines 81*b7893ccfSSadaf Ebrahimi # Internal state - accumulators for different inner block text 82*b7893ccfSSadaf Ebrahimi self.structNames = [] # List of Vulkan struct typenames 83*b7893ccfSSadaf Ebrahimi self.structTypes = dict() # Map of Vulkan struct typename to required VkStructureType 84*b7893ccfSSadaf Ebrahimi self.structMembers = [] # List of StructMemberData records for all Vulkan structs 85*b7893ccfSSadaf Ebrahimi self.object_types = [] # List of all handle types 86*b7893ccfSSadaf Ebrahimi self.object_type_aliases = [] # Aliases to handles types (for handles that were extensions) 87*b7893ccfSSadaf Ebrahimi self.debug_report_object_types = [] # Handy copy of debug_report_object_type enum data 88*b7893ccfSSadaf Ebrahimi self.core_object_types = [] # Handy copy of core_object_type enum data 89*b7893ccfSSadaf Ebrahimi self.device_extension_info = dict() # Dict of device extension name defines and ifdef values 90*b7893ccfSSadaf Ebrahimi self.instance_extension_info = dict() # Dict of instance extension name defines and ifdef values 91*b7893ccfSSadaf Ebrahimi self.structextends_list = [] # List of structs which extend another struct via pNext 92*b7893ccfSSadaf Ebrahimi 93*b7893ccfSSadaf Ebrahimi 94*b7893ccfSSadaf Ebrahimi # Named tuples to store struct and command data 95*b7893ccfSSadaf Ebrahimi self.StructType = namedtuple('StructType', ['name', 'value']) 96*b7893ccfSSadaf Ebrahimi self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isstaticarray', 'isconst', 'iscount', 'len', 'extstructs', 'cdecl']) 97*b7893ccfSSadaf Ebrahimi self.StructMemberData = namedtuple('StructMemberData', ['name', 'members', 'ifdef_protect']) 98*b7893ccfSSadaf Ebrahimi 99*b7893ccfSSadaf Ebrahimi self.custom_construct_params = { 100*b7893ccfSSadaf Ebrahimi # safe_VkGraphicsPipelineCreateInfo needs to know if subpass has color and\or depth\stencil attachments to use its pointers 101*b7893ccfSSadaf Ebrahimi 'VkGraphicsPipelineCreateInfo' : 102*b7893ccfSSadaf Ebrahimi ', const bool uses_color_attachment, const bool uses_depthstencil_attachment', 103*b7893ccfSSadaf Ebrahimi # safe_VkPipelineViewportStateCreateInfo needs to know if viewport and scissor is dynamic to use its pointers 104*b7893ccfSSadaf Ebrahimi 'VkPipelineViewportStateCreateInfo' : 105*b7893ccfSSadaf Ebrahimi ', const bool is_dynamic_viewports, const bool is_dynamic_scissors', 106*b7893ccfSSadaf Ebrahimi } 107*b7893ccfSSadaf Ebrahimi # 108*b7893ccfSSadaf Ebrahimi # Called once at the beginning of each run 109*b7893ccfSSadaf Ebrahimi def beginFile(self, genOpts): 110*b7893ccfSSadaf Ebrahimi OutputGenerator.beginFile(self, genOpts) 111*b7893ccfSSadaf Ebrahimi # Initialize members that require the tree 112*b7893ccfSSadaf Ebrahimi self.handle_types = GetHandleTypes(self.registry.tree) 113*b7893ccfSSadaf Ebrahimi # User-supplied prefix text, if any (list of strings) 114*b7893ccfSSadaf Ebrahimi self.helper_file_type = genOpts.helper_file_type 115*b7893ccfSSadaf Ebrahimi self.library_name = genOpts.library_name 116*b7893ccfSSadaf Ebrahimi # File Comment 117*b7893ccfSSadaf Ebrahimi file_comment = '// *** THIS FILE IS GENERATED - DO NOT EDIT ***\n' 118*b7893ccfSSadaf Ebrahimi file_comment += '// See helper_file_generator.py for modifications\n' 119*b7893ccfSSadaf Ebrahimi write(file_comment, file=self.outFile) 120*b7893ccfSSadaf Ebrahimi # Copyright Notice 121*b7893ccfSSadaf Ebrahimi copyright = '' 122*b7893ccfSSadaf Ebrahimi copyright += '\n' 123*b7893ccfSSadaf Ebrahimi copyright += '/***************************************************************************\n' 124*b7893ccfSSadaf Ebrahimi copyright += ' *\n' 125*b7893ccfSSadaf Ebrahimi copyright += ' * Copyright (c) 2015-2019 The Khronos Group Inc.\n' 126*b7893ccfSSadaf Ebrahimi copyright += ' * Copyright (c) 2015-2019 Valve Corporation\n' 127*b7893ccfSSadaf Ebrahimi copyright += ' * Copyright (c) 2015-2019 LunarG, Inc.\n' 128*b7893ccfSSadaf Ebrahimi copyright += ' * Copyright (c) 2015-2019 Google Inc.\n' 129*b7893ccfSSadaf Ebrahimi copyright += ' *\n' 130*b7893ccfSSadaf Ebrahimi copyright += ' * Licensed under the Apache License, Version 2.0 (the "License");\n' 131*b7893ccfSSadaf Ebrahimi copyright += ' * you may not use this file except in compliance with the License.\n' 132*b7893ccfSSadaf Ebrahimi copyright += ' * You may obtain a copy of the License at\n' 133*b7893ccfSSadaf Ebrahimi copyright += ' *\n' 134*b7893ccfSSadaf Ebrahimi copyright += ' * http://www.apache.org/licenses/LICENSE-2.0\n' 135*b7893ccfSSadaf Ebrahimi copyright += ' *\n' 136*b7893ccfSSadaf Ebrahimi copyright += ' * Unless required by applicable law or agreed to in writing, software\n' 137*b7893ccfSSadaf Ebrahimi copyright += ' * distributed under the License is distributed on an "AS IS" BASIS,\n' 138*b7893ccfSSadaf Ebrahimi copyright += ' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n' 139*b7893ccfSSadaf Ebrahimi copyright += ' * See the License for the specific language governing permissions and\n' 140*b7893ccfSSadaf Ebrahimi copyright += ' * limitations under the License.\n' 141*b7893ccfSSadaf Ebrahimi copyright += ' *\n' 142*b7893ccfSSadaf Ebrahimi copyright += ' * Author: Mark Lobodzinski <[email protected]>\n' 143*b7893ccfSSadaf Ebrahimi copyright += ' * Author: Courtney Goeltzenleuchter <[email protected]>\n' 144*b7893ccfSSadaf Ebrahimi copyright += ' * Author: Tobin Ehlis <[email protected]>\n' 145*b7893ccfSSadaf Ebrahimi copyright += ' * Author: Chris Forbes <[email protected]>\n' 146*b7893ccfSSadaf Ebrahimi copyright += ' * Author: John Zulauf<[email protected]>\n' 147*b7893ccfSSadaf Ebrahimi copyright += ' *\n' 148*b7893ccfSSadaf Ebrahimi copyright += ' ****************************************************************************/\n' 149*b7893ccfSSadaf Ebrahimi write(copyright, file=self.outFile) 150*b7893ccfSSadaf Ebrahimi # 151*b7893ccfSSadaf Ebrahimi # Write generated file content to output file 152*b7893ccfSSadaf Ebrahimi def endFile(self): 153*b7893ccfSSadaf Ebrahimi dest_file = '' 154*b7893ccfSSadaf Ebrahimi dest_file += self.OutputDestFile() 155*b7893ccfSSadaf Ebrahimi # Remove blank lines at EOF 156*b7893ccfSSadaf Ebrahimi if dest_file.endswith('\n'): 157*b7893ccfSSadaf Ebrahimi dest_file = dest_file[:-1] 158*b7893ccfSSadaf Ebrahimi write(dest_file, file=self.outFile); 159*b7893ccfSSadaf Ebrahimi # Finish processing in superclass 160*b7893ccfSSadaf Ebrahimi OutputGenerator.endFile(self) 161*b7893ccfSSadaf Ebrahimi # 162*b7893ccfSSadaf Ebrahimi # Override parent class to be notified of the beginning of an extension 163*b7893ccfSSadaf Ebrahimi def beginFeature(self, interface, emit): 164*b7893ccfSSadaf Ebrahimi # Start processing in superclass 165*b7893ccfSSadaf Ebrahimi OutputGenerator.beginFeature(self, interface, emit) 166*b7893ccfSSadaf Ebrahimi self.featureExtraProtect = GetFeatureProtect(interface) 167*b7893ccfSSadaf Ebrahimi 168*b7893ccfSSadaf Ebrahimi if self.featureName == 'VK_VERSION_1_0' or self.featureName == 'VK_VERSION_1_1': 169*b7893ccfSSadaf Ebrahimi return 170*b7893ccfSSadaf Ebrahimi name = self.featureName 171*b7893ccfSSadaf Ebrahimi nameElem = interface[0][1] 172*b7893ccfSSadaf Ebrahimi name_define = nameElem.get('name') 173*b7893ccfSSadaf Ebrahimi if 'EXTENSION_NAME' not in name_define: 174*b7893ccfSSadaf Ebrahimi print("Error in vk.xml file -- extension name is not available") 175*b7893ccfSSadaf Ebrahimi requires = interface.get('requires') 176*b7893ccfSSadaf Ebrahimi if requires is not None: 177*b7893ccfSSadaf Ebrahimi required_extensions = requires.split(',') 178*b7893ccfSSadaf Ebrahimi else: 179*b7893ccfSSadaf Ebrahimi required_extensions = list() 180*b7893ccfSSadaf Ebrahimi info = { 'define': name_define, 'ifdef':self.featureExtraProtect, 'reqs':required_extensions } 181*b7893ccfSSadaf Ebrahimi if interface.get('type') == 'instance': 182*b7893ccfSSadaf Ebrahimi self.instance_extension_info[name] = info 183*b7893ccfSSadaf Ebrahimi else: 184*b7893ccfSSadaf Ebrahimi self.device_extension_info[name] = info 185*b7893ccfSSadaf Ebrahimi 186*b7893ccfSSadaf Ebrahimi # 187*b7893ccfSSadaf Ebrahimi # Override parent class to be notified of the end of an extension 188*b7893ccfSSadaf Ebrahimi def endFeature(self): 189*b7893ccfSSadaf Ebrahimi # Finish processing in superclass 190*b7893ccfSSadaf Ebrahimi OutputGenerator.endFeature(self) 191*b7893ccfSSadaf Ebrahimi # 192*b7893ccfSSadaf Ebrahimi # Grab group (e.g. C "enum" type) info to output for enum-string conversion helper 193*b7893ccfSSadaf Ebrahimi def genGroup(self, groupinfo, groupName, alias): 194*b7893ccfSSadaf Ebrahimi OutputGenerator.genGroup(self, groupinfo, groupName, alias) 195*b7893ccfSSadaf Ebrahimi groupElem = groupinfo.elem 196*b7893ccfSSadaf Ebrahimi # For enum_string_header 197*b7893ccfSSadaf Ebrahimi if self.helper_file_type == 'enum_string_header': 198*b7893ccfSSadaf Ebrahimi value_set = set() 199*b7893ccfSSadaf Ebrahimi for elem in groupElem.findall('enum'): 200*b7893ccfSSadaf Ebrahimi if elem.get('supported') != 'disabled' and elem.get('alias') is None: 201*b7893ccfSSadaf Ebrahimi value_set.add(elem.get('name')) 202*b7893ccfSSadaf Ebrahimi if value_set != set(): 203*b7893ccfSSadaf Ebrahimi self.enum_output += self.GenerateEnumStringConversion(groupName, value_set) 204*b7893ccfSSadaf Ebrahimi elif self.helper_file_type == 'object_types_header': 205*b7893ccfSSadaf Ebrahimi if groupName == 'VkDebugReportObjectTypeEXT': 206*b7893ccfSSadaf Ebrahimi for elem in groupElem.findall('enum'): 207*b7893ccfSSadaf Ebrahimi if elem.get('supported') != 'disabled': 208*b7893ccfSSadaf Ebrahimi if elem.get('alias') is None: # TODO: Strangely the "alias" fn parameter does not work 209*b7893ccfSSadaf Ebrahimi item_name = elem.get('name') 210*b7893ccfSSadaf Ebrahimi if self.debug_report_object_types.count(item_name) == 0: # TODO: Strangely there are duplicates 211*b7893ccfSSadaf Ebrahimi self.debug_report_object_types.append(item_name) 212*b7893ccfSSadaf Ebrahimi elif groupName == 'VkObjectType': 213*b7893ccfSSadaf Ebrahimi for elem in groupElem.findall('enum'): 214*b7893ccfSSadaf Ebrahimi if elem.get('supported') != 'disabled': 215*b7893ccfSSadaf Ebrahimi if elem.get('alias') is None: # TODO: Strangely the "alias" fn parameter does not work 216*b7893ccfSSadaf Ebrahimi item_name = elem.get('name') 217*b7893ccfSSadaf Ebrahimi self.core_object_types.append(item_name) 218*b7893ccfSSadaf Ebrahimi 219*b7893ccfSSadaf Ebrahimi # 220*b7893ccfSSadaf Ebrahimi # Called for each type -- if the type is a struct/union, grab the metadata 221*b7893ccfSSadaf Ebrahimi def genType(self, typeinfo, name, alias): 222*b7893ccfSSadaf Ebrahimi OutputGenerator.genType(self, typeinfo, name, alias) 223*b7893ccfSSadaf Ebrahimi typeElem = typeinfo.elem 224*b7893ccfSSadaf Ebrahimi # If the type is a struct type, traverse the imbedded <member> tags generating a structure. 225*b7893ccfSSadaf Ebrahimi # Otherwise, emit the tag text. 226*b7893ccfSSadaf Ebrahimi category = typeElem.get('category') 227*b7893ccfSSadaf Ebrahimi if category == 'handle': 228*b7893ccfSSadaf Ebrahimi if alias: 229*b7893ccfSSadaf Ebrahimi self.object_type_aliases.append((name,alias)) 230*b7893ccfSSadaf Ebrahimi else: 231*b7893ccfSSadaf Ebrahimi self.object_types.append(name) 232*b7893ccfSSadaf Ebrahimi elif (category == 'struct' or category == 'union'): 233*b7893ccfSSadaf Ebrahimi self.structNames.append(name) 234*b7893ccfSSadaf Ebrahimi self.genStruct(typeinfo, name, alias) 235*b7893ccfSSadaf Ebrahimi # 236*b7893ccfSSadaf Ebrahimi # Check if the parameter passed in is a pointer 237*b7893ccfSSadaf Ebrahimi def paramIsPointer(self, param): 238*b7893ccfSSadaf Ebrahimi ispointer = False 239*b7893ccfSSadaf Ebrahimi for elem in param: 240*b7893ccfSSadaf Ebrahimi if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail: 241*b7893ccfSSadaf Ebrahimi ispointer = True 242*b7893ccfSSadaf Ebrahimi return ispointer 243*b7893ccfSSadaf Ebrahimi # 244*b7893ccfSSadaf Ebrahimi # Check if the parameter passed in is a static array 245*b7893ccfSSadaf Ebrahimi def paramIsStaticArray(self, param): 246*b7893ccfSSadaf Ebrahimi isstaticarray = 0 247*b7893ccfSSadaf Ebrahimi paramname = param.find('name') 248*b7893ccfSSadaf Ebrahimi if (paramname.tail is not None) and ('[' in paramname.tail): 249*b7893ccfSSadaf Ebrahimi isstaticarray = paramname.tail.count('[') 250*b7893ccfSSadaf Ebrahimi return isstaticarray 251*b7893ccfSSadaf Ebrahimi # 252*b7893ccfSSadaf Ebrahimi # Retrieve the type and name for a parameter 253*b7893ccfSSadaf Ebrahimi def getTypeNameTuple(self, param): 254*b7893ccfSSadaf Ebrahimi type = '' 255*b7893ccfSSadaf Ebrahimi name = '' 256*b7893ccfSSadaf Ebrahimi for elem in param: 257*b7893ccfSSadaf Ebrahimi if elem.tag == 'type': 258*b7893ccfSSadaf Ebrahimi type = noneStr(elem.text) 259*b7893ccfSSadaf Ebrahimi elif elem.tag == 'name': 260*b7893ccfSSadaf Ebrahimi name = noneStr(elem.text) 261*b7893ccfSSadaf Ebrahimi return (type, name) 262*b7893ccfSSadaf Ebrahimi # Extract length values from latexmath. Currently an inflexible solution that looks for specific 263*b7893ccfSSadaf Ebrahimi # patterns that are found in vk.xml. Will need to be updated when new patterns are introduced. 264*b7893ccfSSadaf Ebrahimi def parseLateXMath(self, source): 265*b7893ccfSSadaf Ebrahimi name = 'ERROR' 266*b7893ccfSSadaf Ebrahimi decoratedName = 'ERROR' 267*b7893ccfSSadaf Ebrahimi if 'mathit' in source: 268*b7893ccfSSadaf Ebrahimi # Matches expressions similar to 'latexmath:[\lceil{\mathit{rasterizationSamples} \over 32}\rceil]' 269*b7893ccfSSadaf Ebrahimi match = re.match(r'latexmath\s*\:\s*\[\s*\\l(\w+)\s*\{\s*\\mathit\s*\{\s*(\w+)\s*\}\s*\\over\s*(\d+)\s*\}\s*\\r(\w+)\s*\]', source) 270*b7893ccfSSadaf Ebrahimi if not match or match.group(1) != match.group(4): 271*b7893ccfSSadaf Ebrahimi raise 'Unrecognized latexmath expression' 272*b7893ccfSSadaf Ebrahimi name = match.group(2) 273*b7893ccfSSadaf Ebrahimi # Need to add 1 for ceiling function; otherwise, the allocated packet 274*b7893ccfSSadaf Ebrahimi # size will be less than needed during capture for some title which use 275*b7893ccfSSadaf Ebrahimi # this in VkPipelineMultisampleStateCreateInfo. based on ceiling function 276*b7893ccfSSadaf Ebrahimi # definition,it is '{0}%{1}?{0}/{1} + 1:{0}/{1}'.format(*match.group(2, 3)), 277*b7893ccfSSadaf Ebrahimi # its value <= '{}/{} + 1'. 278*b7893ccfSSadaf Ebrahimi if match.group(1) == 'ceil': 279*b7893ccfSSadaf Ebrahimi decoratedName = '{}/{} + 1'.format(*match.group(2, 3)) 280*b7893ccfSSadaf Ebrahimi else: 281*b7893ccfSSadaf Ebrahimi decoratedName = '{}/{}'.format(*match.group(2, 3)) 282*b7893ccfSSadaf Ebrahimi else: 283*b7893ccfSSadaf Ebrahimi # Matches expressions similar to 'latexmath : [dataSize \over 4]' 284*b7893ccfSSadaf Ebrahimi match = re.match(r'latexmath\s*\:\s*\[\s*(\\textrm\{)?(\w+)\}?\s*\\over\s*(\d+)\s*\]', source) 285*b7893ccfSSadaf Ebrahimi name = match.group(2) 286*b7893ccfSSadaf Ebrahimi decoratedName = '{}/{}'.format(*match.group(2, 3)) 287*b7893ccfSSadaf Ebrahimi return name, decoratedName 288*b7893ccfSSadaf Ebrahimi # 289*b7893ccfSSadaf Ebrahimi # Retrieve the value of the len tag 290*b7893ccfSSadaf Ebrahimi def getLen(self, param): 291*b7893ccfSSadaf Ebrahimi result = None 292*b7893ccfSSadaf Ebrahimi len = param.attrib.get('len') 293*b7893ccfSSadaf Ebrahimi if len and len != 'null-terminated': 294*b7893ccfSSadaf Ebrahimi # For string arrays, 'len' can look like 'count,null-terminated', indicating that we 295*b7893ccfSSadaf Ebrahimi # have a null terminated array of strings. We strip the null-terminated from the 296*b7893ccfSSadaf Ebrahimi # 'len' field and only return the parameter specifying the string count 297*b7893ccfSSadaf Ebrahimi if 'null-terminated' in len: 298*b7893ccfSSadaf Ebrahimi result = len.split(',')[0] 299*b7893ccfSSadaf Ebrahimi else: 300*b7893ccfSSadaf Ebrahimi result = len 301*b7893ccfSSadaf Ebrahimi if 'latexmath' in len: 302*b7893ccfSSadaf Ebrahimi param_type, param_name = self.getTypeNameTuple(param) 303*b7893ccfSSadaf Ebrahimi len_name, result = self.parseLateXMath(len) 304*b7893ccfSSadaf Ebrahimi # Spec has now notation for len attributes, using :: instead of platform specific pointer symbol 305*b7893ccfSSadaf Ebrahimi result = str(result).replace('::', '->') 306*b7893ccfSSadaf Ebrahimi return result 307*b7893ccfSSadaf Ebrahimi # 308*b7893ccfSSadaf Ebrahimi # Check if a structure is or contains a dispatchable (dispatchable = True) or 309*b7893ccfSSadaf Ebrahimi # non-dispatchable (dispatchable = False) handle 310*b7893ccfSSadaf Ebrahimi def TypeContainsObjectHandle(self, handle_type, dispatchable): 311*b7893ccfSSadaf Ebrahimi if dispatchable: 312*b7893ccfSSadaf Ebrahimi type_check = self.handle_types.IsDispatchable 313*b7893ccfSSadaf Ebrahimi else: 314*b7893ccfSSadaf Ebrahimi type_check = self.handle_types.IsNonDispatchable 315*b7893ccfSSadaf Ebrahimi if type_check(handle_type): 316*b7893ccfSSadaf Ebrahimi return True 317*b7893ccfSSadaf Ebrahimi # if handle_type is a struct, search its members 318*b7893ccfSSadaf Ebrahimi if handle_type in self.structNames: 319*b7893ccfSSadaf Ebrahimi member_index = next((i for i, v in enumerate(self.structMembers) if v[0] == handle_type), None) 320*b7893ccfSSadaf Ebrahimi if member_index is not None: 321*b7893ccfSSadaf Ebrahimi for item in self.structMembers[member_index].members: 322*b7893ccfSSadaf Ebrahimi if type_check(item.type): 323*b7893ccfSSadaf Ebrahimi return True 324*b7893ccfSSadaf Ebrahimi return False 325*b7893ccfSSadaf Ebrahimi # 326*b7893ccfSSadaf Ebrahimi # Generate local ready-access data describing Vulkan structures and unions from the XML metadata 327*b7893ccfSSadaf Ebrahimi def genStruct(self, typeinfo, typeName, alias): 328*b7893ccfSSadaf Ebrahimi OutputGenerator.genStruct(self, typeinfo, typeName, alias) 329*b7893ccfSSadaf Ebrahimi members = typeinfo.elem.findall('.//member') 330*b7893ccfSSadaf Ebrahimi # Iterate over members once to get length parameters for arrays 331*b7893ccfSSadaf Ebrahimi lens = set() 332*b7893ccfSSadaf Ebrahimi for member in members: 333*b7893ccfSSadaf Ebrahimi len = self.getLen(member) 334*b7893ccfSSadaf Ebrahimi if len: 335*b7893ccfSSadaf Ebrahimi lens.add(len) 336*b7893ccfSSadaf Ebrahimi # Generate member info 337*b7893ccfSSadaf Ebrahimi membersInfo = [] 338*b7893ccfSSadaf Ebrahimi for member in members: 339*b7893ccfSSadaf Ebrahimi # Get the member's type and name 340*b7893ccfSSadaf Ebrahimi info = self.getTypeNameTuple(member) 341*b7893ccfSSadaf Ebrahimi type = info[0] 342*b7893ccfSSadaf Ebrahimi name = info[1] 343*b7893ccfSSadaf Ebrahimi cdecl = self.makeCParamDecl(member, 1) 344*b7893ccfSSadaf Ebrahimi # Process VkStructureType 345*b7893ccfSSadaf Ebrahimi if type == 'VkStructureType': 346*b7893ccfSSadaf Ebrahimi # Extract the required struct type value from the comments 347*b7893ccfSSadaf Ebrahimi # embedded in the original text defining the 'typeinfo' element 348*b7893ccfSSadaf Ebrahimi rawXml = etree.tostring(typeinfo.elem).decode('ascii') 349*b7893ccfSSadaf Ebrahimi result = re.search(r'VK_STRUCTURE_TYPE_\w+', rawXml) 350*b7893ccfSSadaf Ebrahimi if result: 351*b7893ccfSSadaf Ebrahimi value = result.group(0) 352*b7893ccfSSadaf Ebrahimi # Store the required type value 353*b7893ccfSSadaf Ebrahimi self.structTypes[typeName] = self.StructType(name=name, value=value) 354*b7893ccfSSadaf Ebrahimi # Store pointer/array/string info 355*b7893ccfSSadaf Ebrahimi isstaticarray = self.paramIsStaticArray(member) 356*b7893ccfSSadaf Ebrahimi structextends = False 357*b7893ccfSSadaf Ebrahimi membersInfo.append(self.CommandParam(type=type, 358*b7893ccfSSadaf Ebrahimi name=name, 359*b7893ccfSSadaf Ebrahimi ispointer=self.paramIsPointer(member), 360*b7893ccfSSadaf Ebrahimi isstaticarray=isstaticarray, 361*b7893ccfSSadaf Ebrahimi isconst=True if 'const' in cdecl else False, 362*b7893ccfSSadaf Ebrahimi iscount=True if name in lens else False, 363*b7893ccfSSadaf Ebrahimi len=self.getLen(member), 364*b7893ccfSSadaf Ebrahimi extstructs=self.registry.validextensionstructs[typeName] if name == 'pNext' else None, 365*b7893ccfSSadaf Ebrahimi cdecl=cdecl)) 366*b7893ccfSSadaf Ebrahimi # If this struct extends another, keep its name in list for further processing 367*b7893ccfSSadaf Ebrahimi if typeinfo.elem.attrib.get('structextends') is not None: 368*b7893ccfSSadaf Ebrahimi self.structextends_list.append(typeName) 369*b7893ccfSSadaf Ebrahimi self.structMembers.append(self.StructMemberData(name=typeName, members=membersInfo, ifdef_protect=self.featureExtraProtect)) 370*b7893ccfSSadaf Ebrahimi # 371*b7893ccfSSadaf Ebrahimi # Enum_string_header: Create a routine to convert an enumerated value into a string 372*b7893ccfSSadaf Ebrahimi def GenerateEnumStringConversion(self, groupName, value_list): 373*b7893ccfSSadaf Ebrahimi outstring = '\n' 374*b7893ccfSSadaf Ebrahimi if self.featureExtraProtect is not None: 375*b7893ccfSSadaf Ebrahimi outstring += '\n#ifdef %s\n\n' % self.featureExtraProtect 376*b7893ccfSSadaf Ebrahimi outstring += 'static inline const char* string_%s(%s input_value)\n' % (groupName, groupName) 377*b7893ccfSSadaf Ebrahimi outstring += '{\n' 378*b7893ccfSSadaf Ebrahimi outstring += ' switch ((%s)input_value)\n' % groupName 379*b7893ccfSSadaf Ebrahimi outstring += ' {\n' 380*b7893ccfSSadaf Ebrahimi # Emit these in a repeatable order so file is generated with the same contents each time. 381*b7893ccfSSadaf Ebrahimi # This helps compiler caching systems like ccache. 382*b7893ccfSSadaf Ebrahimi for item in sorted(value_list): 383*b7893ccfSSadaf Ebrahimi outstring += ' case %s:\n' % item 384*b7893ccfSSadaf Ebrahimi outstring += ' return "%s";\n' % item 385*b7893ccfSSadaf Ebrahimi outstring += ' default:\n' 386*b7893ccfSSadaf Ebrahimi outstring += ' return "Unhandled %s";\n' % groupName 387*b7893ccfSSadaf Ebrahimi outstring += ' }\n' 388*b7893ccfSSadaf Ebrahimi outstring += '}\n' 389*b7893ccfSSadaf Ebrahimi 390*b7893ccfSSadaf Ebrahimi bitsIndex = groupName.find('Bits') 391*b7893ccfSSadaf Ebrahimi if (bitsIndex != -1): 392*b7893ccfSSadaf Ebrahimi outstring += '\n' 393*b7893ccfSSadaf Ebrahimi flagsName = groupName[0:bitsIndex] + "s" + groupName[bitsIndex+4:] 394*b7893ccfSSadaf Ebrahimi outstring += 'static inline std::string string_%s(%s input_value)\n' % (flagsName, flagsName) 395*b7893ccfSSadaf Ebrahimi outstring += '{\n' 396*b7893ccfSSadaf Ebrahimi outstring += ' std::string ret;\n' 397*b7893ccfSSadaf Ebrahimi outstring += ' int index = 0;\n' 398*b7893ccfSSadaf Ebrahimi outstring += ' while(input_value) {\n' 399*b7893ccfSSadaf Ebrahimi outstring += ' if (input_value & 1) {\n' 400*b7893ccfSSadaf Ebrahimi outstring += ' if( !ret.empty()) ret.append("|");\n' 401*b7893ccfSSadaf Ebrahimi outstring += ' ret.append(string_%s(static_cast<%s>(1 << index)));\n' % (groupName, groupName) 402*b7893ccfSSadaf Ebrahimi outstring += ' }\n' 403*b7893ccfSSadaf Ebrahimi outstring += ' ++index;\n' 404*b7893ccfSSadaf Ebrahimi outstring += ' input_value >>= 1;\n' 405*b7893ccfSSadaf Ebrahimi outstring += ' }\n' 406*b7893ccfSSadaf Ebrahimi outstring += ' if( ret.empty()) ret.append(string_%s(static_cast<%s>(0)));\n' % (groupName, groupName) 407*b7893ccfSSadaf Ebrahimi outstring += ' return ret;\n' 408*b7893ccfSSadaf Ebrahimi outstring += '}\n' 409*b7893ccfSSadaf Ebrahimi 410*b7893ccfSSadaf Ebrahimi if self.featureExtraProtect is not None: 411*b7893ccfSSadaf Ebrahimi outstring += '#endif // %s\n' % self.featureExtraProtect 412*b7893ccfSSadaf Ebrahimi return outstring 413*b7893ccfSSadaf Ebrahimi # 414*b7893ccfSSadaf Ebrahimi # Tack on a helper which, given an index into a VkPhysicalDeviceFeatures structure, will print the corresponding feature name 415*b7893ccfSSadaf Ebrahimi def DeIndexPhysDevFeatures(self): 416*b7893ccfSSadaf Ebrahimi pdev_members = None 417*b7893ccfSSadaf Ebrahimi for name, members, ifdef in self.structMembers: 418*b7893ccfSSadaf Ebrahimi if name == 'VkPhysicalDeviceFeatures': 419*b7893ccfSSadaf Ebrahimi pdev_members = members 420*b7893ccfSSadaf Ebrahimi break 421*b7893ccfSSadaf Ebrahimi deindex = '\n' 422*b7893ccfSSadaf Ebrahimi deindex += 'static inline const char * GetPhysDevFeatureString(uint32_t index) {\n' 423*b7893ccfSSadaf Ebrahimi deindex += ' const char * IndexToPhysDevFeatureString[] = {\n' 424*b7893ccfSSadaf Ebrahimi for feature in pdev_members: 425*b7893ccfSSadaf Ebrahimi deindex += ' "%s",\n' % feature.name 426*b7893ccfSSadaf Ebrahimi deindex += ' };\n\n' 427*b7893ccfSSadaf Ebrahimi deindex += ' return IndexToPhysDevFeatureString[index];\n' 428*b7893ccfSSadaf Ebrahimi deindex += '}\n' 429*b7893ccfSSadaf Ebrahimi return deindex 430*b7893ccfSSadaf Ebrahimi # 431*b7893ccfSSadaf Ebrahimi # Combine enum string helper header file preamble with body text and return 432*b7893ccfSSadaf Ebrahimi def GenerateEnumStringHelperHeader(self): 433*b7893ccfSSadaf Ebrahimi enum_string_helper_header = '\n' 434*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '#pragma once\n' 435*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '#ifdef _WIN32\n' 436*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '#pragma warning( disable : 4065 )\n' 437*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '#endif\n' 438*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '\n' 439*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '#include <string>\n' 440*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '#include <vulkan/vulkan.h>\n' 441*b7893ccfSSadaf Ebrahimi enum_string_helper_header += '\n' 442*b7893ccfSSadaf Ebrahimi enum_string_helper_header += self.enum_output 443*b7893ccfSSadaf Ebrahimi enum_string_helper_header += self.DeIndexPhysDevFeatures() 444*b7893ccfSSadaf Ebrahimi return enum_string_helper_header 445*b7893ccfSSadaf Ebrahimi # 446*b7893ccfSSadaf Ebrahimi # Helper function for declaring a counter variable only once 447*b7893ccfSSadaf Ebrahimi def DeclareCounter(self, string_var, declare_flag): 448*b7893ccfSSadaf Ebrahimi if declare_flag == False: 449*b7893ccfSSadaf Ebrahimi string_var += ' uint32_t i = 0;\n' 450*b7893ccfSSadaf Ebrahimi declare_flag = True 451*b7893ccfSSadaf Ebrahimi return string_var, declare_flag 452*b7893ccfSSadaf Ebrahimi # 453*b7893ccfSSadaf Ebrahimi # Combine safe struct helper header file preamble with body text and return 454*b7893ccfSSadaf Ebrahimi def GenerateSafeStructHelperHeader(self): 455*b7893ccfSSadaf Ebrahimi safe_struct_helper_header = '\n' 456*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += '#pragma once\n' 457*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += '#include <vulkan/vulkan.h>\n' 458*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += '\n' 459*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += 'void *SafePnextCopy(const void *pNext);\n' 460*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += 'void FreePnextChain(const void *pNext);\n' 461*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += 'char *SafeStringCopy(const char *in_string);\n' 462*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += '\n' 463*b7893ccfSSadaf Ebrahimi safe_struct_helper_header += self.GenerateSafeStructHeader() 464*b7893ccfSSadaf Ebrahimi return safe_struct_helper_header 465*b7893ccfSSadaf Ebrahimi # 466*b7893ccfSSadaf Ebrahimi # safe_struct header: build function prototypes for header file 467*b7893ccfSSadaf Ebrahimi def GenerateSafeStructHeader(self): 468*b7893ccfSSadaf Ebrahimi safe_struct_header = '' 469*b7893ccfSSadaf Ebrahimi for item in self.structMembers: 470*b7893ccfSSadaf Ebrahimi if self.NeedSafeStruct(item) == True: 471*b7893ccfSSadaf Ebrahimi safe_struct_header += '\n' 472*b7893ccfSSadaf Ebrahimi if item.ifdef_protect is not None: 473*b7893ccfSSadaf Ebrahimi safe_struct_header += '#ifdef %s\n' % item.ifdef_protect 474*b7893ccfSSadaf Ebrahimi safe_struct_header += 'struct safe_%s {\n' % (item.name) 475*b7893ccfSSadaf Ebrahimi for member in item.members: 476*b7893ccfSSadaf Ebrahimi if member.type in self.structNames: 477*b7893ccfSSadaf Ebrahimi member_index = next((i for i, v in enumerate(self.structMembers) if v[0] == member.type), None) 478*b7893ccfSSadaf Ebrahimi if member_index is not None and self.NeedSafeStruct(self.structMembers[member_index]) == True: 479*b7893ccfSSadaf Ebrahimi if member.ispointer: 480*b7893ccfSSadaf Ebrahimi safe_struct_header += ' safe_%s* %s;\n' % (member.type, member.name) 481*b7893ccfSSadaf Ebrahimi else: 482*b7893ccfSSadaf Ebrahimi safe_struct_header += ' safe_%s %s;\n' % (member.type, member.name) 483*b7893ccfSSadaf Ebrahimi continue 484*b7893ccfSSadaf Ebrahimi if member.len is not None and (self.TypeContainsObjectHandle(member.type, True) or self.TypeContainsObjectHandle(member.type, False)): 485*b7893ccfSSadaf Ebrahimi safe_struct_header += ' %s* %s;\n' % (member.type, member.name) 486*b7893ccfSSadaf Ebrahimi else: 487*b7893ccfSSadaf Ebrahimi safe_struct_header += '%s;\n' % member.cdecl 488*b7893ccfSSadaf Ebrahimi safe_struct_header += ' safe_%s(const %s* in_struct%s);\n' % (item.name, item.name, self.custom_construct_params.get(item.name, '')) 489*b7893ccfSSadaf Ebrahimi safe_struct_header += ' safe_%s(const safe_%s& src);\n' % (item.name, item.name) 490*b7893ccfSSadaf Ebrahimi safe_struct_header += ' safe_%s& operator=(const safe_%s& src);\n' % (item.name, item.name) 491*b7893ccfSSadaf Ebrahimi safe_struct_header += ' safe_%s();\n' % item.name 492*b7893ccfSSadaf Ebrahimi safe_struct_header += ' ~safe_%s();\n' % item.name 493*b7893ccfSSadaf Ebrahimi safe_struct_header += ' void initialize(const %s* in_struct%s);\n' % (item.name, self.custom_construct_params.get(item.name, '')) 494*b7893ccfSSadaf Ebrahimi safe_struct_header += ' void initialize(const safe_%s* src);\n' % (item.name) 495*b7893ccfSSadaf Ebrahimi safe_struct_header += ' %s *ptr() { return reinterpret_cast<%s *>(this); }\n' % (item.name, item.name) 496*b7893ccfSSadaf Ebrahimi safe_struct_header += ' %s const *ptr() const { return reinterpret_cast<%s const *>(this); }\n' % (item.name, item.name) 497*b7893ccfSSadaf Ebrahimi safe_struct_header += '};\n' 498*b7893ccfSSadaf Ebrahimi if item.ifdef_protect is not None: 499*b7893ccfSSadaf Ebrahimi safe_struct_header += '#endif // %s\n' % item.ifdef_protect 500*b7893ccfSSadaf Ebrahimi return safe_struct_header 501*b7893ccfSSadaf Ebrahimi # 502*b7893ccfSSadaf Ebrahimi # Generate extension helper header file 503*b7893ccfSSadaf Ebrahimi def GenerateExtensionHelperHeader(self): 504*b7893ccfSSadaf Ebrahimi 505*b7893ccfSSadaf Ebrahimi V_1_1_level_feature_set = [ 506*b7893ccfSSadaf Ebrahimi 'VK_VERSION_1_1', 507*b7893ccfSSadaf Ebrahimi ] 508*b7893ccfSSadaf Ebrahimi 509*b7893ccfSSadaf Ebrahimi V_1_0_instance_extensions_promoted_to_V_1_1_core = [ 510*b7893ccfSSadaf Ebrahimi 'vk_khr_device_group_creation', 511*b7893ccfSSadaf Ebrahimi 'vk_khr_external_fence_capabilities', 512*b7893ccfSSadaf Ebrahimi 'vk_khr_external_memory_capabilities', 513*b7893ccfSSadaf Ebrahimi 'vk_khr_external_semaphore_capabilities', 514*b7893ccfSSadaf Ebrahimi 'vk_khr_get_physical_device_properties_2', 515*b7893ccfSSadaf Ebrahimi ] 516*b7893ccfSSadaf Ebrahimi 517*b7893ccfSSadaf Ebrahimi V_1_0_device_extensions_promoted_to_V_1_1_core = [ 518*b7893ccfSSadaf Ebrahimi 'vk_khr_16bit_storage', 519*b7893ccfSSadaf Ebrahimi 'vk_khr_bind_memory_2', 520*b7893ccfSSadaf Ebrahimi 'vk_khr_dedicated_allocation', 521*b7893ccfSSadaf Ebrahimi 'vk_khr_descriptor_update_template', 522*b7893ccfSSadaf Ebrahimi 'vk_khr_device_group', 523*b7893ccfSSadaf Ebrahimi 'vk_khr_external_fence', 524*b7893ccfSSadaf Ebrahimi 'vk_khr_external_memory', 525*b7893ccfSSadaf Ebrahimi 'vk_khr_external_semaphore', 526*b7893ccfSSadaf Ebrahimi 'vk_khr_get_memory_requirements_2', 527*b7893ccfSSadaf Ebrahimi 'vk_khr_maintenance1', 528*b7893ccfSSadaf Ebrahimi 'vk_khr_maintenance2', 529*b7893ccfSSadaf Ebrahimi 'vk_khr_maintenance3', 530*b7893ccfSSadaf Ebrahimi 'vk_khr_multiview', 531*b7893ccfSSadaf Ebrahimi 'vk_khr_relaxed_block_layout', 532*b7893ccfSSadaf Ebrahimi 'vk_khr_sampler_ycbcr_conversion', 533*b7893ccfSSadaf Ebrahimi 'vk_khr_shader_draw_parameters', 534*b7893ccfSSadaf Ebrahimi 'vk_khr_storage_buffer_storage_class', 535*b7893ccfSSadaf Ebrahimi 'vk_khr_variable_pointers', 536*b7893ccfSSadaf Ebrahimi ] 537*b7893ccfSSadaf Ebrahimi 538*b7893ccfSSadaf Ebrahimi output = [ 539*b7893ccfSSadaf Ebrahimi '', 540*b7893ccfSSadaf Ebrahimi '#ifndef VK_EXTENSION_HELPER_H_', 541*b7893ccfSSadaf Ebrahimi '#define VK_EXTENSION_HELPER_H_', 542*b7893ccfSSadaf Ebrahimi '#include <unordered_set>', 543*b7893ccfSSadaf Ebrahimi '#include <string>', 544*b7893ccfSSadaf Ebrahimi '#include <unordered_map>', 545*b7893ccfSSadaf Ebrahimi '#include <utility>', 546*b7893ccfSSadaf Ebrahimi '#include <set>', 547*b7893ccfSSadaf Ebrahimi '#include <vector>', 548*b7893ccfSSadaf Ebrahimi '', 549*b7893ccfSSadaf Ebrahimi '#include <vulkan/vulkan.h>', 550*b7893ccfSSadaf Ebrahimi ''] 551*b7893ccfSSadaf Ebrahimi 552*b7893ccfSSadaf Ebrahimi def guarded(ifdef, value): 553*b7893ccfSSadaf Ebrahimi if ifdef is not None: 554*b7893ccfSSadaf Ebrahimi return '\n'.join([ '#ifdef %s' % ifdef, value, '#endif' ]) 555*b7893ccfSSadaf Ebrahimi else: 556*b7893ccfSSadaf Ebrahimi return value 557*b7893ccfSSadaf Ebrahimi 558*b7893ccfSSadaf Ebrahimi for type in ['Instance', 'Device']: 559*b7893ccfSSadaf Ebrahimi struct_type = '%sExtensions' % type 560*b7893ccfSSadaf Ebrahimi if type == 'Instance': 561*b7893ccfSSadaf Ebrahimi extension_dict = self.instance_extension_info 562*b7893ccfSSadaf Ebrahimi promoted_ext_list = V_1_0_instance_extensions_promoted_to_V_1_1_core 563*b7893ccfSSadaf Ebrahimi struct_decl = 'struct %s {' % struct_type 564*b7893ccfSSadaf Ebrahimi instance_struct_type = struct_type 565*b7893ccfSSadaf Ebrahimi else: 566*b7893ccfSSadaf Ebrahimi extension_dict = self.device_extension_info 567*b7893ccfSSadaf Ebrahimi promoted_ext_list = V_1_0_device_extensions_promoted_to_V_1_1_core 568*b7893ccfSSadaf Ebrahimi struct_decl = 'struct %s : public %s {' % (struct_type, instance_struct_type) 569*b7893ccfSSadaf Ebrahimi 570*b7893ccfSSadaf Ebrahimi extension_items = sorted(extension_dict.items()) 571*b7893ccfSSadaf Ebrahimi 572*b7893ccfSSadaf Ebrahimi field_name = { ext_name: re.sub('_extension_name', '', info['define'].lower()) for ext_name, info in extension_items } 573*b7893ccfSSadaf Ebrahimi 574*b7893ccfSSadaf Ebrahimi if type == 'Instance': 575*b7893ccfSSadaf Ebrahimi instance_field_name = field_name 576*b7893ccfSSadaf Ebrahimi instance_extension_dict = extension_dict 577*b7893ccfSSadaf Ebrahimi else: 578*b7893ccfSSadaf Ebrahimi # Get complete field name and extension data for both Instance and Device extensions 579*b7893ccfSSadaf Ebrahimi field_name.update(instance_field_name) 580*b7893ccfSSadaf Ebrahimi extension_dict = extension_dict.copy() # Don't modify the self.<dict> we're pointing to 581*b7893ccfSSadaf Ebrahimi extension_dict.update(instance_extension_dict) 582*b7893ccfSSadaf Ebrahimi 583*b7893ccfSSadaf Ebrahimi # Output the data member list 584*b7893ccfSSadaf Ebrahimi struct = [struct_decl] 585*b7893ccfSSadaf Ebrahimi struct.extend([ ' bool vk_feature_version_1_1{false};']) 586*b7893ccfSSadaf Ebrahimi struct.extend([ ' bool %s{false};' % field_name[ext_name] for ext_name, info in extension_items]) 587*b7893ccfSSadaf Ebrahimi 588*b7893ccfSSadaf Ebrahimi # Construct the extension information map -- mapping name to data member (field), and required extensions 589*b7893ccfSSadaf Ebrahimi # The map is contained within a static function member for portability reasons. 590*b7893ccfSSadaf Ebrahimi info_type = '%sInfo' % type 591*b7893ccfSSadaf Ebrahimi info_map_type = '%sMap' % info_type 592*b7893ccfSSadaf Ebrahimi req_type = '%sReq' % type 593*b7893ccfSSadaf Ebrahimi req_vec_type = '%sVec' % req_type 594*b7893ccfSSadaf Ebrahimi struct.extend([ 595*b7893ccfSSadaf Ebrahimi '', 596*b7893ccfSSadaf Ebrahimi ' struct %s {' % req_type, 597*b7893ccfSSadaf Ebrahimi ' const bool %s::* enabled;' % struct_type, 598*b7893ccfSSadaf Ebrahimi ' const char *name;', 599*b7893ccfSSadaf Ebrahimi ' };', 600*b7893ccfSSadaf Ebrahimi ' typedef std::vector<%s> %s;' % (req_type, req_vec_type), 601*b7893ccfSSadaf Ebrahimi ' struct %s {' % info_type, 602*b7893ccfSSadaf Ebrahimi ' %s(bool %s::* state_, const %s requires_): state(state_), requires(requires_) {}' % ( info_type, struct_type, req_vec_type), 603*b7893ccfSSadaf Ebrahimi ' bool %s::* state;' % struct_type, 604*b7893ccfSSadaf Ebrahimi ' %s requires;' % req_vec_type, 605*b7893ccfSSadaf Ebrahimi ' };', 606*b7893ccfSSadaf Ebrahimi '', 607*b7893ccfSSadaf Ebrahimi ' typedef std::unordered_map<std::string,%s> %s;' % (info_type, info_map_type), 608*b7893ccfSSadaf Ebrahimi ' static const %s &get_info(const char *name) {' %info_type, 609*b7893ccfSSadaf Ebrahimi ' static const %s info_map = {' % info_map_type ]) 610*b7893ccfSSadaf Ebrahimi struct.extend([ 611*b7893ccfSSadaf Ebrahimi ' std::make_pair("VK_VERSION_1_1", %sInfo(&%sExtensions::vk_feature_version_1_1, {})),' % (type, type)]) 612*b7893ccfSSadaf Ebrahimi 613*b7893ccfSSadaf Ebrahimi field_format = '&' + struct_type + '::%s' 614*b7893ccfSSadaf Ebrahimi req_format = '{' + field_format+ ', %s}' 615*b7893ccfSSadaf Ebrahimi req_indent = '\n ' 616*b7893ccfSSadaf Ebrahimi req_join = ',' + req_indent 617*b7893ccfSSadaf Ebrahimi info_format = (' std::make_pair(%s, ' + info_type + '(' + field_format + ', {%s})),') 618*b7893ccfSSadaf Ebrahimi def format_info(ext_name, info): 619*b7893ccfSSadaf Ebrahimi reqs = req_join.join([req_format % (field_name[req], extension_dict[req]['define']) for req in info['reqs']]) 620*b7893ccfSSadaf Ebrahimi return info_format % (info['define'], field_name[ext_name], '{%s}' % (req_indent + reqs) if reqs else '') 621*b7893ccfSSadaf Ebrahimi 622*b7893ccfSSadaf Ebrahimi struct.extend([guarded(info['ifdef'], format_info(ext_name, info)) for ext_name, info in extension_items]) 623*b7893ccfSSadaf Ebrahimi struct.extend([ 624*b7893ccfSSadaf Ebrahimi ' };', 625*b7893ccfSSadaf Ebrahimi '', 626*b7893ccfSSadaf Ebrahimi ' static const %s empty_info {nullptr, %s()};' % (info_type, req_vec_type), 627*b7893ccfSSadaf Ebrahimi ' %s::const_iterator info = info_map.find(name);' % info_map_type, 628*b7893ccfSSadaf Ebrahimi ' if ( info != info_map.cend()) {', 629*b7893ccfSSadaf Ebrahimi ' return info->second;', 630*b7893ccfSSadaf Ebrahimi ' }', 631*b7893ccfSSadaf Ebrahimi ' return empty_info;', 632*b7893ccfSSadaf Ebrahimi ' }', 633*b7893ccfSSadaf Ebrahimi '']) 634*b7893ccfSSadaf Ebrahimi 635*b7893ccfSSadaf Ebrahimi if type == 'Instance': 636*b7893ccfSSadaf Ebrahimi struct.extend([ 637*b7893ccfSSadaf Ebrahimi ' uint32_t NormalizeApiVersion(uint32_t specified_version) {', 638*b7893ccfSSadaf Ebrahimi ' uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;', 639*b7893ccfSSadaf Ebrahimi ' return api_version;', 640*b7893ccfSSadaf Ebrahimi ' }', 641*b7893ccfSSadaf Ebrahimi '', 642*b7893ccfSSadaf Ebrahimi ' uint32_t InitFromInstanceCreateInfo(uint32_t requested_api_version, const VkInstanceCreateInfo *pCreateInfo) {']) 643*b7893ccfSSadaf Ebrahimi else: 644*b7893ccfSSadaf Ebrahimi struct.extend([ 645*b7893ccfSSadaf Ebrahimi ' %s() = default;' % struct_type, 646*b7893ccfSSadaf Ebrahimi ' %s(const %s& instance_ext) : %s(instance_ext) {}' % (struct_type, instance_struct_type, instance_struct_type), 647*b7893ccfSSadaf Ebrahimi '', 648*b7893ccfSSadaf Ebrahimi ' uint32_t InitFromDeviceCreateInfo(const %s *instance_extensions, uint32_t requested_api_version,' % instance_struct_type, 649*b7893ccfSSadaf Ebrahimi ' const VkDeviceCreateInfo *pCreateInfo) {', 650*b7893ccfSSadaf Ebrahimi ' // Initialize: this to defaults, base class fields to input.', 651*b7893ccfSSadaf Ebrahimi ' assert(instance_extensions);', 652*b7893ccfSSadaf Ebrahimi ' *this = %s(*instance_extensions);' % struct_type, 653*b7893ccfSSadaf Ebrahimi '']), 654*b7893ccfSSadaf Ebrahimi struct.extend([ 655*b7893ccfSSadaf Ebrahimi '', 656*b7893ccfSSadaf Ebrahimi ' static const std::vector<const char *> V_1_1_promoted_%s_apis = {' % type.lower() ]) 657*b7893ccfSSadaf Ebrahimi struct.extend([' %s_EXTENSION_NAME,' % ext_name.upper() for ext_name in promoted_ext_list]) 658*b7893ccfSSadaf Ebrahimi struct.extend([' "VK_VERSION_1_1",']) 659*b7893ccfSSadaf Ebrahimi struct.extend([ 660*b7893ccfSSadaf Ebrahimi ' };', 661*b7893ccfSSadaf Ebrahimi '', 662*b7893ccfSSadaf Ebrahimi ' // Initialize struct data, robust to invalid pCreateInfo', 663*b7893ccfSSadaf Ebrahimi ' if (pCreateInfo->ppEnabledExtensionNames) {', 664*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {', 665*b7893ccfSSadaf Ebrahimi ' if (!pCreateInfo->ppEnabledExtensionNames[i]) continue;', 666*b7893ccfSSadaf Ebrahimi ' auto info = get_info(pCreateInfo->ppEnabledExtensionNames[i]);', 667*b7893ccfSSadaf Ebrahimi ' if(info.state) this->*(info.state) = true;', 668*b7893ccfSSadaf Ebrahimi ' }', 669*b7893ccfSSadaf Ebrahimi ' }', 670*b7893ccfSSadaf Ebrahimi ' uint32_t api_version = NormalizeApiVersion(requested_api_version);', 671*b7893ccfSSadaf Ebrahimi ' if (api_version >= VK_API_VERSION_1_1) {', 672*b7893ccfSSadaf Ebrahimi ' for (auto promoted_ext : V_1_1_promoted_%s_apis) {' % type.lower(), 673*b7893ccfSSadaf Ebrahimi ' auto info = get_info(promoted_ext);', 674*b7893ccfSSadaf Ebrahimi ' assert(info.state);', 675*b7893ccfSSadaf Ebrahimi ' if (info.state) this->*(info.state) = true;', 676*b7893ccfSSadaf Ebrahimi ' }', 677*b7893ccfSSadaf Ebrahimi ' }', 678*b7893ccfSSadaf Ebrahimi ' return api_version;', 679*b7893ccfSSadaf Ebrahimi ' }', 680*b7893ccfSSadaf Ebrahimi '};']) 681*b7893ccfSSadaf Ebrahimi 682*b7893ccfSSadaf Ebrahimi # Output reference lists of instance/device extension names 683*b7893ccfSSadaf Ebrahimi struct.extend(['', 'static const std::set<std::string> k%sExtensionNames = {' % type]) 684*b7893ccfSSadaf Ebrahimi struct.extend([guarded(info['ifdef'], ' %s,' % info['define']) for ext_name, info in extension_items]) 685*b7893ccfSSadaf Ebrahimi struct.extend(['};', '']) 686*b7893ccfSSadaf Ebrahimi output.extend(struct) 687*b7893ccfSSadaf Ebrahimi 688*b7893ccfSSadaf Ebrahimi output.extend(['', '#endif // VK_EXTENSION_HELPER_H_']) 689*b7893ccfSSadaf Ebrahimi return '\n'.join(output) 690*b7893ccfSSadaf Ebrahimi # 691*b7893ccfSSadaf Ebrahimi # Combine object types helper header file preamble with body text and return 692*b7893ccfSSadaf Ebrahimi def GenerateObjectTypesHelperHeader(self): 693*b7893ccfSSadaf Ebrahimi object_types_helper_header = '\n' 694*b7893ccfSSadaf Ebrahimi object_types_helper_header += '#pragma once\n' 695*b7893ccfSSadaf Ebrahimi object_types_helper_header += '\n' 696*b7893ccfSSadaf Ebrahimi object_types_helper_header += self.GenerateObjectTypesHeader() 697*b7893ccfSSadaf Ebrahimi return object_types_helper_header 698*b7893ccfSSadaf Ebrahimi # 699*b7893ccfSSadaf Ebrahimi # Object types header: create object enum type header file 700*b7893ccfSSadaf Ebrahimi def GenerateObjectTypesHeader(self): 701*b7893ccfSSadaf Ebrahimi object_types_header = '#include "cast_utils.h"\n' 702*b7893ccfSSadaf Ebrahimi object_types_header += '\n' 703*b7893ccfSSadaf Ebrahimi object_types_header += '// Object Type enum for validation layer internal object handling\n' 704*b7893ccfSSadaf Ebrahimi object_types_header += 'typedef enum VulkanObjectType {\n' 705*b7893ccfSSadaf Ebrahimi object_types_header += ' kVulkanObjectTypeUnknown = 0,\n' 706*b7893ccfSSadaf Ebrahimi enum_num = 1 707*b7893ccfSSadaf Ebrahimi type_list = []; 708*b7893ccfSSadaf Ebrahimi enum_entry_map = {} 709*b7893ccfSSadaf Ebrahimi non_dispatchable = {} 710*b7893ccfSSadaf Ebrahimi dispatchable = {} 711*b7893ccfSSadaf Ebrahimi object_type_info = {} 712*b7893ccfSSadaf Ebrahimi 713*b7893ccfSSadaf Ebrahimi # Output enum definition as each handle is processed, saving the names to use for the conversion routine 714*b7893ccfSSadaf Ebrahimi for item in self.object_types: 715*b7893ccfSSadaf Ebrahimi fixup_name = item[2:] 716*b7893ccfSSadaf Ebrahimi enum_entry = 'kVulkanObjectType%s' % fixup_name 717*b7893ccfSSadaf Ebrahimi enum_entry_map[item] = enum_entry 718*b7893ccfSSadaf Ebrahimi object_types_header += ' ' + enum_entry 719*b7893ccfSSadaf Ebrahimi object_types_header += ' = %d,\n' % enum_num 720*b7893ccfSSadaf Ebrahimi enum_num += 1 721*b7893ccfSSadaf Ebrahimi type_list.append(enum_entry) 722*b7893ccfSSadaf Ebrahimi object_type_info[enum_entry] = { 'VkType': item } 723*b7893ccfSSadaf Ebrahimi # We'll want lists of the dispatchable and non dispatchable handles below with access to the same info 724*b7893ccfSSadaf Ebrahimi if self.handle_types.IsNonDispatchable(item): 725*b7893ccfSSadaf Ebrahimi non_dispatchable[item] = enum_entry 726*b7893ccfSSadaf Ebrahimi else: 727*b7893ccfSSadaf Ebrahimi dispatchable[item] = enum_entry 728*b7893ccfSSadaf Ebrahimi 729*b7893ccfSSadaf Ebrahimi object_types_header += ' kVulkanObjectTypeMax = %d,\n' % enum_num 730*b7893ccfSSadaf Ebrahimi object_types_header += ' // Aliases for backwards compatibilty of "promoted" types\n' 731*b7893ccfSSadaf Ebrahimi for (name, alias) in self.object_type_aliases: 732*b7893ccfSSadaf Ebrahimi fixup_name = name[2:] 733*b7893ccfSSadaf Ebrahimi object_types_header += ' kVulkanObjectType{} = {},\n'.format(fixup_name, enum_entry_map[alias]) 734*b7893ccfSSadaf Ebrahimi object_types_header += '} VulkanObjectType;\n\n' 735*b7893ccfSSadaf Ebrahimi 736*b7893ccfSSadaf Ebrahimi # Output name string helper 737*b7893ccfSSadaf Ebrahimi object_types_header += '// Array of object name strings for OBJECT_TYPE enum conversion\n' 738*b7893ccfSSadaf Ebrahimi object_types_header += 'static const char * const object_string[kVulkanObjectTypeMax] = {\n' 739*b7893ccfSSadaf Ebrahimi object_types_header += ' "VkNonDispatchableHandle",\n' 740*b7893ccfSSadaf Ebrahimi for item in self.object_types: 741*b7893ccfSSadaf Ebrahimi object_types_header += ' "%s",\n' % item 742*b7893ccfSSadaf Ebrahimi object_types_header += '};\n' 743*b7893ccfSSadaf Ebrahimi 744*b7893ccfSSadaf Ebrahimi # Helpers to create unified dict key from k<Name>, VK_OBJECT_TYPE_<Name>, and VK_DEBUG_REPORT_OBJECT_TYPE_<Name> 745*b7893ccfSSadaf Ebrahimi def dro_to_key(raw_key): return re.search('^VK_DEBUG_REPORT_OBJECT_TYPE_(.*)_EXT$', raw_key).group(1).lower().replace("_","") 746*b7893ccfSSadaf Ebrahimi def vko_to_key(raw_key): return re.search('^VK_OBJECT_TYPE_(.*)', raw_key).group(1).lower().replace("_","") 747*b7893ccfSSadaf Ebrahimi def kenum_to_key(raw_key): return re.search('^kVulkanObjectType(.*)', raw_key).group(1).lower() 748*b7893ccfSSadaf Ebrahimi 749*b7893ccfSSadaf Ebrahimi dro_dict = {dro_to_key(dro) : dro for dro in self.debug_report_object_types} 750*b7893ccfSSadaf Ebrahimi vko_dict = {vko_to_key(vko) : vko for vko in self.core_object_types} 751*b7893ccfSSadaf Ebrahimi 752*b7893ccfSSadaf Ebrahimi # Output a conversion routine from the layer object definitions to the debug report definitions 753*b7893ccfSSadaf Ebrahimi object_types_header += '\n' 754*b7893ccfSSadaf Ebrahimi object_types_header += '// Helper array to get Vulkan VK_EXT_debug_report object type enum from the internal layers version\n' 755*b7893ccfSSadaf Ebrahimi object_types_header += 'const VkDebugReportObjectTypeEXT get_debug_report_enum[] = {\n' 756*b7893ccfSSadaf Ebrahimi object_types_header += ' VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeUnknown\n' # no unknown handle, so this must be here explicitly 757*b7893ccfSSadaf Ebrahimi 758*b7893ccfSSadaf Ebrahimi for object_type in type_list: 759*b7893ccfSSadaf Ebrahimi # VK_DEBUG_REPORT is not updated anymore; there might be missing object types 760*b7893ccfSSadaf Ebrahimi kenum_type = dro_dict.get(kenum_to_key(object_type), 'VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT') 761*b7893ccfSSadaf Ebrahimi object_types_header += ' %s, // %s\n' % (kenum_type, object_type) 762*b7893ccfSSadaf Ebrahimi object_type_info[object_type]['DbgType'] = kenum_type 763*b7893ccfSSadaf Ebrahimi object_types_header += '};\n' 764*b7893ccfSSadaf Ebrahimi 765*b7893ccfSSadaf Ebrahimi # Output a conversion routine from the layer object definitions to the core object type definitions 766*b7893ccfSSadaf Ebrahimi # This will intentionally *fail* for unmatched types as the VK_OBJECT_TYPE list should match the kVulkanObjectType list 767*b7893ccfSSadaf Ebrahimi object_types_header += '\n' 768*b7893ccfSSadaf Ebrahimi object_types_header += '// Helper array to get Official Vulkan VkObjectType enum from the internal layers version\n' 769*b7893ccfSSadaf Ebrahimi object_types_header += 'const VkObjectType get_object_type_enum[] = {\n' 770*b7893ccfSSadaf Ebrahimi object_types_header += ' VK_OBJECT_TYPE_UNKNOWN, // kVulkanObjectTypeUnknown\n' # no unknown handle, so must be here explicitly 771*b7893ccfSSadaf Ebrahimi 772*b7893ccfSSadaf Ebrahimi for object_type in type_list: 773*b7893ccfSSadaf Ebrahimi kenum_type = vko_dict[kenum_to_key(object_type)] 774*b7893ccfSSadaf Ebrahimi object_types_header += ' %s, // %s\n' % (kenum_type, object_type) 775*b7893ccfSSadaf Ebrahimi object_type_info[object_type]['VkoType'] = kenum_type 776*b7893ccfSSadaf Ebrahimi object_types_header += '};\n' 777*b7893ccfSSadaf Ebrahimi 778*b7893ccfSSadaf Ebrahimi # Create a functions to convert between VkDebugReportObjectTypeEXT and VkObjectType 779*b7893ccfSSadaf Ebrahimi object_types_header += '\n' 780*b7893ccfSSadaf Ebrahimi object_types_header += 'static inline VkObjectType convertDebugReportObjectToCoreObject(VkDebugReportObjectTypeEXT debug_report_obj) {\n' 781*b7893ccfSSadaf Ebrahimi object_types_header += ' switch (debug_report_obj) {\n' 782*b7893ccfSSadaf Ebrahimi for dr_object_type in self.debug_report_object_types: 783*b7893ccfSSadaf Ebrahimi object_types_header += ' case %s: return %s;\n' % (dr_object_type, vko_dict[dro_to_key(dr_object_type)]) 784*b7893ccfSSadaf Ebrahimi object_types_header += ' default: return VK_OBJECT_TYPE_UNKNOWN;\n' 785*b7893ccfSSadaf Ebrahimi object_types_header += ' }\n' 786*b7893ccfSSadaf Ebrahimi object_types_header += '}\n' 787*b7893ccfSSadaf Ebrahimi 788*b7893ccfSSadaf Ebrahimi object_types_header += '\n' 789*b7893ccfSSadaf Ebrahimi object_types_header += 'static inline VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj) {\n' 790*b7893ccfSSadaf Ebrahimi object_types_header += ' switch (core_report_obj) {\n' 791*b7893ccfSSadaf Ebrahimi for core_object_type in self.core_object_types: 792*b7893ccfSSadaf Ebrahimi # VK_DEBUG_REPORT is not updated anymore; there might be missing object types 793*b7893ccfSSadaf Ebrahimi dr_object_type = dro_dict.get(vko_to_key(core_object_type)) 794*b7893ccfSSadaf Ebrahimi if dr_object_type is not None: 795*b7893ccfSSadaf Ebrahimi object_types_header += ' case %s: return %s;\n' % (core_object_type, dr_object_type) 796*b7893ccfSSadaf Ebrahimi object_types_header += ' default: return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n' 797*b7893ccfSSadaf Ebrahimi object_types_header += ' }\n' 798*b7893ccfSSadaf Ebrahimi object_types_header += '}\n' 799*b7893ccfSSadaf Ebrahimi 800*b7893ccfSSadaf Ebrahimi # 801*b7893ccfSSadaf Ebrahimi object_types_header += '\n' 802*b7893ccfSSadaf Ebrahimi traits_format = Outdent(''' 803*b7893ccfSSadaf Ebrahimi template <> struct VkHandleInfo<{vk_type}> {{ 804*b7893ccfSSadaf Ebrahimi static const VulkanObjectType kVulkanObjectType = {obj_type}; 805*b7893ccfSSadaf Ebrahimi static const VkDebugReportObjectTypeEXT kDebugReportObjectType = {dbg_type}; 806*b7893ccfSSadaf Ebrahimi static const VkObjectType kVkObjectType = {vko_type}; 807*b7893ccfSSadaf Ebrahimi static const char* Typename() {{ 808*b7893ccfSSadaf Ebrahimi return "{vk_type}"; 809*b7893ccfSSadaf Ebrahimi }} 810*b7893ccfSSadaf Ebrahimi }}; 811*b7893ccfSSadaf Ebrahimi template <> struct VulkanObjectTypeInfo<{obj_type}> {{ 812*b7893ccfSSadaf Ebrahimi typedef {vk_type} Type; 813*b7893ccfSSadaf Ebrahimi }}; 814*b7893ccfSSadaf Ebrahimi ''') 815*b7893ccfSSadaf Ebrahimi 816*b7893ccfSSadaf Ebrahimi object_types_header += Outdent(''' 817*b7893ccfSSadaf Ebrahimi // Traits objects from each type statically map from Vk<handleType> to the various enums 818*b7893ccfSSadaf Ebrahimi template <typename VkType> struct VkHandleInfo {}; 819*b7893ccfSSadaf Ebrahimi template <VulkanObjectType id> struct VulkanObjectTypeInfo {}; 820*b7893ccfSSadaf Ebrahimi 821*b7893ccfSSadaf Ebrahimi // The following line must match the vulkan_core.h condition guarding VK_DEFINE_NON_DISPATCHABLE_HANDLE 822*b7893ccfSSadaf Ebrahimi #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || \ 823*b7893ccfSSadaf Ebrahimi defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) 824*b7893ccfSSadaf Ebrahimi #define TYPESAFE_NONDISPATCHABLE_HANDLES 825*b7893ccfSSadaf Ebrahimi #else 826*b7893ccfSSadaf Ebrahimi VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkNonDispatchableHandle) 827*b7893ccfSSadaf Ebrahimi ''') +'\n' 828*b7893ccfSSadaf Ebrahimi object_types_header += traits_format.format(vk_type='VkNonDispatchableHandle', obj_type='kVulkanObjectTypeUnknown', 829*b7893ccfSSadaf Ebrahimi dbg_type='VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT', 830*b7893ccfSSadaf Ebrahimi vko_type='VK_OBJECT_TYPE_UNKNOWN') + '\n' 831*b7893ccfSSadaf Ebrahimi object_types_header += '#endif // VK_DEFINE_HANDLE logic duplication\n' 832*b7893ccfSSadaf Ebrahimi 833*b7893ccfSSadaf Ebrahimi for vk_type, object_type in sorted(dispatchable.items()): 834*b7893ccfSSadaf Ebrahimi info = object_type_info[object_type] 835*b7893ccfSSadaf Ebrahimi object_types_header += traits_format.format(vk_type=vk_type, obj_type=object_type, dbg_type=info['DbgType'], 836*b7893ccfSSadaf Ebrahimi vko_type=info['VkoType']) 837*b7893ccfSSadaf Ebrahimi object_types_header += '#ifdef TYPESAFE_NONDISPATCHABLE_HANDLES\n' 838*b7893ccfSSadaf Ebrahimi for vk_type, object_type in sorted(non_dispatchable.items()): 839*b7893ccfSSadaf Ebrahimi info = object_type_info[object_type] 840*b7893ccfSSadaf Ebrahimi object_types_header += traits_format.format(vk_type=vk_type, obj_type=object_type, dbg_type=info['DbgType'], 841*b7893ccfSSadaf Ebrahimi vko_type=info['VkoType']) 842*b7893ccfSSadaf Ebrahimi object_types_header += '#endif // TYPESAFE_NONDISPATCHABLE_HANDLES\n' 843*b7893ccfSSadaf Ebrahimi 844*b7893ccfSSadaf Ebrahimi object_types_header += Outdent(''' 845*b7893ccfSSadaf Ebrahimi struct VulkanTypedHandle { 846*b7893ccfSSadaf Ebrahimi uint64_t handle; 847*b7893ccfSSadaf Ebrahimi VulkanObjectType type; 848*b7893ccfSSadaf Ebrahimi template <typename Handle> 849*b7893ccfSSadaf Ebrahimi VulkanTypedHandle(Handle handle_, VulkanObjectType type_) : 850*b7893ccfSSadaf Ebrahimi handle(CastToUint64(handle_)), 851*b7893ccfSSadaf Ebrahimi type(type_) { 852*b7893ccfSSadaf Ebrahimi #ifdef TYPESAFE_NONDISPATCHABLE_HANDLES 853*b7893ccfSSadaf Ebrahimi // For 32 bit it's not always safe to check for traits <-> type 854*b7893ccfSSadaf Ebrahimi // as all non-dispatchable handles have the same type-id and thus traits, 855*b7893ccfSSadaf Ebrahimi // but on 64 bit we can validate the passed type matches the passed handle 856*b7893ccfSSadaf Ebrahimi assert(type == VkHandleInfo<Handle>::kVulkanObjectType); 857*b7893ccfSSadaf Ebrahimi #endif // TYPESAFE_NONDISPATCHABLE_HANDLES 858*b7893ccfSSadaf Ebrahimi } 859*b7893ccfSSadaf Ebrahimi template <typename Handle> 860*b7893ccfSSadaf Ebrahimi Handle Cast() const { 861*b7893ccfSSadaf Ebrahimi #ifdef TYPESAFE_NONDISPATCHABLE_HANDLES 862*b7893ccfSSadaf Ebrahimi assert(type == VkHandleInfo<Handle>::kVulkanObjectType); 863*b7893ccfSSadaf Ebrahimi #endif // TYPESAFE_NONDISPATCHABLE_HANDLES 864*b7893ccfSSadaf Ebrahimi return CastFromUint64<Handle>(handle); 865*b7893ccfSSadaf Ebrahimi } 866*b7893ccfSSadaf Ebrahimi VulkanTypedHandle() : 867*b7893ccfSSadaf Ebrahimi handle(VK_NULL_HANDLE), 868*b7893ccfSSadaf Ebrahimi type(kVulkanObjectTypeUnknown) {} 869*b7893ccfSSadaf Ebrahimi }; ''') +'\n' 870*b7893ccfSSadaf Ebrahimi 871*b7893ccfSSadaf Ebrahimi return object_types_header 872*b7893ccfSSadaf Ebrahimi # 873*b7893ccfSSadaf Ebrahimi # Generate pNext handling function 874*b7893ccfSSadaf Ebrahimi def build_safe_struct_utility_funcs(self): 875*b7893ccfSSadaf Ebrahimi # Construct Safe-struct helper functions 876*b7893ccfSSadaf Ebrahimi 877*b7893ccfSSadaf Ebrahimi string_copy_proc = '\n\n' 878*b7893ccfSSadaf Ebrahimi string_copy_proc += 'char *SafeStringCopy(const char *in_string) {\n' 879*b7893ccfSSadaf Ebrahimi string_copy_proc += ' if (nullptr == in_string) return nullptr;\n' 880*b7893ccfSSadaf Ebrahimi string_copy_proc += ' char* dest = new char[std::strlen(in_string) + 1];\n' 881*b7893ccfSSadaf Ebrahimi string_copy_proc += ' return std::strcpy(dest, in_string);\n' 882*b7893ccfSSadaf Ebrahimi string_copy_proc += '}\n' 883*b7893ccfSSadaf Ebrahimi 884*b7893ccfSSadaf Ebrahimi build_pnext_proc = '\n' 885*b7893ccfSSadaf Ebrahimi build_pnext_proc += 'void *SafePnextCopy(const void *pNext) {\n' 886*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' if (!pNext) return nullptr;\n' 887*b7893ccfSSadaf Ebrahimi build_pnext_proc += '\n' 888*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' void *safe_pNext;\n' 889*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' const VkBaseOutStructure *header = reinterpret_cast<const VkBaseOutStructure *>(pNext);\n' 890*b7893ccfSSadaf Ebrahimi build_pnext_proc += '\n' 891*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' switch (header->sType) {\n' 892*b7893ccfSSadaf Ebrahimi # Add special-case code to copy beloved secret loader structs 893*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' // Special-case Loader Instance Struct passed to/from layer in pNext chain\n' 894*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: {\n' 895*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' VkLayerInstanceCreateInfo *struct_copy = new VkLayerInstanceCreateInfo;\n' 896*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' // TODO: Uses original VkLayerInstanceLink* chain, which should be okay for our uses\n' 897*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' memcpy(struct_copy, pNext, sizeof(VkLayerInstanceCreateInfo));\n' 898*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' struct_copy->pNext = SafePnextCopy(header->pNext);\n' 899*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' safe_pNext = struct_copy;\n' 900*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' break;\n' 901*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' }\n' 902*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' // Special-case Loader Device Struct passed to/from layer in pNext chain\n' 903*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO: {\n' 904*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' VkLayerDeviceCreateInfo *struct_copy = new VkLayerDeviceCreateInfo;\n' 905*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' // TODO: Uses original VkLayerDeviceLink*, which should be okay for our uses\n' 906*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' memcpy(struct_copy, pNext, sizeof(VkLayerDeviceCreateInfo));\n' 907*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' struct_copy->pNext = SafePnextCopy(header->pNext);\n' 908*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' safe_pNext = struct_copy;\n' 909*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' break;\n' 910*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' }\n' 911*b7893ccfSSadaf Ebrahimi 912*b7893ccfSSadaf Ebrahimi free_pnext_proc = '\n' 913*b7893ccfSSadaf Ebrahimi free_pnext_proc += 'void FreePnextChain(const void *pNext) {\n' 914*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' if (!pNext) return;\n' 915*b7893ccfSSadaf Ebrahimi free_pnext_proc += '\n' 916*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' auto header = reinterpret_cast<const VkBaseOutStructure *>(pNext);\n' 917*b7893ccfSSadaf Ebrahimi free_pnext_proc += '\n' 918*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' switch (header->sType) {\n' 919*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' // Special-case Loader Instance Struct passed to/from layer in pNext chain\n' 920*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO:\n' 921*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' FreePnextChain(header->pNext);\n' 922*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' delete reinterpret_cast<const VkLayerInstanceCreateInfo *>(pNext);\n' 923*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' break;\n' 924*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' // Special-case Loader Device Struct passed to/from layer in pNext chain\n' 925*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO:\n' 926*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' FreePnextChain(header->pNext);\n' 927*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' delete reinterpret_cast<const VkLayerDeviceCreateInfo *>(pNext);\n' 928*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' break;\n' 929*b7893ccfSSadaf Ebrahimi 930*b7893ccfSSadaf Ebrahimi chain_structs = tuple(s for s in self.structMembers if s.name in self.structextends_list) 931*b7893ccfSSadaf Ebrahimi ifdefs = sorted({cs.ifdef_protect for cs in chain_structs}, key = lambda i : i if i is not None else '') 932*b7893ccfSSadaf Ebrahimi for ifdef in ifdefs: 933*b7893ccfSSadaf Ebrahimi if ifdef is not None: 934*b7893ccfSSadaf Ebrahimi build_pnext_proc += '#ifdef %s\n' % ifdef 935*b7893ccfSSadaf Ebrahimi free_pnext_proc += '#ifdef %s\n' % ifdef 936*b7893ccfSSadaf Ebrahimi 937*b7893ccfSSadaf Ebrahimi assorted_chain_structs = tuple(s for s in chain_structs if s.ifdef_protect == ifdef) 938*b7893ccfSSadaf Ebrahimi for struct in assorted_chain_structs: 939*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' case %s:\n' % self.structTypes[struct.name].value 940*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' safe_pNext = new safe_%s(reinterpret_cast<const %s *>(pNext));\n' % (struct.name, struct.name) 941*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' break;\n' 942*b7893ccfSSadaf Ebrahimi 943*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' case %s:\n' % self.structTypes[struct.name].value 944*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' delete reinterpret_cast<const safe_%s *>(header);\n' % struct.name 945*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' break;\n' 946*b7893ccfSSadaf Ebrahimi 947*b7893ccfSSadaf Ebrahimi if ifdef is not None: 948*b7893ccfSSadaf Ebrahimi build_pnext_proc += '#endif // %s\n' % ifdef 949*b7893ccfSSadaf Ebrahimi free_pnext_proc += '#endif // %s\n' % ifdef 950*b7893ccfSSadaf Ebrahimi 951*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' default: // Encountered an unknown sType -- skip (do not copy) this entry in the chain\n' 952*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' safe_pNext = SafePnextCopy(header->pNext);\n' 953*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' break;\n' 954*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' }\n' 955*b7893ccfSSadaf Ebrahimi build_pnext_proc += '\n' 956*b7893ccfSSadaf Ebrahimi build_pnext_proc += ' return safe_pNext;\n' 957*b7893ccfSSadaf Ebrahimi build_pnext_proc += '}\n' 958*b7893ccfSSadaf Ebrahimi 959*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' default: // Encountered an unknown sType -- panic, there should be none such in safe chain\n' 960*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' assert(false);\n' 961*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' FreePnextChain(header->pNext);\n' 962*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' break;\n' 963*b7893ccfSSadaf Ebrahimi free_pnext_proc += ' }\n' 964*b7893ccfSSadaf Ebrahimi free_pnext_proc += '}\n' 965*b7893ccfSSadaf Ebrahimi 966*b7893ccfSSadaf Ebrahimi pnext_procs = string_copy_proc + build_pnext_proc + free_pnext_proc 967*b7893ccfSSadaf Ebrahimi return pnext_procs 968*b7893ccfSSadaf Ebrahimi # 969*b7893ccfSSadaf Ebrahimi # Determine if a structure needs a safe_struct helper function 970*b7893ccfSSadaf Ebrahimi # That is, it has an sType or one of its members is a pointer 971*b7893ccfSSadaf Ebrahimi def NeedSafeStruct(self, structure): 972*b7893ccfSSadaf Ebrahimi if 'VkBase' in structure.name: 973*b7893ccfSSadaf Ebrahimi return False 974*b7893ccfSSadaf Ebrahimi if 'sType' == structure.name: 975*b7893ccfSSadaf Ebrahimi return True 976*b7893ccfSSadaf Ebrahimi for member in structure.members: 977*b7893ccfSSadaf Ebrahimi if member.ispointer == True: 978*b7893ccfSSadaf Ebrahimi return True 979*b7893ccfSSadaf Ebrahimi return False 980*b7893ccfSSadaf Ebrahimi # 981*b7893ccfSSadaf Ebrahimi # Combine safe struct helper source file preamble with body text and return 982*b7893ccfSSadaf Ebrahimi def GenerateSafeStructHelperSource(self): 983*b7893ccfSSadaf Ebrahimi safe_struct_helper_source = '\n' 984*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '#include "vk_safe_struct.h"\n' 985*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '\n' 986*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '#include <string.h>\n' 987*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '#include <cassert>\n' 988*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '#include <cstring>\n' 989*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '\n' 990*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '#include <vulkan/vk_layer.h>\n' 991*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += '\n' 992*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += self.GenerateSafeStructSource() 993*b7893ccfSSadaf Ebrahimi safe_struct_helper_source += self.build_safe_struct_utility_funcs() 994*b7893ccfSSadaf Ebrahimi 995*b7893ccfSSadaf Ebrahimi return safe_struct_helper_source 996*b7893ccfSSadaf Ebrahimi # 997*b7893ccfSSadaf Ebrahimi # safe_struct source -- create bodies of safe struct helper functions 998*b7893ccfSSadaf Ebrahimi def GenerateSafeStructSource(self): 999*b7893ccfSSadaf Ebrahimi safe_struct_body = [] 1000*b7893ccfSSadaf Ebrahimi wsi_structs = ['VkXlibSurfaceCreateInfoKHR', 1001*b7893ccfSSadaf Ebrahimi 'VkXcbSurfaceCreateInfoKHR', 1002*b7893ccfSSadaf Ebrahimi 'VkWaylandSurfaceCreateInfoKHR', 1003*b7893ccfSSadaf Ebrahimi 'VkAndroidSurfaceCreateInfoKHR', 1004*b7893ccfSSadaf Ebrahimi 'VkWin32SurfaceCreateInfoKHR' 1005*b7893ccfSSadaf Ebrahimi ] 1006*b7893ccfSSadaf Ebrahimi 1007*b7893ccfSSadaf Ebrahimi # For abstract types just want to save the pointer away 1008*b7893ccfSSadaf Ebrahimi # since we cannot make a copy. 1009*b7893ccfSSadaf Ebrahimi abstract_types = ['AHardwareBuffer', 1010*b7893ccfSSadaf Ebrahimi 'ANativeWindow', 1011*b7893ccfSSadaf Ebrahimi ] 1012*b7893ccfSSadaf Ebrahimi for item in self.structMembers: 1013*b7893ccfSSadaf Ebrahimi if self.NeedSafeStruct(item) == False: 1014*b7893ccfSSadaf Ebrahimi continue 1015*b7893ccfSSadaf Ebrahimi if item.name in wsi_structs: 1016*b7893ccfSSadaf Ebrahimi continue 1017*b7893ccfSSadaf Ebrahimi if item.ifdef_protect is not None: 1018*b7893ccfSSadaf Ebrahimi safe_struct_body.append("#ifdef %s\n" % item.ifdef_protect) 1019*b7893ccfSSadaf Ebrahimi ss_name = "safe_%s" % item.name 1020*b7893ccfSSadaf Ebrahimi init_list = '' # list of members in struct constructor initializer 1021*b7893ccfSSadaf Ebrahimi default_init_list = '' # Default constructor just inits ptrs to nullptr in initializer 1022*b7893ccfSSadaf Ebrahimi init_func_txt = '' # Txt for initialize() function that takes struct ptr and inits members 1023*b7893ccfSSadaf Ebrahimi construct_txt = '' # Body of constuctor as well as body of initialize() func following init_func_txt 1024*b7893ccfSSadaf Ebrahimi destruct_txt = '' 1025*b7893ccfSSadaf Ebrahimi 1026*b7893ccfSSadaf Ebrahimi custom_construct_txt = { 1027*b7893ccfSSadaf Ebrahimi # VkWriteDescriptorSet is special case because pointers may be non-null but ignored 1028*b7893ccfSSadaf Ebrahimi 'VkWriteDescriptorSet' : 1029*b7893ccfSSadaf Ebrahimi ' switch (descriptorType) {\n' 1030*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_SAMPLER:\n' 1031*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:\n' 1032*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:\n' 1033*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:\n' 1034*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:\n' 1035*b7893ccfSSadaf Ebrahimi ' if (descriptorCount && in_struct->pImageInfo) {\n' 1036*b7893ccfSSadaf Ebrahimi ' pImageInfo = new VkDescriptorImageInfo[descriptorCount];\n' 1037*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < descriptorCount; ++i) {\n' 1038*b7893ccfSSadaf Ebrahimi ' pImageInfo[i] = in_struct->pImageInfo[i];\n' 1039*b7893ccfSSadaf Ebrahimi ' }\n' 1040*b7893ccfSSadaf Ebrahimi ' }\n' 1041*b7893ccfSSadaf Ebrahimi ' break;\n' 1042*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:\n' 1043*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:\n' 1044*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:\n' 1045*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:\n' 1046*b7893ccfSSadaf Ebrahimi ' if (descriptorCount && in_struct->pBufferInfo) {\n' 1047*b7893ccfSSadaf Ebrahimi ' pBufferInfo = new VkDescriptorBufferInfo[descriptorCount];\n' 1048*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < descriptorCount; ++i) {\n' 1049*b7893ccfSSadaf Ebrahimi ' pBufferInfo[i] = in_struct->pBufferInfo[i];\n' 1050*b7893ccfSSadaf Ebrahimi ' }\n' 1051*b7893ccfSSadaf Ebrahimi ' }\n' 1052*b7893ccfSSadaf Ebrahimi ' break;\n' 1053*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:\n' 1054*b7893ccfSSadaf Ebrahimi ' case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:\n' 1055*b7893ccfSSadaf Ebrahimi ' if (descriptorCount && in_struct->pTexelBufferView) {\n' 1056*b7893ccfSSadaf Ebrahimi ' pTexelBufferView = new VkBufferView[descriptorCount];\n' 1057*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < descriptorCount; ++i) {\n' 1058*b7893ccfSSadaf Ebrahimi ' pTexelBufferView[i] = in_struct->pTexelBufferView[i];\n' 1059*b7893ccfSSadaf Ebrahimi ' }\n' 1060*b7893ccfSSadaf Ebrahimi ' }\n' 1061*b7893ccfSSadaf Ebrahimi ' break;\n' 1062*b7893ccfSSadaf Ebrahimi ' default:\n' 1063*b7893ccfSSadaf Ebrahimi ' break;\n' 1064*b7893ccfSSadaf Ebrahimi ' }\n', 1065*b7893ccfSSadaf Ebrahimi 'VkShaderModuleCreateInfo' : 1066*b7893ccfSSadaf Ebrahimi ' if (in_struct->pCode) {\n' 1067*b7893ccfSSadaf Ebrahimi ' pCode = reinterpret_cast<uint32_t *>(new uint8_t[codeSize]);\n' 1068*b7893ccfSSadaf Ebrahimi ' memcpy((void *)pCode, (void *)in_struct->pCode, codeSize);\n' 1069*b7893ccfSSadaf Ebrahimi ' }\n', 1070*b7893ccfSSadaf Ebrahimi # VkGraphicsPipelineCreateInfo is special case because its pointers may be non-null but ignored 1071*b7893ccfSSadaf Ebrahimi 'VkGraphicsPipelineCreateInfo' : 1072*b7893ccfSSadaf Ebrahimi ' if (stageCount && in_struct->pStages) {\n' 1073*b7893ccfSSadaf Ebrahimi ' pStages = new safe_VkPipelineShaderStageCreateInfo[stageCount];\n' 1074*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < stageCount; ++i) {\n' 1075*b7893ccfSSadaf Ebrahimi ' pStages[i].initialize(&in_struct->pStages[i]);\n' 1076*b7893ccfSSadaf Ebrahimi ' }\n' 1077*b7893ccfSSadaf Ebrahimi ' }\n' 1078*b7893ccfSSadaf Ebrahimi ' if (in_struct->pVertexInputState)\n' 1079*b7893ccfSSadaf Ebrahimi ' pVertexInputState = new safe_VkPipelineVertexInputStateCreateInfo(in_struct->pVertexInputState);\n' 1080*b7893ccfSSadaf Ebrahimi ' else\n' 1081*b7893ccfSSadaf Ebrahimi ' pVertexInputState = NULL;\n' 1082*b7893ccfSSadaf Ebrahimi ' if (in_struct->pInputAssemblyState)\n' 1083*b7893ccfSSadaf Ebrahimi ' pInputAssemblyState = new safe_VkPipelineInputAssemblyStateCreateInfo(in_struct->pInputAssemblyState);\n' 1084*b7893ccfSSadaf Ebrahimi ' else\n' 1085*b7893ccfSSadaf Ebrahimi ' pInputAssemblyState = NULL;\n' 1086*b7893ccfSSadaf Ebrahimi ' bool has_tessellation_stage = false;\n' 1087*b7893ccfSSadaf Ebrahimi ' if (stageCount && pStages)\n' 1088*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < stageCount && !has_tessellation_stage; ++i)\n' 1089*b7893ccfSSadaf Ebrahimi ' if (pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)\n' 1090*b7893ccfSSadaf Ebrahimi ' has_tessellation_stage = true;\n' 1091*b7893ccfSSadaf Ebrahimi ' if (in_struct->pTessellationState && has_tessellation_stage)\n' 1092*b7893ccfSSadaf Ebrahimi ' pTessellationState = new safe_VkPipelineTessellationStateCreateInfo(in_struct->pTessellationState);\n' 1093*b7893ccfSSadaf Ebrahimi ' else\n' 1094*b7893ccfSSadaf Ebrahimi ' pTessellationState = NULL; // original pTessellationState pointer ignored\n' 1095*b7893ccfSSadaf Ebrahimi ' bool has_rasterization = in_struct->pRasterizationState ? !in_struct->pRasterizationState->rasterizerDiscardEnable : false;\n' 1096*b7893ccfSSadaf Ebrahimi ' if (in_struct->pViewportState && has_rasterization) {\n' 1097*b7893ccfSSadaf Ebrahimi ' bool is_dynamic_viewports = false;\n' 1098*b7893ccfSSadaf Ebrahimi ' bool is_dynamic_scissors = false;\n' 1099*b7893ccfSSadaf Ebrahimi ' if (in_struct->pDynamicState && in_struct->pDynamicState->pDynamicStates) {\n' 1100*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < in_struct->pDynamicState->dynamicStateCount && !is_dynamic_viewports; ++i)\n' 1101*b7893ccfSSadaf Ebrahimi ' if (in_struct->pDynamicState->pDynamicStates[i] == VK_DYNAMIC_STATE_VIEWPORT)\n' 1102*b7893ccfSSadaf Ebrahimi ' is_dynamic_viewports = true;\n' 1103*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < in_struct->pDynamicState->dynamicStateCount && !is_dynamic_scissors; ++i)\n' 1104*b7893ccfSSadaf Ebrahimi ' if (in_struct->pDynamicState->pDynamicStates[i] == VK_DYNAMIC_STATE_SCISSOR)\n' 1105*b7893ccfSSadaf Ebrahimi ' is_dynamic_scissors = true;\n' 1106*b7893ccfSSadaf Ebrahimi ' }\n' 1107*b7893ccfSSadaf Ebrahimi ' pViewportState = new safe_VkPipelineViewportStateCreateInfo(in_struct->pViewportState, is_dynamic_viewports, is_dynamic_scissors);\n' 1108*b7893ccfSSadaf Ebrahimi ' } else\n' 1109*b7893ccfSSadaf Ebrahimi ' pViewportState = NULL; // original pViewportState pointer ignored\n' 1110*b7893ccfSSadaf Ebrahimi ' if (in_struct->pRasterizationState)\n' 1111*b7893ccfSSadaf Ebrahimi ' pRasterizationState = new safe_VkPipelineRasterizationStateCreateInfo(in_struct->pRasterizationState);\n' 1112*b7893ccfSSadaf Ebrahimi ' else\n' 1113*b7893ccfSSadaf Ebrahimi ' pRasterizationState = NULL;\n' 1114*b7893ccfSSadaf Ebrahimi ' if (in_struct->pMultisampleState && has_rasterization)\n' 1115*b7893ccfSSadaf Ebrahimi ' pMultisampleState = new safe_VkPipelineMultisampleStateCreateInfo(in_struct->pMultisampleState);\n' 1116*b7893ccfSSadaf Ebrahimi ' else\n' 1117*b7893ccfSSadaf Ebrahimi ' pMultisampleState = NULL; // original pMultisampleState pointer ignored\n' 1118*b7893ccfSSadaf Ebrahimi ' // needs a tracked subpass state uses_depthstencil_attachment\n' 1119*b7893ccfSSadaf Ebrahimi ' if (in_struct->pDepthStencilState && has_rasterization && uses_depthstencil_attachment)\n' 1120*b7893ccfSSadaf Ebrahimi ' pDepthStencilState = new safe_VkPipelineDepthStencilStateCreateInfo(in_struct->pDepthStencilState);\n' 1121*b7893ccfSSadaf Ebrahimi ' else\n' 1122*b7893ccfSSadaf Ebrahimi ' pDepthStencilState = NULL; // original pDepthStencilState pointer ignored\n' 1123*b7893ccfSSadaf Ebrahimi ' // needs a tracked subpass state usesColorAttachment\n' 1124*b7893ccfSSadaf Ebrahimi ' if (in_struct->pColorBlendState && has_rasterization && uses_color_attachment)\n' 1125*b7893ccfSSadaf Ebrahimi ' pColorBlendState = new safe_VkPipelineColorBlendStateCreateInfo(in_struct->pColorBlendState);\n' 1126*b7893ccfSSadaf Ebrahimi ' else\n' 1127*b7893ccfSSadaf Ebrahimi ' pColorBlendState = NULL; // original pColorBlendState pointer ignored\n' 1128*b7893ccfSSadaf Ebrahimi ' if (in_struct->pDynamicState)\n' 1129*b7893ccfSSadaf Ebrahimi ' pDynamicState = new safe_VkPipelineDynamicStateCreateInfo(in_struct->pDynamicState);\n' 1130*b7893ccfSSadaf Ebrahimi ' else\n' 1131*b7893ccfSSadaf Ebrahimi ' pDynamicState = NULL;\n', 1132*b7893ccfSSadaf Ebrahimi # VkPipelineViewportStateCreateInfo is special case because its pointers may be non-null but ignored 1133*b7893ccfSSadaf Ebrahimi 'VkPipelineViewportStateCreateInfo' : 1134*b7893ccfSSadaf Ebrahimi ' if (in_struct->pViewports && !is_dynamic_viewports) {\n' 1135*b7893ccfSSadaf Ebrahimi ' pViewports = new VkViewport[in_struct->viewportCount];\n' 1136*b7893ccfSSadaf Ebrahimi ' memcpy ((void *)pViewports, (void *)in_struct->pViewports, sizeof(VkViewport)*in_struct->viewportCount);\n' 1137*b7893ccfSSadaf Ebrahimi ' }\n' 1138*b7893ccfSSadaf Ebrahimi ' else\n' 1139*b7893ccfSSadaf Ebrahimi ' pViewports = NULL;\n' 1140*b7893ccfSSadaf Ebrahimi ' if (in_struct->pScissors && !is_dynamic_scissors) {\n' 1141*b7893ccfSSadaf Ebrahimi ' pScissors = new VkRect2D[in_struct->scissorCount];\n' 1142*b7893ccfSSadaf Ebrahimi ' memcpy ((void *)pScissors, (void *)in_struct->pScissors, sizeof(VkRect2D)*in_struct->scissorCount);\n' 1143*b7893ccfSSadaf Ebrahimi ' }\n' 1144*b7893ccfSSadaf Ebrahimi ' else\n' 1145*b7893ccfSSadaf Ebrahimi ' pScissors = NULL;\n', 1146*b7893ccfSSadaf Ebrahimi # VkDescriptorSetLayoutBinding is special case because its pImmutableSamplers pointer may be non-null but ignored 1147*b7893ccfSSadaf Ebrahimi 'VkDescriptorSetLayoutBinding' : 1148*b7893ccfSSadaf Ebrahimi ' const bool sampler_type = in_struct->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || in_struct->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;\n' 1149*b7893ccfSSadaf Ebrahimi ' if (descriptorCount && in_struct->pImmutableSamplers && sampler_type) {\n' 1150*b7893ccfSSadaf Ebrahimi ' pImmutableSamplers = new VkSampler[descriptorCount];\n' 1151*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < descriptorCount; ++i) {\n' 1152*b7893ccfSSadaf Ebrahimi ' pImmutableSamplers[i] = in_struct->pImmutableSamplers[i];\n' 1153*b7893ccfSSadaf Ebrahimi ' }\n' 1154*b7893ccfSSadaf Ebrahimi ' }\n', 1155*b7893ccfSSadaf Ebrahimi } 1156*b7893ccfSSadaf Ebrahimi 1157*b7893ccfSSadaf Ebrahimi custom_copy_txt = { 1158*b7893ccfSSadaf Ebrahimi # VkGraphicsPipelineCreateInfo is special case because it has custom construct parameters 1159*b7893ccfSSadaf Ebrahimi 'VkGraphicsPipelineCreateInfo' : 1160*b7893ccfSSadaf Ebrahimi ' pNext = SafePnextCopy(src.pNext);\n' 1161*b7893ccfSSadaf Ebrahimi ' if (stageCount && src.pStages) {\n' 1162*b7893ccfSSadaf Ebrahimi ' pStages = new safe_VkPipelineShaderStageCreateInfo[stageCount];\n' 1163*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < stageCount; ++i) {\n' 1164*b7893ccfSSadaf Ebrahimi ' pStages[i].initialize(&src.pStages[i]);\n' 1165*b7893ccfSSadaf Ebrahimi ' }\n' 1166*b7893ccfSSadaf Ebrahimi ' }\n' 1167*b7893ccfSSadaf Ebrahimi ' if (src.pVertexInputState)\n' 1168*b7893ccfSSadaf Ebrahimi ' pVertexInputState = new safe_VkPipelineVertexInputStateCreateInfo(*src.pVertexInputState);\n' 1169*b7893ccfSSadaf Ebrahimi ' else\n' 1170*b7893ccfSSadaf Ebrahimi ' pVertexInputState = NULL;\n' 1171*b7893ccfSSadaf Ebrahimi ' if (src.pInputAssemblyState)\n' 1172*b7893ccfSSadaf Ebrahimi ' pInputAssemblyState = new safe_VkPipelineInputAssemblyStateCreateInfo(*src.pInputAssemblyState);\n' 1173*b7893ccfSSadaf Ebrahimi ' else\n' 1174*b7893ccfSSadaf Ebrahimi ' pInputAssemblyState = NULL;\n' 1175*b7893ccfSSadaf Ebrahimi ' bool has_tessellation_stage = false;\n' 1176*b7893ccfSSadaf Ebrahimi ' if (stageCount && pStages)\n' 1177*b7893ccfSSadaf Ebrahimi ' for (uint32_t i = 0; i < stageCount && !has_tessellation_stage; ++i)\n' 1178*b7893ccfSSadaf Ebrahimi ' if (pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)\n' 1179*b7893ccfSSadaf Ebrahimi ' has_tessellation_stage = true;\n' 1180*b7893ccfSSadaf Ebrahimi ' if (src.pTessellationState && has_tessellation_stage)\n' 1181*b7893ccfSSadaf Ebrahimi ' pTessellationState = new safe_VkPipelineTessellationStateCreateInfo(*src.pTessellationState);\n' 1182*b7893ccfSSadaf Ebrahimi ' else\n' 1183*b7893ccfSSadaf Ebrahimi ' pTessellationState = NULL; // original pTessellationState pointer ignored\n' 1184*b7893ccfSSadaf Ebrahimi ' bool has_rasterization = src.pRasterizationState ? !src.pRasterizationState->rasterizerDiscardEnable : false;\n' 1185*b7893ccfSSadaf Ebrahimi ' if (src.pViewportState && has_rasterization) {\n' 1186*b7893ccfSSadaf Ebrahimi ' pViewportState = new safe_VkPipelineViewportStateCreateInfo(*src.pViewportState);\n' 1187*b7893ccfSSadaf Ebrahimi ' } else\n' 1188*b7893ccfSSadaf Ebrahimi ' pViewportState = NULL; // original pViewportState pointer ignored\n' 1189*b7893ccfSSadaf Ebrahimi ' if (src.pRasterizationState)\n' 1190*b7893ccfSSadaf Ebrahimi ' pRasterizationState = new safe_VkPipelineRasterizationStateCreateInfo(*src.pRasterizationState);\n' 1191*b7893ccfSSadaf Ebrahimi ' else\n' 1192*b7893ccfSSadaf Ebrahimi ' pRasterizationState = NULL;\n' 1193*b7893ccfSSadaf Ebrahimi ' if (src.pMultisampleState && has_rasterization)\n' 1194*b7893ccfSSadaf Ebrahimi ' pMultisampleState = new safe_VkPipelineMultisampleStateCreateInfo(*src.pMultisampleState);\n' 1195*b7893ccfSSadaf Ebrahimi ' else\n' 1196*b7893ccfSSadaf Ebrahimi ' pMultisampleState = NULL; // original pMultisampleState pointer ignored\n' 1197*b7893ccfSSadaf Ebrahimi ' if (src.pDepthStencilState && has_rasterization)\n' 1198*b7893ccfSSadaf Ebrahimi ' pDepthStencilState = new safe_VkPipelineDepthStencilStateCreateInfo(*src.pDepthStencilState);\n' 1199*b7893ccfSSadaf Ebrahimi ' else\n' 1200*b7893ccfSSadaf Ebrahimi ' pDepthStencilState = NULL; // original pDepthStencilState pointer ignored\n' 1201*b7893ccfSSadaf Ebrahimi ' if (src.pColorBlendState && has_rasterization)\n' 1202*b7893ccfSSadaf Ebrahimi ' pColorBlendState = new safe_VkPipelineColorBlendStateCreateInfo(*src.pColorBlendState);\n' 1203*b7893ccfSSadaf Ebrahimi ' else\n' 1204*b7893ccfSSadaf Ebrahimi ' pColorBlendState = NULL; // original pColorBlendState pointer ignored\n' 1205*b7893ccfSSadaf Ebrahimi ' if (src.pDynamicState)\n' 1206*b7893ccfSSadaf Ebrahimi ' pDynamicState = new safe_VkPipelineDynamicStateCreateInfo(*src.pDynamicState);\n' 1207*b7893ccfSSadaf Ebrahimi ' else\n' 1208*b7893ccfSSadaf Ebrahimi ' pDynamicState = NULL;\n', 1209*b7893ccfSSadaf Ebrahimi # VkPipelineViewportStateCreateInfo is special case because it has custom construct parameters 1210*b7893ccfSSadaf Ebrahimi 'VkPipelineViewportStateCreateInfo' : 1211*b7893ccfSSadaf Ebrahimi ' pNext = SafePnextCopy(src.pNext);\n' 1212*b7893ccfSSadaf Ebrahimi ' if (src.pViewports) {\n' 1213*b7893ccfSSadaf Ebrahimi ' pViewports = new VkViewport[src.viewportCount];\n' 1214*b7893ccfSSadaf Ebrahimi ' memcpy ((void *)pViewports, (void *)src.pViewports, sizeof(VkViewport)*src.viewportCount);\n' 1215*b7893ccfSSadaf Ebrahimi ' }\n' 1216*b7893ccfSSadaf Ebrahimi ' else\n' 1217*b7893ccfSSadaf Ebrahimi ' pViewports = NULL;\n' 1218*b7893ccfSSadaf Ebrahimi ' if (src.pScissors) {\n' 1219*b7893ccfSSadaf Ebrahimi ' pScissors = new VkRect2D[src.scissorCount];\n' 1220*b7893ccfSSadaf Ebrahimi ' memcpy ((void *)pScissors, (void *)src.pScissors, sizeof(VkRect2D)*src.scissorCount);\n' 1221*b7893ccfSSadaf Ebrahimi ' }\n' 1222*b7893ccfSSadaf Ebrahimi ' else\n' 1223*b7893ccfSSadaf Ebrahimi ' pScissors = NULL;\n', 1224*b7893ccfSSadaf Ebrahimi } 1225*b7893ccfSSadaf Ebrahimi 1226*b7893ccfSSadaf Ebrahimi custom_destruct_txt = {'VkShaderModuleCreateInfo' : 1227*b7893ccfSSadaf Ebrahimi ' if (pCode)\n' 1228*b7893ccfSSadaf Ebrahimi ' delete[] reinterpret_cast<const uint8_t *>(pCode);\n' } 1229*b7893ccfSSadaf Ebrahimi copy_pnext = '' 1230*b7893ccfSSadaf Ebrahimi copy_strings = '' 1231*b7893ccfSSadaf Ebrahimi for member in item.members: 1232*b7893ccfSSadaf Ebrahimi m_type = member.type 1233*b7893ccfSSadaf Ebrahimi if member.name == 'pNext': 1234*b7893ccfSSadaf Ebrahimi copy_pnext = ' pNext = SafePnextCopy(in_struct->pNext);\n' 1235*b7893ccfSSadaf Ebrahimi if member.type in self.structNames: 1236*b7893ccfSSadaf Ebrahimi member_index = next((i for i, v in enumerate(self.structMembers) if v[0] == member.type), None) 1237*b7893ccfSSadaf Ebrahimi if member_index is not None and self.NeedSafeStruct(self.structMembers[member_index]) == True: 1238*b7893ccfSSadaf Ebrahimi m_type = 'safe_%s' % member.type 1239*b7893ccfSSadaf Ebrahimi if member.ispointer and 'safe_' not in m_type and self.TypeContainsObjectHandle(member.type, False) == False: 1240*b7893ccfSSadaf Ebrahimi # Ptr types w/o a safe_struct, for non-null case need to allocate new ptr and copy data in 1241*b7893ccfSSadaf Ebrahimi if m_type in ['void', 'char']: 1242*b7893ccfSSadaf Ebrahimi if member.name != 'pNext': 1243*b7893ccfSSadaf Ebrahimi if m_type == 'char': 1244*b7893ccfSSadaf Ebrahimi # Create deep copies of strings 1245*b7893ccfSSadaf Ebrahimi if member.len: 1246*b7893ccfSSadaf Ebrahimi copy_strings += ' char **tmp_%s = new char *[in_struct->%s];\n' % (member.name, member.len) 1247*b7893ccfSSadaf Ebrahimi copy_strings += ' for (uint32_t i = 0; i < %s; ++i) {\n' % member.len 1248*b7893ccfSSadaf Ebrahimi copy_strings += ' tmp_%s[i] = SafeStringCopy(in_struct->%s[i]);\n' % (member.name, member.name) 1249*b7893ccfSSadaf Ebrahimi copy_strings += ' }\n' 1250*b7893ccfSSadaf Ebrahimi copy_strings += ' %s = tmp_%s;\n' % (member.name, member.name) 1251*b7893ccfSSadaf Ebrahimi 1252*b7893ccfSSadaf Ebrahimi destruct_txt += ' if (%s) {\n' % member.name 1253*b7893ccfSSadaf Ebrahimi destruct_txt += ' for (uint32_t i = 0; i < %s; ++i) {\n' % member.len 1254*b7893ccfSSadaf Ebrahimi destruct_txt += ' delete [] %s[i];\n' % member.name 1255*b7893ccfSSadaf Ebrahimi destruct_txt += ' }\n' 1256*b7893ccfSSadaf Ebrahimi destruct_txt += ' delete [] %s;\n' % member.name 1257*b7893ccfSSadaf Ebrahimi destruct_txt += ' }\n' 1258*b7893ccfSSadaf Ebrahimi else: 1259*b7893ccfSSadaf Ebrahimi copy_strings += ' %s = SafeStringCopy(in_struct->%s);\n' % (member.name, member.name) 1260*b7893ccfSSadaf Ebrahimi destruct_txt += ' if (%s) delete [] %s;\n' % (member.name, member.name) 1261*b7893ccfSSadaf Ebrahimi else: 1262*b7893ccfSSadaf Ebrahimi # For these exceptions just copy initial value over for now 1263*b7893ccfSSadaf Ebrahimi init_list += '\n %s(in_struct->%s),' % (member.name, member.name) 1264*b7893ccfSSadaf Ebrahimi init_func_txt += ' %s = in_struct->%s;\n' % (member.name, member.name) 1265*b7893ccfSSadaf Ebrahimi default_init_list += '\n %s(nullptr),' % (member.name) 1266*b7893ccfSSadaf Ebrahimi else: 1267*b7893ccfSSadaf Ebrahimi default_init_list += '\n %s(nullptr),' % (member.name) 1268*b7893ccfSSadaf Ebrahimi init_list += '\n %s(nullptr),' % (member.name) 1269*b7893ccfSSadaf Ebrahimi if m_type in abstract_types: 1270*b7893ccfSSadaf Ebrahimi construct_txt += ' %s = in_struct->%s;\n' % (member.name, member.name) 1271*b7893ccfSSadaf Ebrahimi else: 1272*b7893ccfSSadaf Ebrahimi init_func_txt += ' %s = nullptr;\n' % (member.name) 1273*b7893ccfSSadaf Ebrahimi if not member.isstaticarray and (member.len is None or '/' in member.len): 1274*b7893ccfSSadaf Ebrahimi construct_txt += ' if (in_struct->%s) {\n' % member.name 1275*b7893ccfSSadaf Ebrahimi construct_txt += ' %s = new %s(*in_struct->%s);\n' % (member.name, m_type, member.name) 1276*b7893ccfSSadaf Ebrahimi construct_txt += ' }\n' 1277*b7893ccfSSadaf Ebrahimi destruct_txt += ' if (%s)\n' % member.name 1278*b7893ccfSSadaf Ebrahimi destruct_txt += ' delete %s;\n' % member.name 1279*b7893ccfSSadaf Ebrahimi else: 1280*b7893ccfSSadaf Ebrahimi construct_txt += ' if (in_struct->%s) {\n' % member.name 1281*b7893ccfSSadaf Ebrahimi construct_txt += ' %s = new %s[in_struct->%s];\n' % (member.name, m_type, member.len) 1282*b7893ccfSSadaf Ebrahimi construct_txt += ' memcpy ((void *)%s, (void *)in_struct->%s, sizeof(%s)*in_struct->%s);\n' % (member.name, member.name, m_type, member.len) 1283*b7893ccfSSadaf Ebrahimi construct_txt += ' }\n' 1284*b7893ccfSSadaf Ebrahimi destruct_txt += ' if (%s)\n' % member.name 1285*b7893ccfSSadaf Ebrahimi destruct_txt += ' delete[] %s;\n' % member.name 1286*b7893ccfSSadaf Ebrahimi elif member.isstaticarray or member.len is not None: 1287*b7893ccfSSadaf Ebrahimi if member.len is None: 1288*b7893ccfSSadaf Ebrahimi # Extract length of static array by grabbing val between [] 1289*b7893ccfSSadaf Ebrahimi static_array_size = re.match(r"[^[]*\[([^]]*)\]", member.cdecl) 1290*b7893ccfSSadaf Ebrahimi construct_txt += ' for (uint32_t i = 0; i < %s; ++i) {\n' % static_array_size.group(1) 1291*b7893ccfSSadaf Ebrahimi construct_txt += ' %s[i] = in_struct->%s[i];\n' % (member.name, member.name) 1292*b7893ccfSSadaf Ebrahimi construct_txt += ' }\n' 1293*b7893ccfSSadaf Ebrahimi else: 1294*b7893ccfSSadaf Ebrahimi # Init array ptr to NULL 1295*b7893ccfSSadaf Ebrahimi default_init_list += '\n %s(nullptr),' % member.name 1296*b7893ccfSSadaf Ebrahimi init_list += '\n %s(nullptr),' % member.name 1297*b7893ccfSSadaf Ebrahimi init_func_txt += ' %s = nullptr;\n' % member.name 1298*b7893ccfSSadaf Ebrahimi array_element = 'in_struct->%s[i]' % member.name 1299*b7893ccfSSadaf Ebrahimi if member.type in self.structNames: 1300*b7893ccfSSadaf Ebrahimi member_index = next((i for i, v in enumerate(self.structMembers) if v[0] == member.type), None) 1301*b7893ccfSSadaf Ebrahimi if member_index is not None and self.NeedSafeStruct(self.structMembers[member_index]) == True: 1302*b7893ccfSSadaf Ebrahimi array_element = '%s(&in_struct->safe_%s[i])' % (member.type, member.name) 1303*b7893ccfSSadaf Ebrahimi construct_txt += ' if (%s && in_struct->%s) {\n' % (member.len, member.name) 1304*b7893ccfSSadaf Ebrahimi construct_txt += ' %s = new %s[%s];\n' % (member.name, m_type, member.len) 1305*b7893ccfSSadaf Ebrahimi destruct_txt += ' if (%s)\n' % member.name 1306*b7893ccfSSadaf Ebrahimi destruct_txt += ' delete[] %s;\n' % member.name 1307*b7893ccfSSadaf Ebrahimi construct_txt += ' for (uint32_t i = 0; i < %s; ++i) {\n' % (member.len) 1308*b7893ccfSSadaf Ebrahimi if 'safe_' in m_type: 1309*b7893ccfSSadaf Ebrahimi construct_txt += ' %s[i].initialize(&in_struct->%s[i]);\n' % (member.name, member.name) 1310*b7893ccfSSadaf Ebrahimi else: 1311*b7893ccfSSadaf Ebrahimi construct_txt += ' %s[i] = %s;\n' % (member.name, array_element) 1312*b7893ccfSSadaf Ebrahimi construct_txt += ' }\n' 1313*b7893ccfSSadaf Ebrahimi construct_txt += ' }\n' 1314*b7893ccfSSadaf Ebrahimi elif member.ispointer == True: 1315*b7893ccfSSadaf Ebrahimi default_init_list += '\n %s(nullptr),' % (member.name) 1316*b7893ccfSSadaf Ebrahimi init_list += '\n %s(nullptr),' % (member.name) 1317*b7893ccfSSadaf Ebrahimi init_func_txt += ' %s = nullptr;\n' % (member.name) 1318*b7893ccfSSadaf Ebrahimi construct_txt += ' if (in_struct->%s)\n' % member.name 1319*b7893ccfSSadaf Ebrahimi construct_txt += ' %s = new %s(in_struct->%s);\n' % (member.name, m_type, member.name) 1320*b7893ccfSSadaf Ebrahimi destruct_txt += ' if (%s)\n' % member.name 1321*b7893ccfSSadaf Ebrahimi destruct_txt += ' delete %s;\n' % member.name 1322*b7893ccfSSadaf Ebrahimi elif 'safe_' in m_type: 1323*b7893ccfSSadaf Ebrahimi init_list += '\n %s(&in_struct->%s),' % (member.name, member.name) 1324*b7893ccfSSadaf Ebrahimi init_func_txt += ' %s.initialize(&in_struct->%s);\n' % (member.name, member.name) 1325*b7893ccfSSadaf Ebrahimi else: 1326*b7893ccfSSadaf Ebrahimi init_list += '\n %s(in_struct->%s),' % (member.name, member.name) 1327*b7893ccfSSadaf Ebrahimi init_func_txt += ' %s = in_struct->%s;\n' % (member.name, member.name) 1328*b7893ccfSSadaf Ebrahimi if '' != init_list: 1329*b7893ccfSSadaf Ebrahimi init_list = init_list[:-1] # hack off final comma 1330*b7893ccfSSadaf Ebrahimi 1331*b7893ccfSSadaf Ebrahimi 1332*b7893ccfSSadaf Ebrahimi if item.name in custom_construct_txt: 1333*b7893ccfSSadaf Ebrahimi construct_txt = custom_construct_txt[item.name] 1334*b7893ccfSSadaf Ebrahimi 1335*b7893ccfSSadaf Ebrahimi construct_txt = copy_pnext + copy_strings + construct_txt 1336*b7893ccfSSadaf Ebrahimi 1337*b7893ccfSSadaf Ebrahimi if item.name in custom_destruct_txt: 1338*b7893ccfSSadaf Ebrahimi destruct_txt = custom_destruct_txt[item.name] 1339*b7893ccfSSadaf Ebrahimi 1340*b7893ccfSSadaf Ebrahimi if copy_pnext: 1341*b7893ccfSSadaf Ebrahimi destruct_txt += ' if (pNext)\n FreePnextChain(pNext);\n' 1342*b7893ccfSSadaf Ebrahimi 1343*b7893ccfSSadaf Ebrahimi safe_struct_body.append("\n%s::%s(const %s* in_struct%s) :%s\n{\n%s}" % (ss_name, ss_name, item.name, self.custom_construct_params.get(item.name, ''), init_list, construct_txt)) 1344*b7893ccfSSadaf Ebrahimi if '' != default_init_list: 1345*b7893ccfSSadaf Ebrahimi default_init_list = " :%s" % (default_init_list[:-1]) 1346*b7893ccfSSadaf Ebrahimi safe_struct_body.append("\n%s::%s()%s\n{}" % (ss_name, ss_name, default_init_list)) 1347*b7893ccfSSadaf Ebrahimi # Create slight variation of init and construct txt for copy constructor that takes a src object reference vs. struct ptr 1348*b7893ccfSSadaf Ebrahimi copy_construct_init = init_func_txt.replace('in_struct->', 'src.') 1349*b7893ccfSSadaf Ebrahimi copy_construct_txt = construct_txt.replace(' (in_struct->', ' (src.') # Exclude 'if' blocks from next line 1350*b7893ccfSSadaf Ebrahimi copy_construct_txt = construct_txt.replace(' (in_struct->', ' (src.') # Exclude 'if' blocks from next line 1351*b7893ccfSSadaf Ebrahimi copy_construct_txt = re.sub('(new \\w+)\\(in_struct->', '\\1(*src.', construct_txt) # Pass object to copy constructors 1352*b7893ccfSSadaf Ebrahimi copy_construct_txt = copy_construct_txt.replace('in_struct->', 'src.') # Modify remaining struct refs for src object 1353*b7893ccfSSadaf Ebrahimi if item.name in custom_copy_txt: 1354*b7893ccfSSadaf Ebrahimi copy_construct_txt = custom_copy_txt[item.name] 1355*b7893ccfSSadaf Ebrahimi copy_assign_txt = ' if (&src == this) return *this;\n\n' + destruct_txt + '\n' + copy_construct_init + copy_construct_txt + '\n return *this;' 1356*b7893ccfSSadaf Ebrahimi safe_struct_body.append("\n%s::%s(const %s& src)\n{\n%s%s}" % (ss_name, ss_name, ss_name, copy_construct_init, copy_construct_txt)) # Copy constructor 1357*b7893ccfSSadaf Ebrahimi safe_struct_body.append("\n%s& %s::operator=(const %s& src)\n{\n%s\n}" % (ss_name, ss_name, ss_name, copy_assign_txt)) # Copy assignment operator 1358*b7893ccfSSadaf Ebrahimi safe_struct_body.append("\n%s::~%s()\n{\n%s}" % (ss_name, ss_name, destruct_txt)) 1359*b7893ccfSSadaf Ebrahimi safe_struct_body.append("\nvoid %s::initialize(const %s* in_struct%s)\n{\n%s%s}" % (ss_name, item.name, self.custom_construct_params.get(item.name, ''), init_func_txt, construct_txt)) 1360*b7893ccfSSadaf Ebrahimi # Copy initializer uses same txt as copy constructor but has a ptr and not a reference 1361*b7893ccfSSadaf Ebrahimi init_copy = copy_construct_init.replace('src.', 'src->') 1362*b7893ccfSSadaf Ebrahimi init_construct = copy_construct_txt.replace('src.', 'src->') 1363*b7893ccfSSadaf Ebrahimi safe_struct_body.append("\nvoid %s::initialize(const %s* src)\n{\n%s%s}" % (ss_name, ss_name, init_copy, init_construct)) 1364*b7893ccfSSadaf Ebrahimi if item.ifdef_protect is not None: 1365*b7893ccfSSadaf Ebrahimi safe_struct_body.append("#endif // %s\n" % item.ifdef_protect) 1366*b7893ccfSSadaf Ebrahimi return "\n".join(safe_struct_body) 1367*b7893ccfSSadaf Ebrahimi # 1368*b7893ccfSSadaf Ebrahimi # Generate the type map 1369*b7893ccfSSadaf Ebrahimi def GenerateTypeMapHelperHeader(self): 1370*b7893ccfSSadaf Ebrahimi prefix = 'Lvl' 1371*b7893ccfSSadaf Ebrahimi fprefix = 'lvl_' 1372*b7893ccfSSadaf Ebrahimi typemap = prefix + 'TypeMap' 1373*b7893ccfSSadaf Ebrahimi idmap = prefix + 'STypeMap' 1374*b7893ccfSSadaf Ebrahimi type_member = 'Type' 1375*b7893ccfSSadaf Ebrahimi id_member = 'kSType' 1376*b7893ccfSSadaf Ebrahimi id_decl = 'static const VkStructureType ' 1377*b7893ccfSSadaf Ebrahimi generic_header = 'VkBaseOutStructure' 1378*b7893ccfSSadaf Ebrahimi typename_func = fprefix + 'typename' 1379*b7893ccfSSadaf Ebrahimi idname_func = fprefix + 'stype_name' 1380*b7893ccfSSadaf Ebrahimi find_func = fprefix + 'find_in_chain' 1381*b7893ccfSSadaf Ebrahimi init_func = fprefix + 'init_struct' 1382*b7893ccfSSadaf Ebrahimi 1383*b7893ccfSSadaf Ebrahimi explanatory_comment = '\n'.join(( 1384*b7893ccfSSadaf Ebrahimi '// These empty generic templates are specialized for each type with sType', 1385*b7893ccfSSadaf Ebrahimi '// members and for each sType -- providing a two way map between structure', 1386*b7893ccfSSadaf Ebrahimi '// types and sTypes')) 1387*b7893ccfSSadaf Ebrahimi 1388*b7893ccfSSadaf Ebrahimi empty_typemap = 'template <typename T> struct ' + typemap + ' {};' 1389*b7893ccfSSadaf Ebrahimi typemap_format = 'template <> struct {template}<{typename}> {{\n' 1390*b7893ccfSSadaf Ebrahimi typemap_format += ' {id_decl}{id_member} = {id_value};\n' 1391*b7893ccfSSadaf Ebrahimi typemap_format += '}};\n' 1392*b7893ccfSSadaf Ebrahimi 1393*b7893ccfSSadaf Ebrahimi empty_idmap = 'template <VkStructureType id> struct ' + idmap + ' {};' 1394*b7893ccfSSadaf Ebrahimi idmap_format = ''.join(( 1395*b7893ccfSSadaf Ebrahimi 'template <> struct {template}<{id_value}> {{\n', 1396*b7893ccfSSadaf Ebrahimi ' typedef {typename} {typedef};\n', 1397*b7893ccfSSadaf Ebrahimi '}};\n')) 1398*b7893ccfSSadaf Ebrahimi 1399*b7893ccfSSadaf Ebrahimi # Define the utilities (here so any renaming stays consistent), if this grows large, refactor to a fixed .h file 1400*b7893ccfSSadaf Ebrahimi utilities_format = '\n'.join(( 1401*b7893ccfSSadaf Ebrahimi '// Find an entry of the given type in the pNext chain', 1402*b7893ccfSSadaf Ebrahimi 'template <typename T> const T *{find_func}(const void *next) {{', 1403*b7893ccfSSadaf Ebrahimi ' const {header} *current = reinterpret_cast<const {header} *>(next);', 1404*b7893ccfSSadaf Ebrahimi ' const T *found = nullptr;', 1405*b7893ccfSSadaf Ebrahimi ' while (current) {{', 1406*b7893ccfSSadaf Ebrahimi ' if ({type_map}<T>::{id_member} == current->sType) {{', 1407*b7893ccfSSadaf Ebrahimi ' found = reinterpret_cast<const T*>(current);', 1408*b7893ccfSSadaf Ebrahimi ' current = nullptr;', 1409*b7893ccfSSadaf Ebrahimi ' }} else {{', 1410*b7893ccfSSadaf Ebrahimi ' current = current->pNext;', 1411*b7893ccfSSadaf Ebrahimi ' }}', 1412*b7893ccfSSadaf Ebrahimi ' }}', 1413*b7893ccfSSadaf Ebrahimi ' return found;', 1414*b7893ccfSSadaf Ebrahimi '}}', 1415*b7893ccfSSadaf Ebrahimi '', 1416*b7893ccfSSadaf Ebrahimi '// Init the header of an sType struct with pNext', 1417*b7893ccfSSadaf Ebrahimi 'template <typename T> T {init_func}(void *p_next) {{', 1418*b7893ccfSSadaf Ebrahimi ' T out = {{}};', 1419*b7893ccfSSadaf Ebrahimi ' out.sType = {type_map}<T>::kSType;', 1420*b7893ccfSSadaf Ebrahimi ' out.pNext = p_next;', 1421*b7893ccfSSadaf Ebrahimi ' return out;', 1422*b7893ccfSSadaf Ebrahimi '}}', 1423*b7893ccfSSadaf Ebrahimi '', 1424*b7893ccfSSadaf Ebrahimi '// Init the header of an sType struct', 1425*b7893ccfSSadaf Ebrahimi 'template <typename T> T {init_func}() {{', 1426*b7893ccfSSadaf Ebrahimi ' T out = {{}};', 1427*b7893ccfSSadaf Ebrahimi ' out.sType = {type_map}<T>::kSType;', 1428*b7893ccfSSadaf Ebrahimi ' return out;', 1429*b7893ccfSSadaf Ebrahimi '}}', 1430*b7893ccfSSadaf Ebrahimi 1431*b7893ccfSSadaf Ebrahimi '')) 1432*b7893ccfSSadaf Ebrahimi 1433*b7893ccfSSadaf Ebrahimi code = [] 1434*b7893ccfSSadaf Ebrahimi 1435*b7893ccfSSadaf Ebrahimi # Generate header 1436*b7893ccfSSadaf Ebrahimi code.append('\n'.join(( 1437*b7893ccfSSadaf Ebrahimi '#pragma once', 1438*b7893ccfSSadaf Ebrahimi '#include <vulkan/vulkan.h>\n', 1439*b7893ccfSSadaf Ebrahimi explanatory_comment, '', 1440*b7893ccfSSadaf Ebrahimi empty_idmap, 1441*b7893ccfSSadaf Ebrahimi empty_typemap, ''))) 1442*b7893ccfSSadaf Ebrahimi 1443*b7893ccfSSadaf Ebrahimi # Generate the specializations for each type and stype 1444*b7893ccfSSadaf Ebrahimi for item in self.structMembers: 1445*b7893ccfSSadaf Ebrahimi typename = item.name 1446*b7893ccfSSadaf Ebrahimi info = self.structTypes.get(typename) 1447*b7893ccfSSadaf Ebrahimi if not info: 1448*b7893ccfSSadaf Ebrahimi continue 1449*b7893ccfSSadaf Ebrahimi 1450*b7893ccfSSadaf Ebrahimi if item.ifdef_protect is not None: 1451*b7893ccfSSadaf Ebrahimi code.append('#ifdef %s' % item.ifdef_protect) 1452*b7893ccfSSadaf Ebrahimi 1453*b7893ccfSSadaf Ebrahimi code.append('// Map type {} to id {}'.format(typename, info.value)) 1454*b7893ccfSSadaf Ebrahimi code.append(typemap_format.format(template=typemap, typename=typename, id_value=info.value, 1455*b7893ccfSSadaf Ebrahimi id_decl=id_decl, id_member=id_member)) 1456*b7893ccfSSadaf Ebrahimi code.append(idmap_format.format(template=idmap, typename=typename, id_value=info.value, typedef=type_member)) 1457*b7893ccfSSadaf Ebrahimi 1458*b7893ccfSSadaf Ebrahimi if item.ifdef_protect is not None: 1459*b7893ccfSSadaf Ebrahimi code.append('#endif // %s' % item.ifdef_protect) 1460*b7893ccfSSadaf Ebrahimi 1461*b7893ccfSSadaf Ebrahimi # Generate utilities for all types 1462*b7893ccfSSadaf Ebrahimi code.append('\n'.join(( 1463*b7893ccfSSadaf Ebrahimi utilities_format.format(id_member=id_member, id_map=idmap, type_map=typemap, 1464*b7893ccfSSadaf Ebrahimi type_member=type_member, header=generic_header, typename_func=typename_func, idname_func=idname_func, 1465*b7893ccfSSadaf Ebrahimi find_func=find_func, init_func=init_func), '' 1466*b7893ccfSSadaf Ebrahimi ))) 1467*b7893ccfSSadaf Ebrahimi 1468*b7893ccfSSadaf Ebrahimi return "\n".join(code) 1469*b7893ccfSSadaf Ebrahimi 1470*b7893ccfSSadaf Ebrahimi # 1471*b7893ccfSSadaf Ebrahimi # Create a helper file and return it as a string 1472*b7893ccfSSadaf Ebrahimi def OutputDestFile(self): 1473*b7893ccfSSadaf Ebrahimi if self.helper_file_type == 'enum_string_header': 1474*b7893ccfSSadaf Ebrahimi return self.GenerateEnumStringHelperHeader() 1475*b7893ccfSSadaf Ebrahimi elif self.helper_file_type == 'safe_struct_header': 1476*b7893ccfSSadaf Ebrahimi return self.GenerateSafeStructHelperHeader() 1477*b7893ccfSSadaf Ebrahimi elif self.helper_file_type == 'safe_struct_source': 1478*b7893ccfSSadaf Ebrahimi return self.GenerateSafeStructHelperSource() 1479*b7893ccfSSadaf Ebrahimi elif self.helper_file_type == 'object_types_header': 1480*b7893ccfSSadaf Ebrahimi return self.GenerateObjectTypesHelperHeader() 1481*b7893ccfSSadaf Ebrahimi elif self.helper_file_type == 'extension_helper_header': 1482*b7893ccfSSadaf Ebrahimi return self.GenerateExtensionHelperHeader() 1483*b7893ccfSSadaf Ebrahimi elif self.helper_file_type == 'typemap_helper_header': 1484*b7893ccfSSadaf Ebrahimi return self.GenerateTypeMapHelperHeader() 1485*b7893ccfSSadaf Ebrahimi else: 1486*b7893ccfSSadaf Ebrahimi return 'Bad Helper File Generator Option %s' % self.helper_file_type 1487