1#!/usr/bin/env python3 2# 3# Copyright (c) 2015-2016 The Khronos Group Inc. 4# Copyright (c) 2015-2016 Valve Corporation 5# Copyright (c) 2015-2016 LunarG, Inc. 6# Copyright (c) 2015-2016 Google Inc. 7# 8# Permission is hereby granted, free of charge, to any person obtaining a copy 9# of this software and/or associated documentation files (the "Materials"), to 10# deal in the Materials without restriction, including without limitation the 11# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12# sell copies of the Materials, and to permit persons to whom the Materials 13# are furnished to do so, subject to the following conditions: 14# 15# The above copyright notice(s) and this permission notice shall be included 16# in all copies or substantial portions of the Materials. 17# 18# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21# 22# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 25# USE OR OTHER DEALINGS IN THE MATERIALS 26# 27# Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 28# Author: Tobin Ehlis <tobin@lunarg.com> 29 30import argparse 31import os 32import sys 33import re 34import vulkan 35from source_line_info import sourcelineinfo 36 37# vk_helper.py overview 38# This script generates code based on vulkan input header 39# It generate wrappers functions that can be used to display 40# structs in a human-readable txt format, as well as utility functions 41# to print enum values as strings 42 43def handle_args(): 44 parser = argparse.ArgumentParser(description='Perform analysis of vogl trace.') 45 parser.add_argument('input_file', help='The input header file from which code will be generated.') 46 parser.add_argument('--rel_out_dir', required=False, default='vktrace_gen', help='Path relative to exec path to write output files. Will be created if needed.') 47 parser.add_argument('--abs_out_dir', required=False, default=None, help='Absolute path to write output files. Will be created if needed.') 48 parser.add_argument('--gen_enum_string_helper', required=False, action='store_true', default=False, help='Enable generation of helper header file to print string versions of enums.') 49 parser.add_argument('--gen_struct_wrappers', required=False, action='store_true', default=False, help='Enable generation of struct wrapper classes.') 50 parser.add_argument('--gen_struct_sizes', required=False, action='store_true', default=False, help='Enable generation of struct sizes.') 51 parser.add_argument('--gen_cmake', required=False, action='store_true', default=False, help='Enable generation of cmake file for generated code.') 52 parser.add_argument('--gen_graphviz', required=False, action='store_true', default=False, help='Enable generation of graphviz dot file.') 53 #parser.add_argument('--test', action='store_true', default=False, help='Run simple test.') 54 return parser.parse_args() 55 56# TODO : Ideally these data structs would be opaque to user and could be wrapped 57# in their own class(es) to make them friendly for data look-up 58# Dicts for Data storage 59# enum_val_dict[value_name] = dict keys are the string enum value names for all enums 60# |-------->['type'] = the type of enum class into which the value falls 61# |-------->['val'] = the value assigned to this particular value_name 62# '-------->['unique'] = bool designating if this enum 'val' is unique within this enum 'type' 63enum_val_dict = {} 64# enum_type_dict['type'] = the type or class of of enum 65# '----->['val_name1', 'val_name2'...] = each type references a list of val_names within this type 66enum_type_dict = {} 67# struct_dict['struct_basename'] = the base (non-typedef'd) name of the struct 68# |->[<member_num>] = members are stored via their integer placement in the struct 69# | |->['name'] = string name of this struct member 70# ... |->['full_type'] = complete type qualifier for this member 71# |->['type'] = base type for this member 72# |->['ptr'] = bool indicating if this member is ptr 73# |->['const'] = bool indicating if this member is const 74# |->['struct'] = bool indicating if this member is a struct type 75# |->['array'] = bool indicating if this member is an array 76# |->['dyn_array'] = bool indicating if member is a dynamically sized array 77# '->['array_size'] = For dyn_array, member name used to size array, else int size for static array 78struct_dict = {} 79struct_order_list = [] # struct names in order they're declared 80# Store struct names that require #ifdef guards 81# dict stores struct and enum definitions that are guarded by ifdef as the key 82# and the txt of the ifdef is the value 83ifdef_dict = {} 84# typedef_fwd_dict stores mapping from orig_type_name -> new_type_name 85typedef_fwd_dict = {} 86# typedef_rev_dict stores mapping from new_type_name -> orig_type_name 87typedef_rev_dict = {} # store new_name -> orig_name mapping 88# types_dict['id_name'] = identifier name will map to it's type 89# '---->'type' = currently either 'struct' or 'enum' 90types_dict = {} # store orig_name -> type mapping 91 92 93# Class that parses header file and generates data structures that can 94# Then be used for other tasks 95class HeaderFileParser: 96 def __init__(self, header_file=None): 97 self.header_file = header_file 98 # store header data in various formats, see above for more info 99 self.enum_val_dict = {} 100 self.enum_type_dict = {} 101 self.struct_dict = {} 102 self.typedef_fwd_dict = {} 103 self.typedef_rev_dict = {} 104 self.types_dict = {} 105 self.last_struct_count_name = '' 106 107 def setHeaderFile(self, header_file): 108 self.header_file = header_file 109 110 def get_enum_val_dict(self): 111 return self.enum_val_dict 112 113 def get_enum_type_dict(self): 114 return self.enum_type_dict 115 116 def get_struct_dict(self): 117 return self.struct_dict 118 119 def get_typedef_fwd_dict(self): 120 return self.typedef_fwd_dict 121 122 def get_typedef_rev_dict(self): 123 return self.typedef_rev_dict 124 125 def get_types_dict(self): 126 return self.types_dict 127 128 # Parse header file into data structures 129 def parse(self): 130 # parse through the file, identifying different sections 131 parse_enum = False 132 parse_struct = False 133 member_num = 0 134 # TODO : Comment parsing is very fragile but handles 2 known files 135 block_comment = False 136 prev_count_name = '' 137 ifdef_txt = '' 138 ifdef_active = 0 139 exclude_struct_list = ['VkPlatformHandleXcbKHR', 'VkPlatformHandleX11KHR'] 140 with open(self.header_file) as f: 141 for line in f: 142 if True in [ifd_txt in line for ifd_txt in ['#ifdef ', '#ifndef ']]: 143 ifdef_txt = line.split()[1] 144 ifdef_active = ifdef_active + 1 145 continue 146 if ifdef_active != 0 and '#endif' in line: 147 ifdef_active = ifdef_active - 1 148 if block_comment: 149 if '*/' in line: 150 block_comment = False 151 continue 152 if '/*' in line: 153 if '*/' in line: # single line block comment 154 continue 155 block_comment = True 156 elif 0 == len(line.split()): 157 #print("Skipping empty line") 158 continue 159 elif line.split()[0].strip().startswith("//"): 160 #print("Skipping commented line %s" % line) 161 continue 162 elif 'typedef enum' in line: 163 (ty_txt, en_txt, base_type) = line.strip().split(None, 2) 164 #print("Found ENUM type %s" % base_type) 165 if '{' == base_type: 166 base_type = 'tmp_enum' 167 parse_enum = True 168 default_enum_val = 0 169 self.types_dict[base_type] = 'enum' 170 elif 'typedef struct' in line or 'typedef union' in line: 171 if True in [ex_type in line for ex_type in exclude_struct_list]: 172 continue 173 174 (ty_txt, st_txt, base_type) = line.strip().split(None, 2) 175 if ' ' in base_type: 176 (ignored, base_type) = base_type.strip().split(None, 1) 177 178 #print("Found STRUCT type: %s" % base_type) 179 # Note: This really needs to be updated to handle one line struct definition, like 180 # typedef struct obj##_T { uint64_t handle; } obj; 181 if ('{' == base_type or not (' ' in base_type)): 182 base_type = 'tmp_struct' 183 parse_struct = True 184 self.types_dict[base_type] = 'struct' 185# elif 'typedef union' in line: 186# (ty_txt, st_txt, base_type) = line.strip().split(None, 2) 187# print("Found UNION type: %s" % base_type) 188# parse_struct = True 189# self.types_dict[base_type] = 'struct' 190 elif '}' in line and (parse_enum or parse_struct): 191 if len(line.split()) > 1: # deals with embedded union in one struct 192 parse_enum = False 193 parse_struct = False 194 self.last_struct_count_name = '' 195 member_num = 0 196 (cur_char, targ_type) = line.strip().split(None, 1) 197 if 'tmp_struct' == base_type: 198 base_type = targ_type.strip(';') 199 if True in [ex_type in base_type for ex_type in exclude_struct_list]: 200 del self.struct_dict['tmp_struct'] 201 continue 202 #print("Found Actual Struct type %s" % base_type) 203 self.struct_dict[base_type] = self.struct_dict['tmp_struct'] 204 self.struct_dict.pop('tmp_struct', 0) 205 struct_order_list.append(base_type) 206 self.types_dict[base_type] = 'struct' 207 self.types_dict.pop('tmp_struct', 0) 208 elif 'tmp_enum' == base_type: 209 base_type = targ_type.strip(';') 210 #print("Found Actual ENUM type %s" % base_type) 211 for n in self.enum_val_dict: 212 if 'tmp_enum' == self.enum_val_dict[n]['type']: 213 self.enum_val_dict[n]['type'] = base_type 214# self.enum_val_dict[base_type] = self.enum_val_dict['tmp_enum'] 215# self.enum_val_dict.pop('tmp_enum', 0) 216 self.enum_type_dict[base_type] = self.enum_type_dict['tmp_enum'] 217 self.enum_type_dict.pop('tmp_enum', 0) 218 self.types_dict[base_type] = 'enum' 219 self.types_dict.pop('tmp_enum', 0) 220 if ifdef_active: 221 ifdef_dict[base_type] = ifdef_txt 222 self.typedef_fwd_dict[base_type] = targ_type.strip(';') 223 self.typedef_rev_dict[targ_type.strip(';')] = base_type 224 #print("fwd_dict: %s = %s" % (base_type, targ_type)) 225 elif parse_enum: 226 #if 'VK_MAX_ENUM' not in line and '{' not in line: 227 if True not in [ens in line for ens in ['{', '_MAX_ENUM', '_BEGIN_RANGE', '_END_RANGE', '_NUM = ', '_ENUM_RANGE']]: 228 self._add_enum(line, base_type, default_enum_val) 229 default_enum_val += 1 230 elif parse_struct: 231 if ';' in line: 232 self._add_struct(line, base_type, member_num) 233 member_num = member_num + 1 234 235 # populate enum dicts based on enum lines 236 def _add_enum(self, line_txt, enum_type, def_enum_val): 237 #print("Parsing enum line %s" % line_txt) 238 if '=' in line_txt: 239 (enum_name, eq_char, enum_val) = line_txt.split(None, 2) 240 else: 241 enum_name = line_txt.split(',')[0] 242 enum_val = str(def_enum_val) 243 self.enum_val_dict[enum_name] = {} 244 self.enum_val_dict[enum_name]['type'] = enum_type 245 # strip comma and comment, then extra split in case of no comma w/ comments 246 enum_val = enum_val.strip().split(',', 1)[0] 247 self.enum_val_dict[enum_name]['val'] = enum_val.split()[0] 248 # Perform conversion of VK_BIT macro 249 if 'VK_BIT' in self.enum_val_dict[enum_name]['val']: 250 vk_bit_val = self.enum_val_dict[enum_name]['val'] 251 bit_shift = int(vk_bit_val[vk_bit_val.find('(')+1:vk_bit_val.find(')')], 0) 252 self.enum_val_dict[enum_name]['val'] = str(1 << bit_shift) 253 else: 254 # account for negative values surrounded by parens 255 self.enum_val_dict[enum_name]['val'] = self.enum_val_dict[enum_name]['val'].strip(')').replace('-(', '-') 256 # Try to cast to int to determine if enum value is unique 257 try: 258 #print("ENUM val:", self.enum_val_dict[enum_name]['val']) 259 int(self.enum_val_dict[enum_name]['val'], 0) 260 self.enum_val_dict[enum_name]['unique'] = True 261 #print("ENUM has num value") 262 except ValueError: 263 self.enum_val_dict[enum_name]['unique'] = False 264 #print("ENUM is not a number value") 265 # Update enum_type_dict as well 266 if not enum_type in self.enum_type_dict: 267 self.enum_type_dict[enum_type] = [] 268 self.enum_type_dict[enum_type].append(enum_name) 269 270 # Return True if struct member is a dynamic array 271 # RULES : This is a bit quirky based on the API 272 # NOTE : Changes in API spec may cause these rules to change 273 # 1. There must be a previous uint var w/ 'count' in the name in the struct 274 # 2. Dynam array must have 'const' and '*' qualifiers 275 # 3a. Name of dynam array must end in 's' char OR 276 # 3b. Name of count var minus 'count' must be contained in name of dynamic array 277 def _is_dynamic_array(self, full_type, name): 278 exceptions = ['pEnabledFeatures', 'pWaitDstStageMask', 'pSampleMask'] 279 if name in exceptions: 280 return False 281 if '' != self.last_struct_count_name: 282 if 'const' in full_type and '*' in full_type: 283 if name.endswith('s') or self.last_struct_count_name.lower().replace('count', '') in name.lower(): 284 return True 285 286 # VkWriteDescriptorSet 287 if self.last_struct_count_name == "descriptorCount": 288 return True 289 290 return False 291 292 # populate struct dicts based on struct lines 293 # TODO : Handle ":" bitfield, "**" ptr->ptr and "const type*const*" 294 def _add_struct(self, line_txt, struct_type, num): 295 #print("Parsing struct line %s" % line_txt) 296 if '{' == struct_type: 297 print("Parsing struct '{' w/ line %s" % line_txt) 298 if not struct_type in self.struct_dict: 299 self.struct_dict[struct_type] = {} 300 members = line_txt.strip().split(';', 1)[0] # first strip semicolon & comments 301 # TODO : Handle bitfields more correctly 302 members = members.strip().split(':', 1)[0] # strip bitfield element 303 (member_type, member_name) = members.rsplit(None, 1) 304 # Store counts to help recognize and size dynamic arrays 305 if 'count' in member_name.lower() and 'samplecount' != member_name.lower() and 'uint' in member_type: 306 self.last_struct_count_name = member_name 307 self.struct_dict[struct_type][num] = {} 308 self.struct_dict[struct_type][num]['full_type'] = member_type 309 self.struct_dict[struct_type][num]['dyn_array'] = False 310 if '*' in member_type: 311 self.struct_dict[struct_type][num]['ptr'] = True 312 # TODO : Need more general purpose way here to reduce down to basic type 313 member_type = member_type.replace(' const*', '') 314 member_type = member_type.strip('*') 315 else: 316 self.struct_dict[struct_type][num]['ptr'] = False 317 if 'const' in member_type: 318 self.struct_dict[struct_type][num]['const'] = True 319 member_type = member_type.replace('const', '').strip() 320 else: 321 self.struct_dict[struct_type][num]['const'] = False 322 # TODO : There is a bug here where it seems that at the time we do this check, 323 # the data is not in the types or typedef_rev_dict, so we never pass this if check 324 if is_type(member_type, 'struct'): 325 self.struct_dict[struct_type][num]['struct'] = True 326 else: 327 self.struct_dict[struct_type][num]['struct'] = False 328 self.struct_dict[struct_type][num]['type'] = member_type 329 if '[' in member_name: 330 (member_name, array_size) = member_name.split('[', 1) 331 #if 'char' in member_type: 332 # self.struct_dict[struct_type][num]['array'] = False 333 # self.struct_dict[struct_type][num]['array_size'] = 0 334 # self.struct_dict[struct_type][num]['ptr'] = True 335 #else: 336 self.struct_dict[struct_type][num]['array'] = True 337 self.struct_dict[struct_type][num]['array_size'] = array_size.strip(']') 338 elif self._is_dynamic_array(self.struct_dict[struct_type][num]['full_type'], member_name): 339 #print("Found dynamic array %s of size %s" % (member_name, self.last_struct_count_name)) 340 self.struct_dict[struct_type][num]['array'] = True 341 self.struct_dict[struct_type][num]['dyn_array'] = True 342 self.struct_dict[struct_type][num]['array_size'] = self.last_struct_count_name 343 elif not 'array' in self.struct_dict[struct_type][num]: 344 self.struct_dict[struct_type][num]['array'] = False 345 self.struct_dict[struct_type][num]['array_size'] = 0 346 self.struct_dict[struct_type][num]['name'] = member_name 347 348# check if given identifier is of specified type_to_check 349def is_type(identifier, type_to_check): 350 if identifier in types_dict and type_to_check == types_dict[identifier]: 351 return True 352 if identifier in typedef_rev_dict: 353 new_id = typedef_rev_dict[identifier] 354 if new_id in types_dict and type_to_check == types_dict[new_id]: 355 return True 356 return False 357 358# This is a validation function to verify that we can reproduce the original structs 359def recreate_structs(): 360 for struct_name in struct_dict: 361 sys.stdout.write("typedef struct %s\n{\n" % struct_name) 362 for mem_num in sorted(struct_dict[struct_name]): 363 sys.stdout.write(" ") 364 if struct_dict[struct_name][mem_num]['const']: 365 sys.stdout.write("const ") 366 #if struct_dict[struct_name][mem_num]['struct']: 367 # sys.stdout.write("struct ") 368 sys.stdout.write (struct_dict[struct_name][mem_num]['type']) 369 if struct_dict[struct_name][mem_num]['ptr']: 370 sys.stdout.write("*") 371 sys.stdout.write(" ") 372 sys.stdout.write(struct_dict[struct_name][mem_num]['name']) 373 if struct_dict[struct_name][mem_num]['array']: 374 sys.stdout.write("[") 375 sys.stdout.write(struct_dict[struct_name][mem_num]['array_size']) 376 sys.stdout.write("]") 377 sys.stdout.write(";\n") 378 sys.stdout.write("} ") 379 sys.stdout.write(typedef_fwd_dict[struct_name]) 380 sys.stdout.write(";\n\n") 381 382# 383# TODO: Fix construction of struct name 384def get_struct_name_from_struct_type(struct_type): 385 # Note: All struct types are now camel-case 386 # Debug Report has an inconsistency - so need special case. 387 if ("VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT" == struct_type): 388 return "VkDebugReportCallbackCreateInfoEXT" 389 caps_struct_name = struct_type.replace("_STRUCTURE_TYPE", "") 390 char_idx = 0 391 struct_name = '' 392 for char in caps_struct_name: 393 if (0 == char_idx) or (caps_struct_name[char_idx-1] == '_'): 394 struct_name += caps_struct_name[char_idx] 395 elif (caps_struct_name[char_idx] == '_'): 396 pass 397 else: 398 struct_name += caps_struct_name[char_idx].lower() 399 char_idx += 1 400 401 return struct_name 402 403# class for writing common file elements 404# Here's how this class lays out a file: 405# COPYRIGHT 406# HEADER 407# BODY 408# FOOTER 409# 410# For each of these sections, there's a "set*" function 411# The class as a whole has a generate function which will write each section in order 412class CommonFileGen: 413 def __init__(self, filename=None, copyright_txt="", header_txt="", body_txt="", footer_txt=""): 414 self.filename = filename 415 self.contents = {'copyright': copyright_txt, 'header': header_txt, 'body': body_txt, 'footer': footer_txt} 416 # TODO : Set a default copyright & footer at least 417 418 def setFilename(self, filename): 419 self.filename = filename 420 421 def setCopyright(self, c): 422 self.contents['copyright'] = c 423 424 def setHeader(self, h): 425 self.contents['header'] = h 426 427 def setBody(self, b): 428 self.contents['body'] = b 429 430 def setFooter(self, f): 431 self.contents['footer'] = f 432 433 def generate(self): 434 #print("Generate to file %s" % self.filename) 435 with open(self.filename, "w") as f: 436 f.write(self.contents['copyright']) 437 f.write(self.contents['header']) 438 f.write(self.contents['body']) 439 f.write(self.contents['footer']) 440 441# class for writing a wrapper class for structures 442# The wrapper class wraps the structs and includes utility functions for 443# setting/getting member values and displaying the struct data in various formats 444class StructWrapperGen: 445 def __init__(self, in_struct_dict, prefix, out_dir): 446 self.struct_dict = in_struct_dict 447 self.include_headers = [] 448 self.lineinfo = sourcelineinfo() 449 self.api = prefix 450 if prefix.lower() == "vulkan": 451 self.api_prefix = "vk" 452 else: 453 self.api_prefix = prefix 454 self.header_filename = os.path.join(out_dir, self.api_prefix+"_struct_wrappers.h") 455 self.class_filename = os.path.join(out_dir, self.api_prefix+"_struct_wrappers.cpp") 456 self.safe_struct_header_filename = os.path.join(out_dir, self.api_prefix+"_safe_struct.h") 457 self.safe_struct_source_filename = os.path.join(out_dir, self.api_prefix+"_safe_struct.cpp") 458 self.string_helper_filename = os.path.join(out_dir, self.api_prefix+"_struct_string_helper.h") 459 self.string_helper_no_addr_filename = os.path.join(out_dir, self.api_prefix+"_struct_string_helper_no_addr.h") 460 self.string_helper_cpp_filename = os.path.join(out_dir, self.api_prefix+"_struct_string_helper_cpp.h") 461 self.string_helper_no_addr_cpp_filename = os.path.join(out_dir, self.api_prefix+"_struct_string_helper_no_addr_cpp.h") 462 self.validate_helper_filename = os.path.join(out_dir, self.api_prefix+"_struct_validate_helper.h") 463 self.no_addr = False 464 # Safe Struct (ss) header and source files 465 self.ssh = CommonFileGen(self.safe_struct_header_filename) 466 self.sss = CommonFileGen(self.safe_struct_source_filename) 467 self.hfg = CommonFileGen(self.header_filename) 468 self.cfg = CommonFileGen(self.class_filename) 469 self.shg = CommonFileGen(self.string_helper_filename) 470 self.shcppg = CommonFileGen(self.string_helper_cpp_filename) 471 self.vhg = CommonFileGen(self.validate_helper_filename) 472 self.size_helper_filename = os.path.join(out_dir, self.api_prefix+"_struct_size_helper.h") 473 self.size_helper_c_filename = os.path.join(out_dir, self.api_prefix+"_struct_size_helper.c") 474 self.size_helper_gen = CommonFileGen(self.size_helper_filename) 475 self.size_helper_c_gen = CommonFileGen(self.size_helper_c_filename) 476 #print(self.header_filename) 477 self.header_txt = "" 478 self.definition_txt = "" 479 480 def set_include_headers(self, include_headers): 481 self.include_headers = include_headers 482 483 def set_no_addr(self, no_addr): 484 self.no_addr = no_addr 485 if self.no_addr: 486 self.shg = CommonFileGen(self.string_helper_no_addr_filename) 487 self.shcppg = CommonFileGen(self.string_helper_no_addr_cpp_filename) 488 else: 489 self.shg = CommonFileGen(self.string_helper_filename) 490 self.shcppg = CommonFileGen(self.string_helper_cpp_filename) 491 492 # Return class name for given struct name 493 def get_class_name(self, struct_name): 494 class_name = struct_name.strip('_').lower() + "_struct_wrapper" 495 return class_name 496 497 def get_file_list(self): 498 return [os.path.basename(self.header_filename), os.path.basename(self.class_filename), os.path.basename(self.string_helper_filename)] 499 500 # Generate class header file 501 def generateHeader(self): 502 self.hfg.setCopyright(self._generateCopyright()) 503 self.hfg.setHeader(self._generateHeader()) 504 self.hfg.setBody(self._generateClassDeclaration()) 505 self.hfg.setFooter(self._generateFooter()) 506 self.hfg.generate() 507 508 # Generate class definition 509 def generateBody(self): 510 self.cfg.setCopyright(self._generateCopyright()) 511 self.cfg.setHeader(self._generateCppHeader()) 512 self.cfg.setBody(self._generateClassDefinition()) 513 self.cfg.setFooter(self._generateFooter()) 514 self.cfg.generate() 515 516 # Safe Structs are versions of vulkan structs with non-const safe ptrs 517 # that make shadowing structures and clean-up of shadowed structures very simple 518 def generateSafeStructHeader(self): 519 self.ssh.setCopyright(self._generateCopyright()) 520 self.ssh.setHeader(self._generateSafeStructHeader()) 521 self.ssh.setBody(self._generateSafeStructDecls()) 522 self.ssh.generate() 523 524 def generateSafeStructs(self): 525 self.sss.setCopyright(self._generateCopyright()) 526 self.sss.setHeader(self._generateSafeStructSourceHeader()) 527 self.sss.setBody(self._generateSafeStructSource()) 528 self.sss.generate() 529 530 # Generate c-style .h file that contains functions for printing structs 531 def generateStringHelper(self): 532 print("Generating struct string helper") 533 self.shg.setCopyright(self._generateCopyright()) 534 self.shg.setHeader(self._generateStringHelperHeader()) 535 self.shg.setBody(self._generateStringHelperFunctions()) 536 self.shg.generate() 537 538 # Generate cpp-style .h file that contains functions for printing structs 539 def generateStringHelperCpp(self): 540 print("Generating struct string helper cpp") 541 self.shcppg.setCopyright(self._generateCopyright()) 542 self.shcppg.setHeader(self._generateStringHelperHeaderCpp()) 543 self.shcppg.setBody(self._generateStringHelperFunctionsCpp()) 544 self.shcppg.generate() 545 546 # Generate c-style .h file that contains functions for printing structs 547 def generateValidateHelper(self): 548 print("Generating struct validate helper") 549 self.vhg.setCopyright(self._generateCopyright()) 550 self.vhg.setHeader(self._generateValidateHelperHeader()) 551 self.vhg.setBody(self._generateValidateHelperFunctions()) 552 self.vhg.generate() 553 554 def generateSizeHelper(self): 555 print("Generating struct size helper") 556 self.size_helper_gen.setCopyright(self._generateCopyright()) 557 self.size_helper_gen.setHeader(self._generateSizeHelperHeader()) 558 self.size_helper_gen.setBody(self._generateSizeHelperFunctions()) 559 self.size_helper_gen.generate() 560 561 def generateSizeHelperC(self): 562 print("Generating struct size helper c") 563 self.size_helper_c_gen.setCopyright(self._generateCopyright()) 564 self.size_helper_c_gen.setHeader(self._generateSizeHelperHeaderC()) 565 self.size_helper_c_gen.setBody(self._generateSizeHelperFunctionsC()) 566 self.size_helper_c_gen.generate() 567 568 def _generateCopyright(self): 569 copyright = [] 570 copyright.append('/* THIS FILE IS GENERATED. DO NOT EDIT. */'); 571 copyright.append(''); 572 copyright.append('/*'); 573 copyright.append(' * Vulkan'); 574 copyright.append(' *'); 575 copyright.append(' * Copyright (c) 2015-2016 The Khronos Group Inc.'); 576 copyright.append(' * Copyright (c) 2015-2016 Valve Corporation.'); 577 copyright.append(' * Copyright (c) 2015-2016 LunarG, Inc.'); 578 copyright.append(' * Copyright (c) 2015-2016 Google Inc.'); 579 copyright.append(' *'); 580 copyright.append(' * Permission is hereby granted, free of charge, to any person obtaining a'); 581 copyright.append(' * copy of this software and associated documentation files (the "Materials"),'); 582 copyright.append(' * to deal in the Materials without restriction, including without limitation'); 583 copyright.append(' * the rights to use, copy, modify, merge, publish, distribute, sublicense,'); 584 copyright.append(' * and/or sell copies of the Materials, and to permit persons to whom the'); 585 copyright.append(' * Materials is furnished to do so, subject to the following conditions:'); 586 copyright.append(' *'); 587 copyright.append(' * The above copyright notice and this permission notice shall be included'); 588 copyright.append(' * in all copies or substantial portions of the Materials.'); 589 copyright.append(' *'); 590 copyright.append(' * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR'); 591 copyright.append(' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,'); 592 copyright.append(' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.'); 593 copyright.append(' *'); 594 copyright.append(' * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,'); 595 copyright.append(' * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR'); 596 copyright.append(' * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE'); 597 copyright.append(' * USE OR OTHER DEALINGS IN THE MATERIALS'); 598 copyright.append(' *'); 599 copyright.append(' * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>'); 600 copyright.append(' * Author: Tobin Ehlis <tobin@lunarg.com>'); 601 copyright.append(' */'); 602 copyright.append(''); 603 return "\n".join(copyright) 604 605 def _generateCppHeader(self): 606 header = [] 607 header.append("//#includes, #defines, globals and such...\n") 608 header.append("#include <stdio.h>\n#include <%s>\n#include <%s_enum_string_helper.h>\n" % (os.path.basename(self.header_filename), self.api_prefix)) 609 return "".join(header) 610 611 def _generateClassDefinition(self): 612 class_def = [] 613 if 'vk' == self.api: 614 class_def.append(self._generateDynamicPrintFunctions()) 615 for s in sorted(self.struct_dict): 616 class_def.append("\n// %s class definition" % self.get_class_name(s)) 617 class_def.append(self._generateConstructorDefinitions(s)) 618 class_def.append(self._generateDestructorDefinitions(s)) 619 class_def.append(self._generateDisplayDefinitions(s)) 620 return "\n".join(class_def) 621 622 def _generateConstructorDefinitions(self, s): 623 con_defs = [] 624 con_defs.append("%s::%s() : m_struct(), m_indent(0), m_dummy_prefix('\\0'), m_origStructAddr(NULL) {}" % (self.get_class_name(s), self.get_class_name(s))) 625 # TODO : This is a shallow copy of ptrs 626 con_defs.append("%s::%s(%s* pInStruct) : m_indent(0), m_dummy_prefix('\\0')\n{\n m_struct = *pInStruct;\n m_origStructAddr = pInStruct;\n}" % (self.get_class_name(s), self.get_class_name(s), typedef_fwd_dict[s])) 627 con_defs.append("%s::%s(const %s* pInStruct) : m_indent(0), m_dummy_prefix('\\0')\n{\n m_struct = *pInStruct;\n m_origStructAddr = pInStruct;\n}" % (self.get_class_name(s), self.get_class_name(s), typedef_fwd_dict[s])) 628 return "\n".join(con_defs) 629 630 def _generateDestructorDefinitions(self, s): 631 return "%s::~%s() {}" % (self.get_class_name(s), self.get_class_name(s)) 632 633 def _generateDynamicPrintFunctions(self): 634 dp_funcs = [] 635 dp_funcs.append("\nvoid dynamic_display_full_txt(const void* pStruct, uint32_t indent)\n{\n // Cast to APP_INFO ptr initially just to pull sType off struct") 636 dp_funcs.append(" VkStructureType sType = ((VkApplicationInfo*)pStruct)->sType;\n") 637 dp_funcs.append(" switch (sType)\n {") 638 for e in enum_type_dict: 639 class_num = 0 640 if "StructureType" in e: 641 for v in sorted(enum_type_dict[e]): 642 struct_name = get_struct_name_from_struct_type(v) 643 if struct_name not in self.struct_dict: 644 continue 645 646 class_name = self.get_class_name(struct_name) 647 instance_name = "swc%i" % class_num 648 dp_funcs.append(" case %s:\n {" % (v)) 649 dp_funcs.append(" %s %s((%s*)pStruct);" % (class_name, instance_name, struct_name)) 650 dp_funcs.append(" %s.set_indent(indent);" % (instance_name)) 651 dp_funcs.append(" %s.display_full_txt();" % (instance_name)) 652 dp_funcs.append(" }") 653 dp_funcs.append(" break;") 654 class_num += 1 655 dp_funcs.append(" }") 656 dp_funcs.append("}\n") 657 return "\n".join(dp_funcs) 658 659 def _get_func_name(self, struct, mid_str): 660 return "%s_%s_%s" % (self.api_prefix, mid_str, struct.lower().strip("_")) 661 662 def _get_sh_func_name(self, struct): 663 return self._get_func_name(struct, 'print') 664 665 def _get_vh_func_name(self, struct): 666 return self._get_func_name(struct, 'validate') 667 668 def _get_size_helper_func_name(self, struct): 669 return self._get_func_name(struct, 'size') 670 671 # Return elements to create formatted string for given struct member 672 def _get_struct_print_formatted(self, struct_member, pre_var_name="prefix", postfix = "\\n", struct_var_name="pStruct", struct_ptr=True, print_array=False): 673 struct_op = "->" 674 if not struct_ptr: 675 struct_op = "." 676 member_name = struct_member['name'] 677 print_type = "p" 678 cast_type = "" 679 member_post = "" 680 array_index = "" 681 member_print_post = "" 682 print_delimiter = "%" 683 if struct_member['array'] and 'char' in struct_member['type'].lower(): # just print char array as string 684 if member_name.startswith('pp'): # TODO : Only printing first element of dynam array of char* for now 685 member_post = "[0]" 686 print_type = "s" 687 print_array = False 688 elif struct_member['array'] and not print_array: 689 # Just print base address of array when not full print_array 690 cast_type = "(void*)" 691 elif is_type(struct_member['type'], 'enum'): 692 cast_type = "string_%s" % struct_member['type'] 693 if struct_member['ptr']: 694 struct_var_name = "*" + struct_var_name 695 print_type = "s" 696 elif is_type(struct_member['type'], 'struct'): # print struct address for now 697 cast_type = "(void*)" 698 if not struct_member['ptr']: 699 cast_type = "(void*)&" 700 elif 'bool' in struct_member['type'].lower(): 701 print_type = "s" 702 member_post = ' ? "TRUE" : "FALSE"' 703 elif 'float' in struct_member['type']: 704 print_type = "f" 705 elif 'uint64' in struct_member['type'] or 'gpusize' in struct_member['type'].lower(): 706 print_type = '" PRId64 "' 707 elif 'uint8' in struct_member['type']: 708 print_type = "hu" 709 elif 'size' in struct_member['type'].lower(): 710 print_type = '" PRINTF_SIZE_T_SPECIFIER "' 711 print_delimiter = "" 712 elif True in [ui_str.lower() in struct_member['type'].lower() for ui_str in ['uint', 'flags', 'samplemask']]: 713 print_type = "u" 714 elif 'int' in struct_member['type']: 715 print_type = "i" 716 elif struct_member['ptr']: 717 pass 718 else: 719 #print("Unhandled struct type: %s" % struct_member['type']) 720 cast_type = "(void*)" 721 if print_array and struct_member['array']: 722 member_print_post = "[%u]" 723 array_index = " i," 724 member_post = "[i]" 725 print_out = "%%s%s%s = %s%s%s" % (member_name, member_print_post, print_delimiter, print_type, postfix) # section of print that goes inside of quotes 726 print_arg = ", %s,%s %s(%s%s%s)%s" % (pre_var_name, array_index, cast_type, struct_var_name, struct_op, member_name, member_post) # section of print passed to portion in quotes 727 if self.no_addr and "p" == print_type: 728 print_out = "%%s%s%s = addr\\n" % (member_name, member_print_post) # section of print that goes inside of quotes 729 print_arg = ", %s" % (pre_var_name) 730 return (print_out, print_arg) 731 732 def _generateStringHelperFunctions(self): 733 sh_funcs = [] 734 # We do two passes, first pass just generates prototypes for all the functsions 735 for s in sorted(self.struct_dict): 736 sh_funcs.append('char* %s(const %s* pStruct, const char* prefix);' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) 737 sh_funcs.append('') 738 sh_funcs.append('#if defined(_WIN32)') 739 sh_funcs.append('// Microsoft did not implement C99 in Visual Studio; but started adding it with') 740 sh_funcs.append('// VS2013. However, VS2013 still did not have snprintf(). The following is a') 741 sh_funcs.append('// work-around.') 742 sh_funcs.append('#define snprintf _snprintf') 743 sh_funcs.append('#endif // _WIN32\n') 744 for s in sorted(self.struct_dict): 745 p_out = "" 746 p_args = "" 747 stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs 748 # This pre-pass flags embedded structs and pNext 749 for m in sorted(self.struct_dict[s]): 750 if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): 751 stp_list.append(self.struct_dict[s][m]) 752 sh_funcs.append('char* %s(const %s* pStruct, const char* prefix)\n{\n char* str;' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) 753 sh_funcs.append(" size_t len;") 754 num_stps = len(stp_list); 755 total_strlen_str = '' 756 if 0 != num_stps: 757 sh_funcs.append(" char* tmpStr;") 758 sh_funcs.append(' char* extra_indent = (char*)malloc(strlen(prefix) + 3);') 759 sh_funcs.append(' strcpy(extra_indent, " ");') 760 sh_funcs.append(' strncat(extra_indent, prefix, strlen(prefix));') 761 sh_funcs.append(' char* stp_strs[%i];' % num_stps) 762 for index in range(num_stps): 763 # If it's an array, print all of the elements 764 # If it's a ptr, print thing it's pointing to 765 # Non-ptr struct case. Print the struct using its address 766 struct_deref = '&' 767 if 1 < stp_list[index]['full_type'].count('*'): 768 struct_deref = '' 769 if (stp_list[index]['ptr']): 770 sh_funcs.append(' if (pStruct->%s) {' % stp_list[index]['name']) 771 if 'pNext' == stp_list[index]['name']: 772 sh_funcs.append(' tmpStr = dynamic_display((void*)pStruct->pNext, prefix);') 773 sh_funcs.append(' len = 256+strlen(tmpStr);') 774 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);' % index) 775 if self.no_addr: 776 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (addr)\\n%%s", prefix, tmpStr);' % index) 777 else: 778 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (%%p)\\n%%s", prefix, (void*)pStruct->pNext, tmpStr);' % index) 779 sh_funcs.append(' free(tmpStr);') 780 else: 781 if stp_list[index]['name'] in ['pImageViews', 'pBufferViews']: 782 # TODO : This is a quick hack to handle these arrays of ptrs 783 sh_funcs.append(' tmpStr = %s(&pStruct->%s[0], extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) 784 else: 785 sh_funcs.append(' tmpStr = %s(pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) 786 sh_funcs.append(' len = 256+strlen(tmpStr)+strlen(prefix);') 787 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);' % (index)) 788 if self.no_addr: 789 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);' % (index, stp_list[index]['name'])) 790 else: 791 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (%%p)\\n%%s", prefix, (void*)pStruct->%s, tmpStr);' % (index, stp_list[index]['name'], stp_list[index]['name'])) 792 sh_funcs.append(' }') 793 sh_funcs.append(" else\n stp_strs[%i] = \"\";" % (index)) 794 elif stp_list[index]['array']: 795 sh_funcs.append(' tmpStr = %s(&pStruct->%s[0], extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) 796 sh_funcs.append(' len = 256+strlen(tmpStr);') 797 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);' % (index)) 798 if self.no_addr: 799 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s[0] (addr)\\n%%s", prefix, tmpStr);' % (index, stp_list[index]['name'])) 800 else: 801 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s[0] (%%p)\\n%%s", prefix, (void*)&pStruct->%s[0], tmpStr);' % (index, stp_list[index]['name'], stp_list[index]['name'])) 802 else: 803 sh_funcs.append(' tmpStr = %s(&pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) 804 sh_funcs.append(' len = 256+strlen(tmpStr);') 805 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);' % (index)) 806 if self.no_addr: 807 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);' % (index, stp_list[index]['name'])) 808 else: 809 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (%%p)\\n%%s", prefix, (void*)&pStruct->%s, tmpStr);' % (index, stp_list[index]['name'], stp_list[index]['name'])) 810 total_strlen_str += 'strlen(stp_strs[%i]) + ' % index 811 sh_funcs.append(' len = %ssizeof(char)*1024;' % (total_strlen_str)) 812 sh_funcs.append(' str = (char*)malloc(len);') 813 sh_funcs.append(' snprintf(str, len, "') 814 for m in sorted(self.struct_dict[s]): 815 (p_out1, p_args1) = self._get_struct_print_formatted(self.struct_dict[s][m]) 816 p_out += p_out1 817 p_args += p_args1 818 p_out += '"' 819 p_args += ");" 820 sh_funcs[-1] = '%s%s%s' % (sh_funcs[-1], p_out, p_args) 821 if 0 != num_stps: 822 sh_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {' % (num_stps-1)) 823 sh_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {') 824 sh_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));') 825 sh_funcs.append(' free(stp_strs[stp_index]);') 826 sh_funcs.append(' }') 827 sh_funcs.append(' }') 828 sh_funcs.append(' free(extra_indent);') 829 sh_funcs.append(" return str;\n}") 830 # Add function to dynamically print out unknown struct 831 sh_funcs.append("char* dynamic_display(const void* pStruct, const char* prefix)\n{") 832 sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct") 833 sh_funcs.append(" if (pStruct == NULL) {") 834 sh_funcs.append(" return NULL;") 835 sh_funcs.append(" }") 836 sh_funcs.append(" VkStructureType sType = ((VkApplicationInfo*)pStruct)->sType;") 837 sh_funcs.append(' char indent[100];\n strcpy(indent, " ");\n strcat(indent, prefix);') 838 sh_funcs.append(" switch (sType)\n {") 839 for e in enum_type_dict: 840 if "StructureType" in e: 841 for v in sorted(enum_type_dict[e]): 842 struct_name = get_struct_name_from_struct_type(v) 843 if struct_name not in self.struct_dict: 844 continue 845 print_func_name = self._get_sh_func_name(struct_name) 846 sh_funcs.append(' case %s:\n {' % (v)) 847 sh_funcs.append(' return %s((%s*)pStruct, indent);' % (print_func_name, struct_name)) 848 sh_funcs.append(' }') 849 sh_funcs.append(' break;') 850 sh_funcs.append(" default:") 851 sh_funcs.append(" return NULL;") 852 sh_funcs.append(" }") 853 sh_funcs.append("}") 854 return "\n".join(sh_funcs) 855 856 def _generateStringHelperFunctionsCpp(self): 857 # declare str & tmp str 858 # declare array of stringstreams for every struct ptr in current struct 859 # declare array of stringstreams for every non-string element in current struct 860 # For every struct ptr, if non-Null, then set its string, else set to NULL str 861 # For every non-string element, set its string stream 862 # create and return final string 863 sh_funcs = [] 864 # First generate prototypes for every struct 865 # XXX - REMOVE this comment 866 lineinfo = sourcelineinfo() 867 sh_funcs.append('%s' % lineinfo.get()) 868 exclude_struct_list = ['VkAndroidSurfaceCreateInfoKHR', 869 'VkMirSurfaceCreateInfoKHR', 870 'VkWaylandSurfaceCreateInfoKHR', 871 'VkXlibSurfaceCreateInfoKHR'] 872 if sys.platform == 'win32': 873 exclude_struct_list.append('VkXcbSurfaceCreateInfoKHR') 874 else: 875 exclude_struct_list.append('VkWin32SurfaceCreateInfoKHR') 876 for s in sorted(self.struct_dict): 877 if (typedef_fwd_dict[s] not in exclude_struct_list): 878 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 879 sh_funcs.append("#ifdef VK_USE_PLATFORM_XCB_KHR") 880 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 881 sh_funcs.append("#ifdef VK_USE_PLATFORM_WIN32_KHR") 882 sh_funcs.append('string %s(const %s* pStruct, const string prefix);' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) 883 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 884 sh_funcs.append("#endif //VK_USE_PLATFORM_WIN32_KHR") 885 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 886 sh_funcs.append("#endif //VK_USE_PLATFORM_XCB_KHR") 887 sh_funcs.append('\n') 888 sh_funcs.append('%s' % lineinfo.get()) 889 for s in sorted(self.struct_dict): 890 num_non_enum_elems = [(is_type(self.struct_dict[s][elem]['type'], 'enum') and not self.struct_dict[s][elem]['ptr']) for elem in self.struct_dict[s]].count(False) 891 stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs 892 # This pre-pass flags embedded structs and pNext 893 for m in sorted(self.struct_dict[s]): 894 if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct') or self.struct_dict[s][m]['array']: 895 # TODO: This is a tmp workaround 896 if 'ppActiveLayerNames' not in self.struct_dict[s][m]['name']: 897 stp_list.append(self.struct_dict[s][m]) 898 if (typedef_fwd_dict[s] in exclude_struct_list): 899 continue 900 sh_funcs.append('%s' % lineinfo.get()) 901 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 902 sh_funcs.append("#ifdef VK_USE_PLATFORM_XCB_KHR") 903 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 904 sh_funcs.append("#ifdef VK_USE_PLATFORM_WIN32_KHR") 905 sh_funcs.append('string %s(const %s* pStruct, const string prefix)\n{' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) 906 sh_funcs.append('%s' % lineinfo.get()) 907 indent = ' ' 908 sh_funcs.append('%susing namespace StreamControl;' % (indent)) 909 sh_funcs.append('%sstring final_str;' % (indent)) 910 sh_funcs.append('%sstring tmp_str;' % (indent)) 911 sh_funcs.append('%sstring extra_indent = " " + prefix;' % (indent)) 912 if (0 != num_non_enum_elems): 913 sh_funcs.append('%sstringstream ss[%u];' % (indent, num_non_enum_elems)) 914 num_stps = len(stp_list) 915 # First generate code for any embedded structs or arrays 916 if 0 < num_stps: 917 sh_funcs.append('%sstring stp_strs[%u];' % (indent, num_stps)) 918 idx_ss_decl = False # Make sure to only decl this once 919 for index in range(num_stps): 920 addr_char = '&' 921 if 1 < stp_list[index]['full_type'].count('*'): 922 addr_char = '' 923 if stp_list[index]['array']: 924 sh_funcs.append('%s' % lineinfo.get()) 925 if stp_list[index]['dyn_array']: 926 sh_funcs.append('%s' % lineinfo.get()) 927 array_count = 'pStruct->%s' % (stp_list[index]['array_size']) 928 else: 929 sh_funcs.append('%s' % lineinfo.get()) 930 array_count = '%s' % (stp_list[index]['array_size']) 931 sh_funcs.append('%s' % lineinfo.get()) 932 sh_funcs.append('%sstp_strs[%u] = "";' % (indent, index)) 933 if not idx_ss_decl: 934 sh_funcs.append('%sstringstream index_ss;' % (indent)) 935 idx_ss_decl = True 936 if (stp_list[index]['name'] == 'pQueueFamilyIndices'): 937 if (typedef_fwd_dict[s] == 'VkSwapchainCreateInfoKHR'): 938 sh_funcs.append('%sif (pStruct->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {' % (indent)) 939 else: 940 sh_funcs.append('%sif (pStruct->sharingMode == VK_SHARING_MODE_CONCURRENT) {' % (indent)) 941 indent += ' ' 942 if (stp_list[index]['name'] == 'pImageInfo'): 943 sh_funcs.append('%sif ((pStruct->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||' % (indent)) 944 sh_funcs.append('%s (pStruct->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||' % (indent)) 945 sh_funcs.append('%s (pStruct->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||' % (indent)) 946 sh_funcs.append('%s (pStruct->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)) {' % (indent)) 947 indent += ' ' 948 elif (stp_list[index]['name'] == 'pBufferInfo'): 949 sh_funcs.append('%sif ((pStruct->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||' % (indent)) 950 sh_funcs.append('%s (pStruct->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||' % (indent)) 951 sh_funcs.append('%s (pStruct->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||' % (indent)) 952 sh_funcs.append('%s (pStruct->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {' % (indent)) 953 indent += ' ' 954 elif (stp_list[index]['name'] == 'pTexelBufferView'): 955 sh_funcs.append('%sif ((pStruct->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||' % (indent)) 956 sh_funcs.append('%s (pStruct->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {' % (indent)) 957 indent += ' ' 958 if stp_list[index]['dyn_array']: 959 sh_funcs.append('%sif (pStruct->%s) {' % (indent, stp_list[index]['name'])) 960 indent += ' ' 961 sh_funcs.append('%sfor (uint32_t i = 0; i < %s; i++) {' % (indent, array_count)) 962 indent += ' ' 963 sh_funcs.append('%sindex_ss.str("");' % (indent)) 964 sh_funcs.append('%sindex_ss << i;' % (indent)) 965 if is_type(stp_list[index]['type'], 'enum'): 966 sh_funcs.append('%s' % lineinfo.get()) 967 addr_char = '' 968 #value_print = 'string_%s(%spStruct->%s)' % (self.struct_dict[s][m]['type'], deref, self.struct_dict[s][m]['name']) 969 sh_funcs.append('%sss[%u] << string_%s(pStruct->%s[i]);' % (indent, index, stp_list[index]['type'], stp_list[index]['name'])) 970 sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] = " + ss[%u].str() + "\\n";' % (indent, index, stp_list[index]['name'], index)) 971 elif is_type(stp_list[index]['type'], 'struct'): 972 sh_funcs.append('%s' % lineinfo.get()) 973 sh_funcs.append('%sss[%u] << %spStruct->%s[i];' % (indent, index, addr_char, stp_list[index]['name'])) 974 sh_funcs.append('%stmp_str = %s(%spStruct->%s[i], extra_indent);' % (indent, self._get_sh_func_name(stp_list[index]['type']), addr_char, stp_list[index]['name'])) 975 if self.no_addr: 976 sh_funcs.append('%s' % lineinfo.get()) 977 sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (addr)\\n" + tmp_str;' % (indent, index, stp_list[index]['name'])) 978 else: 979 sh_funcs.append('%s' % lineinfo.get()) 980 sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (" + ss[%u].str() + ")\\n" + tmp_str;' % (indent, index, stp_list[index]['name'], index)) 981 else: 982 sh_funcs.append('%s' % lineinfo.get()) 983 addr_char = '' 984 sh_funcs.append('%sss[%u] << %spStruct->%s[i];' % (indent, index, addr_char, stp_list[index]['name'])) 985 if stp_list[index]['type'] in vulkan.core.objects: 986 sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "].handle = " + ss[%u].str() + "\\n";' % (indent, index, stp_list[index]['name'], index)) 987 else: 988 sh_funcs.append('%sstp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] = " + ss[%u].str() + "\\n";' % (indent, index, stp_list[index]['name'], index)) 989 sh_funcs.append('%s' % lineinfo.get()) 990 sh_funcs.append('%sss[%u].str("");' % (indent, index)) 991 indent = indent[4:] 992 sh_funcs.append('%s}' % (indent)) 993 if stp_list[index]['dyn_array']: 994 indent = indent[4:] 995 sh_funcs.append('%s}' % (indent)) 996 #endif 997 if (stp_list[index]['name'] == 'pQueueFamilyIndices') or (stp_list[index]['name'] == 'pImageInfo') or (stp_list[index]['name'] == 'pBufferInfo') or (stp_list[index]['name'] == 'pTexelBufferView'): 998 indent = indent[4:] 999 sh_funcs.append('%s}' % (indent)) 1000 elif (stp_list[index]['ptr']): 1001 sh_funcs.append('%s' % lineinfo.get()) 1002 sh_funcs.append('%sif (pStruct->%s) {' % (indent, stp_list[index]['name'])) 1003 indent += ' ' 1004 if 'pNext' == stp_list[index]['name']: 1005 sh_funcs.append('%s' % lineinfo.get()) 1006 sh_funcs.append(' tmp_str = dynamic_display((void*)pStruct->pNext, prefix);') 1007 else: 1008 if stp_list[index]['name'] in ['pImageViews', 'pBufferViews']: 1009 # TODO : This is a quick hack to handle these arrays of ptrs 1010 sh_funcs.append('%s' % lineinfo.get()) 1011 sh_funcs.append(' tmp_str = %s(&pStruct->%s[0], extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) 1012 else: 1013 sh_funcs.append('%s' % lineinfo.get()) 1014 sh_funcs.append(' tmp_str = %s(pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) 1015 sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name'])) 1016 if self.no_addr: 1017 sh_funcs.append('%s' % lineinfo.get()) 1018 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) 1019 else: 1020 sh_funcs.append('%s' % lineinfo.get()) 1021 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) 1022 sh_funcs.append(' ss[%u].str("");' % (index)) 1023 sh_funcs.append(' }') 1024 sh_funcs.append(' else') 1025 sh_funcs.append(' stp_strs[%u] = "";' % index) 1026 else: 1027 sh_funcs.append('%s' % lineinfo.get()) 1028 sh_funcs.append(' tmp_str = %s(&pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) 1029 sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name'])) 1030 if self.no_addr: 1031 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) 1032 sh_funcs.append('%s' % lineinfo.get()) 1033 else: 1034 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) 1035 sh_funcs.append('%s' % lineinfo.get()) 1036 sh_funcs.append(' ss[%u].str("");' % index) 1037 # Now print one-line info for all data members 1038 index = 0 1039 final_str = '' 1040 for m in sorted(self.struct_dict[s]): 1041 if not is_type(self.struct_dict[s][m]['type'], 'enum'): 1042 if is_type(self.struct_dict[s][m]['type'], 'struct') and not self.struct_dict[s][m]['ptr']: 1043 if self.no_addr: 1044 sh_funcs.append('%s' % lineinfo.get()) 1045 sh_funcs.append(' ss[%u].str("addr");' % (index)) 1046 else: 1047 sh_funcs.append('%s' % lineinfo.get()) 1048 sh_funcs.append(' ss[%u] << &pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) 1049 elif self.struct_dict[s][m]['array']: 1050 sh_funcs.append('%s' % lineinfo.get()) 1051 sh_funcs.append(' ss[%u] << (void*)pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) 1052 elif 'bool' in self.struct_dict[s][m]['type'].lower(): 1053 sh_funcs.append('%s' % lineinfo.get()) 1054 sh_funcs.append(' ss[%u].str(pStruct->%s ? "TRUE" : "FALSE");' % (index, self.struct_dict[s][m]['name'])) 1055 elif 'uint8' in self.struct_dict[s][m]['type'].lower(): 1056 sh_funcs.append('%s' % lineinfo.get()) 1057 sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) 1058 elif 'void' in self.struct_dict[s][m]['type'].lower() and self.struct_dict[s][m]['ptr']: 1059 sh_funcs.append('%s' % lineinfo.get()) 1060 sh_funcs.append(' if (StreamControl::writeAddress)') 1061 sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) 1062 sh_funcs.append(' else') 1063 sh_funcs.append(' ss[%u].str("address");' % (index)) 1064 elif 'char' in self.struct_dict[s][m]['type'].lower() and self.struct_dict[s][m]['ptr']: 1065 sh_funcs.append('%s' % lineinfo.get()) 1066 sh_funcs.append(' if (pStruct->%s != NULL) {' % self.struct_dict[s][m]['name']) 1067 sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) 1068 sh_funcs.append(' } else {') 1069 sh_funcs.append(' ss[%u] << "";' % index) 1070 sh_funcs.append(' }') 1071 else: 1072 sh_funcs.append('%s' % lineinfo.get()) 1073 (po, pa) = self._get_struct_print_formatted(self.struct_dict[s][m]) 1074 if "addr" in po: # or self.struct_dict[s][m]['ptr']: 1075 sh_funcs.append(' ss[%u].str("addr");' % (index)) 1076 elif not self.struct_dict[s][m]['ptr'] and self.struct_dict[s][m]['type'] in vulkan.core.objects: 1077 sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) 1078 else: 1079 sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) 1080 value_print = 'ss[%u].str()' % index 1081 index += 1 1082 else: 1083 # For an non-empty array of enums just print address w/ note that array will be displayed below 1084 if self.struct_dict[s][m]['ptr']: 1085 sh_funcs.append('%s' % lineinfo.get()) 1086 sh_funcs.append(' if (pStruct->%s)' % (self.struct_dict[s][m]['name'])) 1087 sh_funcs.append(' ss[%u] << pStruct->%s << " (See individual array values below)";' % (index, self.struct_dict[s][m]['name'])) 1088 sh_funcs.append(' else') 1089 sh_funcs.append(' ss[%u].str("NULL");' % (index)) 1090 value_print = 'ss[%u].str()' % index 1091 index += 1 1092 # For single enum just print the string representation 1093 else: 1094 value_print = 'string_%s(pStruct->%s)' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name']) 1095 final_str += ' + prefix + "%s = " + %s + "\\n"' % (self.struct_dict[s][m]['name'], value_print) 1096 final_str = final_str[3:] # strip off the initial ' + ' 1097 if 0 != num_stps: # Append data for any embedded structs 1098 final_str += " + %s" % " + ".join(['stp_strs[%u]' % n for n in reversed(range(num_stps))]) 1099 sh_funcs.append('%s' % lineinfo.get()) 1100 sh_funcs.append(' final_str = %s;' % final_str) 1101 sh_funcs.append(' return final_str;\n}') 1102 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 1103 sh_funcs.append("#endif //VK_USE_PLATFORM_WIN32_KHR") 1104 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 1105 sh_funcs.append("#endif //VK_USE_PLATFORM_XCB_KHR") 1106 # Add function to return a string value for input void* 1107 sh_funcs.append('%s' % lineinfo.get()) 1108 sh_funcs.append("string string_convert_helper(const void* toString, const string prefix)\n{") 1109 sh_funcs.append(" using namespace StreamControl;") 1110 sh_funcs.append(" stringstream ss;") 1111 sh_funcs.append(' ss << toString;') 1112 sh_funcs.append(' string final_str = prefix + ss.str();') 1113 sh_funcs.append(" return final_str;") 1114 sh_funcs.append("}") 1115 sh_funcs.append('%s' % lineinfo.get()) 1116 # Add function to return a string value for input uint64_t 1117 sh_funcs.append("string string_convert_helper(const uint64_t toString, const string prefix)\n{") 1118 sh_funcs.append(" using namespace StreamControl;") 1119 sh_funcs.append(" stringstream ss;") 1120 sh_funcs.append(' ss << toString;') 1121 sh_funcs.append(' string final_str = prefix + ss.str();') 1122 sh_funcs.append(" return final_str;") 1123 sh_funcs.append("}") 1124 sh_funcs.append('%s' % lineinfo.get()) 1125 # Add function to return a string value for input VkSurfaceFormatKHR* 1126 sh_funcs.append("string string_convert_helper(VkSurfaceFormatKHR toString, const string prefix)\n{") 1127 sh_funcs.append(' string final_str = prefix + "format = " + string_VkFormat(toString.format) + "format = " + string_VkColorSpaceKHR(toString.colorSpace);') 1128 sh_funcs.append(" return final_str;") 1129 sh_funcs.append("}") 1130 sh_funcs.append('%s' % lineinfo.get()) 1131 # Add function to dynamically print out unknown struct 1132 sh_funcs.append("string dynamic_display(const void* pStruct, const string prefix)\n{") 1133 sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct") 1134 sh_funcs.append(" if (pStruct == NULL) {\n") 1135 sh_funcs.append(" return string();") 1136 sh_funcs.append(" }\n") 1137 sh_funcs.append(" VkStructureType sType = ((VkApplicationInfo*)pStruct)->sType;") 1138 sh_funcs.append(' string indent = " ";') 1139 sh_funcs.append(' indent += prefix;') 1140 sh_funcs.append(" switch (sType)\n {") 1141 for e in enum_type_dict: 1142 if "StructureType" in e: 1143 for v in sorted(enum_type_dict[e]): 1144 struct_name = get_struct_name_from_struct_type(v) 1145 if struct_name not in self.struct_dict: 1146 continue 1147 print_func_name = self._get_sh_func_name(struct_name) 1148 #sh_funcs.append('string %s(const %s* pStruct, const string prefix);' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) 1149 sh_funcs.append(' case %s:\n {' % (v)) 1150 sh_funcs.append(' return %s((%s*)pStruct, indent);' % (print_func_name, struct_name)) 1151 sh_funcs.append(' }') 1152 sh_funcs.append(' break;') 1153 sh_funcs.append(" default:") 1154 sh_funcs.append(" return string();") 1155 sh_funcs.append('%s' % lineinfo.get()) 1156 sh_funcs.append(" }") 1157 sh_funcs.append("}") 1158 return "\n".join(sh_funcs) 1159 1160 def _genStructMemberPrint(self, member, s, array, struct_array): 1161 (p_out, p_arg) = self._get_struct_print_formatted(self.struct_dict[s][member], pre_var_name="&m_dummy_prefix", struct_var_name="m_struct", struct_ptr=False, print_array=True) 1162 extra_indent = "" 1163 if array: 1164 extra_indent = " " 1165 if is_type(self.struct_dict[s][member]['type'], 'struct'): # print struct address for now 1166 struct_array.insert(0, self.struct_dict[s][member]) 1167 elif self.struct_dict[s][member]['ptr']: 1168 # Special case for void* named "pNext" 1169 if "void" in self.struct_dict[s][member]['type'] and "pNext" == self.struct_dict[s][member]['name']: 1170 struct_array.insert(0, self.struct_dict[s][member]) 1171 return (' %sprintf("%%*s %s", m_indent, ""%s);' % (extra_indent, p_out, p_arg), struct_array) 1172 1173 def _generateDisplayDefinitions(self, s): 1174 disp_def = [] 1175 struct_array = [] 1176 # Single-line struct print function 1177 disp_def.append("// Output 'structname = struct_address' on a single line") 1178 disp_def.append("void %s::display_single_txt()\n{" % self.get_class_name(s)) 1179 disp_def.append(' printf(" %%*s%s = %%p", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) 1180 disp_def.append("}\n") 1181 # Private helper function to print struct members 1182 disp_def.append("// Private helper function that displays the members of the wrapped struct") 1183 disp_def.append("void %s::display_struct_members()\n{" % self.get_class_name(s)) 1184 i_declared = False 1185 for member in sorted(self.struct_dict[s]): 1186 # TODO : Need to display each member based on its type 1187 # TODO : Need to handle pNext which are structs, but of void* type 1188 # Can grab struct type off of header of struct pointed to 1189 # TODO : Handle Arrays 1190 if self.struct_dict[s][member]['array']: 1191 # Create for loop to print each element of array 1192 if not i_declared: 1193 disp_def.append(' uint32_t i;') 1194 i_declared = True 1195 disp_def.append(' for (i = 0; i<%s; i++) {' % self.struct_dict[s][member]['array_size']) 1196 (return_str, struct_array) = self._genStructMemberPrint(member, s, True, struct_array) 1197 disp_def.append(return_str) 1198 disp_def.append(' }') 1199 else: 1200 (return_str, struct_array) = self._genStructMemberPrint(member, s, False, struct_array) 1201 disp_def.append(return_str) 1202 disp_def.append("}\n") 1203 i_declared = False 1204 # Basic print function to display struct members 1205 disp_def.append("// Output all struct elements, each on their own line") 1206 disp_def.append("void %s::display_txt()\n{" % self.get_class_name(s)) 1207 disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) 1208 disp_def.append(' this->display_struct_members();') 1209 disp_def.append("}\n") 1210 # Advanced print function to display current struct and contents of any pointed-to structs 1211 disp_def.append("// Output all struct elements, and for any structs pointed to, print complete contents") 1212 disp_def.append("void %s::display_full_txt()\n{" % self.get_class_name(s)) 1213 disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) 1214 disp_def.append(' this->display_struct_members();') 1215 class_num = 0 1216 # TODO : Need to handle arrays of structs here 1217 for ms in struct_array: 1218 swc_name = "class%s" % str(class_num) 1219 if ms['array']: 1220 if not i_declared: 1221 disp_def.append(' uint32_t i;') 1222 i_declared = True 1223 disp_def.append(' for (i = 0; i<%s; i++) {' % ms['array_size']) 1224 #disp_def.append(" if (m_struct.%s[i]) {" % (ms['name'])) 1225 disp_def.append(" %s %s(&(m_struct.%s[i]));" % (self.get_class_name(ms['type']), swc_name, ms['name'])) 1226 disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name)) 1227 disp_def.append(" %s.display_full_txt();" % (swc_name)) 1228 #disp_def.append(' }') 1229 disp_def.append(' }') 1230 elif 'pNext' == ms['name']: 1231 # Need some code trickery here 1232 # I'm thinking have a generated function that takes pNext ptr value 1233 # then it checks sType and in large switch statement creates appropriate 1234 # wrapper class type and then prints contents 1235 disp_def.append(" if (m_struct.%s) {" % (ms['name'])) 1236 #disp_def.append(' printf("%*s This is where we would call dynamic print function\\n", m_indent, "");') 1237 disp_def.append(' dynamic_display_full_txt(m_struct.%s, m_indent);' % (ms['name'])) 1238 disp_def.append(" }") 1239 else: 1240 if ms['ptr']: 1241 disp_def.append(" if (m_struct.%s) {" % (ms['name'])) 1242 disp_def.append(" %s %s(m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name'])) 1243 else: 1244 disp_def.append(" if (&m_struct.%s) {" % (ms['name'])) 1245 disp_def.append(" %s %s(&m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name'])) 1246 disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name)) 1247 disp_def.append(" %s.display_full_txt();\n }" % (swc_name)) 1248 class_num += 1 1249 disp_def.append("}\n") 1250 return "\n".join(disp_def) 1251 1252 def _generateStringHelperHeader(self): 1253 header = [] 1254 header.append("//#includes, #defines, globals and such...\n") 1255 for f in self.include_headers: 1256 if 'vk_enum_string_helper' not in f: 1257 header.append("#include <%s>\n" % f) 1258 header.append('#include "vk_enum_string_helper.h"\n\n// Function Prototypes\n') 1259 header.append("char* dynamic_display(const void* pStruct, const char* prefix);\n") 1260 return "".join(header) 1261 1262 def _generateStringHelperHeaderCpp(self): 1263 header = [] 1264 header.append("//#includes, #defines, globals and such...\n") 1265 for f in self.include_headers: 1266 if 'vk_enum_string_helper' not in f: 1267 header.append("#include <%s>\n" % f) 1268 header.append('#include "vk_enum_string_helper.h"\n') 1269 header.append('using namespace std;\n\n// Function Prototypes\n') 1270 header.append('\n') 1271 header.append('namespace StreamControl\n') 1272 header.append('{\n') 1273 header.append('bool writeAddress = true;\n') 1274 header.append('template <typename T>\n') 1275 header.append('std::ostream& operator<< (std::ostream &out, T const* pointer)\n') 1276 header.append('{\n') 1277 header.append(' if(writeAddress)\n') 1278 header.append(' {\n') 1279 header.append(' out.operator<<(pointer);\n') 1280 header.append(' }\n') 1281 header.append(' else\n') 1282 header.append(' {\n') 1283 header.append(' std::operator<<(out, "address");\n') 1284 header.append(' }\n') 1285 header.append(' return out;\n') 1286 header.append('}\n') 1287 header.append('std::ostream& operator<<(std::ostream &out, char const*const s)\n') 1288 header.append('{\n') 1289 header.append(' return std::operator<<(out, s);\n') 1290 header.append('}\n') 1291 header.append('}\n') 1292 header.append('\n') 1293 header.append("string dynamic_display(const void* pStruct, const string prefix);\n") 1294 return "".join(header) 1295 1296 def _generateValidateHelperFunctions(self): 1297 sh_funcs = [] 1298 # We do two passes, first pass just generates prototypes for all the functsions 1299 exclude_struct_list = ['VkAndroidSurfaceCreateInfoKHR', 1300 'VkMirSurfaceCreateInfoKHR', 1301 'VkWaylandSurfaceCreateInfoKHR', 1302 'VkXlibSurfaceCreateInfoKHR'] 1303 if sys.platform == 'win32': 1304 exclude_struct_list.append('VkXcbSurfaceCreateInfoKHR') 1305 else: 1306 exclude_struct_list.append('VkWin32SurfaceCreateInfoKHR') 1307 for s in sorted(self.struct_dict): 1308 if (typedef_fwd_dict[s] not in exclude_struct_list): 1309 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 1310 sh_funcs.append("#ifdef VK_USE_PLATFORM_XCB_KHR") 1311 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 1312 sh_funcs.append("#ifdef VK_USE_PLATFORM_WIN32_KHR") 1313 sh_funcs.append('uint32_t %s(const %s* pStruct);' % (self._get_vh_func_name(s), typedef_fwd_dict[s])) 1314 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 1315 sh_funcs.append("#endif //VK_USE_PLATFORM_WIN32_KHR") 1316 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 1317 sh_funcs.append("#endif //VK_USE_PLATFORM_XCB_KHR") 1318 sh_funcs.append('\n') 1319 for s in sorted(self.struct_dict): 1320 if (typedef_fwd_dict[s] in exclude_struct_list): 1321 continue 1322 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 1323 sh_funcs.append("#ifdef VK_USE_PLATFORM_XCB_KHR") 1324 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 1325 sh_funcs.append("#ifdef VK_USE_PLATFORM_WIN32_KHR") 1326 sh_funcs.append('uint32_t %s(const %s* pStruct)\n{' % (self._get_vh_func_name(s), typedef_fwd_dict[s])) 1327 for m in sorted(self.struct_dict[s]): 1328 # TODO : Need to handle arrays of enums like in VkRenderPassCreateInfo struct 1329 if is_type(self.struct_dict[s][m]['type'], 'enum') and not self.struct_dict[s][m]['ptr']: 1330 sh_funcs.append(' if (!validate_%s(pStruct->%s))\n return 0;' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name'])) 1331 # TODO : Need a little refinement to this code to make sure type of struct matches expected input (ptr, const...) 1332 if is_type(self.struct_dict[s][m]['type'], 'struct'): 1333 if (self.struct_dict[s][m]['ptr']): 1334 sh_funcs.append(' if (pStruct->%s && !%s((const %s*)pStruct->%s))\n return 0;' % (self.struct_dict[s][m]['name'], self._get_vh_func_name(self.struct_dict[s][m]['type']), self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name'])) 1335 else: 1336 sh_funcs.append(' if (!%s((const %s*)&pStruct->%s))\n return 0;' % (self._get_vh_func_name(self.struct_dict[s][m]['type']), self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name'])) 1337 sh_funcs.append(" return 1;\n}") 1338 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 1339 sh_funcs.append("#endif //VK_USE_PLATFORM_WIN32_KHR") 1340 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 1341 sh_funcs.append("#endif //VK_USE_PLATFORM_XCB_KHR") 1342 1343 return "\n".join(sh_funcs) 1344 1345 def _generateValidateHelperHeader(self): 1346 header = [] 1347 header.append("//#includes, #defines, globals and such...\n") 1348 for f in self.include_headers: 1349 if 'vk_enum_validate_helper' not in f: 1350 header.append("#include <%s>\n" % f) 1351 header.append('#include "vk_enum_validate_helper.h"\n\n// Function Prototypes\n') 1352 #header.append("char* dynamic_display(const void* pStruct, const char* prefix);\n") 1353 return "".join(header) 1354 1355 def _generateSizeHelperFunctions(self): 1356 sh_funcs = [] 1357 # just generates prototypes for all the functions 1358 exclude_struct_list = ['VkAndroidSurfaceCreateInfoKHR', 1359 'VkMirSurfaceCreateInfoKHR', 1360 'VkWaylandSurfaceCreateInfoKHR', 1361 'VkXlibSurfaceCreateInfoKHR'] 1362 if sys.platform == 'win32': 1363 exclude_struct_list.append('VkXcbSurfaceCreateInfoKHR') 1364 else: 1365 exclude_struct_list.append('VkWin32SurfaceCreateInfoKHR') 1366 for s in sorted(self.struct_dict): 1367 if (typedef_fwd_dict[s] not in exclude_struct_list): 1368 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 1369 sh_funcs.append("#ifdef VK_USE_PLATFORM_XCB_KHR") 1370 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 1371 sh_funcs.append("#ifdef VK_USE_PLATFORM_WIN32_KHR") 1372 sh_funcs.append('size_t %s(const %s* pStruct);' % (self._get_size_helper_func_name(s), typedef_fwd_dict[s])) 1373 if (re.match(r'.*Win32.*', typedef_fwd_dict[s])): 1374 sh_funcs.append("#endif //VK_USE_PLATFORM_WIN32_KHR") 1375 if (re.match(r'.*Xcb.*', typedef_fwd_dict[s])): 1376 sh_funcs.append("#endif //VK_USE_PLATFORM_XCB_KHR") 1377 return "\n".join(sh_funcs) 1378 1379 1380 def _generateSizeHelperFunctionsC(self): 1381 sh_funcs = [] 1382 # generate function definitions 1383 exclude_struct_list = ['VkAndroidSurfaceCreateInfoKHR', 1384 'VkMirSurfaceCreateInfoKHR', 1385 'VkWaylandSurfaceCreateInfoKHR', 1386 'VkXlibSurfaceCreateInfoKHR'] 1387 if sys.platform == 'win32': 1388 exclude_struct_list.append('VkXcbSurfaceCreateInfoKHR') 1389 else: 1390 exclude_struct_list.append('VkWin32SurfaceCreateInfoKHR') 1391 for s in sorted(self.struct_dict): 1392 if (typedef_fwd_dict[s] in exclude_struct_list): 1393 continue 1394 skip_list = [] # Used when struct elements need to be skipped because size already accounted for 1395 sh_funcs.append('size_t %s(const %s* pStruct)\n{' % (self._get_size_helper_func_name(s), typedef_fwd_dict[s])) 1396 indent = ' ' 1397 sh_funcs.append('%ssize_t structSize = 0;' % (indent)) 1398 sh_funcs.append('%sif (pStruct) {' % (indent)) 1399 indent = ' ' 1400 sh_funcs.append('%sstructSize = sizeof(%s);' % (indent, typedef_fwd_dict[s])) 1401 i_decl = False 1402 for m in sorted(self.struct_dict[s]): 1403 if m in skip_list: 1404 continue 1405 if self.struct_dict[s][m]['dyn_array']: 1406 if self.struct_dict[s][m]['full_type'].count('*') > 1: 1407 if not is_type(self.struct_dict[s][m]['type'], 'struct') and not 'char' in self.struct_dict[s][m]['type'].lower(): 1408 if 'ppMemoryBarriers' == self.struct_dict[s][m]['name']: 1409 # TODO : For now be conservative and consider all memBarrier ptrs as largest possible struct 1410 sh_funcs.append('%sstructSize += pStruct->%s*(sizeof(%s*) + sizeof(VkImageMemoryBarrier));' % (indent, self.struct_dict[s][m]['array_size'], self.struct_dict[s][m]['type'])) 1411 else: 1412 sh_funcs.append('%sstructSize += pStruct->%s*(sizeof(%s*) + sizeof(%s));' % (indent, self.struct_dict[s][m]['array_size'], self.struct_dict[s][m]['type'], self.struct_dict[s][m]['type'])) 1413 else: # This is an array of char* or array of struct ptrs 1414 if not i_decl: 1415 sh_funcs.append('%suint32_t i = 0;' % (indent)) 1416 i_decl = True 1417 sh_funcs.append('%sfor (i = 0; i < pStruct->%s; i++) {' % (indent, self.struct_dict[s][m]['array_size'])) 1418 indent = ' ' 1419 if is_type(self.struct_dict[s][m]['type'], 'struct'): 1420 sh_funcs.append('%sstructSize += (sizeof(%s*) + %s(pStruct->%s[i]));' % (indent, self.struct_dict[s][m]['type'], self._get_size_helper_func_name(self.struct_dict[s][m]['type']), self.struct_dict[s][m]['name'])) 1421 else: 1422 sh_funcs.append('%sstructSize += (sizeof(char*) + (sizeof(char) * (1 + strlen(pStruct->%s[i]))));' % (indent, self.struct_dict[s][m]['name'])) 1423 indent = ' ' 1424 sh_funcs.append('%s}' % (indent)) 1425 else: 1426 if is_type(self.struct_dict[s][m]['type'], 'struct'): 1427 if not i_decl: 1428 sh_funcs.append('%suint32_t i = 0;' % (indent)) 1429 i_decl = True 1430 sh_funcs.append('%sfor (i = 0; i < pStruct->%s; i++) {' % (indent, self.struct_dict[s][m]['array_size'])) 1431 indent = ' ' 1432 sh_funcs.append('%sstructSize += %s(&pStruct->%s[i]);' % (indent, self._get_size_helper_func_name(self.struct_dict[s][m]['type']), self.struct_dict[s][m]['name'])) 1433 indent = ' ' 1434 sh_funcs.append('%s}' % (indent)) 1435 else: 1436 sh_funcs.append('%sstructSize += pStruct->%s*sizeof(%s);' % (indent, self.struct_dict[s][m]['array_size'], self.struct_dict[s][m]['type'])) 1437 elif self.struct_dict[s][m]['ptr'] and 'pNext' != self.struct_dict[s][m]['name']: 1438 if 'char' in self.struct_dict[s][m]['type'].lower(): 1439 sh_funcs.append('%sstructSize += (pStruct->%s != NULL) ? sizeof(%s)*(1+strlen(pStruct->%s)) : 0;' % (indent, self.struct_dict[s][m]['name'], self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name'])) 1440 elif is_type(self.struct_dict[s][m]['type'], 'struct'): 1441 sh_funcs.append('%sstructSize += %s(pStruct->%s);' % (indent, self._get_size_helper_func_name(self.struct_dict[s][m]['type']), self.struct_dict[s][m]['name'])) 1442 elif 'void' not in self.struct_dict[s][m]['type'].lower(): 1443 if (self.struct_dict[s][m]['type'] != 'xcb_connection_t'): 1444 sh_funcs.append('%sstructSize += sizeof(%s);' % (indent, self.struct_dict[s][m]['type'])) 1445 elif 'size_t' == self.struct_dict[s][m]['type'].lower(): 1446 sh_funcs.append('%sstructSize += pStruct->%s;' % (indent, self.struct_dict[s][m]['name'])) 1447 skip_list.append(m+1) 1448 indent = ' ' 1449 sh_funcs.append('%s}' % (indent)) 1450 sh_funcs.append("%sreturn structSize;\n}" % (indent)) 1451 # Now generate generic functions to loop over entire struct chain (or just handle single generic structs) 1452 if '_debug_' not in self.header_filename: 1453 for follow_chain in [True, False]: 1454 sh_funcs.append('%s' % self.lineinfo.get()) 1455 if follow_chain: 1456 sh_funcs.append('size_t get_struct_chain_size(const void* pStruct)\n{') 1457 else: 1458 sh_funcs.append('size_t get_dynamic_struct_size(const void* pStruct)\n{') 1459 indent = ' ' 1460 sh_funcs.append('%s// Just use VkApplicationInfo as struct until actual type is resolved' % (indent)) 1461 sh_funcs.append('%sVkApplicationInfo* pNext = (VkApplicationInfo*)pStruct;' % (indent)) 1462 sh_funcs.append('%ssize_t structSize = 0;' % (indent)) 1463 if follow_chain: 1464 sh_funcs.append('%swhile (pNext) {' % (indent)) 1465 indent = ' ' 1466 sh_funcs.append('%sswitch (pNext->sType) {' % (indent)) 1467 indent += ' ' 1468 for e in enum_type_dict: 1469 if 'StructureType' in e: 1470 for v in sorted(enum_type_dict[e]): 1471 struct_name = get_struct_name_from_struct_type(v) 1472 if struct_name not in self.struct_dict: 1473 continue 1474 1475 sh_funcs.append('%scase %s:' % (indent, v)) 1476 sh_funcs.append('%s{' % (indent)) 1477 indent += ' ' 1478 sh_funcs.append('%sstructSize += %s((%s*)pNext);' % (indent, self._get_size_helper_func_name(struct_name), struct_name)) 1479 sh_funcs.append('%sbreak;' % (indent)) 1480 indent = indent[:-4] 1481 sh_funcs.append('%s}' % (indent)) 1482 sh_funcs.append('%sdefault:' % (indent)) 1483 indent += ' ' 1484 sh_funcs.append('%sassert(0);' % (indent)) 1485 sh_funcs.append('%sstructSize += 0;' % (indent)) 1486 indent = indent[:-4] 1487 indent = indent[:-4] 1488 sh_funcs.append('%s}' % (indent)) 1489 if follow_chain: 1490 sh_funcs.append('%spNext = (VkApplicationInfo*)pNext->pNext;' % (indent)) 1491 indent = indent[:-4] 1492 sh_funcs.append('%s}' % (indent)) 1493 sh_funcs.append('%sreturn structSize;\n}' % indent) 1494 return "\n".join(sh_funcs) 1495 1496 def _generateSizeHelperHeader(self): 1497 header = [] 1498 header.append("//#includes, #defines, globals and such...\n") 1499 for f in self.include_headers: 1500 header.append("#include <%s>\n" % f) 1501 header.append('\n// Function Prototypes\n') 1502 header.append("size_t get_struct_chain_size(const void* pStruct);\n") 1503 header.append("size_t get_dynamic_struct_size(const void* pStruct);\n") 1504 return "".join(header) 1505 1506 def _generateSizeHelperHeaderC(self): 1507 header = [] 1508 header.append('#include "vk_struct_size_helper.h"') 1509 header.append('#include <string.h>') 1510 header.append('#include <assert.h>') 1511 header.append('\n// Function definitions\n') 1512 return "\n".join(header) 1513 1514 1515 def _generateHeader(self): 1516 header = [] 1517 header.append("//#includes, #defines, globals and such...\n") 1518 for f in self.include_headers: 1519 header.append("#include <%s>\n" % f) 1520 return "".join(header) 1521 1522 # Declarations 1523 def _generateConstructorDeclarations(self, s): 1524 constructors = [] 1525 constructors.append(" %s();\n" % self.get_class_name(s)) 1526 constructors.append(" %s(%s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s])) 1527 constructors.append(" %s(const %s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s])) 1528 return "".join(constructors) 1529 1530 def _generateDestructorDeclarations(self, s): 1531 return " virtual ~%s();\n" % self.get_class_name(s) 1532 1533 def _generateDisplayDeclarations(self, s): 1534 return " void display_txt();\n void display_single_txt();\n void display_full_txt();\n" 1535 1536 def _generateGetSetDeclarations(self, s): 1537 get_set = [] 1538 get_set.append(" void set_indent(uint32_t indent) { m_indent = indent; }\n") 1539 for member in sorted(self.struct_dict[s]): 1540 # TODO : Skipping array set/get funcs for now 1541 if self.struct_dict[s][member]['array']: 1542 continue 1543 get_set.append(" %s get_%s() { return m_struct.%s; }\n" % (self.struct_dict[s][member]['full_type'], self.struct_dict[s][member]['name'], self.struct_dict[s][member]['name'])) 1544 if not self.struct_dict[s][member]['const']: 1545 get_set.append(" void set_%s(%s inValue) { m_struct.%s = inValue; }\n" % (self.struct_dict[s][member]['name'], self.struct_dict[s][member]['full_type'], self.struct_dict[s][member]['name'])) 1546 return "".join(get_set) 1547 1548 def _generatePrivateMembers(self, s): 1549 priv = [] 1550 priv.append("\nprivate:\n") 1551 priv.append(" %s m_struct;\n" % typedef_fwd_dict[s]) 1552 priv.append(" const %s* m_origStructAddr;\n" % typedef_fwd_dict[s]) 1553 priv.append(" uint32_t m_indent;\n") 1554 priv.append(" const char m_dummy_prefix;\n") 1555 priv.append(" void display_struct_members();\n") 1556 return "".join(priv) 1557 1558 def _generateClassDeclaration(self): 1559 class_decl = [] 1560 for s in sorted(self.struct_dict): 1561 class_decl.append("\n//class declaration") 1562 class_decl.append("class %s\n{\npublic:" % self.get_class_name(s)) 1563 class_decl.append(self._generateConstructorDeclarations(s)) 1564 class_decl.append(self._generateDestructorDeclarations(s)) 1565 class_decl.append(self._generateDisplayDeclarations(s)) 1566 class_decl.append(self._generateGetSetDeclarations(s)) 1567 class_decl.append(self._generatePrivateMembers(s)) 1568 class_decl.append("};\n") 1569 return "\n".join(class_decl) 1570 1571 def _generateFooter(self): 1572 return "\n//any footer info for class\n" 1573 1574 def _getSafeStructName(self, struct): 1575 return "safe_%s" % (struct) 1576 1577 # If struct has sType or ptr members, generate safe type 1578 def _hasSafeStruct(self, s): 1579 exceptions = ['VkPhysicalDeviceFeatures', 'VkPipelineColorBlendStateCreateInfo'] 1580 if s in exceptions: 1581 return False 1582 if 'sType' == self.struct_dict[s][0]['name']: 1583 return True 1584 for m in self.struct_dict[s]: 1585 if self.struct_dict[s][m]['ptr']: 1586 return True 1587 return False 1588 1589 def _generateSafeStructHeader(self): 1590 header = [] 1591 header.append("//#includes, #defines, globals and such...\n") 1592 header.append('#include "vulkan/vulkan.h"') 1593 return "".join(header) 1594 1595 # If given ty is in obj list, or is a struct that contains anything in obj list, return True 1596 def _typeHasObject(self, ty, obj): 1597 if ty in obj: 1598 return True 1599 if is_type(ty, 'struct'): 1600 for m in self.struct_dict[ty]: 1601 if self.struct_dict[ty][m]['type'] in obj: 1602 return True 1603 return False 1604 1605 def _generateSafeStructDecls(self): 1606 ss_decls = [] 1607 for s in struct_order_list: 1608 if not self._hasSafeStruct(s): 1609 continue 1610 if s in ifdef_dict: 1611 ss_decls.append('#ifdef %s' % ifdef_dict[s]) 1612 ss_name = self._getSafeStructName(s) 1613 ss_decls.append("\nstruct %s {" % (ss_name)) 1614 for m in sorted(self.struct_dict[s]): 1615 m_type = self.struct_dict[s][m]['type'] 1616 if is_type(m_type, 'struct') and self._hasSafeStruct(m_type): 1617 m_type = self._getSafeStructName(m_type) 1618 if self.struct_dict[s][m]['array_size'] != 0 and not self.struct_dict[s][m]['dyn_array']: 1619 ss_decls.append(" %s %s[%s];" % (m_type, self.struct_dict[s][m]['name'], self.struct_dict[s][m]['array_size'])) 1620 elif self.struct_dict[s][m]['ptr'] and 'safe_' not in m_type and not self._typeHasObject(m_type, vulkan.object_non_dispatch_list):#m_type in ['char', 'float', 'uint32_t', 'void', 'VkPhysicalDeviceFeatures']: # We'll never overwrite char* so it can remain const 1621 ss_decls.append(" %s %s;" % (self.struct_dict[s][m]['full_type'], self.struct_dict[s][m]['name'])) 1622 elif self.struct_dict[s][m]['array']: 1623 ss_decls.append(" %s* %s;" % (m_type, self.struct_dict[s][m]['name'])) 1624 elif self.struct_dict[s][m]['ptr']: 1625 ss_decls.append(" %s* %s;" % (m_type, self.struct_dict[s][m]['name'])) 1626 else: 1627 ss_decls.append(" %s %s;" % (m_type, self.struct_dict[s][m]['name'])) 1628 ss_decls.append(" %s(const %s* pInStruct);" % (ss_name, s)) 1629 ss_decls.append(" %s();" % (ss_name)) 1630 ss_decls.append(" ~%s();" % (ss_name)) 1631 ss_decls.append(" void initialize(const %s* pInStruct);" % (s)) 1632 ss_decls.append("};") 1633 if s in ifdef_dict: 1634 ss_decls.append('#endif') 1635 return "\n".join(ss_decls) 1636 1637 def _generateSafeStructSourceHeader(self): 1638 header = [] 1639 header.append("//#includes, #defines, globals and such...\n") 1640 header.append('#include "vk_safe_struct.h"') 1641 return "".join(header) 1642 1643 def _generateSafeStructSource(self): 1644 ss_src = [] 1645 for s in struct_order_list: 1646 if not self._hasSafeStruct(s): 1647 continue 1648 if s in ifdef_dict: 1649 ss_src.append('#ifdef %s' % ifdef_dict[s]) 1650 ss_name = self._getSafeStructName(s) 1651 init_list = '' # list of members in struct constructor initializer 1652 init_func_txt = '' # Txt for initialize() function that takes struct ptr and inits members 1653 construct_txt = '' 1654 destruct_txt = '' 1655 # VkWriteDescriptorSet is special case because pointers may be non-null but ignored 1656 # TODO : This is ugly, figure out better way to do this 1657 custom_construct_txt = {'VkWriteDescriptorSet' : 1658 ' switch (descriptorType) {\n' 1659 ' case VK_DESCRIPTOR_TYPE_SAMPLER:\n' 1660 ' case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:\n' 1661 ' case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:\n' 1662 ' case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:\n' 1663 ' case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:\n' 1664 ' if (descriptorCount && pInStruct->pImageInfo) {\n' 1665 ' pImageInfo = new VkDescriptorImageInfo[descriptorCount];\n' 1666 ' for (uint32_t i=0; i<descriptorCount; ++i) {\n' 1667 ' pImageInfo[i] = pInStruct->pImageInfo[i];\n' 1668 ' }\n' 1669 ' }\n' 1670 ' break;\n' 1671 ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:\n' 1672 ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:\n' 1673 ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:\n' 1674 ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:\n' 1675 ' if (descriptorCount && pInStruct->pBufferInfo) {\n' 1676 ' pBufferInfo = new VkDescriptorBufferInfo[descriptorCount];\n' 1677 ' for (uint32_t i=0; i<descriptorCount; ++i) {\n' 1678 ' pBufferInfo[i] = pInStruct->pBufferInfo[i];\n' 1679 ' }\n' 1680 ' }\n' 1681 ' break;\n' 1682 ' case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:\n' 1683 ' case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:\n' 1684 ' if (descriptorCount && pInStruct->pTexelBufferView) {\n' 1685 ' pTexelBufferView = new VkBufferView[descriptorCount];\n' 1686 ' for (uint32_t i=0; i<descriptorCount; ++i) {\n' 1687 ' pTexelBufferView[i] = pInStruct->pTexelBufferView[i];\n' 1688 ' }\n' 1689 ' }\n' 1690 ' break;\n' 1691 ' default:\n' 1692 ' break;\n' 1693 ' }\n'} 1694 for m in self.struct_dict[s]: 1695 m_name = self.struct_dict[s][m]['name'] 1696 m_type = self.struct_dict[s][m]['type'] 1697 if is_type(m_type, 'struct') and self._hasSafeStruct(m_type): 1698 m_type = self._getSafeStructName(m_type) 1699 if self.struct_dict[s][m]['ptr'] and 'safe_' not in m_type and not self._typeHasObject(m_type, vulkan.object_non_dispatch_list):# in ['char', 'float', 'uint32_t', 'void', 'VkPhysicalDeviceFeatures']) or 'pp' == self.struct_dict[s][m]['name'][0:1]: 1700 init_list += '\n\t%s(pInStruct->%s),' % (m_name, m_name) 1701 init_func_txt += ' %s = pInStruct->%s;\n' % (m_name, m_name) 1702 elif self.struct_dict[s][m]['array']: 1703 # Init array ptr to NULL 1704 init_list += '\n\t%s(NULL),' % (m_name) 1705 init_func_txt += ' %s = NULL;\n' % (m_name) 1706 array_element = 'pInStruct->%s[i]' % (m_name) 1707 if is_type(self.struct_dict[s][m]['type'], 'struct') and self._hasSafeStruct(self.struct_dict[s][m]['type']): 1708 array_element = '%s(&pInStruct->%s[i])' % (self._getSafeStructName(self.struct_dict[s][m]['type']), m_name) 1709 construct_txt += ' if (%s && pInStruct->%s) {\n' % (self.struct_dict[s][m]['array_size'], m_name) 1710 construct_txt += ' %s = new %s[%s];\n' % (m_name, m_type, self.struct_dict[s][m]['array_size']) 1711 destruct_txt += ' if (%s)\n' % (m_name) 1712 destruct_txt += ' delete[] %s;\n' % (m_name) 1713 construct_txt += ' for (uint32_t i=0; i<%s; ++i) {\n' % (self.struct_dict[s][m]['array_size']) 1714 if 'safe_' in m_type: 1715 construct_txt += ' %s[i].initialize(&pInStruct->%s[i]);\n' % (m_name, m_name) 1716 else: 1717 construct_txt += ' %s[i] = %s;\n' % (m_name, array_element) 1718 construct_txt += ' }\n' 1719 construct_txt += ' }\n' 1720 elif self.struct_dict[s][m]['ptr']: 1721 construct_txt += ' if (pInStruct->%s)\n' % (m_name) 1722 construct_txt += ' %s = new %s(pInStruct->%s);\n' % (m_name, m_type, m_name) 1723 construct_txt += ' else\n' 1724 construct_txt += ' %s = NULL;\n' % (m_name) 1725 destruct_txt += ' if (%s)\n' % (m_name) 1726 destruct_txt += ' delete %s;\n' % (m_name) 1727 elif 'safe_' in m_type: # inline struct, need to pass in reference for constructor 1728 init_list += '\n\t%s(&pInStruct->%s),' % (m_name, m_name) 1729 init_func_txt += ' %s.initialize(&pInStruct->%s);\n' % (m_name, m_name) 1730 else: 1731 init_list += '\n\t%s(pInStruct->%s),' % (m_name, m_name) 1732 init_func_txt += ' %s = pInStruct->%s;\n' % (m_name, m_name) 1733 if '' != init_list: 1734 init_list = init_list[:-1] # hack off final comma 1735 if s in custom_construct_txt: 1736 construct_txt = custom_construct_txt[s] 1737 ss_src.append("\n%s::%s(const %s* pInStruct) : %s\n{\n%s}" % (ss_name, ss_name, s, init_list, construct_txt)) 1738 ss_src.append("\n%s::%s() {}" % (ss_name, ss_name)) 1739 ss_src.append("\n%s::~%s()\n{\n%s}" % (ss_name, ss_name, destruct_txt)) 1740 ss_src.append("\nvoid %s::initialize(const %s* pInStruct)\n{\n%s%s}" % (ss_name, s, init_func_txt, construct_txt)) 1741 if s in ifdef_dict: 1742 ss_src.append('#endif') 1743 return "\n".join(ss_src) 1744 1745class EnumCodeGen: 1746 def __init__(self, enum_type_dict=None, enum_val_dict=None, typedef_fwd_dict=None, in_file=None, out_sh_file=None, out_vh_file=None): 1747 self.et_dict = enum_type_dict 1748 self.ev_dict = enum_val_dict 1749 self.tf_dict = typedef_fwd_dict 1750 self.in_file = in_file 1751 self.out_sh_file = out_sh_file 1752 self.eshfg = CommonFileGen(self.out_sh_file) 1753 self.out_vh_file = out_vh_file 1754 self.evhfg = CommonFileGen(self.out_vh_file) 1755 1756 def generateStringHelper(self): 1757 self.eshfg.setHeader(self._generateSHHeader()) 1758 self.eshfg.setBody(self._generateSHBody()) 1759 self.eshfg.generate() 1760 1761 def generateEnumValidate(self): 1762 self.evhfg.setHeader(self._generateSHHeader()) 1763 self.evhfg.setBody(self._generateVHBody()) 1764 self.evhfg.generate() 1765 1766 def _generateVHBody(self): 1767 body = [] 1768 for bet in sorted(self.et_dict): 1769 fet = self.tf_dict[bet] 1770 body.append("static inline uint32_t validate_%s(%s input_value)\n{" % (fet, fet)) 1771 # TODO : This is not ideal, but allows for flag combinations. Need more rigorous validation of realistic flag combinations 1772 if 'flagbits' in bet.lower(): 1773 body.append(' if (input_value > (%s))' % (' | '.join(self.et_dict[bet]))) 1774 body.append(' return 0;') 1775 body.append(' return 1;') 1776 body.append('}\n\n') 1777 else: 1778 body.append(' switch ((%s)input_value)\n {' % (fet)) 1779 for e in sorted(self.et_dict[bet]): 1780 if (self.ev_dict[e]['unique']): 1781 body.append(' case %s:' % (e)) 1782 body.append(' return 1;\n default:\n return 0;\n }\n}\n\n') 1783 return "\n".join(body) 1784 1785 def _generateSHBody(self): 1786 body = [] 1787# with open(self.out_file, "a") as hf: 1788 # bet == base_enum_type, fet == final_enum_type 1789 for bet in sorted(self.et_dict): 1790 fet = self.tf_dict[bet] 1791 body.append("static inline const char* string_%s(%s input_value)\n{\n switch ((%s)input_value)\n {" % (fet, fet, fet)) 1792 for e in sorted(self.et_dict[bet]): 1793 if (self.ev_dict[e]['unique']): 1794 body.append(' case %s:\n return "%s";' % (e, e)) 1795 body.append(' default:\n return "Unhandled %s";\n }\n}\n\n' % (fet)) 1796 return "\n".join(body) 1797 1798 def _generateSHHeader(self): 1799 header = [] 1800 header.append('#pragma once\n') 1801 header.append('#ifdef _WIN32\n') 1802 header.append('#pragma warning( disable : 4065 )\n') 1803 header.append('#endif\n') 1804 header.append('#include <vulkan/%s>\n\n\n' % self.in_file) 1805 return "\n".join(header) 1806 1807 1808class CMakeGen: 1809 def __init__(self, struct_wrapper=None, out_dir=None): 1810 self.sw = struct_wrapper 1811 self.include_headers = [] 1812 self.add_lib_file_list = self.sw.get_file_list() 1813 self.out_dir = out_dir 1814 self.out_file = os.path.join(self.out_dir, "CMakeLists.txt") 1815 self.cmg = CommonFileGen(self.out_file) 1816 1817 def generate(self): 1818 self.cmg.setBody(self._generateBody()) 1819 self.cmg.generate() 1820 1821 def _generateBody(self): 1822 body = [] 1823 body.append("project(%s)" % os.path.basename(self.out_dir)) 1824 body.append("cmake_minimum_required(VERSION 2.8)\n") 1825 body.append("add_library(${PROJECT_NAME} %s)\n" % " ".join(self.add_lib_file_list)) 1826 body.append('set(COMPILE_FLAGS "-fpermissive")') 1827 body.append('set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")\n') 1828 body.append("include_directories(${SRC_DIR}/thirdparty/${GEN_API}/inc/)\n") 1829 body.append("target_include_directories (%s PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n" % os.path.basename(self.out_dir)) 1830 return "\n".join(body) 1831 1832class GraphVizGen: 1833 def __init__(self, struct_dict, prefix, out_dir): 1834 self.struct_dict = struct_dict 1835 self.api = prefix 1836 if prefix == "vulkan": 1837 self.api_prefix = "vk" 1838 else: 1839 self.api_prefix = prefix 1840 self.out_file = os.path.join(out_dir, self.api_prefix+"_struct_graphviz_helper.h") 1841 self.gvg = CommonFileGen(self.out_file) 1842 1843 def generate(self): 1844 self.gvg.setCopyright("//This is the copyright\n") 1845 self.gvg.setHeader(self._generateHeader()) 1846 self.gvg.setBody(self._generateBody()) 1847 #self.gvg.setFooter('}') 1848 self.gvg.generate() 1849 1850 def set_include_headers(self, include_headers): 1851 self.include_headers = include_headers 1852 1853 def _generateHeader(self): 1854 header = [] 1855 header.append("//#includes, #defines, globals and such...\n") 1856 for f in self.include_headers: 1857 if 'vk_enum_string_helper' not in f: 1858 header.append("#include <%s>\n" % f) 1859 #header.append('#include "vk_enum_string_helper.h"\n\n// Function Prototypes\n') 1860 header.append("\nchar* dynamic_gv_display(const void* pStruct, const char* prefix);\n") 1861 return "".join(header) 1862 1863 def _get_gv_func_name(self, struct): 1864 return "%s_gv_print_%s" % (self.api_prefix, struct.lower().strip("_")) 1865 1866 # Return elements to create formatted string for given struct member 1867 def _get_struct_gv_print_formatted(self, struct_member, pre_var_name="", postfix = "\\n", struct_var_name="pStruct", struct_ptr=True, print_array=False, port_label=""): 1868 struct_op = "->" 1869 pre_var_name = '"%s "' % struct_member['full_type'] 1870 if not struct_ptr: 1871 struct_op = "." 1872 member_name = struct_member['name'] 1873 print_type = "p" 1874 cast_type = "" 1875 member_post = "" 1876 array_index = "" 1877 member_print_post = "" 1878 print_delimiter = "%" 1879 if struct_member['array'] and 'char' in struct_member['type'].lower(): # just print char array as string 1880 print_type = "p" 1881 print_array = False 1882 elif struct_member['array'] and not print_array: 1883 # Just print base address of array when not full print_array 1884 cast_type = "(void*)" 1885 elif is_type(struct_member['type'], 'enum'): 1886 if struct_member['ptr']: 1887 struct_var_name = "*" + struct_var_name 1888 cast_type = "string_%s" % struct_member['type'] 1889 print_type = "s" 1890 elif is_type(struct_member['type'], 'struct'): # print struct address for now 1891 cast_type = "(void*)" 1892 if not struct_member['ptr']: 1893 cast_type = "(void*)&" 1894 elif 'bool' in struct_member['type'].lower(): 1895 print_type = "s" 1896 member_post = ' ? "TRUE" : "FALSE"' 1897 elif 'float' in struct_member['type']: 1898 print_type = "f" 1899 elif 'uint64' in struct_member['type'] or 'gpusize' in struct_member['type'].lower(): 1900 print_type = '" PRId64 "' 1901 elif 'uint8' in struct_member['type']: 1902 print_type = "hu" 1903 elif 'size' in struct_member['type'].lower(): 1904 print_type = '" PRINTF_SIZE_T_SPECIFIER "' 1905 print_delimiter = "" 1906 elif True in [ui_str.lower() in struct_member['type'].lower() for ui_str in ['uint', 'flags', 'samplemask']]: 1907 print_type = "u" 1908 elif 'int' in struct_member['type']: 1909 print_type = "i" 1910 elif struct_member['ptr']: 1911 pass 1912 else: 1913 #print("Unhandled struct type: %s" % struct_member['type']) 1914 cast_type = "(void*)" 1915 if print_array and struct_member['array']: 1916 member_print_post = "[%u]" 1917 array_index = " i," 1918 member_post = "[i]" 1919 print_out = "<TR><TD>%%s%s%s</TD><TD%s>%s%s%s</TD></TR>" % (member_name, member_print_post, port_label, print_delimiter, print_type, postfix) # section of print that goes inside of quotes 1920 print_arg = ", %s,%s %s(%s%s%s)%s\n" % (pre_var_name, array_index, cast_type, struct_var_name, struct_op, member_name, member_post) # section of print passed to portion in quotes 1921 return (print_out, print_arg) 1922 1923 def _generateBody(self): 1924 gv_funcs = [] 1925 array_func_list = [] # structs for which we'll generate an array version of their print function 1926 array_func_list.append('vkbufferviewattachinfo') 1927 array_func_list.append('vkimageviewattachinfo') 1928 array_func_list.append('vksamplerimageviewinfo') 1929 array_func_list.append('vkdescriptortypecount') 1930 # For first pass, generate prototype 1931 for s in sorted(self.struct_dict): 1932 gv_funcs.append('char* %s(const %s* pStruct, const char* myNodeName);\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) 1933 if s.lower().strip("_") in array_func_list: 1934 if s.lower().strip("_") in ['vkbufferviewattachinfo', 'vkimageviewattachinfo']: 1935 gv_funcs.append('char* %s_array(uint32_t count, const %s* const* pStruct, const char* myNodeName);\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) 1936 else: 1937 gv_funcs.append('char* %s_array(uint32_t count, const %s* pStruct, const char* myNodeName);\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) 1938 gv_funcs.append('\n') 1939 for s in sorted(self.struct_dict): 1940 p_out = "" 1941 p_args = "" 1942 stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs 1943 # the fields below are a super-hacky way for now to get port labels into GV output, TODO : Clean this up! 1944 pl_dict = {} 1945 struct_num = 0 1946 # This isn't great but this pre-pass flags structs w/ pNext and other struct ptrs 1947 for m in sorted(self.struct_dict[s]): 1948 if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): 1949 stp_list.append(self.struct_dict[s][m]) 1950 if 'pNext' == self.struct_dict[s][m]['name']: 1951 pl_dict[m] = ' PORT=\\"pNext\\"' 1952 else: 1953 pl_dict[m] = ' PORT=\\"struct%i\\"' % struct_num 1954 struct_num += 1 1955 gv_funcs.append('char* %s(const %s* pStruct, const char* myNodeName)\n{\n char* str;\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) 1956 num_stps = len(stp_list); 1957 total_strlen_str = '' 1958 if 0 != num_stps: 1959 gv_funcs.append(" char* tmpStr;\n") 1960 gv_funcs.append(" char nodeName[100];\n") 1961 gv_funcs.append(' char* stp_strs[%i];\n' % num_stps) 1962 for index in range(num_stps): 1963 if (stp_list[index]['ptr']): 1964 if 'pDescriptorInfo' == stp_list[index]['name']: 1965 gv_funcs.append(' if (pStruct->pDescriptorInfo && (0 != pStruct->descriptorCount)) {\n') 1966 else: 1967 gv_funcs.append(' if (pStruct->%s) {\n' % stp_list[index]['name']) 1968 if 'pNext' == stp_list[index]['name']: 1969 gv_funcs.append(' sprintf(nodeName, "pNext_%p", (void*)pStruct->pNext);\n') 1970 gv_funcs.append(' tmpStr = dynamic_gv_display((void*)pStruct->pNext, nodeName);\n') 1971 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % index) 1972 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":pNext -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % index) 1973 gv_funcs.append(' free(tmpStr);\n') 1974 else: 1975 gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name'])) 1976 if stp_list[index]['name'] in ['pTypeCount', 'pSamplerImageViews']: 1977 gv_funcs.append(' tmpStr = %s_array(pStruct->count, pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) 1978 else: 1979 gv_funcs.append(' tmpStr = %s(pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) 1980 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) 1981 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) 1982 gv_funcs.append(' }\n') 1983 gv_funcs.append(" else\n stp_strs[%i] = \"\";\n" % (index)) 1984 elif stp_list[index]['array']: # TODO : For now just printing first element of array 1985 gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s[0]);\n' % (stp_list[index]['name'], stp_list[index]['name'])) 1986 gv_funcs.append(' tmpStr = %s(&pStruct->%s[0], nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) 1987 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) 1988 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) 1989 else: 1990 gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name'])) 1991 gv_funcs.append(' tmpStr = %s(&pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) 1992 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) 1993 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) 1994 total_strlen_str += 'strlen(stp_strs[%i]) + ' % index 1995 gv_funcs.append(' str = (char*)malloc(%ssizeof(char)*2048);\n' % (total_strlen_str)) 1996 gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <<TABLE BORDER=\\"0\\" CELLBORDER=\\"1\\" CELLSPACING=\\"0\\"><TR><TD COLSPAN=\\"2\\">%s (%p)</TD></TR>') 1997 p_args = ", myNodeName, myNodeName, pStruct" 1998 for m in sorted(self.struct_dict[s]): 1999 plabel = "" 2000 if m in pl_dict: 2001 plabel = pl_dict[m] 2002 (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel) 2003 p_out += p_out1 2004 p_args += p_args1 2005 p_out += '</TABLE>>\\n];\\n\\n"' 2006 p_args += ");\n" 2007 gv_funcs.append(p_out) 2008 gv_funcs.append(p_args) 2009 if 0 != num_stps: 2010 gv_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {\n' % (num_stps-1)) 2011 gv_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {\n') 2012 gv_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));\n') 2013 gv_funcs.append(' free(stp_strs[stp_index]);\n') 2014 gv_funcs.append(' }\n') 2015 gv_funcs.append(' }\n') 2016 gv_funcs.append(" return str;\n}\n") 2017 if s.lower().strip("_") in array_func_list: 2018 ptr_array = False 2019 if s.lower().strip("_") in ['vkbufferviewattachinfo', 'vkimageviewattachinfo']: 2020 ptr_array = True 2021 gv_funcs.append('char* %s_array(uint32_t count, const %s* const* pStruct, const char* myNodeName)\n{\n char* str;\n char tmpStr[1024];\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) 2022 else: 2023 gv_funcs.append('char* %s_array(uint32_t count, const %s* pStruct, const char* myNodeName)\n{\n char* str;\n char tmpStr[1024];\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) 2024 gv_funcs.append(' str = (char*)malloc(sizeof(char)*1024*count);\n') 2025 gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <<TABLE BORDER=\\"0\\" CELLBORDER=\\"1\\" CELLSPACING=\\"0\\"><TR><TD COLSPAN=\\"3\\">%s (%p)</TD></TR>", myNodeName, myNodeName, pStruct);\n') 2026 gv_funcs.append(' for (uint32_t i=0; i < count; i++) {\n') 2027 gv_funcs.append(' sprintf(tmpStr, "'); 2028 p_args = "" 2029 p_out = "" 2030 for m in sorted(self.struct_dict[s]): 2031 plabel = "" 2032 (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel) 2033 if 0 == m: # Add array index notation at end of first row 2034 p_out1 = '%s<TD ROWSPAN=\\"%i\\" PORT=\\"slot%%u\\">%%u</TD></TR>' % (p_out1[:-5], len(self.struct_dict[s])) 2035 p_args1 += ', i, i' 2036 p_out += p_out1 2037 p_args += p_args1 2038 p_out += '"' 2039 p_args += ");\n" 2040 if ptr_array: 2041 p_args = p_args.replace('->', '[i]->') 2042 else: 2043 p_args = p_args.replace('->', '[i].') 2044 gv_funcs.append(p_out); 2045 gv_funcs.append(p_args); 2046 gv_funcs.append(' strncat(str, tmpStr, strlen(tmpStr));\n') 2047 gv_funcs.append(' }\n') 2048 gv_funcs.append(' strncat(str, "</TABLE>>\\n];\\n\\n", 20);\n') 2049 gv_funcs.append(' return str;\n}\n') 2050 # Add function to dynamically print out unknown struct 2051 gv_funcs.append("char* dynamic_gv_display(const void* pStruct, const char* nodeName)\n{\n") 2052 gv_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct\n") 2053 gv_funcs.append(" VkStructureType sType = ((VkApplicationInfo*)pStruct)->sType;\n") 2054 gv_funcs.append(" switch (sType)\n {\n") 2055 for e in enum_type_dict: 2056 if "StructureType" in e: 2057 for v in sorted(enum_type_dict[e]): 2058 struct_name = get_struct_name_from_struct_type(v) 2059 if struct_name not in self.struct_dict: 2060 continue 2061 2062 print_func_name = self._get_gv_func_name(struct_name) 2063 # TODO : Hand-coded fixes for some exceptions 2064 #if 'VkPipelineCbStateCreateInfo' in struct_name: 2065 # struct_name = 'VK_PIPELINE_CB_STATE' 2066 if 'VkSemaphoreCreateInfo' in struct_name: 2067 struct_name = 'VkSemaphoreCreateInfo' 2068 print_func_name = self._get_gv_func_name(struct_name) 2069 elif 'VkSemaphoreOpenInfo' in struct_name: 2070 struct_name = 'VkSemaphoreOpenInfo' 2071 print_func_name = self._get_gv_func_name(struct_name) 2072 gv_funcs.append(' case %s:\n' % (v)) 2073 gv_funcs.append(' return %s((%s*)pStruct, nodeName);\n' % (print_func_name, struct_name)) 2074 #gv_funcs.append(' }\n') 2075 #gv_funcs.append(' break;\n') 2076 gv_funcs.append(" default:\n") 2077 gv_funcs.append(" return NULL;\n") 2078 gv_funcs.append(" }\n") 2079 gv_funcs.append("}") 2080 return "".join(gv_funcs) 2081 2082 2083 2084 2085 2086# def _generateHeader(self): 2087# hdr = [] 2088# hdr.append('digraph g {\ngraph [\nrankdir = "LR"\n];') 2089# hdr.append('node [\nfontsize = "16"\nshape = "plaintext"\n];') 2090# hdr.append('edge [\n];\n') 2091# return "\n".join(hdr) 2092# 2093# def _generateBody(self): 2094# body = [] 2095# for s in sorted(self.struc_dict): 2096# field_num = 1 2097# body.append('"%s" [\nlabel = <<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD COLSPAN="2" PORT="f0">%s</TD></TR>' % (s, typedef_fwd_dict[s])) 2098# for m in sorted(self.struc_dict[s]): 2099# body.append('<TR><TD PORT="f%i">%s</TD><TD PORT="f%i">%s</TD></TR>' % (field_num, self.struc_dict[s][m]['full_type'], field_num+1, self.struc_dict[s][m]['name'])) 2100# field_num += 2 2101# body.append('</TABLE>>\n];\n') 2102# return "".join(body) 2103 2104def main(argv=None): 2105 opts = handle_args() 2106 # Parse input file and fill out global dicts 2107 hfp = HeaderFileParser(opts.input_file) 2108 hfp.parse() 2109 # TODO : Don't want these to be global, see note at top about wrapper classes 2110 global enum_val_dict 2111 global enum_type_dict 2112 global struct_dict 2113 global typedef_fwd_dict 2114 global typedef_rev_dict 2115 global types_dict 2116 enum_val_dict = hfp.get_enum_val_dict() 2117 enum_type_dict = hfp.get_enum_type_dict() 2118 struct_dict = hfp.get_struct_dict() 2119 # TODO : Would like to validate struct data here to verify that all of the bools for struct members are correct at this point 2120 typedef_fwd_dict = hfp.get_typedef_fwd_dict() 2121 typedef_rev_dict = hfp.get_typedef_rev_dict() 2122 types_dict = hfp.get_types_dict() 2123 #print(enum_val_dict) 2124 #print(typedef_dict) 2125 #print(struct_dict) 2126 input_header = os.path.basename(opts.input_file) 2127 if 'vulkan.h' == input_header: 2128 input_header = "vulkan/vulkan.h" 2129 2130 prefix = os.path.basename(opts.input_file).strip(".h") 2131 if prefix == "vulkan": 2132 prefix = "vk" 2133 if (opts.abs_out_dir is not None): 2134 enum_sh_filename = os.path.join(opts.abs_out_dir, prefix+"_enum_string_helper.h") 2135 else: 2136 enum_sh_filename = os.path.join(os.getcwd(), opts.rel_out_dir, prefix+"_enum_string_helper.h") 2137 enum_sh_filename = os.path.abspath(enum_sh_filename) 2138 if not os.path.exists(os.path.dirname(enum_sh_filename)): 2139 print("Creating output dir %s" % os.path.dirname(enum_sh_filename)) 2140 os.mkdir(os.path.dirname(enum_sh_filename)) 2141 if opts.gen_enum_string_helper: 2142 print("Generating enum string helper to %s" % enum_sh_filename) 2143 enum_vh_filename = os.path.join(os.path.dirname(enum_sh_filename), prefix+"_enum_validate_helper.h") 2144 print("Generating enum validate helper to %s" % enum_vh_filename) 2145 eg = EnumCodeGen(enum_type_dict, enum_val_dict, typedef_fwd_dict, os.path.basename(opts.input_file), enum_sh_filename, enum_vh_filename) 2146 eg.generateStringHelper() 2147 eg.generateEnumValidate() 2148 #for struct in struct_dict: 2149 #print(struct) 2150 if opts.gen_struct_wrappers: 2151 sw = StructWrapperGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename)) 2152 #print(sw.get_class_name(struct)) 2153 sw.set_include_headers([input_header,os.path.basename(enum_sh_filename),"stdint.h","inttypes.h", "stdio.h","stdlib.h"]) 2154 print("Generating struct wrapper header to %s" % sw.header_filename) 2155 sw.generateHeader() 2156 print("Generating struct wrapper class to %s" % sw.class_filename) 2157 sw.generateBody() 2158 sw.generateStringHelper() 2159 sw.generateValidateHelper() 2160 # Generate a 2nd helper file that excludes addrs 2161 sw.set_no_addr(True) 2162 sw.generateStringHelper() 2163 sw.set_no_addr(False) 2164 sw.set_include_headers([input_header,os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h","iostream","sstream","string"]) 2165 sw.set_no_addr(True) 2166 sw.generateStringHelperCpp() 2167 sw.set_no_addr(False) 2168 sw.generateStringHelperCpp() 2169 sw.set_include_headers(["stdio.h", "stdlib.h", input_header]) 2170 sw.generateSizeHelper() 2171 sw.generateSizeHelperC() 2172 sw.generateSafeStructHeader() 2173 sw.generateSafeStructs() 2174 if opts.gen_struct_sizes: 2175 st = StructWrapperGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename)) 2176 st.set_include_headers(["stdio.h", "stdlib.h", input_header]) 2177 st.generateSizeHelper() 2178 st.generateSizeHelperC() 2179 if opts.gen_cmake: 2180 cmg = CMakeGen(sw, os.path.dirname(enum_sh_filename)) 2181 cmg.generate() 2182 if opts.gen_graphviz: 2183 gv = GraphVizGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename)) 2184 gv.set_include_headers([input_header,os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h", "inttypes.h"]) 2185 gv.generate() 2186 print("DONE!") 2187 #print(typedef_rev_dict) 2188 #print(types_dict) 2189 #recreate_structs() 2190 2191if __name__ == "__main__": 2192 sys.exit(main()) 2193