From 029056732aa8363364e3ccb44caf0e03ca99d4fa Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Wed, 28 Dec 2016 10:46:26 -0700 Subject: scripts: Add struct_size options for source, header Added struct processing guts for building the struct_size_helper header and source files. Change-Id: I8172b921b670b47b8fd66499de6d76ddb3ef934d --- scripts/helper_file_generator.py | 141 +++++++++++++++++++++++++++++++++++---- scripts/lvl_genvk.py | 32 +++++++-- 2 files changed, 154 insertions(+), 19 deletions(-) (limited to 'scripts') diff --git a/scripts/helper_file_generator.py b/scripts/helper_file_generator.py index 4c7ac437..4e18bf39 100644 --- a/scripts/helper_file_generator.py +++ b/scripts/helper_file_generator.py @@ -55,7 +55,6 @@ class HelperFileOutputGeneratorOptions(GeneratorOptions): addExtensions, removeExtensions, sortProcedure) self.prefixText = prefixText self.genFuncPointers = genFuncPointers - self.prefixText = None self.protectFile = protectFile self.protectFeature = protectFeature self.protectProto = protectProto @@ -67,8 +66,7 @@ class HelperFileOutputGeneratorOptions(GeneratorOptions): self.library_name = library_name self.helper_file_type = helper_file_type # -# HelperFileOutputGenerator - subclass of OutputGenerator. -# Outputs Vulkan helper files +# HelperFileOutputGenerator - subclass of OutputGenerator. Outputs Vulkan helper files class HelperFileOutputGenerator(OutputGenerator): """Generate Windows def file based on XML element attributes""" def __init__(self, @@ -79,14 +77,24 @@ class HelperFileOutputGenerator(OutputGenerator): # Internal state - accumulators for different inner block text self.enum_output = '' # string built up of enum string routines self.enum_list = () + # Internal state - accumulators for different inner block text + ########## self.sections = dict([(section, []) for section in self.ALL_SECTIONS]) + self.structNames = [] # List of Vulkan struct typenames + self.structTypes = dict() # Map of Vulkan struct typename to required VkStructureType + self.handleTypes = set() # Set of handle type names + self.commands = [] # List of CommandData records for all Vulkan commands + self.structMembers = [] # List of StructMemberData records for all Vulkan structs + self.flags = set() # Map of flags typenames + # Named tuples to store struct and command data + self.StructType = namedtuple('StructType', ['name', 'value']) + self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isconst', 'iscount', 'len', 'extstructs', 'cdecl', 'islocal', 'iscreate', 'isdestroy']) + self.CommandData = namedtuple('CommandData', ['name', 'return_type', 'params', 'cdecl']) + self.StructMemberData = namedtuple('StructMemberData', ['name', 'members']) # # Called once at the beginning of each run def beginFile(self, genOpts): OutputGenerator.beginFile(self, genOpts) # User-supplied prefix text, if any (list of strings) - if (genOpts.prefixText): - for s in genOpts.prefixText: - write(s, file=self.outFile) self.helper_file_type = genOpts.helper_file_type self.library_name = genOpts.library_name # File Comment @@ -134,8 +142,8 @@ class HelperFileOutputGenerator(OutputGenerator): def genGroup(self, groupinfo, groupName): OutputGenerator.genGroup(self, groupinfo, groupName) groupElem = groupinfo.elem - # For enum_string_helper - if self.helper_file_type == 'enum_string_helper': + # For enum_string_header + if self.helper_file_type == 'enum_string_header': value_list = [] for elem in groupElem.findall('enum'): if elem.get('supported') != 'disabled': @@ -144,7 +152,106 @@ class HelperFileOutputGenerator(OutputGenerator): if value_list is not None: self.enum_output += self.GenerateEnumStringConversion(groupName, value_list) # - # Enum_string_helper: Create a routine to convert an enumerated value into a string + # Called for each type -- if the type is a struct/union, grab the metadata + def genType(self, typeinfo, name): + OutputGenerator.genType(self, typeinfo, name) + typeElem = typeinfo.elem + # If the type is a struct type, traverse the imbedded tags generating a structure. + # Otherwise, emit the tag text. + category = typeElem.get('category') + if (category == 'struct' or category == 'union'): + self.structNames.append(name) + self.genStruct(typeinfo, name) + # + # Generate a VkStructureType based on a structure typename + def genVkStructureType(self, typename): + # Add underscore between lowercase then uppercase + value = re.sub('([a-z0-9])([A-Z])', r'\1_\2', typename) + # Change to uppercase + value = value.upper() + # Add STRUCTURE_TYPE_ + return re.sub('VK_', 'VK_STRUCTURE_TYPE_', value) + # + # Check if the parameter passed in is a pointer + def paramIsPointer(self, param): + ispointer = False + for elem in param: + if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail: + ispointer = True + return ispointer + # + # Retrieve the type and name for a parameter + def getTypeNameTuple(self, param): + type = '' + name = '' + for elem in param: + if elem.tag == 'type': + type = noneStr(elem.text) + elif elem.tag == 'name': + name = noneStr(elem.text) + return (type, name) + # + # Retrieve the value of the len tag + def getLen(self, param): + result = None + len = param.attrib.get('len') + if len and len != 'null-terminated': + # For string arrays, 'len' can look like 'count,null-terminated', indicating that we + # have a null terminated array of strings. We strip the null-terminated from the + # 'len' field and only return the parameter specifying the string count + if 'null-terminated' in len: + result = len.split(',')[0] + else: + result = len + # Spec has now notation for len attributes, using :: instead of platform specific pointer symbol + result = str(result).replace('::', '->') + return result + # + # Generate local ready-access data describing Vulkan structures and unions from the XML metadata + def genStruct(self, typeinfo, typeName): + OutputGenerator.genStruct(self, typeinfo, typeName) + members = typeinfo.elem.findall('.//member') + # Iterate over members once to get length parameters for arrays + lens = set() + for member in members: + len = self.getLen(member) + if len: + lens.add(len) + # Generate member info + membersInfo = [] + for member in members: + # Get the member's type and name + info = self.getTypeNameTuple(member) + type = info[0] + name = info[1] + cdecl = self.makeCParamDecl(member, 0) + # Process VkStructureType + if type == 'VkStructureType': + # Extract the required struct type value from the comments + # embedded in the original text defining the 'typeinfo' element + rawXml = etree.tostring(typeinfo.elem).decode('ascii') + result = re.search(r'VK_STRUCTURE_TYPE_\w+', rawXml) + if result: + value = result.group(0) + else: + value = self.genVkStructureType(typeName) + # Store the required type value + self.structTypes[typeName] = self.StructType(name=name, value=value) + # Store pointer/array/string info + membersInfo.append(self.CommandParam(type=type, + name=name, + ispointer=self.paramIsPointer(member), + isconst=True if 'const' in cdecl else False, + iscount=True if name in lens else False, + len=self.getLen(member), + extstructs=member.attrib.get('validextensionstructs') if name == 'pNext' else None, + cdecl=cdecl, + islocal=False, + iscreate=False, + isdestroy=False)) + self.structMembers.append(self.StructMemberData(name=typeName, members=membersInfo)) + # + # Enum_string_header: Create a routine to convert an enumerated value into a string def GenerateEnumStringConversion(self, groupName, value_list): outstring = '\n' outstring += 'static inline const char* string_%s(%s input_value)\n' % (groupName, groupName) @@ -163,7 +270,8 @@ class HelperFileOutputGenerator(OutputGenerator): # # Create a helper file and return it as a string def OutputDestFile(self): - if self.helper_file_type == 'enum_string_helper': + out_file_entries = '' + if self.helper_file_type == 'enum_string_header': out_file_entries = '\n' out_file_entries += '#pragma once\n' out_file_entries += '#ifdef _WIN32\n' @@ -173,11 +281,16 @@ class HelperFileOutputGenerator(OutputGenerator): out_file_entries += '#include \n' out_file_entries += '\n' out_file_entries += self.enum_output - elif self.helper_file_type == 'test': + elif self.helper_file_type == 'struct_size_header': + out_file_entries = '\n' + out_file_entries += 'Helper File header code\n' + out_file_entries += '\n' + out_file_entries += 'helper file.h \n' + out_file_entries += '\n' + elif self.helper_file_type == 'struct_size_source': out_file_entries = '\n' - out_file_entries += 'TEST FILE!!!!!\n' + out_file_entries += 'Helper File source code\n' out_file_entries += '\n' - out_file_entries += 'THISLL BE SOMETHING, SOMEDAY. \n' - out_file_entries += 'MORE STUFF HERE\n' + out_file_entries += 'helper file.c \n' out_file_entries += '\n' return out_file_entries diff --git a/scripts/lvl_genvk.py b/scripts/lvl_genvk.py index 7f67012e..025e1678 100644 --- a/scripts/lvl_genvk.py +++ b/scripts/lvl_genvk.py @@ -203,14 +203,14 @@ def makeGenOpts(extensions = [], removeExtensions = [], protect = True, director apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, - helper_file_type = 'enum_string_helper') + helper_file_type = 'enum_string_header') ] - # Helper file generator options for vk_test.h - genOpts['vk_test.h'] = [ + # Helper file generator options for vk_struct_size_helper.h + genOpts['vk_struct_size_helper.h'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( - filename = 'vk_test.h', + filename = 'vk_struct_size_helper.h', directory = directory, apiname = 'vulkan', profile = None, @@ -225,7 +225,29 @@ def makeGenOpts(extensions = [], removeExtensions = [], protect = True, director apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, - helper_file_type = 'test') + helper_file_type = 'struct_size_header') + ] + + # Helper file generator options for vk_struct_size_helper.c + genOpts['vk_struct_size_helper.c'] = [ + HelperFileOutputGenerator, + HelperFileOutputGeneratorOptions( + filename = 'vk_struct_size_helper.c', + directory = directory, + apiname = 'vulkan', + profile = None, + versions = allVersions, + emitversions = allVersions, + defaultExtensions = 'vulkan', + addExtensions = addExtensions, + removeExtensions = removeExtensions, + prefixText = prefixStrings + vkPrefixStrings, + protectFeature = False, + apicall = 'VKAPI_ATTR ', + apientry = 'VKAPI_CALL ', + apientryp = 'VKAPI_PTR *', + alignFuncParam = 48, + helper_file_type = 'struct_size_source') ] -- cgit v1.2.3