1// 2// Copyright (C) 2024 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17package main 18 19import ( 20 "berberis/cpp_types" 21 "berberis/vulkan_types" 22 "berberis/vulkan_xml" 23 "errors" 24 "fmt" 25 "io" 26 "io/ioutil" 27 "os" 28 "path" 29 "sort" 30 "strings" 31) 32 33func main() { 34 var host_arch cpp_types.Arch 35 var guest_arch cpp_types.Arch 36 var vk_xml_filename string 37 var vulkan_xml_filename string 38 var custom_trampolines_filename string 39 args := os.Args[1:] 40 id := 0 41 for id < len(args) { 42 if args[id] == "--guest_arch" { 43 id++ 44 switch { 45 case args[id] == "arm": 46 guest_arch = cpp_types.Arm 47 case args[id] == "arm64": 48 guest_arch = cpp_types.Arm64 49 case args[id] == "risvc32": 50 guest_arch = cpp_types.Riscv32 51 case args[id] == "riscv64": 52 guest_arch = cpp_types.Riscv64 53 case args[id] == "x86": 54 guest_arch = cpp_types.X86 55 case args[id] == "x86_64": 56 guest_arch = cpp_types.X86_64 57 } 58 } else if args[id] == "--host_arch" { 59 id++ 60 switch { 61 case args[id] == "arm": 62 host_arch = cpp_types.Arm 63 case args[id] == "arm64": 64 host_arch = cpp_types.Arm64 65 case args[id] == "riscv32": 66 host_arch = cpp_types.Riscv32 67 case args[id] == "riscv64": 68 host_arch = cpp_types.Riscv64 69 case args[id] == "x86": 70 host_arch = cpp_types.X86 71 case args[id] == "x86_64": 72 host_arch = cpp_types.X86_64 73 } 74 } else if args[id] == "--input" { 75 id++ 76 vk_xml_filename = args[id] 77 } else if args[id] == "--xml" { 78 id++ 79 vulkan_xml_filename = args[id] 80 } else if args[id] == "--json" { 81 id++ 82 custom_trampolines_filename = args[id] 83 } else { 84 panic(` 85Spurious arguments! 86 87Usage: gen_vulkan --input vk.xml --output vulkan_xml.h 88`) 89 } 90 id++ 91 } 92 93 xmlFile, err := os.Open(vk_xml_filename) 94 if err != nil { 95 panic(err) 96 } 97 defer xmlFile.Close() 98 99 byteValue, _ := ioutil.ReadAll(xmlFile) 100 101 registry, err := vulkan_xml.Unmarshal(byteValue) 102 if err != nil { 103 panic(err) 104 } 105 106 sorted_type_names, types, sorted_command_names, commands, extensions, err := vulkan_xml.VulkanTypesfromXML(registry) 107 if err != nil { 108 panic(err) 109 } 110 111 if vulkan_xml_filename != "" { 112 err = generateVulkanXML(sorted_type_names, types, sorted_command_names, commands, extensions, vulkan_xml_filename, host_arch, guest_arch) 113 if err != nil { 114 panic(err) 115 } 116 } 117 118 if custom_trampolines_filename != "" { 119 err = generateCustomTrampolines(custom_trampolines_filename, sorted_command_names, commands, host_arch, guest_arch) 120 if err != nil { 121 panic(err) 122 } 123 } 124} 125 126func generateVulkanXML(sorted_type_names []string, types map[string]cpp_types.Type, sorted_command_names []string, commands map[string]cpp_types.Type, extensions map[string]int64, output_file_name string, host_arch, guest_arch cpp_types.Arch) error { 127 128 out_file, err := os.OpenFile(output_file_name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 129 if err != nil { 130 return err 131 } 132 defer out_file.Close() 133 134 _, err = fmt.Fprintf(out_file, 135 `// This file is automatically generated by %s 136// DO NOT EDIT! 137 138// clang-format off 139 140`, path.Base(os.Args[0])) 141 if err != nil { 142 return err 143 } 144 145 sorted_struct_type_names, err := sortStructTypes(sorted_type_names, types) 146 if err != nil { 147 return err 148 } 149 150 err = printAliasTypes(out_file, sorted_type_names, types) 151 if err != nil { 152 return err 153 } 154 155 err = printEnums(out_file, sorted_type_names, types) 156 if err != nil { 157 return err 158 } 159 160 err = printEnumAliases(out_file, sorted_type_names, types) 161 if err != nil { 162 return err 163 } 164 165 conversions, err := getRequiredConversions(commands, types) 166 if err != nil { 167 return err 168 } 169 170 err = printHostStructTypes(out_file, sorted_struct_type_names, types) 171 if err != nil { 172 return err 173 } 174 175 err = printFunctionPointerTypes(out_file, sorted_command_names, commands) 176 if err != nil { 177 return err 178 } 179 180 _, err = fmt.Fprint(out_file, "#ifndef BERBERIS_LAYOUT_CHECK_ONLY\n") 181 if err != nil { 182 return err 183 } 184 185 err = printExtensionsMap(out_file, extensions) 186 if err != nil { 187 return err 188 } 189 190 _, err = fmt.Fprint(out_file, "} // namespace\n\n") 191 if err != nil { 192 return err 193 } 194 195 err = printGuestStructTypes(out_file, sorted_struct_type_names, types, conversions, host_arch, guest_arch) 196 if err != nil { 197 return err 198 } 199 200 err = printConvertOptionalStructures(out_file, sorted_struct_type_names, types, conversions, host_arch, guest_arch) 201 if err != nil { 202 return err 203 } 204 205 _, err = fmt.Fprint(out_file, 206 ` 207 208// Note: we put all the conversion routines in the anonymous namespace to make sure we are not 209// generating dead code or referencing non-existing code: attempt to use static function which 210// is not defined is error and if function is unreferenced that causes error since we are compiling 211// code with -Wunused-function -Werror options. 212// 213// But this requires definition certain stub functions in emulated_api_checker.cc 214 215namespace { 216 217// These trampolines and runners are too complex to be auto-generated. 218void DoCustomTrampolineWithThunk_vkAllocateCommandBuffers(HostCode callee, ProcessState* state); 219void DoCustomTrampolineWithThunk_vkBeginCommandBuffer(HostCode callee, ProcessState* state); 220void DoCustomTrampolineWithThunk_vkEnumerateDeviceExtensionProperties(HostCode callee, ProcessState* state); 221void DoCustomTrampolineWithThunk_vkEnumerateInstanceExtensionProperties(HostCode callee, ProcessState* state); 222void DoCustomTrampolineWithThunk_vkFreeCommandBuffers(HostCode callee, ProcessState* state); 223void DoCustomTrampolineWithThunk_vkGetDeviceProcAddr(HostCode callee, ProcessState* state); 224void DoCustomTrampolineWithThunk_vkGetInstanceProcAddr(HostCode callee, ProcessState* state); 225void RunGuest_vkEnumerateDeviceExtensionProperties(GuestAddr pc, GuestArgumentBuffer* buf); 226void RunGuest_vkEnumerateInstanceExtensionProperties(GuestAddr pc, GuestArgumentBuffer* buf); 227void RunGuest_vkCreateInstance(GuestAddr pc, GuestArgumentBuffer* buf); 228void RunGuest_vkGetDeviceProcAddr(GuestAddr pc, GuestArgumentBuffer* buf); 229void RunGuest_vkGetInstanceProcAddr(GuestAddr pc, GuestArgumentBuffer* buf); 230 231`) 232 if err != nil { 233 return err 234 } 235 236 err = printCustomTrampolies(out_file, sorted_command_names, commands, host_arch, guest_arch) 237 if err != nil { 238 return err 239 } 240 241 err = printCustomGuestRunners(out_file, sorted_command_names, commands, host_arch, guest_arch) 242 if err != nil { 243 return err 244 } 245 246 err = printMaps(out_file, sorted_command_names, commands, host_arch, guest_arch) 247 if err != nil { 248 return err 249 } 250 251 err = printGuestStructVerification(out_file, sorted_type_names, types, host_arch, guest_arch) 252 if err != nil { 253 return err 254 } 255 256 _, err = fmt.Fprintf(out_file, 257 `#endif // BERBERIS_LAYOUT_CHECK_ONLY 258 259} // namespace 260 261} // namespace berberis 262 263// Note: above we define all the Vulkan-related types that we are using, and don't rely on types 264// from official "vulkan.h" header. 265 266// This is because certain "official" types can only be used on certain platforms. E.g. you must be 267// on Windows platform to imclude Windows-specific types from vulkan_win32.h, you need OS with 268// Wayland support to use vulkan_wayland.h and so on. 269 270// The majority of types are platform-independent though thus comparing layout of our host-based 271// types to these is an excellent way to make sure our generator doesn't generate bogus type 272// definitions. 273 274#define VK_ENABLE_BETA_EXTENSIONS 1 275#include <vulkan/vk_android_native_buffer.h> 276#include <vulkan/vulkan.h> 277#include <vulkan/vulkan_android.h> 278#include <vulkan/vulkan_beta.h> 279 280`) 281 if err != nil { 282 return err 283 } 284 285 err = printAliasVerification(out_file, sorted_type_names, types, host_arch, guest_arch) 286 if err != nil { 287 return err 288 } 289 290 err = printEnumVerification(out_file, sorted_type_names, types, host_arch, guest_arch) 291 if err != nil { 292 return err 293 } 294 295 err = printHostStructVerification(out_file, sorted_type_names, types, host_arch, guest_arch) 296 if err != nil { 297 return err 298 } 299 300 _, err = fmt.Fprintf(out_file, "// clang-format on\n") 301 return err 302} 303 304func generateCustomTrampolines(output_file_name string, sorted_command_names []string, commands map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) (err error) { 305 out_file, err := os.OpenFile(output_file_name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 306 if err != nil { 307 return err 308 } 309 defer out_file.Close() 310 311 symbols_list := []string{} 312 for _, name := range sorted_command_names { 313 command := commands[name] 314 params_are_compatible := true 315 switch name { 316 // These functions are compatible based on signatures, but actually need special processing. 317 case "vkGetDeviceProcAddr", "vkGetInstanceProcAddr": 318 params_are_compatible = false 319 } 320 for i := uint(0); i < command.NumField(guest_arch); i++ { 321 param_type := command.Field(i, guest_arch).Type() 322 if !isInputCompatible(param_type, host_arch, guest_arch) { 323 params_are_compatible = false 324 break 325 } 326 } 327 if !params_are_compatible { 328 symbols_list = append(symbols_list, fmt.Sprintf(` "%s": { 329 "call_method": "custom_trampoline_with_thunk" 330 }`, name)) 331 } 332 } 333 _, err = fmt.Fprintf(out_file, `{ 334 "config": { 335 "ignore_non_present": true, 336 "reason": "some Vulkan functions are in drivers and are supported by our proxy while libvulkan.so lags behind" 337 }, 338 "symbols": { 339%s 340 }, 341 "types": { 342 "struct ANativeWindow": { 343 "force_compatible": true, 344 "reason_for_compatible": [ 345 "This struct is full of function pointers ", 346 "which actually could be used by a guest code. ", 347 "It's too late to try to fix anything in ", 348 "Vulkan library though since these functions ", 349 "could be used before that point. This must ", 350 "be handled by NativeActivity wrapper. " 351 ] 352 } 353 } 354} 355`, 356 strings.Join(symbols_list, ",\n")) 357 if err != nil { 358 return err 359 } 360 return err 361} 362 363func printAliasTypes(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type) (err error) { 364 printed_aliases := make(map[string]cpp_types.Type) 365 next_alias_types_list := []cpp_types.Type{} 366 for _, name := range sorted_type_names { 367 typе := types[name] 368 if vulkan_types.IsVulkanHandle(typе) { 369 _, err := fmt.Fprintf(w, "BERBERIS_VK_DEFINE_HANDLE(%s);\n\n", name) 370 if err != nil { 371 return err 372 } 373 printed_aliases[name] = typе 374 } else if vulkan_types.IsVulkanNondispatchableHandle(typе) { 375 _, err := fmt.Fprintf(w, "BERBERIS_VK_DEFINE_NON_DISPATCHABLE_HANDLE(%s);\n\n", name) 376 if err != nil { 377 return err 378 } 379 printed_aliases[name] = typе 380 } else if isAlias(typе) && !isAliasOfEnum(typе) { 381 base_name := typе.Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch) 382 for arch := cpp_types.FirstArch + 1; arch <= cpp_types.LastArch; arch++ { 383 if base_name != typе.Elem(arch).Name(arch) { 384 return errors.New("Inconsistent alias \"" + name + "\"") 385 } 386 } 387 next_alias_types_list = append(next_alias_types_list, typе) 388 } 389 } 390 var alias_types_list []cpp_types.Type 391 for len(next_alias_types_list) > 0 { 392 // If next list is the same as previous one then we have some kind of loop and types couldn't be defined. 393 if len(alias_types_list) == len(next_alias_types_list) { 394 return errors.New("Cannot make any progress: type \"" + alias_types_list[0].Name(cpp_types.FirstArch) + "\" refers to undefined type: \"" + alias_types_list[0].Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch) + "\"\"") 395 } 396 alias_types_list = next_alias_types_list 397 next_alias_types_list = []cpp_types.Type{} 398 for _, typе := range alias_types_list { 399 if _, ok := printed_aliases[typе.Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch)]; ok || !isAlias(typе.Elem(cpp_types.FirstArch)) { 400 name := typе.Name(cpp_types.FirstArch) 401 base_type := typе.Elem(cpp_types.FirstArch) 402 base_name := base_type.Name(cpp_types.FirstArch) 403 if isStruct(base_type) || isUnion(base_type) { 404 _, err := fmt.Fprintf(w, "%s;\n", base_name) 405 if err != nil { 406 return err 407 } 408 } 409 _, err := fmt.Fprintf(w, "using %s = %s;\n\n", name, base_name) 410 if err != nil { 411 return err 412 } 413 printed_aliases[name] = typе 414 } else { 415 next_alias_types_list = append(next_alias_types_list, typе) 416 } 417 } 418 } 419 return nil 420} 421 422func printAliasVerification(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) error { 423 for _, name := range sorted_type_names { 424 typе := types[name] 425 if !vulkan_types.IsVulkanHandle(typе) && !vulkan_types.IsVulkanNondispatchableHandle(typе) && !isAlias(typе) { 426 continue 427 } 428 if isAliasOfOpaque(typе) { 429 continue 430 } 431 _, err := fmt.Fprintf( 432 w, 433 `#if %[7]s 434CHECK_STRUCT_LAYOUT(berberis::%[2]s, %[3]d, %[4]d); 435#if !defined(BERBERIS_%[1]s) 436CHECK_STRUCT_LAYOUT(::%[2]s, %[3]d, %[4]d); 437#endif /* BERBERIS_%[1]s */ 438#elif %[8]s 439CHECK_STRUCT_LAYOUT(berberis::%[2]s, %[5]d, %[6]d); 440#if !defined(BERBERIS_%[1]s) 441CHECK_STRUCT_LAYOUT(::%[2]s, %[5]d, %[6]d); 442#endif /* BERBERIS_%[1]s */ 443#else 444#error Unsupported architecture. 445#endif 446 447`, 448 toEnumNameWithSuffix(name, "NOVERIFY"), 449 name, 450 typе.Bits(host_arch), 451 typе.Align(host_arch), 452 typе.Bits(guest_arch), 453 typе.Align(guest_arch), 454 cpp_types.Define(host_arch), 455 cpp_types.Define(guest_arch)) 456 if err != nil { 457 return err 458 } 459 } 460 return nil 461} 462 463func printEnums(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type) (err error) { 464 for _, name := range sorted_type_names { 465 typе := types[name] 466 // Note: currently enums in vk.xml are architecture-agnostic. If some type is enum then it's always enum, on all 467 // architecturs. And base type doesn't depend on the architecture either. 468 err := checkEnumConsistency(typе, name) 469 if err != nil { 470 return err 471 } 472 if !isEnum(typе) { 473 continue 474 } 475 _, err = fmt.Fprintf(w, "enum %s : %s {\n", name, typе.Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch)) 476 if err != nil { 477 return err 478 } 479 for i := uint(0); i < typе.NumField(cpp_types.FirstArch); i++ { 480 field := typе.Field(i, cpp_types.FirstArch).(cpp_types.EnumFieldInfo) 481 if field.Alias() == "" { 482 _, err = fmt.Fprintf(w, " BERBERIS_%s = %d,\n", field.Name(), field.Value()) 483 if err != nil { 484 return err 485 } 486 } 487 } 488 for i := uint(0); i < typе.NumField(cpp_types.FirstArch); i++ { 489 field := typе.Field(i, cpp_types.FirstArch).(cpp_types.EnumFieldInfo) 490 if field.Alias() != "" { 491 _, err = fmt.Fprintf(w, " BERBERIS_%s = BERBERIS_%s,\n", field.Name(), field.Alias()) 492 if err != nil { 493 return err 494 } 495 } 496 } 497 var maximum_value string 498 if isInt32T(typе.Elem(cpp_types.FirstArch)) { 499 maximum_value = "0x7FFF'FFFF" 500 } else if isUInt32T(typе.Elem(cpp_types.FirstArch)) { 501 maximum_value = "0xFFFF'FFFFU" 502 } else if isInt64T(typе.Elem(cpp_types.FirstArch)) { 503 maximum_value = "0x7FFF'FFFF'FFFF'FFFFULL" 504 } else { 505 return errors.New("Unknown enum base type definitions for type " + name) 506 } 507 _, err = fmt.Fprintf(w, " BERBERIS_%s = %s\n};\n\n", toEnumNameWithSuffix(name, "MAX_ENUM"), maximum_value) 508 if err != nil { 509 return err 510 } 511 } 512 return nil 513} 514 515func printEnumVerification(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) error { 516 for _, name := range sorted_type_names { 517 typе := types[name] 518 // Note: currently enums in vk.xml are architecture-agnostic. If some type is enum then it's always enum, on all 519 // architectures. And base type doesn't depend on the architecture either. 520 err := checkEnumConsistency(typе, name) 521 if err != nil { 522 return err 523 } 524 if !isEnum(typе) { 525 continue 526 } 527 _, err = fmt.Fprintf( 528 w, 529 `#if %[7]s 530CHECK_STRUCT_LAYOUT(berberis::%[2]s, %[3]d, %[4]d); 531#elif %[8]s 532CHECK_STRUCT_LAYOUT(berberis::%[2]s, %[5]d, %[6]d); 533#else 534#error Unsupported architecture. 535#endif 536#if !defined(BERBERIS_%[1]s) 537#if %[7]s 538CHECK_STRUCT_LAYOUT(::%[2]s, %[3]d, %[4]d); 539#elif %[8]s 540CHECK_STRUCT_LAYOUT(::%[2]s, %[5]d, %[6]d); 541#else 542#error Unsupported architecture. 543#endif 544`, 545 toEnumNameWithSuffix(name, "NOVERIFY"), 546 name, 547 typе.Bits(host_arch), 548 typе.Align(host_arch), 549 typе.Bits(guest_arch), 550 typе.Align(guest_arch), 551 cpp_types.Define(host_arch), 552 cpp_types.Define(guest_arch)) 553 if err != nil { 554 return err 555 } 556 for i := uint(0); i < typе.NumField(cpp_types.FirstArch); i++ { 557 field := typе.Field(i, cpp_types.FirstArch).(cpp_types.EnumFieldInfo) 558 _, err = fmt.Fprintf( 559 w, 560 `#if !defined(BERBERIS_%[1]s_NOVERIFY) 561static_assert(std::int64_t(%[1]s) == std::int64_t(berberis::BERBERIS_%[1]s)); 562#endif 563`, 564 field.Name()) 565 if err != nil { 566 return err 567 } 568 } 569 _, err = fmt.Fprintf( 570 w, 571 `#if !defined(BERBERIS_%[2]s_NOVERIFY) 572static_assert(std::int64_t(%[2]s) == std::int64_t(berberis::BERBERIS_%[2]s)); 573#endif /* BERBERIS_%[2]s_NOVERIFY */ 574#endif /* BERBERIS_%[1]s */ 575 576`, 577 toEnumNameWithSuffix(name, "NOVERIFY"), 578 toEnumNameWithSuffix(name, "MAX_ENUM")) 579 if err != nil { 580 return err 581 } 582 } 583 return nil 584} 585 586// Note: currently enums in vk.xml are architecture-agnostic. If some type is enum then it's always enum, on all 587// architectures. And base type doesn't depend on the architecture either. 588// 589// Generators (above) rely on that property. 590func checkEnumConsistency(typе cpp_types.Type, name string) error { 591 if typе.Kind(cpp_types.FirstArch) != cpp_types.Enum { 592 for arch := cpp_types.FirstArch + 1; arch <= cpp_types.LastArch; arch++ { 593 if typе.Kind(arch) == cpp_types.Enum { 594 return errors.New("Inconsistent types definitions for type " + name) 595 } 596 } 597 return nil 598 } 599 if !isInputCompatible(typе, cpp_types.X86, cpp_types.Arm) || !isInputCompatible(typе, cpp_types.Arm64, cpp_types.X86_64) { 600 return errors.New("Inconsistent types definitions for type " + name) 601 } 602 return nil 603} 604 605func printEnumAliases(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type) (err error) { 606 // Note: currently enums in vk.xml are architecture-agnostic. If some type is enum then it's always enum, on all 607 // architecturs. And base type doesn't depend on the architecture either. 608 // 609 // This simplifies the generation but we must verify that it's so to make sure this code would be adjusted in the 610 // [very unlikely] case where vk.xml would be changed to violate these invariants. 611 for _, name := range sorted_type_names { 612 typе := types[name] 613 if typе.Kind(cpp_types.FirstArch) != cpp_types.Alias || typе.Elem(cpp_types.FirstArch).Kind(cpp_types.FirstArch) != cpp_types.Enum { 614 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 615 if typе.Kind(arch) == cpp_types.Alias && typе.Elem(cpp_types.FirstArch).Kind(cpp_types.FirstArch) == cpp_types.Enum { 616 return errors.New("Inconsistest types definitions for type " + name) 617 } 618 } 619 continue 620 } else { 621 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 622 if typе.Kind(arch) != cpp_types.Alias || typе.Elem(cpp_types.FirstArch).Kind(cpp_types.FirstArch) != cpp_types.Enum { 623 return errors.New("Inconsistest types definitions for type " + name) 624 } 625 if typе.Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch) != typе.Elem(arch).Name(arch) { 626 return errors.New("Inconsistest enum alias base type definitions for type " + name) 627 } 628 } 629 } 630 fmt.Fprintf(w, "using %s = %s;\n\n", name, typе.Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch)) 631 } 632 return nil 633} 634 635func sortStructTypes(sorted_type_names []string, types map[string]cpp_types.Type) (sorted_struct_types_names []string, err error) { 636 next_struct_names_list := []string{} 637 for _, name := range sorted_type_names { 638 typе := types[name] 639 if !isStruct(typе) && !isUnion(typе) { 640 continue 641 } 642 ids := typе.NumField(cpp_types.FirstArch) 643 for arch := cpp_types.FirstArch + 1; arch <= cpp_types.LastArch; arch++ { 644 if typе.Kind(cpp_types.FirstArch) != typе.Kind(arch) { 645 return nil, errors.New("Inconsistent struct \"" + name + "\"") 646 } 647 if ids != typе.NumField(arch) { 648 return nil, errors.New("Inconsistent struct \"" + name + "\"") 649 } 650 for id := uint(0); id < ids; id++ { 651 if typе.Field(id, cpp_types.FirstArch).Type().Name(cpp_types.FirstArch) != typе.Field(id, arch).Type().Name(arch) { 652 return nil, errors.New("Inconsistent struct \"" + name + "\"") 653 } 654 } 655 } 656 next_struct_names_list = append(next_struct_names_list, name) 657 } 658 sorted_struct_types_names = []string{} 659 declared_types := make(map[string]cpp_types.Type) 660 var struct_names_list []string 661 for len(next_struct_names_list) > 0 { 662 // If next list is the same as previous one then we have some kind of loop and types couldn't be defined. 663 if len(struct_names_list) == len(next_struct_names_list) { 664 return nil, errors.New("Cannot make any progress: type \"" + struct_names_list[0] + "\" refers to undefined type") 665 } 666 struct_names_list = next_struct_names_list 667 next_struct_names_list = []string{} 668 type_list: 669 for _, name := range struct_names_list { 670 typе := types[name] 671 ids := typе.NumField(cpp_types.FirstArch) 672 for id := uint(0); id < ids; id++ { 673 field_type := typе.Field(id, cpp_types.FirstArch).Type() 674 if !areBaseTypesDeclared(field_type, declared_types) { 675 next_struct_names_list = append(next_struct_names_list, name) 676 continue type_list 677 } 678 } 679 sorted_struct_types_names = append(sorted_struct_types_names, name) 680 declared_types[typе.Name(cpp_types.FirstArch)] = typе 681 } 682 } 683 return sorted_struct_types_names, nil 684} 685 686func areBaseTypesDeclared(typе cpp_types.Type, declared_types map[string]cpp_types.Type) bool { 687 if typе.Name(cpp_types.FirstArch) == "struct VkBaseInStructure" || typе.Name(cpp_types.FirstArch) == "struct VkBaseOutStructure" { 688 return true 689 } 690 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 691 switch typе.Kind(arch) { 692 // If struct or union type is used then we need to have it declared. 693 // This is true both for Host and Guest types. 694 case cpp_types.Struct, cpp_types.Union: 695 if _, ok := declared_types[typе.Name(arch)]; !ok { 696 return false 697 } 698 // Aliases, Arrays, Consts don't change anything 699 case cpp_types.Alias, cpp_types.Array, cpp_types.Const: 700 if !areBaseTypesDeclared(typе.Elem(arch), declared_types) { 701 return false 702 } 703 // Pointers can be used with opaque structs, but it doesn't work if need to perform custom Host/Guest conversions. 704 case cpp_types.Ptr: 705 if !areBaseTypesDeclared(typе.Elem(arch), declared_types) { 706 return false 707 } 708 } 709 } 710 return true 711} 712 713func printHostStructTypes(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type) (err error) { 714 for _, name := range sorted_type_names { 715 if isStruct(types[name]) { 716 _, err = fmt.Fprintf(w, "struct %s;\n\n", name) 717 } else { 718 _, err = fmt.Fprintf(w, "union %s;\n\n", name) 719 } 720 if err != nil { 721 return err 722 } 723 } 724 for _, name := range sorted_type_names { 725 typе := types[name] 726 name := typе.Name(cpp_types.FirstArch) 727 _, err = fmt.Fprintf(w, "%s {\n", name) 728 if err != nil { 729 return err 730 } 731 ids := typе.NumField(cpp_types.FirstArch) 732 for id := uint(0); id < ids; id++ { 733 field_name := typе.Field(id, cpp_types.FirstArch).Name() 734 field_type := typе.Field(id, cpp_types.FirstArch).Type() 735 if isPtrToOpaque(field_type) { 736 // Assume opaque types are structs. 737 _, err = fmt.Fprintf(w, " struct %s;\n", field_type.DeclareVar(field_name, cpp_types.FirstArch)) 738 } else if isPtrToConstOpaque(field_type) { 739 // Assume opaque types are structs. 740 _, err = fmt.Fprintf(w, " const struct %s;\n", cpp_types.PointerType(field_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch)).DeclareVar(field_name, cpp_types.FirstArch)) 741 } else if isPtrToFunc(field_type) { 742 // Declare functions with BERBERIS_VKAPI_PTR attribute. 743 // This is needed if we want to use these on ARM platform because default Android API is 744 // “aapcs” but Vulkan needs “aapcs-vfp”. 745 _, err = fmt.Fprintf(w, " %s;\n", field_type.Elem(cpp_types.FirstArch).DeclareVar( 746 fmt.Sprintf("(BERBERIS_VKAPI_PTR *%s)", field_name), cpp_types.FirstArch)) 747 } else if isConstPtrToFunc(field_type) { 748 // Declare functions with BERBERIS_VKAPI_PTR attribute. 749 // This is needed if we want to use these on ARM platform because default Android API is 750 // “aapcs” but Vulkan needs “aapcs-vfp”. 751 _, err = fmt.Fprintf(w, " %s;\n", field_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch).DeclareVar( 752 fmt.Sprintf("(BERBERIS_VKAPI_PTR *%sconst)", field_name), cpp_types.FirstArch)) 753 } else { 754 _, err = fmt.Fprintf(w, " %s;\n", field_type.DeclareVar(field_name, cpp_types.FirstArch)) 755 } 756 if err != nil { 757 return err 758 } 759 } 760 _, err = fmt.Fprintf(w, "};\n\n") 761 if err != nil { 762 return err 763 } 764 } 765 return nil 766} 767 768func printFunctionPointerTypes(w io.Writer, sorted_command_names []string, commands map[string]cpp_types.Type) (err error) { 769 for _, name := range sorted_command_names { 770 _, err = fmt.Fprintf(w, "using PFN_%s = %s;\n", name, commands[name].DeclareVar("(BERBERIS_VKAPI_PTR*)", cpp_types.FirstArch)) 771 if err != nil { 772 return err 773 } 774 } 775 return nil 776} 777 778func getRequiredConversions(commands map[string]cpp_types.Type, types map[string]cpp_types.Type) (conversion map[string]*NeededConvertor, err error) { 779 conversion = make(map[string]*NeededConvertor) 780 for name, _ := range types { 781 conversion[name] = &NeededConvertor{ 782 need_base_convertor: false, 783 need_array_convertor: false, 784 need_const_convertor: false, 785 need_const_array_convertor: false, 786 } 787 } 788 // We need convertors for types referred in functions (commands in Vulkan-speak) and all 789 // types which they refer too (transitively). 790 // 791 // We always have to handle all of them symmetrically because Layers require conversions 792 // in both directions. 793 for _, command := range commands { 794 for i := uint(0); i < command.NumField(cpp_types.FirstArch); i++ { 795 param_type := command.Field(i, cpp_types.FirstArch).Type() 796 if isPtrToAlias(param_type) { 797 param_type = cpp_types.PointerType(param_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch)) 798 } 799 if isPtrToConstAlias(param_type) { 800 param_type = cpp_types.PointerType(cpp_types.ConstType(param_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch))) 801 } 802 param_length := command.Field(i, cpp_types.FirstArch).BaseFieldInfo().(vulkan_xml.ExtendedFieldInfo).Length() 803 if isPtrToConstStruct(param_type) { 804 base_name := param_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch).BaseName(cpp_types.FirstArch) 805 if param_length == nil { 806 conversion[base_name].need_const_convertor = true 807 } else if isPtr(param_length.Type()) { 808 return nil, errors.New("Unsupported combination of types for command") 809 } else { 810 if base_name == "VkDescriptorBufferBindingInfoEXT" { 811 // TODO(b/322902400): Make VkDescriptorBufferBindingInfoEXT work with berberis. 812 } else { 813 conversion[base_name].need_const_array_convertor = true 814 } 815 } 816 } else if isPtrToStruct(param_type) { 817 base_name := param_type.Elem(cpp_types.FirstArch).BaseName(cpp_types.FirstArch) 818 if param_length == nil { 819 if base_name == "VkGetLatencyMarkerInfoNV" { 820 // TODO(b/322902403): Make VkGetLatencyMarkerInfoNV work with berberis. 821 } else { 822 conversion[base_name].need_base_convertor = true 823 } 824 } else if isPtr(param_length.Type()) { 825 conversion[base_name].need_array_convertor = true 826 } else { 827 return nil, errors.New("Unsupported combination of types for command") 828 } 829 } 830 } 831 } 832 for { 833 attributes_changed := false 834 for name, typе := range types { 835 if !isStruct(typе) { 836 continue 837 } 838 ids := typе.NumField(cpp_types.FirstArch) 839 field_types := []cpp_types.Type{} 840 field_lengths := []cpp_types.FieldInfo{} 841 for id := uint(0); id < ids; id++ { 842 field_type := typе.Field(id, cpp_types.FirstArch).Type() 843 if isUnion(field_type) { 844 union_ids := field_type.NumField(cpp_types.FirstArch) 845 for union_id := uint(0); union_id < union_ids; union_id++ { 846 field_types = append(field_types, field_type.Field(union_id, cpp_types.FirstArch).Type()) 847 field_lengths = append(field_lengths, field_type.Field(union_id, cpp_types.FirstArch).BaseFieldInfo().(vulkan_xml.ExtendedFieldInfo).Length()) 848 } 849 } else { 850 field_types = append(field_types, field_type) 851 field_lengths = append(field_lengths, typе.Field(id, cpp_types.FirstArch).BaseFieldInfo().(vulkan_xml.ExtendedFieldInfo).Length()) 852 } 853 } 854 if len(typе.(vulkan_xml.ExtendedStructInfo).ExtendedWith()) > 0 { 855 if typе.Field(0, cpp_types.FirstArch).Name() != "sType" { 856 return nil, errors.New("Extensible data structure without sType") 857 } 858 if typе.Field(1, cpp_types.FirstArch).Name() != "pNext" { 859 return nil, errors.New("Extensible data structure without pNext") 860 } 861 for _, extra_type := range typе.(vulkan_xml.ExtendedStructInfo).ExtendedWith() { 862 if isPtrToConst(typе.Field(1, cpp_types.FirstArch).Type()) { 863 field_types = append(field_types, cpp_types.PointerType(cpp_types.ConstType(extra_type))) 864 } else { 865 field_types = append(field_types, cpp_types.PointerType(extra_type)) 866 } 867 field_lengths = append(field_lengths, nil) 868 } 869 } 870 for id, field_type := range field_types { 871 field_length := field_lengths[id] 872 if isPtrToAlias(field_type) { 873 field_type = cpp_types.PointerType(field_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch)) 874 } 875 if isPtrToConstAlias(field_type) { 876 field_type = cpp_types.PointerType(cpp_types.ConstType(field_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch))) 877 } 878 if isPtrToConstStruct(field_type) { 879 base_type := field_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch) 880 base_name := base_type.BaseName(cpp_types.FirstArch) 881 if field_length == nil { 882 if (conversion[name].need_const_convertor || conversion[name].need_const_array_convertor) && 883 !conversion[base_name].need_const_convertor { 884 if base_name == "VkFaultCallbackInfo" { 885 // TODO(b/322902053): Make VkFaultCallbackInfo work with berberis. 886 } else { 887 conversion[base_name].need_const_convertor = true 888 attributes_changed = true 889 } 890 } 891 // Optional data structures may be used both as inputs and outputs thus we can not rely on the constness of the "Next" pointer. 892 if conversion[name].need_base_convertor && 893 !conversion[name].need_array_convertor && 894 base_type.(vulkan_xml.ExtendedStructInfo).OptionalStruct() { 895 if !conversion[base_name].need_base_convertor { 896 conversion[base_name].need_base_convertor = true 897 attributes_changed = true 898 } 899 } else if conversion[name].need_base_convertor || 900 conversion[name].need_array_convertor { 901 return nil, errors.New("Unsupported combination of types for struct") 902 } 903 } else if isPtr(field_length.Type()) { 904 return nil, errors.New("Unsupported combination of types for struct") 905 } else { 906 if (conversion[name].need_const_convertor || conversion[name].need_const_array_convertor) && 907 !conversion[base_name].need_const_array_convertor { 908 conversion[base_name].need_const_array_convertor = true 909 attributes_changed = true 910 } else if conversion[name].need_base_convertor || 911 conversion[name].need_array_convertor { 912 return nil, errors.New("Unsupported combination of types for struct") 913 } 914 } 915 } else if isPtrToStruct(field_type) { 916 base_type := field_type.Elem(cpp_types.FirstArch) 917 base_name := base_type.BaseName(cpp_types.FirstArch) 918 if base_name == "VkDescriptorBufferBindingPushDescriptorBufferHandleEXT" || 919 base_name == "VkDrmFormatModifierProperties2EXT" || 920 base_name == "VkDrmFormatModifierPropertiesEXT" || 921 base_name == "VkRenderPassCreationFeedbackInfoEXT" || 922 base_name == "VkRenderPassSubpassFeedbackInfoEXT" || 923 base_name == "VkPhysicalDeviceLayeredApiPropertiesListKHR" { 924 // TODO(b/171255170): Process the optional structures correctly. 925 } else if base_name == "VkPipelineCreationFeedback" { 926 // VkPipelineCreationFeedback is referred from input data structure VkPipelineCreationFeedbackCreateInfo 927 if !conversion[base_name].need_base_convertor { 928 conversion[base_name].need_base_convertor = true 929 attributes_changed = true 930 } 931 if !conversion[base_name].need_array_convertor { 932 conversion[base_name].need_array_convertor = true 933 attributes_changed = true 934 } 935 } else if field_length == nil { 936 if (conversion[name].need_base_convertor || conversion[name].need_array_convertor) && 937 !conversion[base_name].need_base_convertor { 938 conversion[base_name].need_base_convertor = true 939 attributes_changed = true 940 } 941 // Optional data structures may be used both as inputs and outputs thus we can not rely on the constness of the "Next" pointer. 942 if conversion[name].need_const_convertor && 943 !conversion[name].need_const_array_convertor && 944 base_type.(vulkan_xml.ExtendedStructInfo).OptionalStruct() { 945 if !conversion[base_name].need_const_convertor { 946 conversion[base_name].need_const_convertor = true 947 attributes_changed = true 948 } 949 } else if conversion[name].need_const_convertor || 950 conversion[name].need_const_array_convertor { 951 return nil, errors.New("Unsupported combination of types for struct") 952 } 953 } else { 954 // We don't even try to handle nested out structures (except one case above). 955 if conversion[name].need_const_convertor || 956 conversion[name].need_base_convertor || 957 conversion[name].need_const_array_convertor || 958 conversion[name].need_array_convertor { 959 return nil, errors.New("Unsupported combination of types for struct") 960 } 961 } 962 } 963 } 964 } 965 if !attributes_changed { 966 break 967 } 968 } 969 return conversion, nil 970} 971 972type NeededConvertor struct { 973 need_base_convertor bool 974 need_array_convertor bool 975 need_const_convertor bool 976 need_const_array_convertor bool 977} 978 979func printGuestStructTypes(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type, conversion map[string]*NeededConvertor, host_arch, guest_arch cpp_types.Arch) (err error) { 980 for _, name := range sorted_type_names { 981 typе := types[name] 982 if isInputCompatible(typе, host_arch, guest_arch) { 983 continue 984 } 985 // The goal is to resolve issue with recursive structures like 986 // VkBaseInStructure/VkBaseOutStructure. 987 // 988 // These structures include pNext type which is not pointer to void 989 // (as usual), but point to the structures of the same type. 990 // 991 // Thus we have the following definition: 992 // 993 // template<> 994 // class GuestType<VkBaseOutStructure> { 995 // public: 996 // using Type = VkBaseOutStructure; 997 // 998 // GuestType<VkStructureType> sType; 999 // GuestType<struct VkBaseOutStructure*> pNext; 1000 // }; 1001 // 1002 // It can only be processed if “class GuestType<VkBaseOutStructure*>” is defined 1003 // before “class GuestType<VkBaseOutStructure>”, but then we would have problem 1004 // with all conversion routines for “class GuestType<VkBaseOutStructure*>” since 1005 // these require access to “class GuestType<VkBaseOutStructure>”! 1006 // 1007 // Resolution is to declare “class GuestType<VkBaseOutStructure*>”, then declare 1008 // “class GuestType<VkBaseOutStructure>” and only then declare conversion routines. 1009 // 1010 err = printGuestStructPointerType(w, name, typе, host_arch, guest_arch, conversion) 1011 if err != nil { 1012 return err 1013 } 1014 err = printGuestStructType(w, name, typе, host_arch, guest_arch) 1015 if err != nil { 1016 return err 1017 } 1018 err = printGuestStructPointerConversionsType(w, name, typе, host_arch, guest_arch, conversion) 1019 if err != nil { 1020 return err 1021 } 1022 } 1023 return nil 1024} 1025 1026func printGuestStructType(w io.Writer, name string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) error { 1027 // Note: it's not possible to pass struct as an out argument in C (possible with C++ and references, but not with C) 1028 // and it looks as if GuestType<const StructType> is not needed (arguments of "const StructType" and "StructType" 1029 // are identical in C). 1030 // 1031 // But we need GuestType<StructType> and GuestType<const StructType> to handle the following corners case: 1032 // struct Foo { 1033 // … ← here we have pointers, optional extensions or other complex data. 1034 // }; 1035 // struct Bar { 1036 // Foo foo; 1037 // }; 1038 // void baz(Bar* bar); 1039 // 1040 // Here function baz returns struct “struct Bar” (using pointer argument) which embeds “struct Foo”. 1041 // Note that these structs can be nested few levels in depth. 1042 // 1043 // Here we effectively return value of type Foo (even if that's not possible, strictly speaking, in C) and the 1044 // simplest way is to keep origin and do conversion in destructor. 1045 // 1046 // That's not very efficient (we are keeping address which can, actually, be calculated) but that's simpler and, 1047 // thankfully, that's rare corner case, not the norm. 1048 for _, cоnst := range []string{"", "const "} { 1049 _, err := fmt.Fprintf(w, "template<>\nclass GuestType<%[1]s%[2]s> {\n public:\n using Type = %[1]s%[2]s;\n\n", cоnst, name) 1050 if err != nil { 1051 return err 1052 } 1053 if isUnion(typе) { 1054 _, err := fmt.Fprintln(w, " union Union {") 1055 if err != nil { 1056 return err 1057 } 1058 } 1059 ids := typе.NumField(cpp_types.FirstArch) 1060 for id := uint(0); id < ids; id++ { 1061 field_name := typе.Field(id, cpp_types.FirstArch).Name() 1062 field_type := typе.Field(id, cpp_types.FirstArch).Type() 1063 if cоnst == "const " { 1064 if isArray(field_type) { 1065 field_type = cpp_types.ArrayType(cpp_types.ConstType(field_type.Elem(cpp_types.FirstArch)), field_type.NumField(cpp_types.FirstArch)) 1066 } else { 1067 field_type = cpp_types.ConstType(field_type) 1068 } 1069 } 1070 if isPtrToOpaque(field_type) { 1071 // Assume opaque types are structs. 1072 _, err = fmt.Fprintf(w, " GuestType<%sstruct %s> %s;\n", cоnst, field_type.Name(cpp_types.FirstArch), field_name) 1073 } else if isPtrToConstOpaque(field_type) { 1074 // Assume opaque types are structs. 1075 _, err = fmt.Fprintf(w, " GuestType<const struct %s> %s;\n", cpp_types.PointerType(field_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch)).Name(cpp_types.FirstArch), field_name) 1076 } else if isPtrToFunc(field_type) { 1077 // Declare functions with BERBERIS_VKAPI_PTR attribute. 1078 // This is needed if we want to use these on ARM platform because default Android API is 1079 // “aapcs” but Vulkan needs “aapcs-vfp”. 1080 _, err = fmt.Fprintf(w, " GuestType<%s> %s;\n", field_type.Elem(cpp_types.FirstArch).DeclareVar( 1081 "(BERBERIS_VKAPI_PTR*)", cpp_types.FirstArch), field_name) 1082 } else if isConstPtrToFunc(field_type) { 1083 // Declare functions with BERBERIS_VKAPI_PTR attribute. 1084 // This is needed if we want to use these on ARM platform because default Android API is 1085 // “aapcs” but Vulkan needs “aapcs-vfp”. 1086 _, err = fmt.Fprintf(w, " GuestType<%s> %s;\n", field_type.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch).DeclareVar( 1087 "(BERBERIS_VKAPI_PTR*const)", cpp_types.FirstArch), field_name) 1088 } else if isArray(field_type) { 1089 elem := field_type.Elem(cpp_types.FirstArch) 1090 if isArray(elem) || isPtr(elem) { 1091 return errors.New("Array of complex type: " + field_type.Name(cpp_types.FirstArch)) 1092 } 1093 _, err = fmt.Fprintf(w, " GuestType<%s> %s[%d];\n", field_type.Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch), field_name, field_type.NumField(cpp_types.FirstArch)) 1094 } else if field_type.Align(host_arch) != field_type.Align(guest_arch) { 1095 _, err = fmt.Fprintf(w, " alignas(%d) GuestType<%s> %s;\n", field_type.Align(guest_arch)/8, field_type.Name(cpp_types.FirstArch), field_name) 1096 } else { 1097 _, err = fmt.Fprintf(w, " GuestType<%s> %s;\n", field_type.Name(cpp_types.FirstArch), field_name) 1098 } 1099 if err != nil { 1100 return err 1101 } 1102 } 1103 if isUnion(typе) { 1104 // Make the uniоn default-constructible by initializing first field. We need it to support holders. 1105 _, err := fmt.Fprintf(w, " } uniоn = { .%s = {} };\n", typе.Field(0, cpp_types.FirstArch).Name()) 1106 if err != nil { 1107 return err 1108 } 1109 } 1110 _, err = fmt.Fprint(w, "};\n\n") 1111 if err != nil { 1112 return err 1113 } 1114 } 1115 return nil 1116} 1117 1118func printGuestStructPointerType(w io.Writer, name string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch, conversion map[string]*NeededConvertor) error { 1119 // Naked unions are never passed around in Vulkan. They are always embedded into structure with selector field. 1120 if isUnion(typе) { 1121 return nil 1122 } 1123 1124 // We are not trying to convert on ARM64 because we don't know if pointer is valid (and if all extensions are compatible). 1125 // On ARM32 we need to convert some data structures, but tests pass because of quirk of how they are run. 1126 // TODO(b/274875580): fix properly. 1127 if guest_arch == cpp_types.Arm64 && name == "VkCommandBufferInheritanceInfo" { 1128 return nil 1129 } 1130 1131 _, err := fmt.Fprintf(w, `template<> 1132class GuestType<%[1]s*> { 1133 public: 1134 using Type = %[1]s*; 1135 class GuestHolder; 1136 class GuestArrayHolder; 1137 class HostHolder; 1138 class HostArrayHolder; 1139 GuestType(%[1]s* const new_value, GuestHolder& holder, bool& out_of_memory); 1140 GuestType(%[1]s* const new_value, GuestArrayHolder& holder, const std::uint32_t* size, bool& out_of_memory); 1141 GuestType(GuestType<%[1]s>* const& new_value); 1142 GuestType(GuestType<%[1]s>*&& new_value); 1143 GuestType() = default; 1144 GuestType(const GuestType&) = default; 1145 GuestType(GuestType&&) = default; 1146 GuestType& operator=(const GuestType& data) = default; 1147 GuestType& operator=(GuestType&& data) = default; 1148 ~GuestType() = default; 1149`, 1150 name) 1151 if err != nil { 1152 return err 1153 } 1154 1155 if conversion[name].need_base_convertor { 1156 _, err = fmt.Fprintf(w, " friend %[1]s* ToHostType(const GuestType&, HostHolder& holder, bool& out_of_memory);\n", name) 1157 if err != nil { 1158 return err 1159 } 1160 } 1161 1162 if conversion[name].need_array_convertor { 1163 _, err = fmt.Fprintf(w, " friend %[1]s* ToHostType(const GuestType&, HostArrayHolder& holder, const std::uint32_t* size, bool& out_of_memory);\n", name) 1164 if err != nil { 1165 return err 1166 } 1167 } 1168 1169 _, err = fmt.Fprintf(w, ` friend GuestAddr ToGuestAddr(const GuestType& guest_type) { return guest_type.value_; } 1170 1171 private: 1172 GuestAddr value_; 1173}; 1174 1175`) 1176 if err != nil { 1177 return err 1178 } 1179 1180 _, err = fmt.Fprintf(w, `template<> 1181class GuestType<const %[1]s*> { 1182 public: 1183 using Type = const %[1]s*; 1184 class GuestHolder; 1185 class GuestArrayHolder; 1186 class HostHolder; 1187 class HostArrayHolder; 1188 GuestType(const %[1]s* const new_value, GuestHolder& holder, bool& out_of_memory); 1189`, 1190 name) 1191 if err != nil { 1192 return err 1193 } 1194 1195 if name == "VkAccelerationStructureGeometryKHR" { 1196 _, err = fmt.Fprintf(w, " GuestType(const VkAccelerationStructureGeometryKHR* const new_value, const VkAccelerationStructureGeometryKHR* const* const new_value_ptr, GuestArrayHolder& holder, std::size_t size, bool& out_of_memory);\n") 1197 } else { 1198 _, err = fmt.Fprintf(w, " GuestType(const %[1]s* const new_value, GuestArrayHolder& holder, std::size_t size, bool& out_of_memory);\n", name) 1199 } 1200 if err != nil { 1201 return err 1202 } 1203 1204 _, err = fmt.Fprintf(w, ` GuestType(GuestType<const %[1]s>* const& new_value); 1205 GuestType(GuestType<const %[1]s>*&& new_value); 1206 GuestType(GuestType<%[1]s>* const& new_value); 1207 GuestType(GuestType<%[1]s>*&& new_value); 1208 GuestType() = default; 1209 GuestType(const GuestType&) = default; 1210 GuestType(GuestType&&) = default; 1211 GuestType& operator=(const GuestType& data) = default; 1212 GuestType& operator=(GuestType&& data) = default; 1213 ~GuestType() = default; 1214`, 1215 name) 1216 if err != nil { 1217 return err 1218 } 1219 1220 if conversion[name].need_const_convertor { 1221 if name == "VkCommandBufferBeginInfo" { 1222 _, err = fmt.Fprintf(w, " friend const %[1]s* ToHostType(const GuestType&, HostHolder& holder, bool has_inheritance_info, bool& out_of_memory);\n", name) 1223 } else { 1224 _, err = fmt.Fprintf(w, " friend const %[1]s* ToHostType(const GuestType&, HostHolder& holder, bool& out_of_memory);\n", name) 1225 } 1226 if err != nil { 1227 return err 1228 } 1229 } 1230 1231 if name == "VkAccelerationStructureGeometryKHR" { 1232 _, err = fmt.Fprintf(w, " friend const %[1]s* ToHostType(const GuestType& new_value, GuestType<const VkAccelerationStructureGeometryKHR* const*> const new_value_ptr, HostArrayHolder& holder, std::size_t size, bool& out_of_memory);\n", name) 1233 } else if conversion[name].need_const_array_convertor { 1234 _, err = fmt.Fprintf(w, " friend const %[1]s* ToHostType(const GuestType&, HostArrayHolder& holder, std::size_t size, bool& out_of_memory);\n", name) 1235 } 1236 if err != nil { 1237 return err 1238 } 1239 1240 _, err = fmt.Fprintf(w, ` friend GuestAddr ToGuestAddr(const GuestType& guest_type) { return guest_type.value_; } 1241 1242 private: 1243 GuestAddr value_; 1244}; 1245 1246`) 1247 if err != nil { 1248 return err 1249 } 1250 return nil 1251} 1252 1253func printGuestStructPointerConversionsType(w io.Writer, name string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch, conversion map[string]*NeededConvertor) error { 1254 // Naked unions are never passed around in Vulkan. They are always embedded into structure with selector field. 1255 if isUnion(typе) { 1256 return nil 1257 } 1258 1259 // We are not trying to convert on ARM64 because we don't know if pointer is valid (and if all extensions are compatible). 1260 // On ARM32 we need to convert some data structures, but tests pass because of quirk of how they are run. 1261 // TODO(b/274875580): fix properly. 1262 if guest_arch == cpp_types.Arm64 && name == "VkCommandBufferInheritanceInfo" { 1263 return nil 1264 } 1265 1266 // Any data structure which have sType fields and pNext fields can be, potentially, expanded: 1267 // https://github.com/KhronosGroup/Vulkan-Guide/blob/main/chapters/pnext_and_stype.adoc 1268 // We support extensions with data structures we are familiar with, but not unknown ones. 1269 extensible_type := isExtensibleType(typе) 1270 1271 _, err := fmt.Fprintf(w, `inline GuestType<%[1]s*>::GuestType(GuestType<%[1]s>* const& new_value) : value_(ToGuestAddr(new_value)) {} 1272inline GuestType<%[1]s*>::GuestType(GuestType<%[1]s>*&& new_value) : value_(ToGuestAddr(new_value)) {} 1273 1274inline GuestType<const %[1]s*>::GuestType(GuestType<const %[1]s>* const& new_value) : value_(ToGuestAddr(new_value)) {} 1275inline GuestType<const %[1]s*>::GuestType(GuestType<const %[1]s>*&& new_value) : value_(ToGuestAddr(new_value)) {} 1276inline GuestType<const %[1]s*>::GuestType(GuestType<%[1]s>* const& new_value) : value_(ToGuestAddr(new_value)) {} 1277inline GuestType<const %[1]s*>::GuestType(GuestType<%[1]s>*&& new_value) : value_(ToGuestAddr(new_value)) {} 1278 1279`, 1280 name) 1281 if err != nil { 1282 return err 1283 } 1284 1285 if conversion[name].need_base_convertor { 1286 if typе.(vulkan_xml.ExtendedStructInfo).OptionalStruct() { 1287 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::GuestHolder : public GuestHolderBase { 1288 public: 1289 virtual ~GuestHolder() override; 1290`, 1291 name) 1292 } else { 1293 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::GuestHolder { 1294 public: 1295 ~GuestHolder(); 1296`, 1297 name) 1298 } 1299 if err != nil { 1300 return err 1301 } 1302 holder := "" 1303 if extensible_type { 1304 holder = "std::unique_ptr<GuestHolderBase> extensions_;\n " 1305 } 1306 holder += "GuestType<" + name + "> data_;" 1307 if isInputCompatible(typе, host_arch, guest_arch) { 1308 _, err = fmt.Fprintf(w, ` friend GuestType<%[1]s*>; 1309 1310 private: 1311}; 1312 1313inline GuestType<%[1]s*>::GuestHolder::~GuestHolder() { 1314} 1315 1316inline GuestType<%[1]s*>::GuestType(%[1]s* const new_value, GuestType<%[1]s*>::GuestHolder&, bool&) : value_(bit_cast<GuestAddr>(new_value)) { 1317} 1318 1319`, 1320 name) 1321 } else { 1322 _, err = fmt.Fprintf(w, ` friend GuestType<%[1]s*>; 1323 1324 private: 1325 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1326 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1327 %[1]s* origin_ = nullptr; 1328 %[2]s 1329}; 1330 1331inline GuestType<%[1]s*>::GuestHolder::~GuestHolder() { 1332 *origin_ = { 1333 %[3]s }; 1334} 1335 1336inline GuestType<%[1]s*>::GuestType(%[1]s* const new_value, GuestType<%[1]s*>::GuestHolder& holder, [[maybe_unused]] bool& out_of_memory) : value_(new_value == nullptr ? kNullGuestAddr : ToGuestAddr(&holder.data_)) { 1337 holder.origin_ = new_value; 1338 holder.data_ = { 1339 %[4]s }; 1340} 1341 1342`, 1343 name, 1344 strings.Join(append( 1345 makeHolderList("GuestType<%s>::Guest%sHolder %s_holder_;", false, typе, host_arch, guest_arch), 1346 holder), "\n "), 1347 strings.Join(makeHostInitializerList(initializeDataMembers, name, typе, host_arch, guest_arch), "\n "), 1348 strings.Join(makeGuestInitializerList(initializePointers, name, typе, host_arch, guest_arch), "\n ")) 1349 } 1350 if err != nil { 1351 return err 1352 } 1353 if typе.(vulkan_xml.ExtendedStructInfo).OptionalStruct() { 1354 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::HostHolder: HostHolderBase { 1355 public: 1356 virtual ~HostHolder() override; 1357`, 1358 name) 1359 } else { 1360 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::HostHolder { 1361 public: 1362 ~HostHolder(); 1363`, 1364 name) 1365 } 1366 if err != nil { 1367 return err 1368 } 1369 holder = "" 1370 if extensible_type { 1371 holder = "std::unique_ptr<HostHolderBase> extensions_;\n " 1372 } 1373 holder += name + " data_;" 1374 extra_holder_argument := "" 1375 if name == "VkCommandBufferBeginInfo" { 1376 extra_holder_argument = "bool has_inheritance_info, " 1377 } 1378 if isInputCompatible(typе, host_arch, guest_arch) { 1379 _, err = fmt.Fprintf(w, ` friend %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostHolder& holder, bool& out_of_memory); 1380 1381 private: 1382}; 1383 1384inline GuestType<%[1]s*>::HostHolder::~HostHolder() { 1385} 1386 1387inline %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostHolder&, bool&) { 1388 return ToHostAddr<%[1]s>(ToGuestAddr(new_value)); 1389} 1390 1391`, 1392 name) 1393 } else { 1394 _, err = fmt.Fprintf(w, ` friend %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostHolder& holder, bool& out_of_memory); 1395 1396 private: 1397 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 1398 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 1399 GuestType<%[1]s>* origin_ = nullptr; 1400 %[2]s 1401}; 1402 1403inline GuestType<%[1]s*>::HostHolder::~HostHolder() { 1404 *origin_ = { 1405 %[3]s }; 1406} 1407 1408inline %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostHolder& holder, %[5]s[[maybe_unused]] bool& out_of_memory) { 1409 if (ToGuestAddr(new_value) == kNullGuestAddr) { 1410 return nullptr; 1411 } 1412 holder.origin_ = ToHostAddr<GuestType<%[1]s>>(ToGuestAddr(new_value)); 1413 holder.data_ = { 1414 %[4]s }; 1415 return &holder.data_; 1416} 1417 1418`, 1419 name, 1420 strings.Join(append( 1421 makeHolderList("GuestType<%s>::Host%sHolder %s_holder_;", false, typе, host_arch, guest_arch), 1422 holder), "\n "), 1423 strings.Join(makeGuestInitializerList(initializeDataMembers, name, typе, host_arch, guest_arch), "\n "), 1424 strings.Join(makeHostInitializerList(initializePointers, name, typе, host_arch, guest_arch), "\n "), 1425 extra_holder_argument) 1426 } 1427 if err != nil { 1428 return err 1429 } 1430 } 1431 1432 if conversion[name].need_array_convertor { 1433 holder := "" 1434 if extensible_type { 1435 holder = "std::unique_ptr<GuestHolderBase> extensions_;\n " 1436 } 1437 holder += "GuestType<" + name + ">* data_ = nullptr;" 1438 if isInputCompatible(typе, host_arch, guest_arch) { 1439 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::GuestArrayHolder { 1440 public: 1441 ~GuestArrayHolder(); 1442 friend GuestType<%[1]s*>; 1443 1444 private: 1445}; 1446 1447inline GuestType<%[1]s*>::GuestArrayHolder::~GuestArrayHolder() { 1448} 1449 1450inline GuestType<%[1]s*>::GuestType(%[1]s* const new_value, GuestType<%[1]s*>::GuestArrayHolder&, const std::uint32_t*, bool&) : value_(bit_cast<GuestAddr>(new_value)) { 1451} 1452 1453`, 1454 name) 1455 } else { 1456 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::GuestArrayHolder { 1457 public: 1458 ~GuestArrayHolder(); 1459 friend GuestType<%[1]s*>; 1460 1461 private: 1462 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1463 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1464 const std::uint32_t* size_ = nullptr; 1465 %[1]s* origin_ = nullptr; 1466 %[2]s 1467}; 1468 1469inline GuestType<%[1]s*>::GuestArrayHolder::~GuestArrayHolder() { 1470 if (size_ == nullptr) { 1471 return; 1472 } 1473 for (std::size_t index = 0; index < *size_; ++index) { 1474 origin_[index] = { 1475 %[5]s }; 1476 } 1477 %[3]s 1478} 1479 1480// Note: for output data structures combo where “*size == 0” and yet data pointer is not nullptr is both valid and different from situation where data pointer is nullptr. 1481// Correct handling relies on obscure fact that “new Foo[0]” is also valid call in C++ and is guaranteed to produce non-nullptr pointer (which can not be dereferenced). 1482 1483inline GuestType<%[1]s*>::GuestType(%[1]s* const new_value, GuestType<%[1]s*>::GuestArrayHolder& holder, const std::uint32_t* size, [[maybe_unused]] bool& out_of_memory) : value_((new_value == nullptr) ? kNullGuestAddr : ToGuestAddr(holder.data_ = new (std::nothrow) GuestType<%[1]s>[*size])) { 1484 %[4]s 1485 for (std::size_t index = 0; index < *size; ++index) { 1486 ToHostAddr<GuestType<%[1]s>>(value_)[index] = { 1487 %[6]s }; 1488 } 1489} 1490 1491`, 1492 name, 1493 strings.Join(append([]string{holder}, 1494 // Note %s after * is to intentionally trigger error if/when arrays to arrays would occur in the output data structures. 1495 // TODO: read the documentation and fix the code if that would ever happen. 1496 makeHolderList("GuestType<%s>::GuestHolder*%s %s_holder_ = nullptr;", false, typе, host_arch, guest_arch)...), "\n "), 1497 strings.Join(append( 1498 makeHolderList("delete[] %[3]s_holder_;", false, typе, host_arch, guest_arch), 1499 "delete[] data_;"), "\n "), 1500 strings.Join(append([]string{"holder.origin_ = new_value;\n if (value_ == kNullGuestAddr) {\n if (new_value != nullptr) {\n out_of_memory = true;\n }\n return;\n }\n holder.size_ = size;"}, 1501 makeHolderList("if ((holder.%[3]s_holder_ = new (std::nothrow) GuestType<%[1]s>::GuestHolder%[2]s[*size]) == nullptr) {\n out_of_memory = true;\n return;\n };", false, typе, host_arch, guest_arch)...), "\n "), 1502 strings.Join(makeHostInitializerListForArray(initializeDataMembers, name, typе, host_arch, guest_arch), "\n "), 1503 strings.Join(makeGuestInitializerListForArray(initializePointers, name, typе, host_arch, guest_arch), "\n ")) 1504 } 1505 if err != nil { 1506 return err 1507 } 1508 1509 holder = "" 1510 if extensible_type { 1511 holder = "std::unique_ptr<HostHolderBase> extensions_;\n " 1512 } 1513 holder += name + "* data_ = nullptr;" 1514 if isInputCompatible(typе, host_arch, guest_arch) { 1515 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::HostArrayHolder { 1516 public: 1517 ~HostArrayHolder(); 1518 friend %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostArrayHolder& holder, const std::uint32_t* size, bool& out_of_memory); 1519 1520 private: 1521}; 1522 1523inline GuestType<%[1]s*>::HostArrayHolder::~HostArrayHolder() { 1524} 1525 1526inline %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostArrayHolder&, const std::uint32_t*, bool&) { 1527 return ToHostAddr<%[1]s>(ToGuestAddr(new_value)); 1528} 1529 1530`, 1531 name) 1532 } else { 1533 _, err = fmt.Fprintf(w, `class GuestType<%[1]s*>::HostArrayHolder { 1534 public: 1535 ~HostArrayHolder(); 1536 friend %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostArrayHolder& holder, const std::uint32_t* size, bool& out_of_memory); 1537 1538 private: 1539 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 1540 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 1541 const std::uint32_t* size_ = nullptr; 1542 GuestType<%[1]s>* origin_ = nullptr; 1543 %[2]s 1544}; 1545 1546inline GuestType<%[1]s*>::HostArrayHolder::~HostArrayHolder() { 1547 if (size_ == nullptr) { 1548 return; 1549 } 1550 for (std::size_t index = 0; index < *size_; ++index) { 1551 origin_[index] = { 1552 %[5]s }; 1553 } 1554 %[3]s 1555} 1556 1557inline %[1]s* ToHostType(const GuestType<%[1]s*>& new_value, GuestType<%[1]s*>::HostArrayHolder& holder, const std::uint32_t* size, bool& out_of_memory) { 1558 holder.origin_ = ToHostAddr<GuestType<%[1]s>>(ToGuestAddr(new_value)); 1559 %[4]s 1560 for (std::size_t index = 0; index < *size; ++index) { 1561 holder.data_[index] = { 1562 %[6]s }; 1563 } 1564 return holder.data_; 1565} 1566 1567`, 1568 name, 1569 strings.Join(append([]string{holder}, 1570 // Note %s after * is to intentionally trigger error if/when arrays to arrays would occur in the output data structures. 1571 // TODO: read the documentation and fix the code if that would ever happen. 1572 makeHolderList("GuestType<%s>::HostHolder*%s %s_holder_ = nullptr;", false, typе, host_arch, guest_arch)...), "\n "), 1573 strings.Join(append( 1574 makeHolderList("delete[] %[3]s_holder_;", false, typе, host_arch, guest_arch), 1575 "delete[] data_;"), "\n "), 1576 strings.Join(append([]string{"if (ToGuestAddr(new_value) == kNullGuestAddr) {\n return nullptr;\n }\n holder.size_ = size;\n if ((holder.data_ = new (std::nothrow) " + name + "[*size]) == nullptr) {\n out_of_memory = true;\n return nullptr;\n }"}, 1577 makeHolderList("if ((holder.%[3]s_holder_ = new (std::nothrow) GuestType<%[1]s>::HostHolder%[2]s[*size]) == nullptr) {\n out_of_memory = true;\n return nullptr;\n };", false, typе, host_arch, guest_arch)...), "\n "), 1578 strings.Join(makeGuestInitializerListForArray(initializeDataMembers, name, typе, host_arch, guest_arch), "\n "), 1579 strings.Join(makeHostInitializerListForArray(initializePointers, name, typе, host_arch, guest_arch), "\n ")) 1580 } 1581 if err != nil { 1582 return err 1583 } 1584 } 1585 1586 if conversion[name].need_const_convertor { 1587 if name == "VkAccelerationStructureBuildGeometryInfoKHR" { 1588 if isInputCompatible(typе, host_arch, guest_arch) { 1589 _, err = fmt.Fprintf(w, `class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestHolder { 1590 public: 1591 friend GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>; 1592 1593 private: 1594}; 1595 1596inline GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestType( 1597 const VkAccelerationStructureBuildGeometryInfoKHR* new_value, 1598 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestHolder&, 1599 bool&) 1600 : value_(bit_cast<GuestAddr>(new_value)) { 1601} 1602 1603class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostHolder { 1604 public: 1605 friend const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 1606 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 1607 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostHolder& holder, 1608 bool& out_of_memory); 1609 1610 private: 1611}; 1612 1613inline const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 1614 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 1615 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostHolder&, 1616 bool&) { 1617 return ToHostAddr<VkAccelerationStructureBuildGeometryInfoKHR>(ToGuestAddr(new_value)); 1618} 1619 1620`) 1621 } else { 1622 _, err = fmt.Fprintf(w, `class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestHolder { 1623 public: 1624 friend GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>; 1625 1626 private: 1627 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1628 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1629 GuestType<const struct VkAccelerationStructureGeometryKHR*>::GuestArrayHolder pGeometries_holder_; 1630 std::unique_ptr<GuestHolderBase> extensions_; 1631 GuestType<VkAccelerationStructureBuildGeometryInfoKHR> data_; 1632}; 1633 1634inline GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestType( 1635 const VkAccelerationStructureBuildGeometryInfoKHR* new_value, 1636 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestHolder& holder, 1637 bool& out_of_memory) 1638 : value_(new_value == nullptr ? kNullGuestAddr : ToGuestAddr(&holder.data_)) { 1639 if (new_value != nullptr) { 1640 holder.data_ = { 1641 .sType = GuestType<VkStructureType>(new_value->sType), 1642 .pNext = ConvertOptionalStructures(new_value->pNext, holder.extensions_, out_of_memory), 1643 .type = GuestType<VkAccelerationStructureTypeKHR>(new_value->type), 1644 .flags = GuestType<VkBuildAccelerationStructureFlagsKHR>(new_value->flags), 1645 .mode = GuestType<VkBuildAccelerationStructureModeKHR>(new_value->mode), 1646 .srcAccelerationStructure = 1647 GuestType<VkAccelerationStructureKHR>(new_value->srcAccelerationStructure), 1648 .dstAccelerationStructure = 1649 GuestType<VkAccelerationStructureKHR>(new_value->dstAccelerationStructure), 1650 .geometryCount = GuestType<std::uint32_t>(new_value->geometryCount), 1651 .pGeometries = 1652 GuestType<const struct VkAccelerationStructureGeometryKHR*>(new_value->pGeometries, 1653 new_value->ppGeometries, 1654 holder.pGeometries_holder_, 1655 new_value->geometryCount, 1656 out_of_memory), 1657 .ppGeometries = 1658 GuestType<const struct VkAccelerationStructureGeometryKHR* const*>(nullptr)}; 1659 } 1660} 1661 1662class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostHolder { 1663 public: 1664 friend const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 1665 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 1666 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostHolder& holder, 1667 bool& out_of_memory); 1668 1669 private: 1670 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 1671 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 1672 GuestType<const struct VkAccelerationStructureGeometryKHR*>::HostArrayHolder pGeometries_holder_; 1673 std::unique_ptr<HostHolderBase> extensions_; 1674 VkAccelerationStructureBuildGeometryInfoKHR data_; 1675}; 1676 1677inline const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 1678 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 1679 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostHolder& holder, 1680 bool& out_of_memory) { 1681 if (ToGuestAddr(new_value) == kNullGuestAddr) { 1682 return nullptr; 1683 } 1684 holder.data_ = { 1685 .sType = VkStructureType( 1686 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1687 ->sType), 1688 .pNext = ConvertOptionalStructures( 1689 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1690 ->pNext, 1691 holder.extensions_, 1692 out_of_memory), 1693 .type = VkAccelerationStructureTypeKHR( 1694 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1695 ->type), 1696 .flags = VkBuildAccelerationStructureFlagsKHR( 1697 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1698 ->flags), 1699 .mode = VkBuildAccelerationStructureModeKHR( 1700 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1701 ->mode), 1702 .srcAccelerationStructure = VkAccelerationStructureKHR( 1703 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1704 ->srcAccelerationStructure), 1705 .dstAccelerationStructure = VkAccelerationStructureKHR( 1706 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1707 ->dstAccelerationStructure), 1708 .geometryCount = std::uint32_t( 1709 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1710 ->geometryCount), 1711 .pGeometries = ToHostType( 1712 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1713 ->pGeometries, 1714 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1715 ->ppGeometries, 1716 holder.pGeometries_holder_, 1717 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(ToGuestAddr(new_value)) 1718 ->geometryCount, 1719 out_of_memory), 1720 .ppGeometries = nullptr}; 1721 return &holder.data_; 1722} 1723 1724`) 1725 } 1726 if err != nil { 1727 return err 1728 } 1729 } else { 1730 if typе.(vulkan_xml.ExtendedStructInfo).OptionalStruct() { 1731 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::GuestHolder: GuestHolderBase { 1732 public: 1733 virtual ~GuestHolder() override = default; 1734`, 1735 name) 1736 } else { 1737 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::GuestHolder { 1738 public: 1739`, 1740 name) 1741 } 1742 if err != nil { 1743 return err 1744 } 1745 if name == "VkDescriptorGetInfoEXT" { 1746 if isInputCompatible(typе, host_arch, guest_arch) { 1747 _, err = fmt.Fprintf(w, ` friend GuestType<const VkDescriptorGetInfoEXT*>; 1748 1749 private: 1750}; 1751 1752inline GuestType<const VkDescriptorGetInfoEXT*>::GuestType( 1753 const VkDescriptorGetInfoEXT* new_value, 1754 GuestType<const VkDescriptorGetInfoEXT*>::GuestHolder&, 1755 bool&) 1756 : value_(bit_cast<GuestAddr>(new_value)) {} 1757 1758#endif 1759 1760`) 1761 } else { 1762 _, err = fmt.Fprintf(w, ` friend GuestType<const VkDescriptorGetInfoEXT*>; 1763 1764 private: 1765 friend GuestType<void*> ConvertOptionalStructures(void* head, 1766 std::unique_ptr<GuestHolderBase>& holder, 1767 bool& out_of_memory); 1768 friend GuestType<const void*> ConvertOptionalStructures(const void* head, 1769 std::unique_ptr<GuestHolderBase>& holder, 1770 bool& out_of_memory); 1771#if defined(__i386__) 1772 GuestType<const struct VkDescriptorImageInfo*>::GuestHolder VkDescriptorImageInfo_holder_; 1773#endif 1774 GuestType<const struct VkDescriptorAddressInfoEXT*>::GuestHolder 1775 VkDescriptorAddressInfoEXT_holder_; 1776 std::unique_ptr<GuestHolderBase> extensions_; 1777 GuestType<VkDescriptorGetInfoEXT> data_; 1778}; 1779 1780inline GuestType<const VkDescriptorGetInfoEXT*>::GuestType( 1781 const VkDescriptorGetInfoEXT* new_value, 1782 GuestType<const VkDescriptorGetInfoEXT*>::GuestHolder& holder, 1783 [[maybe_unused]] bool& out_of_memory) 1784 : value_(new_value == nullptr ? kNullGuestAddr : ToGuestAddr(&holder.data_)) { 1785 if (new_value != nullptr) { 1786 holder.data_ = { 1787 .sType = GuestType<VkStructureType>(new_value->sType), 1788 .pNext = ConvertOptionalStructures(new_value->pNext, holder.extensions_, out_of_memory), 1789 .type = GuestType<VkDescriptorType>(new_value->type), 1790 .data = 1791 new_value->type == BERBERIS_VK_DESCRIPTOR_TYPE_SAMPLER 1792 ? GuestType<VkDescriptorDataEXT>{.uniоn = {.pSampler = GuestType<const VkSampler*>( 1793 new_value->data.pSampler)}} 1794 : new_value->type == BERBERIS_VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 1795 new_value->type == BERBERIS_VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT || 1796 new_value->type == BERBERIS_VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 1797 new_value->type == BERBERIS_VK_DESCRIPTOR_TYPE_STORAGE_IMAGE 1798#if defined(__i386__) 1799 ? GuestType<VkDescriptorDataEXT>{.uniоn = 1800 {.pSampledImage = 1801 GuestType<const VkDescriptorImageInfo*>( 1802 new_value->data.pSampledImage, 1803 holder.VkDescriptorImageInfo_holder_, 1804 out_of_memory)}} 1805#else 1806 ? GuestType<VkDescriptorDataEXT>{ 1807 .uniоn = {.pSampledImage = bit_cast<GuestType<const VkDescriptorImageInfo*>>( 1808 GuestType<const VkDescriptorImageInfo*>( 1809 new_value->data.pSampledImage))}} 1810#endif 1811 : new_value->type == BERBERIS_VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR || 1812 new_value->type == BERBERIS_VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV 1813 ? GuestType<VkDescriptorDataEXT>{.uniоn = {.accelerationStructure = 1814 GuestType<VkDeviceAddress>( 1815 new_value->data 1816 .accelerationStructure)}} 1817 : GuestType<VkDescriptorDataEXT>{ 1818 .uniоn = {.pUniformBuffer = GuestType<const VkDescriptorAddressInfoEXT*>( 1819 new_value->data.pUniformBuffer, 1820 holder.VkDescriptorAddressInfoEXT_holder_, 1821 out_of_memory)}}}; 1822 } 1823} 1824 1825`) 1826 } 1827 } else { 1828 holder := "" 1829 if extensible_type { 1830 holder = "std::unique_ptr<GuestHolderBase> extensions_;\n " 1831 } 1832 holder += "GuestType<" + name + "> data_;" 1833 if isInputCompatible(typе, host_arch, guest_arch) { 1834 _, err = fmt.Fprintf(w, ` friend GuestType<const %[1]s*>; 1835 1836 private: 1837}; 1838 1839inline GuestType<const %[1]s*>::GuestType(const %[1]s* new_value, GuestType<const %[1]s*>::GuestHolder&, bool&) : value_(bit_cast<GuestAddr>(new_value)) { 1840} 1841 1842`, 1843 name) 1844 } else { 1845 _, err = fmt.Fprintf(w, ` friend GuestType<const %[1]s*>; 1846 1847 private: 1848 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1849 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 1850 %[2]s 1851}; 1852 1853inline GuestType<const %[1]s*>::GuestType(const %[1]s* new_value, GuestType<const %[1]s*>::GuestHolder& holder, [[maybe_unused]] bool& out_of_memory) : value_(new_value == nullptr ? kNullGuestAddr : ToGuestAddr(&holder.data_)) { 1854 if (new_value != nullptr) { 1855 holder.data_ = { 1856 %[3]s }; 1857 } 1858} 1859 1860`, 1861 name, 1862 strings.Join(append( 1863 makeHolderList("GuestType<%s>::Guest%sHolder %s_holder_;", true, typе, host_arch, guest_arch), 1864 holder), "\n "), 1865 strings.Join(makeGuestInitializerList(initializeConstStruct, name, typе, host_arch, guest_arch), "\n ")) 1866 } 1867 } 1868 if err != nil { 1869 return err 1870 } 1871 if typе.(vulkan_xml.ExtendedStructInfo).OptionalStruct() { 1872 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::HostHolder: public HostHolderBase { 1873 public: 1874 virtual ~HostHolder() override = default; 1875`, 1876 name) 1877 } else { 1878 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::HostHolder { 1879 public: 1880`, 1881 name) 1882 } 1883 if err != nil { 1884 return err 1885 } 1886 if name == "VkDescriptorGetInfoEXT" { 1887 if isInputCompatible(typе, host_arch, guest_arch) { 1888 _, err = fmt.Fprintf(w, ` friend const VkDescriptorGetInfoEXT* ToHostType( 1889 const GuestType<const VkDescriptorGetInfoEXT*>& new_value, 1890 GuestType<const VkDescriptorGetInfoEXT*>::HostHolder& holder, 1891 bool& out_of_memory); 1892 1893 private: 1894}; 1895 1896inline const VkDescriptorGetInfoEXT* ToHostType( 1897 const GuestType<const VkDescriptorGetInfoEXT*>& new_value, 1898 GuestType<const VkDescriptorGetInfoEXT*>::HostHolder&, 1899 bool&) { 1900 return ToHostAddr<const VkDescriptorGetInfoEXT>(ToGuestAddr(new_value)); 1901} 1902 1903`) 1904 } else { 1905 _, err = fmt.Fprintf(w, ` friend const VkDescriptorGetInfoEXT* ToHostType( 1906 const GuestType<const VkDescriptorGetInfoEXT*>& new_value, 1907 GuestType<const VkDescriptorGetInfoEXT*>::HostHolder& holder, 1908 bool& out_of_memory); 1909 1910 private: 1911 friend void* ConvertOptionalStructures(GuestType<void*> head, 1912 std::unique_ptr<HostHolderBase>& holder, 1913 bool& out_of_memory); 1914 friend const void* ConvertOptionalStructures(GuestType<const void*> head, 1915 std::unique_ptr<HostHolderBase>& holder, 1916 bool& out_of_memory); 1917#if defined(__i386__) 1918 GuestType<const struct VkDescriptorImageInfo*>::HostHolder VkDescriptorImageInfo_holder_; 1919#endif 1920 GuestType<const struct VkDescriptorAddressInfoEXT*>::HostHolder 1921 VkDescriptorAddressInfoEXT_holder_; 1922 std::unique_ptr<HostHolderBase> extensions_; 1923 VkDescriptorGetInfoEXT data_; 1924}; 1925 1926inline const VkDescriptorGetInfoEXT* ToHostType( 1927 const GuestType<const VkDescriptorGetInfoEXT*>& new_value, 1928 GuestType<const VkDescriptorGetInfoEXT*>::HostHolder& holder, 1929 [[maybe_unused]] bool& out_of_memory) { 1930 if (ToGuestAddr(new_value) == kNullGuestAddr) { 1931 return nullptr; 1932 } 1933 holder.data_ = { 1934 .sType = VkStructureType( 1935 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value))->sType), 1936 .pNext = ConvertOptionalStructures( 1937 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value))->pNext, 1938 holder.extensions_, 1939 out_of_memory), 1940 .type = VkDescriptorType( 1941 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value))->type), 1942 .data = 1943 VkDescriptorType( 1944 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value))->type) == 1945 BERBERIS_VK_DESCRIPTOR_TYPE_SAMPLER 1946 ? VkDescriptorDataEXT{.pSampler = ToHostAddr<const VkSampler>( 1947 ToGuestAddr(ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>( 1948 ToGuestAddr(new_value)) 1949 ->data.uniоn.pSampler))} 1950 : VkDescriptorType( 1951 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value))->type) == 1952 BERBERIS_VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 1953 VkDescriptorType( 1954 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value)) 1955 ->type) == BERBERIS_VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT || 1956 VkDescriptorType( 1957 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value)) 1958 ->type) == BERBERIS_VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 1959 VkDescriptorType( 1960 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value)) 1961 ->type) == BERBERIS_VK_DESCRIPTOR_TYPE_STORAGE_IMAGE 1962#if defined(__i386__) 1963 ? VkDescriptorDataEXT{.pSampledImage = 1964 ToHostType(ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>( 1965 ToGuestAddr(new_value)) 1966 ->data.uniоn.pSampledImage, 1967 holder.VkDescriptorImageInfo_holder_, 1968 out_of_memory)} 1969#else 1970 ? VkDescriptorDataEXT{ 1971 .pSampledImage = 1972 bit_cast<const VkDescriptorImageInfo*>( 1973 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>( 1974 ToGuestAddr(new_value))->data.uniоn.pSampledImage)} 1975#endif 1976 : VkDescriptorType( 1977 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value))->type) == 1978 BERBERIS_VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR || 1979 VkDescriptorType( 1980 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value)) 1981 ->type) == BERBERIS_VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV 1982 ? VkDescriptorDataEXT{.accelerationStructure = VkDeviceAddress( 1983 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>( 1984 ToGuestAddr(new_value)) 1985 ->data.uniоn.accelerationStructure)} 1986 : VkDescriptorDataEXT{ 1987 .pUniformBuffer = ToHostType( 1988 ToHostAddr<GuestType<VkDescriptorGetInfoEXT>>(ToGuestAddr(new_value)) 1989 ->data.uniоn.pUniformBuffer, 1990 holder.VkDescriptorAddressInfoEXT_holder_, 1991 out_of_memory)}}; 1992 return &holder.data_; 1993} 1994 1995`) 1996 } 1997 } else { 1998 holder := "" 1999 if extensible_type { 2000 holder = "std::unique_ptr<HostHolderBase> extensions_;\n " 2001 } 2002 holder += name + " data_;" 2003 extra_holder_argument := "" 2004 if name == "VkCommandBufferBeginInfo" { 2005 extra_holder_argument = "[[maybe_unused]] bool has_inheritance_info, " 2006 } 2007 if isInputCompatible(typе, host_arch, guest_arch) { 2008 _, err = fmt.Fprintf(w, ` friend const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostHolder& holder, %[2]sbool& out_of_memory); 2009 2010 private: 2011}; 2012 2013inline const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostHolder&, bool&) { 2014 return ToHostAddr<const %[1]s>(ToGuestAddr(new_value)); 2015} 2016 2017`, 2018 name, 2019 extra_holder_argument) 2020 } else { 2021 _, err = fmt.Fprintf(w, ` friend const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostHolder& holder, %[4]sbool& out_of_memory); 2022 2023 private: 2024 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2025 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2026 %[2]s 2027}; 2028 2029inline const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostHolder& holder, %[4]s[[maybe_unused]] bool& out_of_memory) { 2030 if (ToGuestAddr(new_value) == kNullGuestAddr) { 2031 return nullptr; 2032 } 2033 holder.data_ = { 2034 %[3]s }; 2035 return &holder.data_; 2036} 2037 2038`, 2039 name, 2040 strings.Join(append( 2041 makeHolderList("GuestType<%s>::Host%sHolder %s_holder_;", true, typе, host_arch, guest_arch), 2042 holder), "\n "), 2043 strings.Join(makeHostInitializerList(initializeConstStruct, name, typе, host_arch, guest_arch), "\n "), 2044 extra_holder_argument) 2045 } 2046 } 2047 if err != nil { 2048 return err 2049 } 2050 } 2051 } 2052 2053 if conversion[name].need_const_array_convertor { 2054 if name == "VkAccelerationStructureGeometryKHR" { 2055 if isInputCompatible(typе, host_arch, guest_arch) { 2056 _, err = fmt.Fprintf(w, `class GuestType<const VkAccelerationStructureGeometryKHR*>::GuestArrayHolder { 2057 public: 2058 ~GuestArrayHolder(); 2059 friend GuestType<const VkAccelerationStructureGeometryKHR*>; 2060 2061 private: 2062}; 2063 2064inline GuestType<const VkAccelerationStructureGeometryKHR*>::GuestArrayHolder::~GuestArrayHolder() { 2065} 2066 2067inline GuestType<const VkAccelerationStructureGeometryKHR*>::GuestType( 2068 const VkAccelerationStructureGeometryKHR* const new_value, 2069 const VkAccelerationStructureGeometryKHR* const* const, 2070 GuestType<const VkAccelerationStructureGeometryKHR*>::GuestArrayHolder&, 2071 std::size_t, 2072 bool&) 2073 : value_(bit_cast<GuestAddr>(new_value)) { 2074} 2075 2076class GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder { 2077 public: 2078 ~HostArrayHolder(); 2079 friend const VkAccelerationStructureGeometryKHR* ToHostType( 2080 const GuestType<const VkAccelerationStructureGeometryKHR*>& new_value, 2081 GuestType<const VkAccelerationStructureGeometryKHR* const*> const new_value_ptr, 2082 GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder& holder, 2083 std::size_t size, 2084 bool& out_of_memory); 2085 2086 private: 2087}; 2088 2089inline GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder::~HostArrayHolder() { 2090} 2091 2092inline const VkAccelerationStructureGeometryKHR* ToHostType( 2093 const GuestType<const VkAccelerationStructureGeometryKHR*>& new_value, 2094 GuestType<const VkAccelerationStructureGeometryKHR* const*> const, 2095 GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder&, 2096 std::size_t, 2097 bool&) { 2098 return ToHostAddr<const VkAccelerationStructureGeometryKHR>(ToGuestAddr(new_value)); 2099} 2100 2101`) 2102 } else { 2103 _, err = fmt.Fprintf(w, `class GuestType<const VkAccelerationStructureGeometryKHR*>::GuestArrayHolder { 2104 public: 2105 ~GuestArrayHolder(); 2106 friend GuestType<const VkAccelerationStructureGeometryKHR*>; 2107 2108 private: 2109 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2110 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2111 std::size_t size_ = 0; 2112 const VkAccelerationStructureGeometryKHR* origin_ = nullptr; 2113 std::unique_ptr<GuestHolderBase> extensions_; 2114 GuestType<const VkAccelerationStructureGeometryKHR>* data_ = nullptr; 2115}; 2116 2117inline GuestType<const VkAccelerationStructureGeometryKHR*>::GuestArrayHolder::~GuestArrayHolder() { 2118 delete[] data_; 2119} 2120 2121inline GuestType<const VkAccelerationStructureGeometryKHR*>::GuestType( 2122 const VkAccelerationStructureGeometryKHR* const new_value, 2123 const VkAccelerationStructureGeometryKHR* const* const new_value_ptr, 2124 GuestType<const VkAccelerationStructureGeometryKHR*>::GuestArrayHolder& holder, 2125 std::size_t size, 2126 [[maybe_unused]] bool& out_of_memory) 2127 : value_((new_value == nullptr && new_value_ptr == nullptr) 2128 ? kNullGuestAddr 2129 : ToGuestAddr(holder.data_ = new (std::nothrow) 2130 GuestType<const VkAccelerationStructureGeometryKHR>[size])) { 2131 if ((new_value != nullptr || new_value_ptr != nullptr) && value_ == kNullGuestAddr) { 2132 out_of_memory = true; 2133 return; 2134 } 2135 holder.size_ = size; 2136 holder.origin_ = new_value; 2137 if (new_value != nullptr) { 2138 for (std::size_t index = 0; index < size; ++index) { 2139 ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>>(value_)[index] = { 2140 .sType = GuestType<VkStructureType>(new_value[index].sType), 2141 .pNext = ConvertOptionalStructures(new_value[index].pNext, holder.extensions_, out_of_memory), 2142 .geometryType = GuestType<VkGeometryTypeKHR>(new_value[index].geometryType), 2143 .flags = GuestType<VkGeometryFlagsKHR>(new_value[index].flags)}; 2144 } 2145 } else { 2146 for (std::size_t index = 0; index < size; ++index) { 2147 ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>>(value_)[index] = { 2148 .sType = GuestType<VkStructureType>(new_value_ptr[index]->sType), 2149 .pNext = ConvertOptionalStructures(new_value_ptr[index]->pNext, holder.extensions_, out_of_memory), 2150 .geometryType = GuestType<VkGeometryTypeKHR>(new_value_ptr[index]->geometryType), 2151 .flags = GuestType<VkGeometryFlagsKHR>(new_value_ptr[index]->flags)}; 2152 } 2153 } 2154} 2155 2156class GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder { 2157 public: 2158 ~HostArrayHolder(); 2159 friend const VkAccelerationStructureGeometryKHR* ToHostType( 2160 const GuestType<const VkAccelerationStructureGeometryKHR*>& new_value, 2161 GuestType<const VkAccelerationStructureGeometryKHR* const*> const new_value_ptr, 2162 GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder& holder, 2163 std::size_t size, 2164 bool& out_of_memory); 2165 2166 private: 2167 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2168 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2169 std::size_t size_ = 0; 2170 std::unique_ptr<GuestHolderBase> extensions_; 2171 VkAccelerationStructureGeometryKHR* data_ = nullptr; 2172}; 2173 2174inline GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder::~HostArrayHolder() { 2175 delete[] data_; 2176} 2177 2178inline const VkAccelerationStructureGeometryKHR* ToHostType( 2179 const GuestType<const VkAccelerationStructureGeometryKHR*>& new_value, 2180 GuestType<const VkAccelerationStructureGeometryKHR* const*> const new_value_ptr, 2181 GuestType<const VkAccelerationStructureGeometryKHR*>::HostArrayHolder& holder, 2182 std::size_t size, 2183 bool& out_of_memory) { 2184 if (ToGuestAddr(new_value) == kNullGuestAddr && ToGuestAddr(new_value_ptr) == kNullGuestAddr) { 2185 return nullptr; 2186 } 2187 if ((holder.data_ = new (std::nothrow) VkAccelerationStructureGeometryKHR[size]) == nullptr) { 2188 out_of_memory = true; 2189 return nullptr; 2190 } 2191 holder.size_ = size; 2192 if (ToGuestAddr(new_value) != 0) { 2193 for (std::size_t index = 0; index < size; ++index) { 2194 holder.data_[index] = { 2195 .sType = VkStructureType(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>>( 2196 ToGuestAddr(new_value))[index] 2197 .sType), 2198 .pNext = ConvertOptionalStructures(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>>( 2199 ToGuestAddr(new_value))[index] 2200 .pNext, 2201 holder.extensions_, 2202 out_of_memory), 2203 .geometryType = 2204 VkGeometryTypeKHR(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>>( 2205 ToGuestAddr(new_value))[index] 2206 .geometryType), 2207 .flags = VkGeometryFlagsKHR(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>>( 2208 ToGuestAddr(new_value))[index] 2209 .flags)}; 2210 } 2211 } else { 2212 for (std::size_t index = 0; index < size; ++index) { 2213 holder.data_[index] = { 2214 .sType = VkStructureType(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>*>( 2215 ToGuestAddr(new_value_ptr))[index] 2216 ->sType), 2217 .pNext = ConvertOptionalStructures(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>*>( 2218 ToGuestAddr(new_value))[index] 2219 ->pNext, 2220 holder.extensions_, 2221 out_of_memory), 2222 .geometryType = 2223 VkGeometryTypeKHR(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>*>( 2224 ToGuestAddr(new_value))[index] 2225 ->geometryType), 2226 .flags = VkGeometryFlagsKHR(ToHostAddr<GuestType<VkAccelerationStructureGeometryKHR>*>( 2227 ToGuestAddr(new_value))[index] 2228 ->flags)}; 2229 } 2230 } 2231 return holder.data_; 2232} 2233 2234`) 2235 } 2236 if err != nil { 2237 return err 2238 } 2239 } else if name == "VkAccelerationStructureBuildGeometryInfoKHR" { 2240 if isInputCompatible(typе, host_arch, guest_arch) { 2241 _, err = fmt.Fprintf(w, `class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestArrayHolder { 2242 public: 2243 ~GuestArrayHolder(); 2244 friend GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>; 2245 2246 private: 2247}; 2248 2249inline GuestType< 2250 const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestArrayHolder::~GuestArrayHolder() { 2251} 2252 2253inline GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestType( 2254 const VkAccelerationStructureBuildGeometryInfoKHR* const new_value, 2255 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestArrayHolder&, 2256 std::size_t, 2257 bool&) 2258 : value_(bit_cast<GuestAddr>(new_value)) { 2259} 2260 2261class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder { 2262 public: 2263 ~HostArrayHolder(); 2264 friend const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 2265 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 2266 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder& holder, 2267 std::size_t size, 2268 bool& out_of_memory); 2269 2270 private: 2271}; 2272 2273inline GuestType< 2274 const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder::~HostArrayHolder() { 2275} 2276 2277inline const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 2278 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 2279 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder&, 2280 std::size_t, 2281 bool&) { 2282 return ToHostAddr<VkAccelerationStructureBuildGeometryInfoKHR>(ToGuestAddr(new_value)); 2283} 2284 2285`) 2286 } else { 2287 _, err = fmt.Fprintf(w, `class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestArrayHolder { 2288 public: 2289 ~GuestArrayHolder(); 2290 friend GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>; 2291 2292 private: 2293 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2294 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2295 std::size_t size_ = 0; 2296 std::unique_ptr<GuestHolderBase> extensions_; 2297 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR>* data_ = nullptr; 2298 GuestType<const struct VkAccelerationStructureGeometryKHR*>::GuestArrayHolder* 2299 pGeometries_holder_ = nullptr; 2300}; 2301 2302inline GuestType< 2303 const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestArrayHolder::~GuestArrayHolder() { 2304 delete[] pGeometries_holder_; 2305 delete[] data_; 2306} 2307 2308inline GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestType( 2309 const VkAccelerationStructureBuildGeometryInfoKHR* const new_value, 2310 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::GuestArrayHolder& holder, 2311 std::size_t size, 2312 [[maybe_unused]] bool& out_of_memory) 2313 : value_(new_value == nullptr 2314 ? kNullGuestAddr 2315 : ToGuestAddr( 2316 holder.data_ = new (std::nothrow) 2317 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR>[size])) { 2318 if (new_value == nullptr) { 2319 holder.pGeometries_holder_ = new (std::nothrow) 2320 GuestType<const struct VkAccelerationStructureGeometryKHR*>::GuestArrayHolder[size]; 2321 } 2322 if (new_value != nullptr && (value_ == kNullGuestAddr || holder.pGeometries_holder_ == nullptr)) { 2323 out_of_memory = true; 2324 return; 2325 } 2326 holder.size_ = size; 2327 for (std::size_t index = 0; index < size; ++index) { 2328 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>(value_)[index] = { 2329 .sType = GuestType<VkStructureType>(new_value[index].sType), 2330 .pNext = ConvertOptionalStructures(new_value[index].pNext, holder.extensions_, out_of_memory), 2331 .type = GuestType<VkAccelerationStructureTypeKHR>(new_value[index].type), 2332 .flags = GuestType<VkBuildAccelerationStructureFlagsKHR>(new_value[index].flags), 2333 .mode = GuestType<VkBuildAccelerationStructureModeKHR>(new_value[index].mode), 2334 .srcAccelerationStructure = 2335 GuestType<VkAccelerationStructureKHR>(new_value[index].srcAccelerationStructure), 2336 .dstAccelerationStructure = 2337 GuestType<VkAccelerationStructureKHR>(new_value[index].dstAccelerationStructure), 2338 .geometryCount = GuestType<std::uint32_t>(new_value[index].geometryCount), 2339 .pGeometries = GuestType<const struct VkAccelerationStructureGeometryKHR*>( 2340 new_value[index].pGeometries, 2341 new_value[index].ppGeometries, 2342 holder.pGeometries_holder_[index], 2343 new_value[index].geometryCount, 2344 out_of_memory), 2345 .ppGeometries = 2346 GuestType<const struct VkAccelerationStructureGeometryKHR* const*>(nullptr)}; 2347 } 2348} 2349 2350class GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder { 2351 public: 2352 ~HostArrayHolder(); 2353 friend const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 2354 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 2355 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder& holder, 2356 std::size_t size, 2357 bool& out_of_memory); 2358 2359 private: 2360 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2361 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2362 std::size_t size_ = 0; 2363 std::unique_ptr<HostHolderBase> extensions_; 2364 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR>* origin_ = nullptr; 2365 VkAccelerationStructureBuildGeometryInfoKHR* data_ = nullptr; 2366 GuestType<const struct VkAccelerationStructureGeometryKHR*>::HostArrayHolder pGeometries_holder_; 2367}; 2368 2369inline GuestType< 2370 const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder::~HostArrayHolder() { 2371 delete[] data_; 2372} 2373 2374inline const VkAccelerationStructureBuildGeometryInfoKHR* ToHostType( 2375 const GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>& new_value, 2376 GuestType<const VkAccelerationStructureBuildGeometryInfoKHR*>::HostArrayHolder& holder, 2377 std::size_t size, 2378 bool& out_of_memory) { 2379 if (ToGuestAddr(new_value) == kNullGuestAddr) { 2380 return nullptr; 2381 } 2382 if ((holder.data_ = new (std::nothrow) VkAccelerationStructureBuildGeometryInfoKHR[size]) == 2383 nullptr) { 2384 out_of_memory = true; 2385 return nullptr; 2386 } 2387 holder.size_ = size; 2388 holder.origin_ = ToHostAddr<GuestType<const VkAccelerationStructureBuildGeometryInfoKHR>>( 2389 ToGuestAddr(new_value)); 2390 for (std::size_t index = 0; index < size; ++index) { 2391 holder.data_[index] = { 2392 .sType = VkStructureType(ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2393 ToGuestAddr(new_value))[index] 2394 .sType), 2395 .pNext = ConvertOptionalStructures(ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2396 ToGuestAddr(new_value))[index] 2397 .pNext, 2398 holder.extensions_, 2399 out_of_memory), 2400 .type = VkAccelerationStructureTypeKHR( 2401 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2402 ToGuestAddr(new_value))[index] 2403 .type), 2404 .flags = VkBuildAccelerationStructureFlagsKHR( 2405 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2406 ToGuestAddr(new_value))[index] 2407 .flags), 2408 .mode = VkBuildAccelerationStructureModeKHR( 2409 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2410 ToGuestAddr(new_value))[index] 2411 .mode), 2412 .srcAccelerationStructure = VkAccelerationStructureKHR( 2413 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2414 ToGuestAddr(new_value))[index] 2415 .srcAccelerationStructure), 2416 .dstAccelerationStructure = VkAccelerationStructureKHR( 2417 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2418 ToGuestAddr(new_value))[index] 2419 .dstAccelerationStructure), 2420 .geometryCount = 2421 std::uint32_t(ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2422 ToGuestAddr(new_value))[index] 2423 .geometryCount), 2424 .pGeometries = 2425 ToHostType(ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2426 ToGuestAddr(new_value))[index] 2427 .pGeometries, 2428 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2429 ToGuestAddr(new_value))[index] 2430 .ppGeometries, 2431 holder.pGeometries_holder_, 2432 ToHostAddr<GuestType<VkAccelerationStructureBuildGeometryInfoKHR>>( 2433 ToGuestAddr(new_value))[index] 2434 .geometryCount, 2435 out_of_memory), 2436 .ppGeometries = nullptr}; 2437 } 2438 return holder.data_; 2439} 2440 2441`) 2442 } 2443 if err != nil { 2444 return err 2445 } 2446 } else if name == "VkGraphicsPipelineCreateInfo" { 2447 // Some fields can be invalid depending on whether rasterization is enabled. 2448 // We cannot touch/convert them automatically. Thus manual implementation. 2449 // All modifications compared to autogenerated version are marked with MOD START/END. 2450 _, err = fmt.Fprintf(w, `class GuestType<const VkGraphicsPipelineCreateInfo*>::GuestArrayHolder { 2451 public: 2452 ~GuestArrayHolder(); 2453 friend GuestType<const VkGraphicsPipelineCreateInfo*>; 2454 2455 private: 2456 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2457 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2458 std::size_t size_ = 0; 2459 std::unique_ptr<GuestHolderBase> extensions_; 2460 GuestType<const VkGraphicsPipelineCreateInfo>* data_ = nullptr; 2461 GuestType<const struct VkPipelineShaderStageCreateInfo *>::GuestArrayHolder* pStages_holder_ = nullptr; 2462 GuestType<const struct VkPipelineVertexInputStateCreateInfo *>::GuestHolder* pVertexInputState_holder_ = nullptr; 2463 GuestType<const struct VkPipelineInputAssemblyStateCreateInfo *>::GuestHolder* pInputAssemblyState_holder_ = nullptr; 2464 GuestType<const struct VkPipelineTessellationStateCreateInfo *>::GuestHolder* pTessellationState_holder_ = nullptr; 2465 GuestType<const struct VkPipelineViewportStateCreateInfo *>::GuestHolder* pViewportState_holder_ = nullptr; 2466 GuestType<const struct VkPipelineRasterizationStateCreateInfo *>::GuestHolder* pRasterizationState_holder_ = nullptr; 2467 GuestType<const struct VkPipelineMultisampleStateCreateInfo *>::GuestHolder* pMultisampleState_holder_ = nullptr; 2468 GuestType<const struct VkPipelineDepthStencilStateCreateInfo *>::GuestHolder* pDepthStencilState_holder_ = nullptr; 2469 GuestType<const struct VkPipelineColorBlendStateCreateInfo *>::GuestHolder* pColorBlendState_holder_ = nullptr; 2470 GuestType<const struct VkPipelineDynamicStateCreateInfo *>::GuestHolder* pDynamicState_holder_ = nullptr; 2471}; 2472 2473inline GuestType<const VkGraphicsPipelineCreateInfo*>::GuestArrayHolder::~GuestArrayHolder() { 2474 delete[] data_; 2475 delete[] pStages_holder_; 2476 delete[] pVertexInputState_holder_; 2477 delete[] pInputAssemblyState_holder_; 2478 delete[] pTessellationState_holder_; 2479 delete[] pViewportState_holder_; 2480 delete[] pRasterizationState_holder_; 2481 delete[] pMultisampleState_holder_; 2482 delete[] pDepthStencilState_holder_; 2483 delete[] pColorBlendState_holder_; 2484 delete[] pDynamicState_holder_; 2485} 2486 2487inline GuestType<const VkGraphicsPipelineCreateInfo*>::GuestType(const VkGraphicsPipelineCreateInfo* const new_value, GuestType<const VkGraphicsPipelineCreateInfo*>::GuestArrayHolder& holder, std::size_t size, [[maybe_unused]] bool& out_of_memory) : value_(new_value == nullptr ? kNullGuestAddr : ToGuestAddr(holder.data_ = new (std::nothrow) GuestType<const VkGraphicsPipelineCreateInfo>[size])) { 2488 if (new_value != nullptr && value_ == kNullGuestAddr) { 2489 out_of_memory = true; 2490 return; 2491 } 2492 holder.size_ = size; 2493 if ((holder.pStages_holder_ = new (std::nothrow) GuestType<const struct VkPipelineShaderStageCreateInfo *>::GuestArrayHolder[size]) == nullptr) { 2494 out_of_memory = true; 2495 return; 2496 }; 2497 if ((holder.pVertexInputState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineVertexInputStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2498 out_of_memory = true; 2499 return; 2500 }; 2501 if ((holder.pInputAssemblyState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineInputAssemblyStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2502 out_of_memory = true; 2503 return; 2504 }; 2505 if ((holder.pTessellationState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineTessellationStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2506 out_of_memory = true; 2507 return; 2508 }; 2509 if ((holder.pViewportState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineViewportStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2510 out_of_memory = true; 2511 return; 2512 }; 2513 if ((holder.pRasterizationState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineRasterizationStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2514 out_of_memory = true; 2515 return; 2516 }; 2517 if ((holder.pMultisampleState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineMultisampleStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2518 out_of_memory = true; 2519 return; 2520 }; 2521 if ((holder.pDepthStencilState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineDepthStencilStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2522 out_of_memory = true; 2523 return; 2524 }; 2525 if ((holder.pColorBlendState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineColorBlendStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2526 out_of_memory = true; 2527 return; 2528 }; 2529 if ((holder.pDynamicState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineDynamicStateCreateInfo *>::GuestHolder[size]) == nullptr) { 2530 out_of_memory = true; 2531 return; 2532 }; 2533 for (std::size_t index = 0; index < size; ++index) { 2534 // MOD START 2535 auto* host_rasterization_state = new_value[index].pRasterizationState; 2536 bool rasterization_enabled = host_rasterization_state->rasterizerDiscardEnable == BERBERIS_VK_FALSE || 2537 // When dynamic state presents the rasterization may be enabled later. 2538 new_value[index].pDynamicState; 2539 // MOD END 2540 ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(value_)[index] = { 2541 .sType = GuestType<VkStructureType>(new_value[index].sType), 2542 .pNext = ConvertOptionalStructures(new_value[index].pNext, holder.extensions_, out_of_memory), 2543 .flags = GuestType<VkPipelineCreateFlags>(new_value[index].flags), 2544 .stageCount = GuestType<std::uint32_t>(new_value[index].stageCount), 2545 .pStages = GuestType<const struct VkPipelineShaderStageCreateInfo *>(new_value[index].pStages, holder.pStages_holder_[index], new_value[index].stageCount, out_of_memory), 2546 .pVertexInputState = GuestType<const struct VkPipelineVertexInputStateCreateInfo *>(new_value[index].pVertexInputState, holder.pVertexInputState_holder_[index], out_of_memory), 2547 .pInputAssemblyState = GuestType<const struct VkPipelineInputAssemblyStateCreateInfo *>(new_value[index].pInputAssemblyState, holder.pInputAssemblyState_holder_[index], out_of_memory), 2548 .pTessellationState = GuestType<const struct VkPipelineTessellationStateCreateInfo *>(new_value[index].pTessellationState, holder.pTessellationState_holder_[index], out_of_memory), 2549 // MOD START 2550 .pViewportState = rasterization_enabled ? GuestType<const struct VkPipelineViewportStateCreateInfo *>(new_value[index].pViewportState, holder.pViewportState_holder_[index], out_of_memory) : GuestType<const struct VkPipelineViewportStateCreateInfo *>(), 2551 .pRasterizationState = GuestType<const struct VkPipelineRasterizationStateCreateInfo *>(new_value[index].pRasterizationState, holder.pRasterizationState_holder_[index], out_of_memory), 2552 .pMultisampleState = rasterization_enabled ? GuestType<const struct VkPipelineMultisampleStateCreateInfo *>(new_value[index].pMultisampleState, holder.pMultisampleState_holder_[index], out_of_memory) : GuestType<const struct VkPipelineMultisampleStateCreateInfo *>(), 2553 .pDepthStencilState = rasterization_enabled ? GuestType<const struct VkPipelineDepthStencilStateCreateInfo *>(new_value[index].pDepthStencilState, holder.pDepthStencilState_holder_[index], out_of_memory) : GuestType<const struct VkPipelineDepthStencilStateCreateInfo *>(), 2554 .pColorBlendState = rasterization_enabled ? GuestType<const struct VkPipelineColorBlendStateCreateInfo *>(new_value[index].pColorBlendState, holder.pColorBlendState_holder_[index], out_of_memory) : GuestType<const struct VkPipelineColorBlendStateCreateInfo *>(), 2555 // MOD END 2556 .pDynamicState = GuestType<const struct VkPipelineDynamicStateCreateInfo *>(new_value[index].pDynamicState, holder.pDynamicState_holder_[index], out_of_memory), 2557 .layout = GuestType<VkPipelineLayout>(new_value[index].layout), 2558 .renderPass = GuestType<VkRenderPass>(new_value[index].renderPass), 2559 .subpass = GuestType<std::uint32_t>(new_value[index].subpass), 2560 .basePipelineHandle = GuestType<VkPipeline>(new_value[index].basePipelineHandle), 2561 .basePipelineIndex = GuestType<std::int32_t>(new_value[index].basePipelineIndex) }; 2562 } 2563} 2564 2565class GuestType<const VkGraphicsPipelineCreateInfo*>::HostArrayHolder { 2566 public: 2567 ~HostArrayHolder(); 2568 friend const VkGraphicsPipelineCreateInfo* ToHostType(const GuestType<const VkGraphicsPipelineCreateInfo*>& new_value, GuestType<const VkGraphicsPipelineCreateInfo*>::HostArrayHolder& holder, std::size_t size, bool& out_of_memory); 2569 2570 private: 2571 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2572 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2573 std::size_t size_ = 0; 2574 std::unique_ptr<HostHolderBase> extensions_; 2575 VkGraphicsPipelineCreateInfo* data_ = nullptr; 2576 GuestType<const struct VkPipelineShaderStageCreateInfo *>::HostArrayHolder* pStages_holder_ = nullptr; 2577 GuestType<const struct VkPipelineVertexInputStateCreateInfo *>::HostHolder* pVertexInputState_holder_ = nullptr; 2578 GuestType<const struct VkPipelineInputAssemblyStateCreateInfo *>::HostHolder* pInputAssemblyState_holder_ = nullptr; 2579 GuestType<const struct VkPipelineTessellationStateCreateInfo *>::HostHolder* pTessellationState_holder_ = nullptr; 2580 GuestType<const struct VkPipelineViewportStateCreateInfo *>::HostHolder* pViewportState_holder_ = nullptr; 2581 GuestType<const struct VkPipelineRasterizationStateCreateInfo *>::HostHolder* pRasterizationState_holder_ = nullptr; 2582 GuestType<const struct VkPipelineMultisampleStateCreateInfo *>::HostHolder* pMultisampleState_holder_ = nullptr; 2583 GuestType<const struct VkPipelineDepthStencilStateCreateInfo *>::HostHolder* pDepthStencilState_holder_ = nullptr; 2584 GuestType<const struct VkPipelineColorBlendStateCreateInfo *>::HostHolder* pColorBlendState_holder_ = nullptr; 2585 GuestType<const struct VkPipelineDynamicStateCreateInfo *>::HostHolder* pDynamicState_holder_ = nullptr; 2586}; 2587 2588inline GuestType<const VkGraphicsPipelineCreateInfo*>::HostArrayHolder::~HostArrayHolder() { 2589 delete[] data_; 2590 delete[] pStages_holder_; 2591 delete[] pVertexInputState_holder_; 2592 delete[] pInputAssemblyState_holder_; 2593 delete[] pTessellationState_holder_; 2594 delete[] pViewportState_holder_; 2595 delete[] pRasterizationState_holder_; 2596 delete[] pMultisampleState_holder_; 2597 delete[] pDepthStencilState_holder_; 2598 delete[] pColorBlendState_holder_; 2599 delete[] pDynamicState_holder_; 2600} 2601 2602inline const VkGraphicsPipelineCreateInfo* ToHostType(const GuestType<const VkGraphicsPipelineCreateInfo*>& new_value, GuestType<const VkGraphicsPipelineCreateInfo*>::HostArrayHolder& holder, std::size_t size, bool& out_of_memory) { 2603 if (ToGuestAddr(new_value) == kNullGuestAddr) { 2604 return nullptr; 2605 } 2606 if ((holder.data_ = new (std::nothrow) VkGraphicsPipelineCreateInfo[size]) == nullptr) { 2607 out_of_memory = true; 2608 return nullptr; 2609 } 2610 if ((holder.pStages_holder_ = new (std::nothrow) GuestType<const struct VkPipelineShaderStageCreateInfo *>::HostArrayHolder[size]) == nullptr) { 2611 out_of_memory = true; 2612 return nullptr; 2613 }; 2614 if ((holder.pVertexInputState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineVertexInputStateCreateInfo *>::HostHolder[size]) == nullptr) { 2615 out_of_memory = true; 2616 return nullptr; 2617 }; 2618 if ((holder.pInputAssemblyState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineInputAssemblyStateCreateInfo *>::HostHolder[size]) == nullptr) { 2619 out_of_memory = true; 2620 return nullptr; 2621 }; 2622 if ((holder.pTessellationState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineTessellationStateCreateInfo *>::HostHolder[size]) == nullptr) { 2623 out_of_memory = true; 2624 return nullptr; 2625 }; 2626 if ((holder.pViewportState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineViewportStateCreateInfo *>::HostHolder[size]) == nullptr) { 2627 out_of_memory = true; 2628 return nullptr; 2629 }; 2630 if ((holder.pRasterizationState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineRasterizationStateCreateInfo *>::HostHolder[size]) == nullptr) { 2631 out_of_memory = true; 2632 return nullptr; 2633 }; 2634 if ((holder.pMultisampleState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineMultisampleStateCreateInfo *>::HostHolder[size]) == nullptr) { 2635 out_of_memory = true; 2636 return nullptr; 2637 }; 2638 if ((holder.pDepthStencilState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineDepthStencilStateCreateInfo *>::HostHolder[size]) == nullptr) { 2639 out_of_memory = true; 2640 return nullptr; 2641 }; 2642 if ((holder.pColorBlendState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineColorBlendStateCreateInfo *>::HostHolder[size]) == nullptr) { 2643 out_of_memory = true; 2644 return nullptr; 2645 }; 2646 if ((holder.pDynamicState_holder_ = new (std::nothrow) GuestType<const struct VkPipelineDynamicStateCreateInfo *>::HostHolder[size]) == nullptr) { 2647 out_of_memory = true; 2648 return nullptr; 2649 }; 2650 holder.size_ = size; 2651 for (std::size_t index = 0; index < size; ++index) { 2652 // MOD START 2653 auto& pipeline_info = ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index]; 2654 auto guest_rasterization_state = pipeline_info.pRasterizationState; 2655 bool rasterization_enabled = ToHostAddr<GuestType<VkPipelineRasterizationStateCreateInfo>>(ToGuestAddr(guest_rasterization_state))->rasterizerDiscardEnable == BERBERIS_VK_FALSE 2656 // When dynamic state presents the rasterization may be enabled later. 2657 || ToGuestAddr(pipeline_info.pDynamicState) != kNullGuestAddr; 2658 // MOD END 2659 holder.data_[index] = { 2660 .sType = VkStructureType(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].sType), 2661 .pNext = ConvertOptionalStructures(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].pNext, holder.extensions_, out_of_memory), 2662 .flags = VkPipelineCreateFlags(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].flags), 2663 .stageCount = std::uint32_t(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].stageCount), 2664 .pStages = ToHostType(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].pStages, holder.pStages_holder_[index], ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].stageCount, out_of_memory), 2665 .pVertexInputState = ToHostType(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].pVertexInputState, holder.pVertexInputState_holder_[index], out_of_memory), 2666 .pInputAssemblyState = ToHostType(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].pInputAssemblyState, holder.pInputAssemblyState_holder_[index], out_of_memory), 2667 .pTessellationState = ToHostType(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].pTessellationState, holder.pTessellationState_holder_[index], out_of_memory), 2668 // MOD START 2669 .pViewportState = rasterization_enabled ? ToHostType(pipeline_info.pViewportState, holder.pViewportState_holder_[index], out_of_memory) : nullptr, 2670 .pRasterizationState = ToHostType(pipeline_info.pRasterizationState, holder.pRasterizationState_holder_[index], out_of_memory), 2671 .pMultisampleState = rasterization_enabled ? ToHostType(pipeline_info.pMultisampleState, holder.pMultisampleState_holder_[index], out_of_memory) : 2672 nullptr, 2673 .pDepthStencilState = rasterization_enabled ? ToHostType(pipeline_info.pDepthStencilState, holder.pDepthStencilState_holder_[index], out_of_memory) : nullptr, 2674 .pColorBlendState = rasterization_enabled ? ToHostType(pipeline_info.pColorBlendState, holder.pColorBlendState_holder_[index], out_of_memory) : nullptr, 2675 // MOD END 2676 .pDynamicState = ToHostType(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].pDynamicState, holder.pDynamicState_holder_[index], out_of_memory), 2677 .layout = VkPipelineLayout(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].layout), 2678 .renderPass = VkRenderPass(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].renderPass), 2679 .subpass = std::uint32_t(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].subpass), 2680 .basePipelineHandle = VkPipeline(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].basePipelineHandle), 2681 .basePipelineIndex = std::int32_t(ToHostAddr<GuestType<VkGraphicsPipelineCreateInfo>>(ToGuestAddr(new_value))[index].basePipelineIndex) }; 2682 } 2683 return holder.data_; 2684} 2685 2686`) 2687 if err != nil { 2688 return err 2689 } 2690 } else { 2691 holder := "" 2692 if extensible_type { 2693 holder = "std::unique_ptr<GuestHolderBase> extensions_;\n " 2694 } 2695 holder += "GuestType<const " + name + ">* data_ = nullptr;" 2696 if isInputCompatible(typе, host_arch, guest_arch) { 2697 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::GuestArrayHolder { 2698 public: 2699 ~GuestArrayHolder(); 2700 friend GuestType<const %[1]s*>; 2701 2702 private: 2703}; 2704 2705inline GuestType<const %[1]s*>::GuestArrayHolder::~GuestArrayHolder() { 2706} 2707 2708inline GuestType<const %[1]s*>::GuestType(const %[1]s* const new_value, GuestType<const %[1]s*>::GuestArrayHolder&, std::size_t, bool&) : value_(bit_cast<GuestAddr>(new_value)) { 2709} 2710 2711`, 2712 name) 2713 } else { 2714 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::GuestArrayHolder { 2715 public: 2716 ~GuestArrayHolder(); 2717 friend GuestType<const %[1]s*>; 2718 2719 private: 2720 friend GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2721 friend GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory); 2722 std::size_t size_ = 0; 2723 %[2]s 2724}; 2725 2726inline GuestType<const %[1]s*>::GuestArrayHolder::~GuestArrayHolder() { 2727 %[3]s 2728} 2729 2730// Apparently "size == 0" is used for pointers marked as noautovalidity="true" in vk.xml and "new_value == nullptr" is used for pointers marked with optional="true", but it's not clear how consistent is it. 2731// 2732// Better to check both options in all cases, it's not too slow in practice. 2733// 2734inline GuestType<const %[1]s*>::GuestType(const %[1]s* const new_value, GuestType<const %[1]s*>::GuestArrayHolder& holder, std::size_t size, [[maybe_unused]] bool& out_of_memory) : value_((size == 0 || new_value == nullptr) ? kNullGuestAddr : ToGuestAddr(holder.data_ = new (std::nothrow) GuestType<const %[1]s>[size])) { 2735 %[4]s 2736 for (std::size_t index = 0; index < size; ++index) { 2737 ToHostAddr<GuestType<%[1]s>>(value_)[index] = { 2738 %[5]s }; 2739 } 2740} 2741 2742`, 2743 name, 2744 strings.Join(append([]string{holder}, 2745 makeHolderList("GuestType<%s>::Guest%sHolder* %s_holder_ = nullptr;", true, typе, host_arch, guest_arch)...), "\n "), 2746 strings.Join(append([]string{"delete[] data_;"}, 2747 makeHolderList("delete[] %[3]s_holder_;", true, typе, host_arch, guest_arch)...), "\n "), 2748 strings.Join(append([]string{"if (value_ == kNullGuestAddr) {\n if (size != 0 && new_value != nullptr) {\n out_of_memory = true;\n }\n return;\n }\n holder.size_ = size;"}, 2749 makeHolderList("if ((holder.%[3]s_holder_ = new (std::nothrow) GuestType<%[1]s>::Guest%[2]sHolder[size]) == nullptr) {\n out_of_memory = true;\n return;\n };", true, typе, host_arch, guest_arch)...), "\n "), 2750 strings.Join(makeGuestInitializerListForArray(initializeConstStruct, name, typе, host_arch, guest_arch), "\n ")) 2751 } 2752 if err != nil { 2753 return err 2754 } 2755 2756 holder = "" 2757 if extensible_type { 2758 holder = "std::unique_ptr<HostHolderBase> extensions_;\n " 2759 } 2760 holder += name + "* data_ = nullptr;" 2761 if isInputCompatible(typе, host_arch, guest_arch) { 2762 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::HostArrayHolder { 2763 public: 2764 ~HostArrayHolder(); 2765 friend const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostArrayHolder& holder, std::size_t size, bool& out_of_memory); 2766 2767 private: 2768}; 2769 2770inline GuestType<const %[1]s*>::HostArrayHolder::~HostArrayHolder() { 2771} 2772 2773inline const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostArrayHolder&, std::size_t, bool&) { 2774 return ToHostAddr<const %[1]s>(ToGuestAddr(new_value)); 2775} 2776 2777`, 2778 name) 2779 } else { 2780 _, err = fmt.Fprintf(w, `class GuestType<const %[1]s*>::HostArrayHolder { 2781 public: 2782 ~HostArrayHolder(); 2783 friend const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostArrayHolder& holder, std::size_t size, bool& out_of_memory); 2784 2785 private: 2786 friend void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2787 friend const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory); 2788 std::size_t size_ = 0; 2789 %[2]s 2790}; 2791 2792inline GuestType<const %[1]s*>::HostArrayHolder::~HostArrayHolder() { 2793 %[3]s 2794} 2795 2796inline const %[1]s* ToHostType(const GuestType<const %[1]s*>& new_value, GuestType<const %[1]s*>::HostArrayHolder& holder, std::size_t size, bool& out_of_memory) { 2797 %[4]s 2798 for (std::size_t index = 0; index < size; ++index) { 2799 holder.data_[index] = { 2800 %[5]s }; 2801 } 2802 return holder.data_; 2803} 2804 2805`, 2806 name, 2807 strings.Join(append([]string{holder}, 2808 makeHolderList("GuestType<%s>::Host%sHolder* %s_holder_ = nullptr;", true, typе, host_arch, guest_arch)...), "\n "), 2809 strings.Join(append([]string{"delete[] data_;"}, 2810 makeHolderList("delete[] %[3]s_holder_;", true, typе, host_arch, guest_arch)...), "\n "), 2811 strings.Join(append([]string{"if (size == 0 || ToGuestAddr(new_value) == kNullGuestAddr) {\n return nullptr;\n }\n holder.size_ = size;\n if ((holder.data_ = new (std::nothrow) " + name + "[size]) == nullptr) {\n out_of_memory = true;\n return nullptr;\n }"}, 2812 makeHolderList("if ((holder.%[3]s_holder_ = new (std::nothrow) GuestType<%[1]s>::Host%[2]sHolder[size]) == nullptr) {\n out_of_memory = true;\n return nullptr;\n };", true, typе, host_arch, guest_arch)...), "\n "), 2813 strings.Join(makeHostInitializerListForArray(initializeConstStruct, name, typе, host_arch, guest_arch), "\n ")) 2814 } 2815 if err != nil { 2816 return err 2817 } 2818 } 2819 } 2820 2821 return nil 2822} 2823 2824func makeHolderList(format string, const_types bool, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) []string { 2825 holders := []string{} 2826 return fillHolderList(holders, format, const_types, typе, host_arch, guest_arch) 2827} 2828 2829func fillHolderList(holders []string, format string, const_types bool, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) []string { 2830 ids := typе.NumField(cpp_types.FirstArch) 2831 for id := uint(0); id < ids; id++ { 2832 field_name := typе.Field(id, cpp_types.FirstArch).Name() 2833 field_type := typе.Field(id, cpp_types.FirstArch).Type() 2834 if !doesNeedHolder(field_type, host_arch, guest_arch) || field_name == "pNext" { 2835 continue 2836 } 2837 switch field_type.Kind(cpp_types.FirstArch) { 2838 case cpp_types.Struct, cpp_types.Union: 2839 holders = fillHolderList(holders, format, const_types, field_type, host_arch, guest_arch) 2840 default: 2841 field_length := typе.Field(id, cpp_types.FirstArch).BaseFieldInfo().(vulkan_xml.ExtendedFieldInfo).Length() 2842 if field_length == nil { 2843 holders = append(holders, fmt.Sprintf( 2844 format, 2845 field_type.Name(host_arch), 2846 "", 2847 field_name)) 2848 } else { 2849 holders = append(holders, fmt.Sprintf( 2850 format, 2851 field_type.Name(host_arch), 2852 "Array", 2853 field_name)) 2854 } 2855 } 2856 } 2857 return holders 2858} 2859 2860// initializeConstStruct - copy all data elements (used for const types) 2861// initializePointers - copy pointers, zero non-pointers (used for non-const types on input) 2862// initializeDataMembers - copy non-pointers, retain pointers (used for non-const types on output) 2863type initializeStructMode uint 2864 2865const ( 2866 initializeConstStruct = iota 2867 initializePointers 2868 initializeDataMembers 2869) 2870 2871func makeGuestInitializerList(mode initializeStructMode, name string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) []string { 2872 guest_initializer_list := []string{} 2873 var prefix string 2874 if mode == initializeDataMembers { 2875 prefix = "data_." 2876 } else { 2877 prefix = "new_value->" 2878 } 2879 return makeInitializerList(guest_initializer_list, mode, true, prefix, "origin_->", "", typе, host_arch, guest_arch) 2880} 2881 2882func makeGuestInitializerListForArray(mode initializeStructMode, name string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) []string { 2883 guest_initializer_list := []string{} 2884 var prefix string 2885 if mode == initializeDataMembers { 2886 prefix = "data_[index]." 2887 } else { 2888 prefix = "new_value[index]." 2889 } 2890 return makeInitializerList(guest_initializer_list, mode, true, prefix, "origin_[index].", "[index]", typе, host_arch, guest_arch) 2891} 2892 2893func makeHostInitializerList(mode initializeStructMode, name string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) []string { 2894 host_initializer_list := []string{} 2895 var prefix string 2896 if mode == initializeDataMembers { 2897 prefix = "data_." 2898 } else { 2899 prefix = fmt.Sprintf("ToHostAddr<GuestType<%s>>(ToGuestAddr(new_value))->", name) 2900 } 2901 return makeInitializerList(host_initializer_list, mode, false, prefix, "origin_->", "", typе, host_arch, guest_arch) 2902} 2903 2904func makeHostInitializerListForArray(mode initializeStructMode, name string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) []string { 2905 host_initializer_list := []string{} 2906 var prefix string 2907 if mode == initializeDataMembers { 2908 prefix = "data_[index]." 2909 } else { 2910 prefix = fmt.Sprintf("ToHostAddr<GuestType<%s>>(ToGuestAddr(new_value))[index].", name) 2911 } 2912 return makeInitializerList(host_initializer_list, mode, false, prefix, "origin_[index].", "[index]", typе, host_arch, guest_arch) 2913} 2914 2915func makeInitializerList(initializer_list []string, mode initializeStructMode, convert_to_guest bool, prefix, origin, index string, typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) []string { 2916 ids := typе.NumField(cpp_types.FirstArch) 2917 if mode == initializePointers { 2918 // We must ensure that last element produces output to properly generate "comma" variable below. 2919 for ids > 0 { 2920 if !isPtr(typе.Field(ids-1, cpp_types.FirstArch).Type()) { 2921 ids-- 2922 } else { 2923 break 2924 } 2925 } 2926 } 2927 if ids == 0 { 2928 return initializer_list 2929 } 2930 for id := uint(0); id < ids; id++ { 2931 field_name := typе.Field(id, cpp_types.FirstArch).Name() 2932 field_type := typе.Field(id, cpp_types.FirstArch).Type() 2933 if mode == initializePointers { 2934 if !isPtr(field_type) && field_name != "sType" { 2935 continue 2936 } 2937 } else if initializeConstStruct == initializeConstStruct { 2938 field_type = cpp_types.ConstType(field_type) 2939 } 2940 field_type_name := targetTypeName(field_type, convert_to_guest) 2941 comma := "," 2942 if id == ids-1 { 2943 comma = "" 2944 } 2945 initializer := fmt.Sprintf( 2946 ".%[1]s = %[2]s(%[3]s%[1]s)%[4]s", field_name, field_type_name, prefix, comma) 2947 field_kind := field_type.Kind(cpp_types.FirstArch) 2948 if field_kind == cpp_types.Const { 2949 field_type = field_type.Elem(cpp_types.FirstArch) 2950 field_kind = field_type.Kind(cpp_types.FirstArch) 2951 } 2952 switch field_kind { 2953 case cpp_types.Array: 2954 elem := field_type.Elem(cpp_types.FirstArch) 2955 field_type_name = targetTypeName(elem, convert_to_guest) 2956 initializer_list = append(initializer_list, fmt.Sprintf(".%s = {", field_name)) 2957 max_index := field_type.NumField(cpp_types.FirstArch) - 1 2958 if max_index > 0 { 2959 for cur_index := uint(0); cur_index < max_index; cur_index++ { 2960 if isStruct(elem) && !isInputCompatible(field_type, host_arch, guest_arch) { 2961 initializer_list = append(initializer_list, field_type_name+"{") 2962 initializer_list = makeInitializerList( 2963 initializer_list, 2964 mode, 2965 convert_to_guest, 2966 fmt.Sprintf("%s%s[%d].", prefix, field_name, cur_index), 2967 fmt.Sprintf("%s%s[%d].", origin, field_name, cur_index), 2968 fmt.Sprintf("[%d]", origin, field_name, cur_index), 2969 elem, 2970 host_arch, 2971 guest_arch) 2972 initializer_list = append(initializer_list, "},") 2973 continue 2974 } 2975 initializer_list = append(initializer_list, fmt.Sprintf( 2976 " %[2]s%[1]s[%[3]d],", field_name, prefix, cur_index)) 2977 } 2978 } 2979 if isStruct(elem) && !isInputCompatible(field_type, host_arch, guest_arch) { 2980 initializer_list = append(initializer_list, field_type_name+"{") 2981 initializer_list = makeInitializerList( 2982 initializer_list, 2983 mode, 2984 convert_to_guest, 2985 fmt.Sprintf("%s%s[%d].", prefix, field_name, max_index), 2986 fmt.Sprintf("%s%s[%d].", origin, field_name, max_index), 2987 fmt.Sprintf("[%d]", origin, field_name, max_index), 2988 elem, 2989 host_arch, 2990 guest_arch) 2991 initializer_list = append(initializer_list, "}", "}"+comma) 2992 } else { 2993 initializer_list = append(initializer_list, fmt.Sprintf( 2994 " %[2]s%[1]s[%[3]d]}%[4]s", field_name, prefix, max_index, comma)) 2995 } 2996 continue 2997 case cpp_types.Ptr: 2998 initializer_fmt := "" 2999 if mode == initializeDataMembers { 3000 // When we are copying data members we have to keep pointers unchanged. 3001 initializer_fmt = ".%[1]s = %[6]s%[1]s%[8]s" 3002 // Most Vulkan data structures use "void*" or "const void*" types for the pNext field. 3003 // Only two data structures use something different: VkBaseInStructure/VkBaseOutStructure. 3004 // Handle them separately. 3005 } else if field_name == "pNext" { 3006 if field_type.Name(cpp_types.FirstArch) != "void *" && field_type.Name(cpp_types.FirstArch) != "const void *" { 3007 panic("Unsupported type of \"pNext\" field") 3008 } 3009 if mode == initializeConstStruct && !isPtrToConst(field_type) { 3010 if convert_to_guest { 3011 initializer_fmt = ".%[1]s = ConstCast<GuestType<void*>>(ConvertOptionalStructures(static_cast<const void*>(%[5]s%[1]s), holder.extensions_, out_of_memory))%[8]s" 3012 } else { 3013 initializer_fmt = ".%[1]s = const_cast<void *>(ConvertOptionalStructures(ConstCast<GuestType<const void*>>(%[5]s%[1]s), holder.extensions_, out_of_memory))%[8]s" 3014 } 3015 } else { 3016 if convert_to_guest { 3017 initializer_fmt = ".%[1]s = ConvertOptionalStructures(%[5]s%[1]s, holder.extensions_, out_of_memory)%[8]s" 3018 } else { 3019 initializer_fmt = ".%[1]s = ConvertOptionalStructures(%[5]s%[1]s, holder.extensions_, out_of_memory)%[8]s" 3020 } 3021 } 3022 } else if doesNeedHolder(field_type, host_arch, guest_arch) { 3023 // VkCommandBufferBeginInfo has field pInheritanceInfo which may or may not be used and it's quite hard to determine if it can be touched. 3024 // Because it's part of Vulkan API and can not be changed we are doing complex dance with maps and lock on the input side. 3025 // When layers are involved, though, we assume that nullptr that we are introducing here would pass to other layers thus there is 3026 // no need to deal with this problem in the GuestRunners. 3027 if !convert_to_guest && field_name == "pInheritanceInfo" && typе.Name(cpp_types.FirstArch) == "struct VkCommandBufferBeginInfo" { 3028 initializer_fmt = ".%[1]s = has_inheritance_info ? ToHostType(%[5]s%[1]s, holder.%[1]s_holder_%[7]s%[4]s, out_of_memory) : nullptr%[8]s" 3029 // pImageInfo is marked with noautovalidity="true" and there's the following comment: 3030 // Sampler, image view, and layout for SAMPLER, COMBINED_IMAGE_SAMPLER, {SAMPLED,STORAGE}_IMAGE, and INPUT_ATTACHMENT descriptor types. 3031 // Replace it with nullptr if descriptor type is not in the five listed ones. 3032 } else if !convert_to_guest && field_name == "pImageInfo" && typе.Name(cpp_types.FirstArch) == "struct VkWriteDescriptorSet" { 3033 initializer_fmt = `.%[1]s = 3034 (VkDescriptorType(ToHostAddr<GuestType<VkWriteDescriptorSet>>(ToGuestAddr(new_value))[index].descriptorType) == BERBERIS_VK_DESCRIPTOR_TYPE_SAMPLER || 3035 VkDescriptorType(ToHostAddr<GuestType<VkWriteDescriptorSet>>(ToGuestAddr(new_value))[index].descriptorType) == BERBERIS_VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 3036 VkDescriptorType(ToHostAddr<GuestType<VkWriteDescriptorSet>>(ToGuestAddr(new_value))[index].descriptorType) == BERBERIS_VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 3037 VkDescriptorType(ToHostAddr<GuestType<VkWriteDescriptorSet>>(ToGuestAddr(new_value))[index].descriptorType) == BERBERIS_VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT || 3038 VkDescriptorType(ToHostAddr<GuestType<VkWriteDescriptorSet>>(ToGuestAddr(new_value))[index].descriptorType) == BERBERIS_VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ? 3039 ToHostType(%[5]s%[1]s, holder.%[1]s_holder_%[7]s%[4]s, out_of_memory): nullptr%[8]s` 3040 } else { 3041 if convert_to_guest { 3042 initializer_fmt = ".%[1]s = GuestType<%[2]s>(%[5]s%[1]s, holder.%[1]s_holder_%[7]s%[4]s, out_of_memory)%[8]s" 3043 } else { 3044 initializer_fmt = ".%[1]s = ToHostType(%[5]s%[1]s, holder.%[1]s_holder_%[7]s%[4]s, out_of_memory)%[8]s" 3045 } 3046 } 3047 } else if isPtrToFunc(field_type) { 3048 if convert_to_guest { 3049 initializer_fmt = ".%[1]s = WrapHostFunctionIfNeeded(%[5]s%[1]s, \"%[1]s\")%[8]s" 3050 } else { 3051 initializer_fmt = ".%[1]s = WrapGuestFunctionIfNeeded(GuestType<%[3]s>(%[5]s%[1]s), \"%[1]s\")%[8]s" 3052 } 3053 } 3054 if initializer_fmt != "" { 3055 field_length := typе.Field(id, cpp_types.FirstArch).BaseFieldInfo().(vulkan_xml.ExtendedFieldInfo).Length() 3056 field_length_ref := "" 3057 if field_length != nil { 3058 if mode == initializeConstStruct && !isPtrToConst(field_type) { 3059 if convert_to_guest { 3060 field_length_ref = ", &" + prefix + field_length.Name() 3061 } else { 3062 // After taking address we end up with weird “GuestType<GuestType<std::uint32_t>*>” which we can only convert to “const ::uint32_t*” using bit_cast 3063 field_length_ref = ", bit_cast<const ::uint32_t*>(&" + prefix + field_length.Name() + ")" 3064 } 3065 } else { 3066 field_length_ref = ", " + prefix + field_length.Name() 3067 } 3068 } 3069 initializer = fmt.Sprintf(initializer_fmt, field_name, field_type.Name(cpp_types.FirstArch), field_type_name, field_length_ref, prefix, origin, index, comma) 3070 } 3071 case cpp_types.Struct: 3072 if !isInputCompatible(field_type, host_arch, guest_arch) { 3073 initializer_list = append(initializer_list, fmt.Sprintf( 3074 ".%[1]s = %[2]s{", field_name, field_type_name)) 3075 initializer_list = makeInitializerList( 3076 initializer_list, 3077 mode, 3078 convert_to_guest, 3079 prefix+field_name+".", 3080 origin+field_name+".", 3081 "", 3082 field_type, 3083 host_arch, 3084 guest_arch) 3085 initializer = "}" + comma 3086 } 3087 case cpp_types.Union: 3088 // Temprorary kludge. 3089 if field_type.BaseName(cpp_types.FirstArch) == "VkDescriptorDataEXT" { 3090 continue 3091 } 3092 if !isInputCompatible(field_type, cpp_types.X86, cpp_types.Arm) || 3093 !isInputCompatible(field_type, cpp_types.X86_64, cpp_types.Arm64) { 3094 panic("Unsupported union field in incompatible type: " + typе.Name(cpp_types.FirstArch) + " " + field_name) 3095 } 3096 } 3097 initializer_list = append(initializer_list, initializer) 3098 } 3099 return initializer_list 3100} 3101func targetTypeName(typе cpp_types.Type, convert_to_guest bool) string { 3102 if isConst(typе) { 3103 typе = typе.Elem(cpp_types.FirstArch) 3104 } 3105 type_name := typе.Name(cpp_types.FirstArch) 3106 // Outer const just makes conversion harder and doesn't affect anything, really, 3107 // since we are only producing temporary object here which would be assigned to 3108 // proper const field. 3109 if convert_to_guest { 3110 type_name = fmt.Sprintf("GuestType<%s>", type_name) 3111 } else { 3112 switch typе.Kind(cpp_types.FirstArch) { 3113 case cpp_types.Struct, cpp_types.Union: 3114 type_name = typе.BaseName(cpp_types.FirstArch) 3115 case cpp_types.Ptr: 3116 if !isPtrToFunc(typе) { 3117 type_name = "ToHostAddr" 3118 } 3119 } 3120 } 3121 return type_name 3122} 3123 3124func doesNeedHolder(typе cpp_types.Type, host_arch cpp_types.Arch, guest_arch cpp_types.Arch) bool { 3125 if isInputCompatible(typе, host_arch, guest_arch) { 3126 return false 3127 } 3128 // We are not trying to convert on ARM64 because we don't know if pointer is valid (and if all extensions are compatible). 3129 // On ARM32 we need to convert some data structures, but tests pass because of quirk of how they are run. 3130 // TODO(b/274875580): fix properly. 3131 if guest_arch == cpp_types.Arm64 && typе.Name(cpp_types.Arm64) == "const struct VkCommandBufferInheritanceInfo *" { 3132 return false 3133 } 3134 kind := typе.Kind(cpp_types.FirstArch) 3135 switch kind { 3136 // We need holders when we are working with pointers to structures. 3137 // But pointers to function don't need holders (even if then need coversion routines). 3138 case cpp_types.Ptr: 3139 pointee := typе.Elem(cpp_types.FirstArch) 3140 if isConst(pointee) { 3141 pointee = pointee.Elem(cpp_types.FirstArch) 3142 } 3143 if isStruct(pointee) || isUnion(pointee) { 3144 return true 3145 } else if isFunc(pointee) { 3146 return false 3147 } else { 3148 panic("Unsupported field in incompatible type: " + typе.Name(cpp_types.FirstArch)) 3149 } 3150 case cpp_types.Struct, cpp_types.Union: 3151 ids := typе.NumField(cpp_types.FirstArch) 3152 for id := uint(0); id < ids; id++ { 3153 field_type := typе.Field(id, cpp_types.FirstArch).Type() 3154 if doesNeedHolder(field_type, host_arch, guest_arch) { 3155 return true 3156 } 3157 } 3158 } 3159 return false 3160} 3161 3162func printHostStructVerification(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) error { 3163 for _, name := range sorted_type_names { 3164 typе := types[name] 3165 if !isStruct(typе) && !isUnion(typе) { 3166 continue 3167 } 3168 fields_check_berberis_host := []string{} 3169 fields_check_platform_host := []string{} 3170 for i := uint(0); i < typе.NumField(host_arch); i++ { 3171 field := typе.Field(i, host_arch) 3172 var field_offset uint 3173 if !isUnion(typе) { 3174 field_offset = field.(cpp_types.StructFieldInfo).Offset() 3175 } else { 3176 field_offset = 0 3177 } 3178 fields_check_berberis_host = append(fields_check_berberis_host, 3179 fmt.Sprintf("CHECK_FIELD_LAYOUT(berberis::%[1]s, %[2]s, %[3]d, %[4]d);", 3180 name, 3181 field.Name(), 3182 field_offset, 3183 field.Type().Bits(host_arch))) 3184 fields_check_platform_host = append(fields_check_platform_host, 3185 fmt.Sprintf("CHECK_FIELD_LAYOUT(::%[1]s, %[2]s, %[3]d, %[4]d);", 3186 name, 3187 field.Name(), 3188 field_offset, 3189 field.Type().Bits(host_arch))) 3190 } 3191 fields_check_berberis_guest := []string{} 3192 fields_check_platform_guest := []string{} 3193 for i := uint(0); i < typе.NumField(guest_arch); i++ { 3194 field := typе.Field(i, guest_arch) 3195 var field_offset uint 3196 if !isUnion(typе) { 3197 field_offset = field.(cpp_types.StructFieldInfo).Offset() 3198 } else { 3199 field_offset = 0 3200 } 3201 fields_check_berberis_guest = append(fields_check_berberis_guest, 3202 fmt.Sprintf("CHECK_FIELD_LAYOUT(berberis::%[1]s, %[2]s, %[3]d, %[4]d);", 3203 name, 3204 field.Name(), 3205 field_offset, 3206 field.Type().Bits(guest_arch))) 3207 fields_check_platform_guest = append(fields_check_platform_guest, 3208 fmt.Sprintf("CHECK_FIELD_LAYOUT(::%[1]s, %[2]s, %[3]d, %[4]d);", 3209 name, 3210 field.Name(), 3211 field_offset, 3212 field.Type().Bits(guest_arch))) 3213 } 3214 _, err := fmt.Fprintf( 3215 w, 3216 `#if %[7]s 3217CHECK_STRUCT_LAYOUT(berberis::%[2]s, %[3]d, %[4]d); 3218%[9]s 3219#if !defined(BERBERIS_%[1]s) 3220CHECK_STRUCT_LAYOUT(::%[2]s, %[3]d, %[4]d); 3221%[10]s 3222#endif /* BERBERIS_%[1]s */ 3223#elif %[8]s 3224CHECK_STRUCT_LAYOUT(berberis::%[2]s, %[5]d, %[6]d); 3225%[11]s 3226#if !defined(BERBERIS_%[1]s) 3227CHECK_STRUCT_LAYOUT(::%[2]s, %[5]d, %[6]d); 3228%[12]s 3229#endif /* BERBERIS_%[1]s */ 3230#else 3231#error Unsupported architecture. 3232#endif 3233 3234`, 3235 toEnumNameWithSuffix(name, "NOVERIFY"), 3236 name, 3237 typе.Bits(host_arch), 3238 typе.Align(host_arch), 3239 typе.Bits(guest_arch), 3240 typе.Align(guest_arch), 3241 cpp_types.Define(host_arch), 3242 cpp_types.Define(guest_arch), 3243 strings.Join(fields_check_berberis_host, "\n"), 3244 strings.Join(fields_check_platform_host, "\n"), 3245 strings.Join(fields_check_berberis_guest, "\n"), 3246 strings.Join(fields_check_platform_guest, "\n")) 3247 if err != nil { 3248 return err 3249 } 3250 } 3251 return nil 3252} 3253 3254func printGuestStructVerification(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) error { 3255 for _, name := range sorted_type_names { 3256 typе := types[name] 3257 if typе.Kind(guest_arch) != cpp_types.Struct && 3258 typе.Kind(guest_arch) != cpp_types.Union { 3259 continue 3260 } 3261 if isInputCompatible(typе, host_arch, guest_arch) { 3262 continue 3263 } 3264 for _, cоnst := range []string{"", "const "} { 3265 _, err := fmt.Fprintf( 3266 w, 3267 "CHECK_STRUCT_LAYOUT(berberis::GuestType<%s berberis::%s>, %d, %d);\n", 3268 cоnst, 3269 name, 3270 typе.Bits(guest_arch), 3271 typе.Align(guest_arch)) 3272 if err != nil { 3273 return err 3274 } 3275 for i := uint(0); i < typе.NumField(cpp_types.FirstArch); i++ { 3276 field := typе.Field(i, guest_arch) 3277 field_type := field.Type() 3278 var field_name string 3279 var field_offset uint 3280 if typе.Kind(guest_arch) == cpp_types.Struct { 3281 field_name = field.Name() 3282 field_offset = field.(cpp_types.StructFieldInfo).Offset() 3283 } else { 3284 field_name = "uniоn." + field.Name() 3285 field_offset = 0 3286 } 3287 _, err = fmt.Fprintf( 3288 w, 3289 "CHECK_FIELD_LAYOUT(berberis::GuestType<%s berberis::%s>, %s, %d, %d);\n", 3290 cоnst, 3291 name, 3292 field_name, 3293 field_offset, 3294 field_type.Bits(guest_arch)) 3295 if err != nil { 3296 return err 3297 } 3298 } 3299 _, err = fmt.Fprintln(w, "") 3300 if err != nil { 3301 return err 3302 } 3303 } 3304 } 3305 return nil 3306} 3307 3308func printConvertOptionalStructures(w io.Writer, sorted_type_names []string, types map[string]cpp_types.Type, conversion map[string]*NeededConvertor, host_arch, guest_arch cpp_types.Arch) (err error) { 3309 var compatible_structs []string 3310 var convert_guest_in_structure []string 3311 var convert_host_in_structure []string 3312 var convert_guest_out_structure []string 3313 var convert_host_out_structure []string 3314 for _, name := range sorted_type_names { 3315 typе := types[name] 3316 if isUnion(typе) { 3317 continue 3318 } 3319 if !typе.(vulkan_xml.ExtendedStructInfo).OptionalStruct() { 3320 continue 3321 } 3322 optional_value := typе.(vulkan_xml.ExtendedStructInfo).OptionalValue() 3323 if cpp_types.IsInputCompatible(typе, host_arch, guest_arch) { 3324 compatible_structs = append(compatible_structs, "BERBERIS_"+optional_value) 3325 } 3326 if conversion[name].need_base_convertor { 3327 convert_guest_out_structure = append(convert_guest_out_structure, fmt.Sprintf(` case %[1]s: { 3328 auto new_holder = new (std::nothrow) GuestType<%[2]s*>::HostHolder; 3329 if (new_holder == nullptr) { 3330 out_of_memory = true; 3331 return nullptr; 3332 } 3333 new_holder->extensions_ = std::move(holder); 3334 holder.reset(new_holder); 3335 auto* converted_type = ToHostType(StaticCast<GuestType<%[2]s*>>(StaticCast<GuestType<void*>>(ptr)), *new_holder, out_of_memory); 3336 if (out_of_memory) { 3337 return nullptr; 3338 } 3339 return converted_type; 3340 } 3341`, 3342 "BERBERIS_"+optional_value, 3343 name)) 3344 convert_host_out_structure = append(convert_host_out_structure, fmt.Sprintf(` case %[1]s: { 3345 auto new_holder = new (std::nothrow) GuestType<%[2]s*>::GuestHolder; 3346 if (new_holder == nullptr) { 3347 out_of_memory = true; 3348 return nullptr; 3349 } 3350 new_holder->extensions_ = std::move(holder); 3351 holder.reset(new_holder); 3352 auto converted_type = StaticCast<GuestType<void*>>(GuestType<%[2]s*>(static_cast<%[2]s*>(static_cast<void*>(ptr)), *new_holder, out_of_memory)); 3353 if (out_of_memory) { 3354 return nullptr; 3355 } 3356 return converted_type; 3357 } 3358`, 3359 "BERBERIS_"+optional_value, 3360 name)) 3361 } 3362 if conversion[name].need_const_convertor { 3363 convert_guest_in_structure = append(convert_guest_in_structure, fmt.Sprintf(` case %[1]s: { 3364 auto new_holder = new (std::nothrow) GuestType<const %[2]s*>::HostHolder; 3365 if (new_holder == nullptr) { 3366 out_of_memory = true; 3367 return nullptr; 3368 } 3369 new_holder->extensions_ = std::move(holder); 3370 holder.reset(new_holder); 3371 auto* converted_type = ToHostType(StaticCast<GuestType<const %[2]s*>>(StaticCast<GuestType<const void*>>(ptr)), *new_holder, out_of_memory); 3372 if (out_of_memory) { 3373 return nullptr; 3374 } 3375 return converted_type; 3376 } 3377`, 3378 "BERBERIS_"+optional_value, 3379 name)) 3380 convert_host_in_structure = append(convert_host_in_structure, fmt.Sprintf(` case %[1]s: { 3381 auto new_holder = new (std::nothrow) GuestType<const %[2]s*>::GuestHolder; 3382 if (new_holder == nullptr) { 3383 out_of_memory = true; 3384 return nullptr; 3385 } 3386 new_holder->extensions_ = std::move(holder); 3387 holder.reset(new_holder); 3388 auto converted_type = StaticCast<GuestType<const void*>>(GuestType<const %[2]s*>(static_cast<const %[2]s*>(static_cast<const void*>(ptr)), *new_holder, out_of_memory)); 3389 if (out_of_memory) { 3390 return nullptr; 3391 } 3392 return converted_type; 3393 } 3394`, 3395 "BERBERIS_"+optional_value, 3396 name)) 3397 } 3398 } 3399 3400 _, err = fmt.Fprintf(w, 3401 ` 3402bool AreAllOptionalStructuresCompatible(GuestType<const void*> head) { 3403 for (auto ptr = StaticCast<GuestType<const VkBaseInStructure*>>(head); ToGuestAddr(ptr) != kNullGuestAddr; ptr = ToHostAddr<GuestType<VkBaseInStructure>>(ToGuestAddr(ptr))->pNext) { 3404 switch (VkStructureType(ToHostAddr<GuestType<const VkBaseInStructure>>(ToGuestAddr(ptr))->sType)) { 3405 case %[1]s: 3406 continue; 3407 default: 3408 return false; 3409 } 3410 } 3411 return true; 3412} 3413 3414bool AreAllOptionalStructuresCompatible(GuestType<void*> head) { 3415 for (auto ptr = StaticCast<GuestType<VkBaseOutStructure*>>(head); ToGuestAddr(ptr) != kNullGuestAddr; ptr = ToHostAddr<GuestType<VkBaseOutStructure>>(ToGuestAddr(ptr))->pNext) { 3416 switch (VkStructureType(ToHostAddr<GuestType<VkBaseOutStructure>>(ToGuestAddr(ptr))->sType)) { 3417 case %[1]s: 3418 continue; 3419 default: 3420 return false; 3421 } 3422 } 3423 return true; 3424} 3425 3426bool AreAllOptionalStructuresCompatible(const void* head) { 3427 for (auto* ptr = static_cast<const VkBaseInStructure*>(head); ptr != nullptr; ptr = ptr->pNext) { 3428 switch (ptr->sType) { 3429 case %[1]s: 3430 continue; 3431 default: 3432 return false; 3433 } 3434 } 3435 return true; 3436} 3437 3438bool AreAllOptionalStructuresCompatible(void* head) { 3439 for (auto* ptr = static_cast<VkBaseOutStructure*>(head); ptr != nullptr; ptr = ptr->pNext) { 3440 switch (ptr->sType) { 3441 case %[1]s: 3442 continue; 3443 default: 3444 return false; 3445 } 3446 } 3447 return true; 3448} 3449 3450const void* ConvertOptionalStructures(GuestType<const void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory) { 3451 if (AreAllOptionalStructuresCompatible(head)) { 3452 return ToHostAddr(head); 3453 } 3454 for (auto ptr = StaticCast<GuestType<const VkBaseInStructure*>>(head); ToGuestAddr(ptr) != kNullGuestAddr; ptr = ToHostAddr<GuestType<VkBaseInStructure>>(ToGuestAddr(ptr))->pNext) { 3455 switch (VkStructureType(ToHostAddr<GuestType<const VkBaseInStructure>>(ToGuestAddr(ptr))->sType)) { 3456%[2]s 3457 default: 3458 continue; 3459 } 3460 } 3461 return nullptr; 3462} 3463 3464void* ConvertOptionalStructures(GuestType<void*> head, std::unique_ptr<HostHolderBase>& holder, bool& out_of_memory) { 3465 if (AreAllOptionalStructuresCompatible(head)) { 3466 return ToHostAddr(head); 3467 } 3468 for (auto ptr = StaticCast<GuestType<VkBaseOutStructure*>>(head); ToGuestAddr(ptr) != kNullGuestAddr; ptr = ToHostAddr<GuestType<VkBaseOutStructure>>(ToGuestAddr(ptr))->pNext) { 3469 switch (VkStructureType(ToHostAddr<GuestType<const VkBaseOutStructure>>(ToGuestAddr(ptr))->sType)) { 3470%[3]s 3471 default: 3472 continue; 3473 } 3474 } 3475 return nullptr; 3476} 3477 3478GuestType<const void*> ConvertOptionalStructures(const void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory) { 3479 if (AreAllOptionalStructuresCompatible(head)) { 3480 return GuestType<const void*>(head); 3481 } 3482 for (auto ptr = static_cast<const VkBaseInStructure*>(head); ptr != nullptr; ptr = ptr->pNext) { 3483 switch (ptr->sType) { 3484%[4]s 3485 default: 3486 continue; 3487 } 3488 } 3489 return GuestType<const void*>(nullptr); 3490} 3491 3492GuestType<void*> ConvertOptionalStructures(void* head, std::unique_ptr<GuestHolderBase>& holder, bool& out_of_memory) { 3493 if (AreAllOptionalStructuresCompatible(head)) { 3494 return GuestType<void*>(head); 3495 } 3496 for (auto ptr = static_cast<VkBaseOutStructure*>(head); ptr != nullptr; ptr = ptr->pNext) { 3497 switch (ptr->sType) { 3498%[5]s 3499 default: 3500 continue; 3501 } 3502 } 3503 return GuestType<void*>(nullptr); 3504} 3505 3506`, 3507 strings.Join(compatible_structs, ":\n case "), 3508 strings.Join(convert_guest_in_structure, ""), 3509 strings.Join(convert_guest_out_structure, ""), 3510 strings.Join(convert_host_in_structure, ""), 3511 strings.Join(convert_host_out_structure, "")) 3512 if err != nil { 3513 return err 3514 } 3515 return nil 3516} 3517 3518func printCustomTrampolies(w io.Writer, sorted_command_names []string, commands map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) (err error) { 3519 for _, name := range sorted_command_names { 3520 vfp := "" 3521 if guest_arch == cpp_types.Arm { 3522 vfp = ", GuestAbi::kAapcsVfp" 3523 } 3524 command := commands[name] 3525 param_names := []string{} 3526 variable_declarations := []string{} 3527 params_are_compatible := true 3528 for i := uint(0); i < command.NumField(cpp_types.FirstArch); i++ { 3529 param_name := command.Field(i, cpp_types.FirstArch).Name() 3530 param_type := command.Field(i, cpp_types.FirstArch).Type() 3531 param_names = append(param_names, param_name) 3532 if isInputCompatible(param_type, host_arch, guest_arch) { 3533 variable_declarations = append(variable_declarations, fmt.Sprintf( 3534 "%s = %s_guest", param_type.DeclareVar(param_name+"_host", cpp_types.FirstArch), param_name)) 3535 } else { 3536 params_are_compatible = false 3537 param_length := command.Field(i, cpp_types.FirstArch).BaseFieldInfo().(vulkan_xml.ExtendedFieldInfo).Length() 3538 if param_length == nil { 3539 variable_declarations = append( 3540 variable_declarations, 3541 fmt.Sprintf("GuestType<%s>::HostHolder %s_holder", param_type.Name(cpp_types.FirstArch), param_name), 3542 fmt.Sprintf( 3543 "%[1]s = ToHostType(%[2]s_guest, %[2]s_holder, out_of_memory)", 3544 param_type.DeclareVar(param_name+"_host", cpp_types.FirstArch), 3545 param_name)) 3546 } else { 3547 variable_declarations = append( 3548 variable_declarations, 3549 fmt.Sprintf("GuestType<%s>::HostArrayHolder %s_holder", param_type.Name(cpp_types.FirstArch), param_name), 3550 fmt.Sprintf( 3551 "%[1]s = ToHostType(%[2]s_guest, %[2]s_holder, %[3]s_host, out_of_memory)", 3552 param_type.DeclareVar(param_name+"_host", cpp_types.FirstArch), 3553 param_name, 3554 param_length.Name())) 3555 } 3556 } 3557 } 3558 // vkAllocateCommandBuffers and vkBeginCommandBuffer are manually written to handle awful pInheritanceInfo field. 3559 // The VkCommandBufferBeginInfo data structure doesn't include any clue which may allow someone to understand if 3560 // that field can be used or not. Instead that information is only available in entirely different time and place 3561 // when vkAllocateCommandBuffers functions is called. 3562 // To handle VkCommandBufferBeginInfo we need side-channel to pass that boolean from vkAllocateCommandBuffers to 3563 // vkBeginCommandBuffer, that's why we need to skip automatically generation of converter. 3564 if params_are_compatible || name == "vkAllocateCommandBuffers" || name == "vkBeginCommandBuffer" { 3565 continue 3566 } 3567 declare_ret := "" 3568 if command.Elem(cpp_types.FirstArch).Kind(cpp_types.FirstArch) != cpp_types.Void { 3569 declare_ret = fmt.Sprintf("auto&& [ret] = GuestReturnReference<PFN_%s%s>(state);\n ret = ", name, vfp) 3570 } 3571 _, err = fmt.Fprintf(w, `void DoCustomTrampolineWithThunk_%[1]s(HostCode callee, ProcessState* state) { 3572 PFN_%[1]s callee_function = AsFuncPtr(callee); 3573 auto [%[3]s_guest] = GuestParamsValues<PFN_%[1]s%[2]s>(state); 3574 [[maybe_unused]] bool out_of_memory; 3575 %[5]s; 3576 %[6]scallee_function(%[4]s_host); 3577} 3578 3579`, 3580 name, 3581 vfp, 3582 strings.Join(param_names, "_guest, "), 3583 strings.Join(param_names, "_host, "), 3584 strings.Join(variable_declarations, ";\n "), 3585 declare_ret) 3586 if err != nil { 3587 return err 3588 } 3589 } 3590 return nil 3591} 3592 3593func printCustomGuestRunners(w io.Writer, sorted_command_names []string, commands map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) (err error) { 3594 for _, name := range sorted_command_names { 3595 command := commands[name] 3596 param_names := []string{} 3597 variable_declarations := []string{} 3598 params_are_compatible := true 3599 for i := uint(0); i < command.NumField(cpp_types.FirstArch); i++ { 3600 param_name := command.Field(i, cpp_types.FirstArch).Name() 3601 param_type := command.Field(i, cpp_types.FirstArch).Type() 3602 param_names = append(param_names, param_name) 3603 if isInputCompatible(param_type, host_arch, guest_arch) { 3604 variable_declarations = append(variable_declarations, fmt.Sprintf( 3605 "%[1]s_guest = %[1]s_host", param_name)) 3606 } else { 3607 params_are_compatible = false 3608 param_length := command.Field(i, cpp_types.FirstArch).BaseFieldInfo().(vulkan_xml.ExtendedFieldInfo).Length() 3609 if param_length == nil { 3610 variable_declarations = append( 3611 variable_declarations, 3612 fmt.Sprintf("GuestType<%s>::GuestHolder %s_holder", param_type.Name(cpp_types.FirstArch), param_name), 3613 fmt.Sprintf( 3614 "%[2]s_guest = GuestType<%[1]s>(%[2]s_host, %[2]s_holder, out_of_memory)", 3615 param_type.Name(cpp_types.FirstArch), 3616 param_name)) 3617 } else { 3618 variable_declarations = append( 3619 variable_declarations, 3620 fmt.Sprintf("GuestType<%s>::GuestArrayHolder %s_holder", param_type.Name(cpp_types.FirstArch), param_name), 3621 fmt.Sprintf( 3622 "%[2]s_guest = GuestType<%[1]s>(%[2]s_host, %[2]s_holder, %[3]s_host, out_of_memory)", 3623 param_type.Name(cpp_types.FirstArch), 3624 param_name, 3625 param_length.Name())) 3626 } 3627 } 3628 } 3629 // vkCreateInstance needs additional non-trivial processing. 3630 if params_are_compatible || name == "vkCreateInstance" { 3631 continue 3632 } 3633 _, err = fmt.Fprintf(w, `void RunGuest_%[1]s(GuestAddr pc, GuestArgumentBuffer* buf) { 3634 auto [%[3]s_host] = HostArgumentsValues<PFN_%[1]s>(buf); 3635 { 3636 [[maybe_unused]] bool out_of_memory; 3637 auto [%[2]s_guest] = GuestArgumentsReferences<PFN_%[1]s>(buf); 3638 %[4]s; 3639 RunGuestCall(pc, buf); 3640 } 3641} 3642 3643`, 3644 name, 3645 strings.Join(param_names, "_guest, "), 3646 strings.Join(param_names, "_host, "), 3647 strings.Join(variable_declarations, ";\n ")) 3648 if err != nil { 3649 return err 3650 } 3651 } 3652 return nil 3653} 3654 3655func printExtensionsMap(w io.Writer, extensions map[string]int64) (err error) { 3656 names := make([]string, 0, len(extensions)) 3657 for extension := range extensions { 3658 names = append(names, fmt.Sprintf("{\"%s\", %d}", extension, extensions[extension])) 3659 } 3660 sort.Strings(names) 3661 _, err = fmt.Fprintf(w, ` 3662struct ExtensionInfo { 3663 const char* name; 3664 uint32_t maxsupported_spec; 3665}; 3666 3667[[maybe_unused]] auto& GetExtensionsMap() { 3668#if defined(__i386__) 3669 static constexpr std::array<ExtensionInfo, %[1]d> map{ 3670#else 3671 static constexpr std::array<ExtensionInfo, %[2]d> map{ 3672#endif 3673 {%[3]s}}; 3674 static_assert(IsSorted(std::begin(map), std::end(map), StrCmpLessName)); 3675 return map; 3676} 3677 3678`, 3679 len(extensions)-1, 3680 len(extensions), 3681 // Disable VK_EXT_device_memory_report extension only for arm32. 3682 strings.Replace( 3683 strings.Join(names, ",\n "), 3684 " {\"VK_EXT_device_memory_report\", 2},\n", 3685 `#if !defined(__i386__) 3686 {"VK_EXT_device_memory_report", 2}, 3687#endif 3688`, 3689 1)) 3690 return nil 3691} 3692 3693func printMaps(w io.Writer, sorted_command_names []string, commands map[string]cpp_types.Type, host_arch, guest_arch cpp_types.Arch) (err error) { 3694 command_trampolines := []string{} 3695 command_wrappers := []string{} 3696 for _, name := range sorted_command_names { 3697 command := commands[name] 3698 params_are_compatible := true 3699 switch name { 3700 // These functions are compatible based on signatures, but actually need special processing. 3701 case "vkGetDeviceProcAddr", "vkGetInstanceProcAddr": 3702 params_are_compatible = false 3703 } 3704 for i := uint(0); i < command.NumField(guest_arch); i++ { 3705 param_type := command.Field(i, guest_arch).Type() 3706 if !isInputCompatible(param_type, host_arch, guest_arch) { 3707 params_are_compatible = false 3708 break 3709 } 3710 } 3711 // Data structures in vkEnumerate{Device,Instance}ExtensionProperties are compatible, 3712 // but we need to filter out unsupported extensions. 3713 // Data structures in vkFreeCommandBuffers are compatible but we need to free memory 3714 // allocated for meta-information in vkAllocateCommandBuffers. 3715 if params_are_compatible && name != "vkEnumerateDeviceExtensionProperties" && name != "vkEnumerateInstanceExtensionProperties" && name != "vkFreeCommandBuffers" { 3716 if guest_arch == cpp_types.Arm { 3717 command_trampolines = append(command_trampolines, fmt.Sprintf( 3718 "{\"%s\", GetTrampolineFunc<%s, GuestAbi::kAapcsVfp>()}", name, command.Name(guest_arch))) 3719 } else { 3720 command_trampolines = append(command_trampolines, fmt.Sprintf( 3721 "{\"%s\", GetTrampolineFunc<%s>()}", name, command.Name(guest_arch))) 3722 } 3723 } else { 3724 command_trampolines = append(command_trampolines, fmt.Sprintf( 3725 "{\"%[1]s\", DoCustomTrampolineWithThunk_%[1]s}", name)) 3726 } 3727 // Data structures in vkEnumerate{Device,Instance}ExtensionProperties are compatible, 3728 // but we need to filter out unsupported extensions. 3729 if params_are_compatible && name != "vkEnumerateDeviceExtensionProperties" && name != "vkEnumerateInstanceExtensionProperties" { 3730 command_wrappers = append(command_wrappers, fmt.Sprintf( 3731 "{\"%[1]s\", [](GuestAddr pc) { return WrapGuestFunctionImpl(pc, kGuestFunctionWrapperSignature<%[2]s>, RunGuestCall, \"%[1]s\"); }}", 3732 name, 3733 command.Name(guest_arch))) 3734 } else { 3735 command_wrappers = append(command_wrappers, fmt.Sprintf( 3736 "{\"%[1]s\", [](GuestAddr pc) { return WrapGuestFunctionImpl(pc, kGuestFunctionWrapperSignature<%[2]s>, RunGuest_%[1]s, \"%[1]s\"); }}", 3737 name, 3738 command.Name(guest_arch))) 3739 } 3740 } 3741 _, err = fmt.Fprintf(w, `auto& GetMapForvkGetProcAddr() { 3742 static constexpr std::array<NamedTrampolineFunc, %[1]d> map{ 3743 {%[2]s}}; 3744 static_assert(IsSorted(std::begin(map), std::end(map), StrCmpLessName)); 3745 return map; 3746} 3747 3748auto& GetMapForRunGuestvkGetInstanceProcAddr() { 3749 static constexpr std::array<NamedGuestFunctionWrapper, %[1]d> map{ 3750 {%[3]s}}; 3751 static_assert(IsSorted(std::begin(map), std::end(map), StrCmpLessName)); 3752 return map; 3753} 3754 3755`, 3756 len(sorted_command_names), 3757 strings.Join(command_trampolines, ",\n "), 3758 strings.Join(command_wrappers, ",\n ")) 3759 if err != nil { 3760 return err 3761 } 3762 return nil 3763} 3764 3765// The same name as in generator.py in vulkan_headers package 3766func toEnumNameWithSuffix(name, mark string) string { 3767 split_point := len(name) 3768 for isAsciiUpperCase(rune(name[split_point-1])) { 3769 split_point-- 3770 if split_point == 0 { 3771 split_point = len(name) 3772 break 3773 } 3774 } 3775 var enum_name_with_suffix string 3776 for _, runе := range name[0:split_point] { 3777 if isAsciiUpperCase(runе) && 3778 len(enum_name_with_suffix) > 0 && 3779 isAsciiLowerCase(rune(enum_name_with_suffix[len(enum_name_with_suffix)-1])) { 3780 enum_name_with_suffix += string('_') 3781 } 3782 enum_name_with_suffix += string(runе) 3783 } 3784 enum_name_with_suffix += "_" + mark 3785 if split_point != len(name) { 3786 enum_name_with_suffix += "_" + name[split_point:] 3787 } 3788 return strings.ToUpper(enum_name_with_suffix) 3789} 3790 3791func isAsciiUpperCase(runе rune) bool { 3792 return 'A' <= runе && runе <= 'Z' 3793} 3794 3795func isAsciiLowerCase(runе rune) bool { 3796 return '0' <= runе && runе <= '9' || 'a' <= runе && runе <= 'z' || runе == '_' 3797} 3798 3799func isInputCompatible(typе cpp_types.Type, host_arch, guest_arch cpp_types.Arch) bool { 3800 if isPtrToAlias(typе) { 3801 return isInputCompatible(typе.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch), host_arch, guest_arch) 3802 } 3803 if isPtrToConstAlias(typе) { 3804 return isInputCompatible(typе.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch), host_arch, guest_arch) 3805 } 3806 if isPtrToStruct(typе) { 3807 return isInputCompatible(typе.Elem(cpp_types.FirstArch), host_arch, guest_arch) 3808 } 3809 if isPtrToConstStruct(typе) { 3810 return isInputCompatible(typе.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch), host_arch, guest_arch) 3811 } 3812 // TODO(b/171255170): remove when arrays conversion in optional structures would be supported. 3813 if typе.Name(cpp_types.FirstArch) == "struct VkDrmFormatModifierProperties2EXT" { 3814 return true 3815 } 3816 // TODO(b/171255170): remove when conversion of optional structures in callbacks would be supported. 3817 if typе.Name(cpp_types.FirstArch) == "struct VkDebugUtilsMessengerCallbackDataEXT" || typе.Name(cpp_types.FirstArch) == "struct VkDeviceMemoryReportCallbackDataEXT" { 3818 return true 3819 } 3820 // TODO(b/322902403): Make VkGetLatencyMarkerInfoNV work with berberis. 3821 if typе.Name(cpp_types.FirstArch) == "struct VkGetLatencyMarkerInfoNV" { 3822 return true 3823 } 3824 if typе.Name(cpp_types.FirstArch) == "struct VkLatencyTimingsFrameReportNV" { 3825 return true 3826 } 3827 // TODO(b/322902053): Make VkFaultCallbackInfo work with berberis. 3828 if typе.Name(cpp_types.FirstArch) == "struct VkFaultData" { 3829 return true 3830 } 3831 // TODO(b/322902400): Make VkDescriptorBufferBindingInfoEXT work with berberis. 3832 if typе.Name(cpp_types.FirstArch) == "struct VkDescriptorBufferBindingInfoEXT" { 3833 return true 3834 } 3835 // If structure is extensible then it may always be extended with incompatible extension via it's “pNext” field 3836 if isExtensibleType(typе) { 3837 return false 3838 } 3839 return cpp_types.IsInputCompatible(typе, host_arch, guest_arch) 3840} 3841 3842func isExtensibleType(typе cpp_types.Type) bool { 3843 if isPtrToAlias(typе) { 3844 return isExtensibleType(typе.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch)) 3845 } 3846 if isPtrToConstAlias(typе) { 3847 return isExtensibleType(typе.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch)) 3848 } 3849 if isPtrToStruct(typе) { 3850 return isExtensibleType(typе.Elem(cpp_types.FirstArch)) 3851 } 3852 if isPtrToConstStruct(typе) { 3853 return isExtensibleType(typе.Elem(cpp_types.FirstArch).Elem(cpp_types.FirstArch)) 3854 } 3855 if isStruct(typе) && 3856 (typе.(vulkan_xml.ExtendedStructInfo).OptionalStruct() || 3857 (typе.Field(0, cpp_types.FirstArch).Name() == "sType" && typе.Field(1, cpp_types.FirstArch).Name() == "pNext")) { 3858 return true 3859 } 3860 // Union or struct by itself may not be extensible, but it may include pointers to structs that are extensible, we have to check for that case, too. 3861 if isUnion(typе) || isStruct(typе) { 3862 ids := typе.NumField(cpp_types.FirstArch) 3863 for id := uint(0); id < ids; id++ { 3864 if isExtensibleType(typе.Field(id, cpp_types.FirstArch).Type()) { 3865 return true 3866 } 3867 } 3868 } 3869 return false 3870} 3871 3872func isAlias(typе cpp_types.Type) bool { 3873 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Alias}) 3874} 3875 3876func isAliasOfEnum(typе cpp_types.Type) bool { 3877 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Alias, cpp_types.Enum}) 3878} 3879 3880func isAliasOfOpaque(typе cpp_types.Type) bool { 3881 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Alias, cpp_types.Opaque}) 3882} 3883 3884func isArray(typе cpp_types.Type) bool { 3885 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Array}) 3886} 3887 3888func isConst(typе cpp_types.Type) bool { 3889 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Const}) 3890} 3891 3892func isConstPtr(typе cpp_types.Type) bool { 3893 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Const, cpp_types.Ptr}) 3894} 3895 3896func isConstPtrToFunc(typе cpp_types.Type) bool { 3897 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Const, cpp_types.Ptr, cpp_types.Func}) 3898} 3899 3900func isEnum(typе cpp_types.Type) bool { 3901 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Enum}) 3902} 3903 3904func isFunc(typе cpp_types.Type) bool { 3905 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Func}) 3906} 3907 3908func isInt8T(typе cpp_types.Type) bool { 3909 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Int8T}) 3910} 3911 3912func isInt16T(typе cpp_types.Type) bool { 3913 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Int16T}) 3914} 3915 3916func isInt32T(typе cpp_types.Type) bool { 3917 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Int32T}) 3918} 3919 3920func isInt64T(typе cpp_types.Type) bool { 3921 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Int64T}) 3922} 3923 3924func isPtr(typе cpp_types.Type) bool { 3925 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr}) 3926} 3927 3928func isPtrToAlias(typе cpp_types.Type) bool { 3929 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Alias}) 3930} 3931 3932func isPtrToConstAlias(typе cpp_types.Type) bool { 3933 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Const, cpp_types.Alias}) 3934} 3935 3936func isPtrToConst(typе cpp_types.Type) bool { 3937 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Const}) 3938} 3939 3940func isPtrToConstOpaque(typе cpp_types.Type) bool { 3941 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Const, cpp_types.Opaque}) 3942} 3943 3944func isPtrToConstStruct(typе cpp_types.Type) bool { 3945 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Const, cpp_types.Struct}) 3946} 3947 3948func isPtrToFunc(typе cpp_types.Type) bool { 3949 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Func}) 3950} 3951 3952func isPtrToOpaque(typе cpp_types.Type) bool { 3953 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Opaque}) 3954} 3955 3956func isPtrToStruct(typе cpp_types.Type) bool { 3957 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Ptr, cpp_types.Struct}) 3958} 3959 3960func isStruct(typе cpp_types.Type) bool { 3961 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Struct}) 3962} 3963 3964func isUInt8T(typе cpp_types.Type) bool { 3965 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.UInt8T}) 3966} 3967 3968func isUInt16T(typе cpp_types.Type) bool { 3969 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.UInt16T}) 3970} 3971 3972func isUInt32T(typе cpp_types.Type) bool { 3973 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.UInt32T}) 3974} 3975 3976func isUInt64T(typе cpp_types.Type) bool { 3977 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.UInt64T}) 3978} 3979 3980func isUnion(typе cpp_types.Type) bool { 3981 return cpp_types.IsKind(typе, []cpp_types.Kind{cpp_types.Union}) 3982} 3983 3984func toIntVal(b bool) int { 3985 if b { 3986 return 1 3987 } else { 3988 return 0 3989 } 3990} 3991