• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2025 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Generates the vkjson files.
18"""
19import dataclasses
20import os
21import re
22from typing import get_origin
23
24import generator_common as gencom
25import vk as VK
26
27dataclass_field = dataclasses.field
28
29
30COPYRIGHT_WARNINGS = """///////////////////////////////////////////////////////////////////////////////
31//
32// Copyright (c) 2015-2016 The Khronos Group Inc.
33// Copyright (c) 2015-2016 Valve Corporation
34// Copyright (c) 2015-2016 LunarG, Inc.
35// Copyright (c) 2015-2016 Google, Inc.
36//
37// Licensed under the Apache License, Version 2.0 (the "License");
38// you may not use this file except in compliance with the License.
39// You may obtain a copy of the License at
40//
41//     http://www.apache.org/licenses/LICENSE-2.0
42//
43// Unless required by applicable law or agreed to in writing, software
44// distributed under the License is distributed on an "AS IS" BASIS,
45// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46// See the License for the specific language governing permissions and
47// limitations under the License.
48///////////////////////////////////////////////////////////////////////////////
49"""
50
51
52def get_copyright_warnings():
53  return COPYRIGHT_WARNINGS
54
55
56def get_vkjson_struct_name(extension_name):
57  """Gets the corresponding structure name from a Vulkan extension name.
58  Example: "VK_KHR_shader_float16_int8" → "VkJsonKHRShaderFloat16Int8"
59  """
60  prefix_map = {
61    "VK_KHR": "VkJsonKHR",
62    "VK_EXT": "VkJsonExt",
63    "VK_IMG": "VkJsonIMG"
64  }
65
66  for prefix, replacement in prefix_map.items():
67    if extension_name.startswith(prefix):
68      struct_name = replacement + extension_name[len(prefix):]
69      break
70  else:
71    struct_name = f"VkJsonExt{extension_name}"
72
73  # Convert underscores to camel case
74  # Example: "VK_KHR_shader_float16_int8" → "VkJsonKHRShaderFloat16Int8"
75  struct_name = re.sub(r"_(.)", lambda m: m.group(1).upper(), struct_name)
76
77  return struct_name
78
79
80def get_vkjson_struct_variable_name(extension_name):
81  """Gets corresponding instance name from a Vulkan extension name.
82  Example: "VK_KHR_shader_float16_int8" → "khr_shader_float16_int8"
83  """
84  prefix_map = {
85    "VK_KHR_": "khr_",
86    "VK_EXT_": "ext_",
87    "VK_IMG_": "img_"
88  }
89
90  for prefix, replacement in prefix_map.items():
91    if extension_name.startswith(prefix):
92      return replacement + extension_name[len(prefix):]
93
94  return extension_name.lower()  # Default case if no known prefix matches
95
96
97def get_struct_name(struct_name):
98  """Gets corresponding instance name
99  Example: "VkPhysicalDeviceShaderFloat16Int8FeaturesKHR" → "shader_float16_int8_features_khr"
100  """
101  # Remove "VkPhysicalDevice" prefix and any of the known suffixes
102  base_name = struct_name.removeprefix("VkPhysicalDevice").removesuffix("KHR").removesuffix("EXT").removesuffix("IMG")
103
104  # Convert CamelCase to snake_case
105  # Example: "ShaderFloat16Int8Features" → "shader_float16_int8_features"
106  variable_name = re.sub(r"(?<!^)(?=[A-Z])", "_", base_name).lower()
107
108  # Fix special cases
109  variable_name = variable_name.replace("2_d_", "_2d_").replace("3_d_", "_3d_")
110
111  # Add back the correct suffix if it was removed
112  suffix_map = {"KHR": "_khr", "EXT": "_ext", "IMG": "_img"}
113  for suffix, replacement in suffix_map.items():
114    if struct_name.endswith(suffix):
115      variable_name += replacement
116      break
117
118  # Handle specific exceptions
119  special_cases = {
120    "8_bit_storage_features_khr": "bit8_storage_features_khr",
121    "memory_properties": "memory",
122    "16_bit_storage_features": "bit16_storage_features",
123    "i_d_properties": "id_properties"
124  }
125
126  return special_cases.get(variable_name, variable_name)
127
128
129def generate_extension_struct_definition(f):
130  """Generates struct definition code for extension based structs
131  Example:
132  struct VkJsonKHRShaderFloatControls {
133    VkJsonKHRShaderFloatControls() {
134      reported = false;
135      memset(&float_controls_properties_khr, 0,
136            sizeof(VkPhysicalDeviceFloatControlsPropertiesKHR));
137    }
138    bool reported;
139    VkPhysicalDeviceFloatControlsPropertiesKHR float_controls_properties_khr;
140  };
141  """
142  vkJson_entries = []
143
144  for extension_name, struct_list in VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"].items():
145    vkjson_struct_name = get_vkjson_struct_name(extension_name)
146    vkjson_struct_variable_name = get_vkjson_struct_variable_name(extension_name)
147    vkJson_entries.append(f"{vkjson_struct_name} {vkjson_struct_variable_name}")
148
149    struct_entries = []
150
151    f.write(f"struct {vkjson_struct_name} {{\n")
152    f.write(f"  {vkjson_struct_name}() {{\n")
153    f.write("    reported = false;\n")
154
155    for struct_map in struct_list:
156      for struct_name, _ in struct_map.items():
157        variable_name = get_struct_name(struct_name)
158        f.write(f"    memset(&{variable_name}, 0, sizeof({struct_name}));\n")
159        struct_entries.append(f"{struct_name} {variable_name}")
160
161    f.write("  }\n")  # End of constructor
162    f.write("  bool reported;\n")
163
164    for entry in struct_entries:
165      f.write(f"  {entry};\n")
166
167    f.write("};\n\n")  # End of struct
168
169  return vkJson_entries
170
171
172def generate_vk_core_struct_definition(f):
173  """Generates struct definition code for vulkan cores
174  Example:
175  struct VkJsonCore11 {
176    VkPhysicalDeviceVulkan11Properties properties;
177    VkPhysicalDeviceVulkan11Features features;
178  };
179  """
180  vkJson_core_entries = []
181
182  for version, items in VK.VULKAN_CORES_AND_STRUCTS_MAPPING["versions"].items():
183    struct_name = f"VkJson{version}"
184    vkJson_core_entries.append(f"{struct_name} {version.lower()}")
185
186    f.write(f"struct {struct_name} {{\n")
187    f.write(f"  {struct_name}() {{\n") # Start of constructor
188    for item in items:
189      for struct_type, _ in item.items():
190        field_name = "properties" if "Properties" in struct_type else "features"
191        f.write(f" memset(&{field_name}, 0, sizeof({struct_type}));\n")
192    f.write("  }\n")  # End of constructor
193
194    for item in items:
195      for struct_type, _ in item.items():
196        field_name = "properties" if "Properties" in struct_type else "features"
197        f.write(f"  {struct_type} {field_name};\n")
198
199    if version == "Core14":
200      f.write(f"std::vector<VkImageLayout> copy_src_layouts;\n")
201      f.write(f"std::vector<VkImageLayout> copy_dst_layouts;\n")
202
203    f.write("};\n\n")
204
205  return vkJson_core_entries
206
207
208def generate_memset_statements(f):
209  """Generates memset statements for all independent Vulkan structs and core Vulkan versions.
210  This initializes struct instances to zero before use.
211
212  Example:
213    memset(&properties, 0, sizeof(VkPhysicalDeviceProperties));
214    VkPhysicalDeviceProperties properties;
215  """
216  entries = []
217
218  # Process independent structs
219  for dataclass_type in VK.EXTENSION_INDEPENDENT_STRUCTS:
220    class_name = dataclass_type.__name__
221    variable_name = get_struct_name(class_name)
222    f.write(f"memset(&{variable_name}, 0, sizeof({class_name}));\n")
223    entries.append(f"{class_name} {variable_name}")
224
225  return entries
226
227
228def gen_h():
229  """Generates vkjson.h file.
230  """
231  genfile = os.path.join(os.path.dirname(__file__),
232                         "..", "vkjson", "vkjson.h")
233
234  with open(genfile, "w") as f:
235    f.write(f'{get_copyright_warnings()}\n')
236
237    f.write("""\
238#ifndef VKJSON_H_
239#define VKJSON_H_
240
241#include <string.h>
242#include <vulkan/vulkan.h>
243
244#include <map>
245#include <string>
246#include <vector>
247
248#ifdef WIN32
249#undef min
250#undef max
251#endif
252
253/*
254 * This file is autogenerated by vkjson_generator.py. Do not edit directly.
255 */
256struct VkJsonLayer {
257  VkLayerProperties properties;
258  std::vector<VkExtensionProperties> extensions;
259};
260
261\n""")
262
263    vkjson_extension_structs = generate_extension_struct_definition(f)
264    vkjson_core_structs = generate_vk_core_struct_definition(f)
265
266    f.write("""\
267struct VkJsonDevice {
268  VkJsonDevice() {""")
269
270    feature_property_structs = generate_memset_statements(f)
271
272    f.write("""\
273  }\n""")
274    for struct_entries in (vkjson_extension_structs, vkjson_core_structs, feature_property_structs):
275      for entry in struct_entries:
276        f.write(entry + ";\n")
277
278    f.write("""\
279  std::vector<VkQueueFamilyProperties> queues;
280  std::vector<VkExtensionProperties> extensions;
281  std::vector<VkLayerProperties> layers;
282  std::map<VkFormat, VkFormatProperties> formats;
283  std::map<VkExternalFenceHandleTypeFlagBits, VkExternalFenceProperties>
284      external_fence_properties;
285  std::map<VkExternalSemaphoreHandleTypeFlagBits, VkExternalSemaphoreProperties>
286      external_semaphore_properties;
287};
288
289struct VkJsonDeviceGroup {
290  VkJsonDeviceGroup() {
291    memset(&properties, 0, sizeof(VkPhysicalDeviceGroupProperties));
292  }
293  VkPhysicalDeviceGroupProperties properties;
294  std::vector<uint32_t> device_inds;
295};
296
297struct VkJsonInstance {
298  VkJsonInstance() : api_version(0) {}
299  uint32_t api_version;
300  std::vector<VkJsonLayer> layers;
301  std::vector<VkExtensionProperties> extensions;
302  std::vector<VkJsonDevice> devices;
303  std::vector<VkJsonDeviceGroup> device_groups;
304};
305
306VkJsonInstance VkJsonGetInstance();
307std::string VkJsonInstanceToJson(const VkJsonInstance& instance);
308bool VkJsonInstanceFromJson(const std::string& json,
309                            VkJsonInstance* instance,
310                            std::string* errors);
311
312VkJsonDevice VkJsonGetDevice(VkPhysicalDevice device);
313std::string VkJsonDeviceToJson(const VkJsonDevice& device);
314bool VkJsonDeviceFromJson(const std::string& json,
315                          VkJsonDevice* device,
316                          std::string* errors);
317
318std::string VkJsonImageFormatPropertiesToJson(
319    const VkImageFormatProperties& properties);
320bool VkJsonImageFormatPropertiesFromJson(const std::string& json,
321                                         VkImageFormatProperties* properties,
322                                         std::string* errors);
323
324// Backward-compatibility aliases
325typedef VkJsonDevice VkJsonAllProperties;
326inline VkJsonAllProperties VkJsonGetAllProperties(
327    VkPhysicalDevice physicalDevice) {
328  return VkJsonGetDevice(physicalDevice);
329}
330inline std::string VkJsonAllPropertiesToJson(
331    const VkJsonAllProperties& properties) {
332  return VkJsonDeviceToJson(properties);
333}
334inline bool VkJsonAllPropertiesFromJson(const std::string& json,
335                                        VkJsonAllProperties* properties,
336                                        std::string* errors) {
337  return VkJsonDeviceFromJson(json, properties, errors);
338}
339
340#endif  // VKJSON_H_""")
341
342    f.close()
343  gencom.run_clang_format(genfile)
344
345
346def generate_extension_struct_template():
347  """Generates templates for extensions
348  Example:
349    template <typename Visitor>
350    inline bool Iterate(Visitor* visitor, VkJsonKHRVariablePointers* structs) {
351      return visitor->Visit("variablePointerFeaturesKHR",
352                            &structs->variable_pointer_features_khr) &&
353            visitor->Visit("variablePointersFeaturesKHR",
354                            &structs->variable_pointers_features_khr);
355    }
356  """
357  template_code = []
358
359  for extension, struct_mappings in VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"].items():
360    struct_type = get_vkjson_struct_name(extension)
361
362    template_code.append(f"template <typename Visitor>")
363    template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_type}* structs) {{")
364    template_code.append("  return ")
365
366    visitor_calls = []
367    for struct_map in struct_mappings:
368      for struct_name in struct_map:
369        json_field_name = struct_name.replace("VkPhysicalDevice", "")
370        json_field_name = json_field_name[0].lower() + json_field_name[1:]
371
372        # Special case renaming
373        if json_field_name == "8BitStorageFeaturesKHR":
374          json_field_name = "bit8StorageFeaturesKHR"
375
376        visitor_calls.append(
377            f'visitor->Visit("{json_field_name}", &structs->{get_struct_name(struct_name)})'
378        )
379
380    template_code.append(" &&\n         ".join(visitor_calls) + ";")
381    template_code.append("}\n")
382
383  return "\n".join(template_code)
384
385
386def generate_core_template():
387  """Generates templates for vulkan cores.
388  template <typename Visitor>
389  inline bool Iterate(Visitor* visitor, VkJsonCore11* core) {
390    return visitor->Visit("properties", &core->properties) &&
391          visitor->Visit("features", &core->features);
392  }
393  """
394  template_code = []
395
396  for version, struct_list in VK.VULKAN_CORES_AND_STRUCTS_MAPPING["versions"].items():
397    struct_type = f"VkJson{version}"
398
399    template_code.append(f"template <typename Visitor>")
400    template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_type}* core) {{")
401    template_code.append("  return")
402
403    visitor_calls = []
404    for struct_map in struct_list:
405      for struct_name in struct_map:
406        member_name = "properties" if "Properties" in struct_name else "features"
407        visitor_calls.append(f'visitor->Visit("{member_name}", &core->{member_name})')
408
409    template_code.append(" &&\n         ".join(visitor_calls) + ";")
410    template_code.append("}\n")
411
412  return "\n".join(template_code)
413
414
415def generate_struct_template(data_classes):
416  """Generates templates for all the structs
417  template <typename Visitor>
418  inline bool Iterate(Visitor* visitor,
419                      VkPhysicalDevicePointClippingProperties* properties) {
420    return visitor->Visit("pointClippingBehavior",
421                          &properties->pointClippingBehavior);
422  }
423  """
424  template_code = []
425  processed_classes = set()  # Track processed class names
426
427  for dataclass_type in data_classes:
428    struct_name = dataclass_type.__name__
429
430    if struct_name in processed_classes:
431      continue  # Skip already processed struct
432    processed_classes.add(struct_name)
433
434    struct_fields = dataclasses.fields(dataclass_type)
435    template_code.append("template <typename Visitor>")
436
437    # Determine the correct variable name based on the struct type
438    struct_var = "properties" if "Properties" in struct_name else "features" if "Features" in struct_name else "limits" if "Limits" in struct_name else None
439
440    if not struct_var:
441      continue  # Skip structs that don't match expected patterns
442
443    template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_name}* {struct_var}) {{")
444    template_code.append(f"return\n")
445
446    visitor_calls = []
447    for struct_field in struct_fields:
448      field_name = struct_field.name
449      field_type = struct_field.type
450
451      if get_origin(field_type) is list:
452        # Handle list types (VisitArray)
453        size_field_name = VK.LIST_TYPE_FIELD_AND_SIZE_MAPPING[field_name]
454        visitor_calls.append(f'visitor->VisitArray("{field_name}", {struct_var}->{size_field_name}, &{struct_var}->{field_name})')
455      else:
456        # Handle other types (Visit)
457        visitor_calls.append(f'visitor->Visit("{field_name}", &{struct_var}->{field_name})')
458
459    template_code.append(" &&\n         ".join(visitor_calls) + ";")
460    template_code.append("}\n\n")
461
462  return "\n".join(template_code)
463
464
465def emit_struct_visits_by_vk_version(f, version):
466  """Emits visitor calls for Vulkan version structs
467  """
468  for struct_map in VK.VULKAN_VERSIONS_AND_STRUCTS_MAPPING[version]:
469    for struct_name, _ in struct_map.items():
470      struct_var = get_struct_name(struct_name)
471      # Converts struct_var from snake_case (e.g., point_clipping_properties)
472      # to camelCase (e.g., pointClippingProperties) for struct_display_name.
473      struct_display_name = re.sub(r"_([a-z])", lambda match: match.group(1).upper(), struct_var)
474      f.write(f'visitor->Visit("{struct_display_name}", &device->{struct_var}) &&\n')
475
476
477def gen_cc():
478  """Generates vkjson.cc file.
479  """
480  genfile = os.path.join(os.path.dirname(__file__),
481                         "..", "vkjson", "vkjson.cc")
482
483  with open(genfile, "w") as f:
484
485    f.write(get_copyright_warnings())
486    f.write("\n")
487
488    f.write("""\
489#include "vkjson.h"
490
491#include <assert.h>
492#include <stdlib.h>
493#include <string.h>
494
495#include <json/json.h>
496
497#include <algorithm>
498#include <cinttypes>
499#include <cmath>
500#include <cstdio>
501#include <limits>
502#include <memory>
503#include <sstream>
504#include <type_traits>
505#include <utility>
506
507/*
508 * This file is autogenerated by vkjson_generator.py. Do not edit directly.
509 */
510namespace {
511
512/*
513 * Annotation to tell clang that we intend to fall through from one case to
514 * another in a switch. Sourced from android-base/macros.h.
515 */
516#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
517
518inline bool IsIntegral(double value) {
519#if defined(ANDROID)
520  // Android NDK doesn't provide std::trunc yet
521  return trunc(value) == value;
522#else
523  return std::trunc(value) == value;
524#endif
525}
526
527// Floating point fields of Vulkan structure use single precision. The string
528// output of max double value in c++ will be larger than Java double's infinity
529// value. Below fake double max/min values are only to serve the safe json text
530// parsing in between C++ and Java, because Java json library simply cannot
531// handle infinity.
532static const double SAFE_DOUBLE_MAX = 0.99 * std::numeric_limits<double>::max();
533static const double SAFE_DOUBLE_MIN = -SAFE_DOUBLE_MAX;
534
535template <typename T> struct EnumTraits;
536template <> struct EnumTraits<VkPhysicalDeviceType> {
537  static bool exist(uint32_t e) {
538    switch (e) {
539      case VK_PHYSICAL_DEVICE_TYPE_OTHER:
540      case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
541      case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
542      case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
543      case VK_PHYSICAL_DEVICE_TYPE_CPU:
544        return true;
545    }
546    return false;
547  }
548};
549
550template <> struct EnumTraits<VkFormat> {
551  static bool exist(uint32_t e) {
552    switch (e) {
553      case VK_FORMAT_UNDEFINED:
554      case VK_FORMAT_R4G4_UNORM_PACK8:
555      case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
556      case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
557      case VK_FORMAT_R5G6B5_UNORM_PACK16:
558      case VK_FORMAT_B5G6R5_UNORM_PACK16:
559      case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
560      case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
561      case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
562      case VK_FORMAT_R8_UNORM:
563      case VK_FORMAT_R8_SNORM:
564      case VK_FORMAT_R8_USCALED:
565      case VK_FORMAT_R8_SSCALED:
566      case VK_FORMAT_R8_UINT:
567      case VK_FORMAT_R8_SINT:
568      case VK_FORMAT_R8_SRGB:
569      case VK_FORMAT_R8G8_UNORM:
570      case VK_FORMAT_R8G8_SNORM:
571      case VK_FORMAT_R8G8_USCALED:
572      case VK_FORMAT_R8G8_SSCALED:
573      case VK_FORMAT_R8G8_UINT:
574      case VK_FORMAT_R8G8_SINT:
575      case VK_FORMAT_R8G8_SRGB:
576      case VK_FORMAT_R8G8B8_UNORM:
577      case VK_FORMAT_R8G8B8_SNORM:
578      case VK_FORMAT_R8G8B8_USCALED:
579      case VK_FORMAT_R8G8B8_SSCALED:
580      case VK_FORMAT_R8G8B8_UINT:
581      case VK_FORMAT_R8G8B8_SINT:
582      case VK_FORMAT_R8G8B8_SRGB:
583      case VK_FORMAT_B8G8R8_UNORM:
584      case VK_FORMAT_B8G8R8_SNORM:
585      case VK_FORMAT_B8G8R8_USCALED:
586      case VK_FORMAT_B8G8R8_SSCALED:
587      case VK_FORMAT_B8G8R8_UINT:
588      case VK_FORMAT_B8G8R8_SINT:
589      case VK_FORMAT_B8G8R8_SRGB:
590      case VK_FORMAT_R8G8B8A8_UNORM:
591      case VK_FORMAT_R8G8B8A8_SNORM:
592      case VK_FORMAT_R8G8B8A8_USCALED:
593      case VK_FORMAT_R8G8B8A8_SSCALED:
594      case VK_FORMAT_R8G8B8A8_UINT:
595      case VK_FORMAT_R8G8B8A8_SINT:
596      case VK_FORMAT_R8G8B8A8_SRGB:
597      case VK_FORMAT_B8G8R8A8_UNORM:
598      case VK_FORMAT_B8G8R8A8_SNORM:
599      case VK_FORMAT_B8G8R8A8_USCALED:
600      case VK_FORMAT_B8G8R8A8_SSCALED:
601      case VK_FORMAT_B8G8R8A8_UINT:
602      case VK_FORMAT_B8G8R8A8_SINT:
603      case VK_FORMAT_B8G8R8A8_SRGB:
604      case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
605      case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
606      case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
607      case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
608      case VK_FORMAT_A8B8G8R8_UINT_PACK32:
609      case VK_FORMAT_A8B8G8R8_SINT_PACK32:
610      case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
611      case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
612      case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
613      case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
614      case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
615      case VK_FORMAT_A2R10G10B10_UINT_PACK32:
616      case VK_FORMAT_A2R10G10B10_SINT_PACK32:
617      case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
618      case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
619      case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
620      case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
621      case VK_FORMAT_A2B10G10R10_UINT_PACK32:
622      case VK_FORMAT_A2B10G10R10_SINT_PACK32:
623      case VK_FORMAT_R16_UNORM:
624      case VK_FORMAT_R16_SNORM:
625      case VK_FORMAT_R16_USCALED:
626      case VK_FORMAT_R16_SSCALED:
627      case VK_FORMAT_R16_UINT:
628      case VK_FORMAT_R16_SINT:
629      case VK_FORMAT_R16_SFLOAT:
630      case VK_FORMAT_R16G16_UNORM:
631      case VK_FORMAT_R16G16_SNORM:
632      case VK_FORMAT_R16G16_USCALED:
633      case VK_FORMAT_R16G16_SSCALED:
634      case VK_FORMAT_R16G16_UINT:
635      case VK_FORMAT_R16G16_SINT:
636      case VK_FORMAT_R16G16_SFLOAT:
637      case VK_FORMAT_R16G16B16_UNORM:
638      case VK_FORMAT_R16G16B16_SNORM:
639      case VK_FORMAT_R16G16B16_USCALED:
640      case VK_FORMAT_R16G16B16_SSCALED:
641      case VK_FORMAT_R16G16B16_UINT:
642      case VK_FORMAT_R16G16B16_SINT:
643      case VK_FORMAT_R16G16B16_SFLOAT:
644      case VK_FORMAT_R16G16B16A16_UNORM:
645      case VK_FORMAT_R16G16B16A16_SNORM:
646      case VK_FORMAT_R16G16B16A16_USCALED:
647      case VK_FORMAT_R16G16B16A16_SSCALED:
648      case VK_FORMAT_R16G16B16A16_UINT:
649      case VK_FORMAT_R16G16B16A16_SINT:
650      case VK_FORMAT_R16G16B16A16_SFLOAT:
651      case VK_FORMAT_R32_UINT:
652      case VK_FORMAT_R32_SINT:
653      case VK_FORMAT_R32_SFLOAT:
654      case VK_FORMAT_R32G32_UINT:
655      case VK_FORMAT_R32G32_SINT:
656      case VK_FORMAT_R32G32_SFLOAT:
657      case VK_FORMAT_R32G32B32_UINT:
658      case VK_FORMAT_R32G32B32_SINT:
659      case VK_FORMAT_R32G32B32_SFLOAT:
660      case VK_FORMAT_R32G32B32A32_UINT:
661      case VK_FORMAT_R32G32B32A32_SINT:
662      case VK_FORMAT_R32G32B32A32_SFLOAT:
663      case VK_FORMAT_R64_UINT:
664      case VK_FORMAT_R64_SINT:
665      case VK_FORMAT_R64_SFLOAT:
666      case VK_FORMAT_R64G64_UINT:
667      case VK_FORMAT_R64G64_SINT:
668      case VK_FORMAT_R64G64_SFLOAT:
669      case VK_FORMAT_R64G64B64_UINT:
670      case VK_FORMAT_R64G64B64_SINT:
671      case VK_FORMAT_R64G64B64_SFLOAT:
672      case VK_FORMAT_R64G64B64A64_UINT:
673      case VK_FORMAT_R64G64B64A64_SINT:
674      case VK_FORMAT_R64G64B64A64_SFLOAT:
675      case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
676      case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
677      case VK_FORMAT_D16_UNORM:
678      case VK_FORMAT_X8_D24_UNORM_PACK32:
679      case VK_FORMAT_D32_SFLOAT:
680      case VK_FORMAT_S8_UINT:
681      case VK_FORMAT_D16_UNORM_S8_UINT:
682      case VK_FORMAT_D24_UNORM_S8_UINT:
683      case VK_FORMAT_D32_SFLOAT_S8_UINT:
684      case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
685      case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
686      case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
687      case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
688      case VK_FORMAT_BC2_UNORM_BLOCK:
689      case VK_FORMAT_BC2_SRGB_BLOCK:
690      case VK_FORMAT_BC3_UNORM_BLOCK:
691      case VK_FORMAT_BC3_SRGB_BLOCK:
692      case VK_FORMAT_BC4_UNORM_BLOCK:
693      case VK_FORMAT_BC4_SNORM_BLOCK:
694      case VK_FORMAT_BC5_UNORM_BLOCK:
695      case VK_FORMAT_BC5_SNORM_BLOCK:
696      case VK_FORMAT_BC6H_UFLOAT_BLOCK:
697      case VK_FORMAT_BC6H_SFLOAT_BLOCK:
698      case VK_FORMAT_BC7_UNORM_BLOCK:
699      case VK_FORMAT_BC7_SRGB_BLOCK:
700      case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
701      case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
702      case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
703      case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
704      case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
705      case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
706      case VK_FORMAT_EAC_R11_UNORM_BLOCK:
707      case VK_FORMAT_EAC_R11_SNORM_BLOCK:
708      case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
709      case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
710      case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
711      case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
712      case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
713      case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
714      case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
715      case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
716      case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
717      case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
718      case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
719      case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
720      case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
721      case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
722      case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
723      case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
724      case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
725      case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
726      case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
727      case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
728      case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
729      case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
730      case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
731      case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
732      case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
733      case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
734      case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
735      case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
736      case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
737      case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
738      case VK_FORMAT_G8B8G8R8_422_UNORM:
739      case VK_FORMAT_B8G8R8G8_422_UNORM:
740      case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
741      case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
742      case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
743      case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
744      case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
745      case VK_FORMAT_R10X6_UNORM_PACK16:
746      case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
747      case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
748      case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
749      case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
750      case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
751      case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
752      case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
753      case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
754      case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
755      case VK_FORMAT_R12X4_UNORM_PACK16:
756      case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
757      case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
758      case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
759      case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
760      case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
761      case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
762      case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
763      case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
764      case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
765      case VK_FORMAT_G16B16G16R16_422_UNORM:
766      case VK_FORMAT_B16G16R16G16_422_UNORM:
767      case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
768      case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
769      case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
770      case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
771      case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
772      case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
773      case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
774      case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
775      case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
776      case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
777      case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
778      case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
779      case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
780      case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
781      case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
782      case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
783      case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
784      case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
785      case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
786      case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
787      case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
788      case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
789      case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
790      case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
791      case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
792      case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
793      case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
794      case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT:
795      case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT:
796        return true;
797    }
798    return false;
799  }
800};
801
802template <>
803struct EnumTraits<VkPointClippingBehavior> {
804  static bool exist(uint32_t e) {
805    switch (e) {
806      case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES:
807      case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY:
808        return true;
809    }
810    return false;
811  }
812};
813
814template <>
815struct EnumTraits<VkExternalFenceHandleTypeFlagBits> {
816  static bool exist(uint32_t e) {
817    switch (e) {
818      case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
819      case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
820      case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
821      case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
822        return true;
823    }
824    return false;
825  }
826};
827
828template <>
829struct EnumTraits<VkExternalSemaphoreHandleTypeFlagBits> {
830  static bool exist(uint32_t e) {
831    switch (e) {
832      case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
833      case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
834      case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
835      case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT:
836      case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
837        return true;
838    }
839    return false;
840  }
841};
842
843template <>
844struct EnumTraits<VkDriverIdKHR> {
845  static bool exist(uint32_t e) {
846    switch (e) {
847      case VK_DRIVER_ID_AMD_PROPRIETARY:
848      case VK_DRIVER_ID_AMD_OPEN_SOURCE:
849      case VK_DRIVER_ID_MESA_RADV:
850      case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
851      case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS:
852      case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
853      case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
854      case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
855      case VK_DRIVER_ID_ARM_PROPRIETARY:
856      case VK_DRIVER_ID_GOOGLE_SWIFTSHADER:
857      case VK_DRIVER_ID_GGP_PROPRIETARY:
858      case VK_DRIVER_ID_BROADCOM_PROPRIETARY:
859      case VK_DRIVER_ID_MESA_LLVMPIPE:
860      case VK_DRIVER_ID_MOLTENVK:
861        return true;
862    }
863    return false;
864  }
865};
866
867template <>
868struct EnumTraits<VkShaderFloatControlsIndependence> {
869  static bool exist(uint32_t e) {
870    switch (e) {
871      case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY:
872      case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL:
873      case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE:
874        return true;
875    }
876    return false;
877  }
878};
879
880template <>
881struct EnumTraits<VkPipelineRobustnessBufferBehavior> {
882  static bool exist(uint32_t e) {
883    switch (e) {
884      case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT:
885      case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED:
886      case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS:
887      case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2:
888        return true;
889    }
890    return false;
891  }
892};
893
894template <>
895struct EnumTraits<VkPipelineRobustnessImageBehavior> {
896  static bool exist(uint32_t e) {
897    switch (e) {
898      case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT:
899      case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED:
900      case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS:
901      case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2:
902        return true;
903    }
904    return false;
905  }
906};
907
908template <>
909struct EnumTraits<VkImageLayout> {
910  static bool exist(uint32_t e) {
911    switch (e) {
912      case VK_IMAGE_LAYOUT_UNDEFINED:
913      case VK_IMAGE_LAYOUT_GENERAL:
914      case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
915      case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
916      case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
917      case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
918      case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
919      case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
920      case VK_IMAGE_LAYOUT_PREINITIALIZED:
921      case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
922      case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
923      case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
924      case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
925      case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
926      case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
927      case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL:
928      case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL:
929      case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
930      case VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR:
931      case VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR:
932      case VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR:
933      case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
934      case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
935      case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR:
936#ifdef VK_ENABLE_BETA_EXTENSIONS
937      case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR:
938#endif
939#ifdef VK_ENABLE_BETA_EXTENSIONS
940      case VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR:
941#endif
942#ifdef VK_ENABLE_BETA_EXTENSIONS
943      case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR:
944#endif
945      case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
946        return true;
947    }
948    return false;
949  }
950};
951
952// VkSparseImageFormatProperties
953
954template <typename Visitor>
955inline bool Iterate(Visitor* visitor, VkExtent3D* extents) {
956  return
957    visitor->Visit("width", &extents->width) &&
958    visitor->Visit("height", &extents->height) &&
959    visitor->Visit("depth", &extents->depth);
960}
961
962template <typename Visitor>
963inline bool Iterate(Visitor* visitor,
964                    VkConformanceVersionKHR* version) {
965  return visitor->Visit("major", &version->major) &&
966         visitor->Visit("minor", &version->minor) &&
967         visitor->Visit("subminor", &version->subminor) &&
968         visitor->Visit("patch", &version->patch);
969}
970
971template <typename Visitor>
972inline bool Iterate(Visitor* visitor, VkMemoryType* type) {
973  return
974    visitor->Visit("propertyFlags", &type->propertyFlags) &&
975    visitor->Visit("heapIndex", &type->heapIndex);
976}
977
978template <typename Visitor>
979inline bool Iterate(Visitor* visitor, VkMemoryHeap* heap) {
980  return
981    visitor->Visit("size", &heap->size) &&
982    visitor->Visit("flags", &heap->flags);
983}\n\n""")
984
985    f.write(f"{generate_core_template()}\n\n{generate_extension_struct_template()}\n\n")
986    f.write(generate_struct_template(VK.ALL_STRUCTS))
987
988    f.write("""\
989template <typename Visitor>
990inline bool Iterate(Visitor* visitor, VkExternalFenceProperties* properties) {
991  return visitor->Visit("exportFromImportedHandleTypes",
992                        &properties->exportFromImportedHandleTypes) &&
993         visitor->Visit("compatibleHandleTypes",
994                        &properties->compatibleHandleTypes) &&
995         visitor->Visit("externalFenceFeatures",
996                        &properties->externalFenceFeatures);
997}
998
999template <typename Visitor>
1000inline bool Iterate(Visitor* visitor,
1001                    VkExternalSemaphoreProperties* properties) {
1002  return visitor->Visit("exportFromImportedHandleTypes",
1003                        &properties->exportFromImportedHandleTypes) &&
1004         visitor->Visit("compatibleHandleTypes",
1005                        &properties->compatibleHandleTypes) &&
1006         visitor->Visit("externalSemaphoreFeatures",
1007                        &properties->externalSemaphoreFeatures);
1008}
1009
1010template <typename Visitor>
1011inline bool Iterate(Visitor* visitor, VkJsonLayer* layer) {
1012  return visitor->Visit("properties", &layer->properties) &&
1013         visitor->Visit("extensions", &layer->extensions);
1014}
1015
1016template <typename Visitor>
1017inline bool Iterate(Visitor* visitor, VkJsonDeviceGroup* device_group) {
1018  return visitor->Visit("devices", &device_group->device_inds) &&
1019         visitor->Visit("subsetAllocation",
1020                        &device_group->properties.subsetAllocation);
1021}
1022
1023template <typename Visitor>
1024inline bool Iterate(Visitor* visitor, VkJsonDevice* device) {
1025  bool ret = true;
1026  switch (device->properties.apiVersion ^
1027          VK_API_VERSION_PATCH(device->properties.apiVersion)) {
1028    case VK_API_VERSION_1_4:
1029      ret &= visitor->Visit("core14", &device->core14);
1030      FALLTHROUGH_INTENDED;
1031    case VK_API_VERSION_1_3:
1032      ret &= visitor->Visit("core13", &device->core13);
1033      FALLTHROUGH_INTENDED;
1034    case VK_API_VERSION_1_2:
1035      ret &= visitor->Visit("core11", &device->core11);
1036      ret &= visitor->Visit("core12", &device->core12);
1037      FALLTHROUGH_INTENDED;
1038    case VK_API_VERSION_1_1:
1039      ret &=\n""")
1040
1041    emit_struct_visits_by_vk_version(f, "VK_VERSION_1_1")
1042
1043    f.write("""\
1044          visitor->Visit("externalFenceProperties",
1045                         &device->external_fence_properties) &&
1046          visitor->Visit("externalSemaphoreProperties",
1047                         &device->external_semaphore_properties);
1048      FALLTHROUGH_INTENDED;
1049    case VK_API_VERSION_1_0:
1050      ret &=\n""")
1051
1052    emit_struct_visits_by_vk_version(f, "VK_VERSION_1_0")
1053
1054    f.write("""\
1055             visitor->Visit("queues", &device->queues) &&
1056             visitor->Visit("extensions", &device->extensions) &&
1057             visitor->Visit("layers", &device->layers) &&
1058             visitor->Visit("formats", &device->formats);\n\n""")
1059
1060    for extension_name, _ in VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"].items():
1061      struct_var = get_vkjson_struct_variable_name(extension_name)
1062      f.write(f"  if (device->{struct_var}.reported) {{\n")
1063      f.write(f"    ret &= visitor->Visit(\"{extension_name}\", &device->{struct_var});\n")
1064      f.write("  }\n")
1065
1066    f.write("""\
1067    } return ret; }
1068
1069template <typename Visitor>
1070inline bool Iterate(Visitor* visitor, VkJsonInstance* instance) {
1071  bool ret = true;
1072  switch (instance->api_version ^ VK_API_VERSION_PATCH(instance->api_version)) {
1073    case VK_API_VERSION_1_4:
1074      FALLTHROUGH_INTENDED;
1075    case VK_API_VERSION_1_3:
1076      FALLTHROUGH_INTENDED;
1077    case VK_API_VERSION_1_2:
1078      ret &= visitor->Visit("apiVersion", &instance->api_version);
1079      FALLTHROUGH_INTENDED;
1080    case VK_API_VERSION_1_1:
1081      ret &= visitor->Visit("deviceGroups", &instance->device_groups);
1082      FALLTHROUGH_INTENDED;
1083    case VK_API_VERSION_1_0:
1084      char depString[] =
1085          "vkjson is deprecated, and will be replaced in a future release";
1086      ret &= visitor->Visit("layers", &instance->layers) &&
1087             visitor->Visit("extensions", &instance->extensions) &&
1088             visitor->Visit("devices", &instance->devices) &&
1089             visitor->Visit("_comment", &depString);
1090  }
1091  return ret;
1092}
1093
1094template <typename T>
1095using EnableForArithmetic =
1096    typename std::enable_if<std::is_arithmetic<T>::value, void>::type;
1097
1098template <typename T>
1099using EnableForStruct =
1100    typename std::enable_if<std::is_class<T>::value, void>::type;
1101
1102template <typename T>
1103using EnableForEnum =
1104    typename std::enable_if<std::is_enum<T>::value, void>::type;
1105
1106template <typename T, typename = EnableForStruct<T>, typename = void>
1107Json::Value ToJsonValue(const T& value);
1108
1109template <typename T, typename = EnableForArithmetic<T>>
1110inline Json::Value ToJsonValue(const T& value) {
1111  return Json::Value(
1112      std::clamp(static_cast<double>(value), SAFE_DOUBLE_MIN, SAFE_DOUBLE_MAX));
1113}
1114
1115inline Json::Value ToJsonValue(const uint64_t& value) {
1116  char string[19] = {0};  // "0x" + 16 digits + terminal \\0
1117  snprintf(string, sizeof(string), "0x%016" PRIx64, value);
1118  return Json::Value(string);
1119}
1120
1121template <typename T, typename = EnableForEnum<T>, typename = void,
1122          typename = void>
1123inline Json::Value ToJsonValue(const T& value) {
1124  return Json::Value(static_cast<double>(value));
1125}
1126
1127template <typename T>
1128inline Json::Value ArrayToJsonValue(uint32_t count, const T* values) {
1129  Json::Value array(Json::arrayValue);
1130  for (unsigned int i = 0; i < count; ++i) array.append(ToJsonValue(values[i]));
1131  return array;
1132}
1133
1134template <typename T, size_t N>
1135inline Json::Value ToJsonValue(const T (&value)[N]) {
1136  return ArrayToJsonValue(N, value);
1137}
1138
1139template <size_t N>
1140inline Json::Value ToJsonValue(const char (&value)[N]) {
1141  assert(strlen(value) < N);
1142  return Json::Value(value);
1143}
1144
1145template <typename T>
1146inline Json::Value ToJsonValue(const std::vector<T>& value) {
1147  assert(value.size() <= std::numeric_limits<uint32_t>::max());
1148  return ArrayToJsonValue(static_cast<uint32_t>(value.size()), value.data());
1149}
1150
1151template <typename F, typename S>
1152inline Json::Value ToJsonValue(const std::pair<F, S>& value) {
1153  Json::Value array(Json::arrayValue);
1154  array.append(ToJsonValue(value.first));
1155  array.append(ToJsonValue(value.second));
1156  return array;
1157}
1158
1159template <typename F, typename S>
1160inline Json::Value ToJsonValue(const std::map<F, S>& value) {
1161  Json::Value array(Json::arrayValue);
1162  for (auto& kv : value) array.append(ToJsonValue(kv));
1163  return array;
1164}
1165
1166class JsonWriterVisitor {
1167 public:
1168  JsonWriterVisitor() : object_(Json::objectValue) {}
1169
1170  ~JsonWriterVisitor() {}
1171
1172  template <typename T> bool Visit(const char* key, const T* value) {
1173    object_[key] = ToJsonValue(*value);
1174    return true;
1175  }
1176
1177  template <typename T, uint32_t N>
1178  bool VisitArray(const char* key, uint32_t count, const T (*value)[N]) {
1179    assert(count <= N);
1180    object_[key] = ArrayToJsonValue(count, *value);
1181    return true;
1182  }
1183
1184  template <typename T>
1185  bool VisitArray(const char* key, uint32_t count, const T *value) {
1186    object_[key] = ArrayToJsonValue(count, *value);
1187    return true;
1188  }
1189
1190  Json::Value get_object() const { return object_; }
1191
1192 private:
1193  Json::Value object_;
1194};
1195
1196template <typename Visitor, typename T>
1197inline void VisitForWrite(Visitor* visitor, const T& t) {
1198  Iterate(visitor, const_cast<T*>(&t));
1199}
1200
1201template <typename T, typename /*= EnableForStruct<T>*/, typename /*= void*/>
1202Json::Value ToJsonValue(const T& value) {
1203  JsonWriterVisitor visitor;
1204  VisitForWrite(&visitor, value);
1205  return visitor.get_object();
1206}
1207
1208template <typename T, typename = EnableForStruct<T>>
1209bool AsValue(Json::Value* json_value, T* t);
1210
1211inline bool AsValue(Json::Value* json_value, int32_t* value) {
1212  if (json_value->type() != Json::realValue) return false;
1213  double d = json_value->asDouble();
1214  if (!IsIntegral(d) ||
1215      d < static_cast<double>(std::numeric_limits<int32_t>::min()) ||
1216      d > static_cast<double>(std::numeric_limits<int32_t>::max()))
1217    return false;
1218  *value = static_cast<int32_t>(d);
1219  return true;
1220}
1221
1222inline bool AsValue(Json::Value* json_value, uint64_t* value) {
1223  if (json_value->type() != Json::stringValue) return false;
1224  int result =
1225      std::sscanf(json_value->asString().c_str(), "0x%016" PRIx64, value);
1226  return result == 1;
1227}
1228
1229inline bool AsValue(Json::Value* json_value, uint32_t* value) {
1230  if (json_value->type() != Json::realValue) return false;
1231  double d = json_value->asDouble();
1232  if (!IsIntegral(d) || d < 0.0 ||
1233      d > static_cast<double>(std::numeric_limits<uint32_t>::max()))
1234    return false;
1235  *value = static_cast<uint32_t>(d);
1236  return true;
1237}
1238
1239inline bool AsValue(Json::Value* json_value, uint8_t* value) {
1240  uint32_t value32 = 0;
1241  AsValue(json_value, &value32);
1242  if (value32 > std::numeric_limits<uint8_t>::max())
1243    return false;
1244  *value = static_cast<uint8_t>(value32);
1245  return true;
1246}
1247
1248inline bool AsValue(Json::Value* json_value, float* value) {
1249  if (json_value->type() != Json::realValue) return false;
1250  *value = static_cast<float>(json_value->asDouble());
1251  return true;
1252}
1253
1254inline bool AsValue(Json::Value* json_value, VkImageLayout* t) {
1255  uint32_t value = 0;
1256  if (!AsValue(json_value, &value))
1257    return false;
1258  if (!EnumTraits<VkImageLayout>::exist(value)) return false;
1259  *t = static_cast<VkImageLayout>(value);
1260  return true;
1261}
1262
1263template <typename T>
1264inline bool AsArray(Json::Value* json_value, uint32_t count, T* values) {
1265  if (json_value->type() != Json::arrayValue || json_value->size() != count)
1266    return false;
1267  for (uint32_t i = 0; i < count; ++i) {
1268    if (!AsValue(&(*json_value)[i], values + i)) return false;
1269  }
1270  return true;
1271}
1272
1273template <typename T, size_t N>
1274inline bool AsValue(Json::Value* json_value, T (*value)[N]) {
1275  return AsArray(json_value, N, *value);
1276}
1277
1278template <size_t N>
1279inline bool AsValue(Json::Value* json_value, char (*value)[N]) {
1280  if (json_value->type() != Json::stringValue) return false;
1281  size_t len = json_value->asString().length();
1282  if (len >= N)
1283    return false;
1284  memcpy(*value, json_value->asString().c_str(), len);
1285  memset(*value + len, 0, N-len);
1286  return true;
1287}
1288
1289template <typename T, typename = EnableForEnum<T>, typename = void>
1290inline bool AsValue(Json::Value* json_value, T* t) {
1291  uint32_t value = 0;
1292  if (!AsValue(json_value, &value))
1293      return false;
1294  if (!EnumTraits<T>::exist(value)) return false;
1295  *t = static_cast<T>(value);
1296  return true;
1297}
1298
1299template <typename T>
1300inline bool AsValue(Json::Value* json_value, std::vector<T>* value) {
1301  if (json_value->type() != Json::arrayValue) return false;
1302  int size = json_value->size();
1303  value->resize(size);
1304  return AsArray(json_value, size, value->data());
1305}
1306
1307template <typename F, typename S>
1308inline bool AsValue(Json::Value* json_value, std::pair<F, S>* value) {
1309  if (json_value->type() != Json::arrayValue || json_value->size() != 2)
1310    return false;
1311  return AsValue(&(*json_value)[0], &value->first) &&
1312         AsValue(&(*json_value)[1], &value->second);
1313}
1314
1315template <typename F, typename S>
1316inline bool AsValue(Json::Value* json_value, std::map<F, S>* value) {
1317  if (json_value->type() != Json::arrayValue) return false;
1318  int size = json_value->size();
1319  for (int i = 0; i < size; ++i) {
1320    std::pair<F, S> elem;
1321    if (!AsValue(&(*json_value)[i], &elem)) return false;
1322    if (!value->insert(elem).second)
1323      return false;
1324  }
1325  return true;
1326}
1327
1328template <typename T>
1329bool ReadValue(Json::Value* object, const char* key, T* value,
1330               std::string* errors) {
1331  Json::Value json_value = (*object)[key];
1332  if (!json_value) {
1333    if (errors)
1334      *errors = std::string(key) + " missing.";
1335    return false;
1336  }
1337  if (AsValue(&json_value, value)) return true;
1338  if (errors)
1339    *errors = std::string("Wrong type for ") + std::string(key) + ".";
1340  return false;
1341}
1342
1343template <typename Visitor, typename T>
1344inline bool VisitForRead(Visitor* visitor, T* t) {
1345  return Iterate(visitor, t);
1346}
1347
1348class JsonReaderVisitor {
1349 public:
1350  JsonReaderVisitor(Json::Value* object, std::string* errors)
1351      : object_(object), errors_(errors) {}
1352
1353  template <typename T> bool Visit(const char* key, T* value) const {
1354    return ReadValue(object_, key, value, errors_);
1355  }
1356
1357  template <typename T, uint32_t N>
1358  bool VisitArray(const char* key, uint32_t count, T (*value)[N]) {
1359    if (count > N)
1360      return false;
1361    Json::Value json_value = (*object_)[key];
1362    if (!json_value) {
1363      if (errors_)
1364        *errors_ = std::string(key) + " missing.";
1365      return false;
1366    }
1367    if (AsArray(&json_value, count, *value)) return true;
1368    if (errors_)
1369      *errors_ = std::string("Wrong type for ") + std::string(key) + ".";
1370    return false;
1371  }
1372
1373  template <typename T>
1374  bool VisitArray(const char* key, uint32_t count, T *value) {
1375    Json::Value json_value = (*object_)[key];
1376    if (!json_value) {
1377      if (errors_)
1378        *errors_ = std::string(key) + " missing.";
1379      return false;
1380    }
1381    if (AsArray(&json_value, count, *value)) return true;
1382    if (errors_)
1383      *errors_ = std::string("Wrong type for ") + std::string(key) + ".";
1384    return false;
1385  }
1386
1387
1388 private:
1389  Json::Value* object_;
1390  std::string* errors_;
1391};
1392
1393template <typename T, typename /*= EnableForStruct<T>*/>
1394bool AsValue(Json::Value* json_value, T* t) {
1395  if (json_value->type() != Json::objectValue) return false;
1396  JsonReaderVisitor visitor(json_value, nullptr);
1397  return VisitForRead(&visitor, t);
1398}
1399
1400
1401template <typename T> std::string VkTypeToJson(const T& t) {
1402  JsonWriterVisitor visitor;
1403  VisitForWrite(&visitor, t);
1404  return visitor.get_object().toStyledString();
1405}
1406
1407template <typename T> bool VkTypeFromJson(const std::string& json,
1408                                          T* t,
1409                                          std::string* errors) {
1410  *t = T();
1411  Json::Value object(Json::objectValue);
1412  Json::CharReaderBuilder builder;
1413  builder["collectComments"] = false;
1414  std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
1415  if (!reader->parse(json.data(), json.data() + json.size(), &object, errors)) {
1416    return false;
1417  }
1418  return AsValue(&object, t);
1419}
1420
1421}  // anonymous namespace
1422
1423std::string VkJsonInstanceToJson(const VkJsonInstance& instance) {
1424  return VkTypeToJson(instance);
1425}
1426
1427bool VkJsonInstanceFromJson(const std::string& json,
1428                            VkJsonInstance* instance,
1429                            std::string* errors) {
1430  return VkTypeFromJson(json, instance, errors);
1431}
1432
1433std::string VkJsonDeviceToJson(const VkJsonDevice& device) {
1434  return VkTypeToJson(device);
1435}
1436
1437bool VkJsonDeviceFromJson(const std::string& json,
1438                          VkJsonDevice* device,
1439                          std::string* errors) {
1440  return VkTypeFromJson(json, device, errors);
1441};
1442
1443std::string VkJsonImageFormatPropertiesToJson(
1444    const VkImageFormatProperties& properties) {
1445  return VkTypeToJson(properties);
1446}
1447
1448bool VkJsonImageFormatPropertiesFromJson(const std::string& json,
1449                                         VkImageFormatProperties* properties,
1450                                         std::string* errors) {
1451  return VkTypeFromJson(json, properties, errors);
1452};
1453""")
1454    f.close()
1455  gencom.run_clang_format(genfile)
1456
1457
1458def generate_vk_core_structs_init_code(version):
1459  """Generates code to initialize properties and features
1460  for structs based on its vulkan API version dependency.
1461  """
1462  properties_code, features_code = [], []
1463
1464  for item in VK.VULKAN_CORES_AND_STRUCTS_MAPPING["versions"].get(version, []):
1465    for struct_name, struct_type in item.items():
1466      version_lower = version.lower()
1467
1468      if "Properties" in struct_name:
1469        properties_code.extend([
1470            f"device.{version_lower}.properties.sType = {struct_type};",
1471            f"device.{version_lower}.properties.pNext = properties.pNext;",
1472            f"properties.pNext = &device.{version_lower}.properties;\n\n"
1473        ])
1474
1475      elif "Features" in struct_name:
1476        features_code.extend([
1477            f"device.{version_lower}.features.sType = {struct_type};",
1478            f"device.{version_lower}.features.pNext = features.pNext;",
1479            f"features.pNext = &device.{version_lower}.features;\n\n"
1480        ])
1481
1482  return "\n".join(properties_code), "\n".join(features_code)
1483
1484
1485def generate_vk_extension_structs_init_code(mapping, struct_category, next_pointer):
1486  """Generates Vulkan struct initialization code for given struct category (Properties/Features)
1487  based on its extension dependency.
1488  """
1489  generated_code = []
1490
1491  for extension, struct_mappings in mapping.items():
1492    struct_var_name = get_vkjson_struct_variable_name(extension)
1493    extension_code = [
1494        f"  if (HasExtension(\"{extension}\", device.extensions)) {{",
1495        f"    device.{struct_var_name}.reported = true;"
1496    ]
1497
1498    struct_count = 0
1499    for struct_mapping in struct_mappings:
1500      for struct_name, struct_type in struct_mapping.items():
1501        if struct_category in struct_name:
1502          struct_count += 1
1503          struct_instance = get_struct_name(struct_name)
1504          extension_code.extend([
1505              f"    device.{struct_var_name}.{struct_instance}.sType = {struct_type};",
1506              f"    device.{struct_var_name}.{struct_instance}.pNext = {next_pointer}.pNext;",
1507              f"    {next_pointer}.pNext = &device.{struct_var_name}.{struct_instance};"
1508          ])
1509
1510    extension_code.append("  }\n")
1511
1512    if struct_count > 0:
1513      generated_code.extend(extension_code)
1514
1515  return "\n".join(generated_code)
1516
1517
1518def generate_vk_version_structs_initialization(version_data, struct_type_keyword, next_pointer):
1519  """Generates Vulkan struct initialization code for given struct category (Properties/Features)
1520  of vulkan api version s.
1521  """
1522  struct_initialization_code = []
1523
1524  for struct_mapping in version_data:
1525    for struct_name, struct_type in struct_mapping.items():
1526      if struct_type_keyword in struct_name:
1527        struct_variable = get_struct_name(struct_name)
1528        struct_initialization_code.extend([
1529            f"device.{struct_variable}.sType = {struct_type};",
1530            f"device.{struct_variable}.pNext = {next_pointer}.pNext;",
1531            f"{next_pointer}.pNext = &device.{struct_variable};\n"
1532        ])
1533
1534  return "\n".join(struct_initialization_code)
1535
1536
1537def gen_instance_cc():
1538  """Generates vkjson_instance.cc file.
1539  """
1540  genfile = os.path.join(os.path.dirname(__file__),
1541                         "..", "vkjson", "vkjson_instance.cc")
1542
1543  with open(genfile, "w") as f:
1544    f.write(get_copyright_warnings())
1545    f.write("\n")
1546
1547    f.write("""\
1548#ifndef VK_PROTOTYPES
1549#define VK_PROTOTYPES
1550#endif
1551
1552#include "vkjson.h"
1553
1554#include <algorithm>
1555#include <utility>
1556
1557/*
1558 * This file is autogenerated by vkjson_generator.py. Do not edit directly.
1559 */
1560namespace {
1561
1562bool EnumerateExtensions(const char* layer_name,
1563                         std::vector<VkExtensionProperties>* extensions) {
1564  VkResult result;
1565  uint32_t count = 0;
1566  result = vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
1567  if (result != VK_SUCCESS)
1568    return false;
1569  extensions->resize(count);
1570  result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
1571                                                  extensions->data());
1572  if (result != VK_SUCCESS)
1573    return false;
1574  return true;
1575}
1576
1577bool HasExtension(const char* extension_name,
1578                  const std::vector<VkExtensionProperties>& extensions) {
1579  return std::find_if(extensions.cbegin(), extensions.cend(),
1580                      [extension_name](const VkExtensionProperties& extension) {
1581                        return strcmp(extension.extensionName,
1582                                      extension_name) == 0;
1583                      }) != extensions.cend();
1584}
1585}  // anonymous namespace
1586
1587VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) {
1588  VkJsonDevice device;
1589
1590  uint32_t extension_count = 0;
1591  vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
1592                                       &extension_count, nullptr);
1593  if (extension_count > 0) {
1594    device.extensions.resize(extension_count);
1595    vkEnumerateDeviceExtensionProperties(
1596        physical_device, nullptr, &extension_count, device.extensions.data());
1597  }
1598
1599  uint32_t layer_count = 0;
1600  vkEnumerateDeviceLayerProperties(physical_device, &layer_count, nullptr);
1601  if (layer_count > 0) {
1602    device.layers.resize(layer_count);
1603    vkEnumerateDeviceLayerProperties(physical_device, &layer_count,
1604                                     device.layers.data());
1605  }
1606
1607  VkPhysicalDeviceProperties2 properties = {
1608      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
1609      nullptr,
1610      {},
1611  };\n\n""")
1612
1613    cc_code_properties = generate_vk_extension_structs_init_code(
1614    VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"], "Properties", "properties"
1615    )
1616    f.write(f'{cc_code_properties}\n')
1617
1618    f.write("""\
1619
1620  vkGetPhysicalDeviceProperties2(physical_device, &properties);
1621  device.properties = properties.properties;
1622
1623  VkPhysicalDeviceFeatures2 features = {
1624      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
1625      nullptr,
1626      {},
1627  };\n\n""")
1628
1629    cc_code_features = generate_vk_extension_structs_init_code(
1630      VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"], "Features", "features"
1631    )
1632    f.write(f'{cc_code_features}\n')
1633
1634    f.write("""\
1635
1636  vkGetPhysicalDeviceFeatures2(physical_device, &features);
1637  device.features = features.features;
1638
1639  vkGetPhysicalDeviceMemoryProperties(physical_device, &device.memory);
1640
1641  uint32_t queue_family_count = 0;
1642  vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count,
1643                                           nullptr);
1644  if (queue_family_count > 0) {
1645    device.queues.resize(queue_family_count);
1646    vkGetPhysicalDeviceQueueFamilyProperties(
1647        physical_device, &queue_family_count, device.queues.data());
1648  }
1649
1650  VkFormatProperties format_properties = {};
1651  for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8;
1652       // TODO(http://b/171403054): avoid hard-coding last value in the
1653       // contiguous range
1654       format <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
1655       format = static_cast<VkFormat>(format + 1)) {
1656    vkGetPhysicalDeviceFormatProperties(physical_device, format,
1657                                        &format_properties);
1658    if (format_properties.linearTilingFeatures ||
1659        format_properties.optimalTilingFeatures ||
1660        format_properties.bufferFeatures) {
1661      device.formats.insert(std::make_pair(format, format_properties));
1662    }
1663  }
1664
1665  if (device.properties.apiVersion >= VK_API_VERSION_1_1) {
1666    for (VkFormat format = VK_FORMAT_G8B8G8R8_422_UNORM;
1667         // TODO(http://b/171403054): avoid hard-coding last value in the
1668         // contiguous range
1669         format <= VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM;
1670         format = static_cast<VkFormat>(format + 1)) {
1671      vkGetPhysicalDeviceFormatProperties(physical_device, format,
1672                                          &format_properties);
1673      if (format_properties.linearTilingFeatures ||
1674          format_properties.optimalTilingFeatures ||
1675          format_properties.bufferFeatures) {
1676        device.formats.insert(std::make_pair(format, format_properties));
1677      }
1678    }\n\n""")
1679
1680    # Vulkan version data for VK_VERSION_1_1
1681    vk_version_data = VK.VULKAN_VERSIONS_AND_STRUCTS_MAPPING["VK_VERSION_1_1"]
1682    f.write(generate_vk_version_structs_initialization(vk_version_data, "Properties", "properties") + "\n")
1683
1684    f.write("""\
1685    vkGetPhysicalDeviceProperties2(physical_device, &properties);\n\n""")
1686
1687    features_initialization_code = generate_vk_version_structs_initialization(vk_version_data, "Features", "features")
1688    f.write(features_initialization_code)
1689
1690    f.write("""\
1691
1692    vkGetPhysicalDeviceFeatures2(physical_device, &features);
1693
1694    VkPhysicalDeviceExternalFenceInfo external_fence_info = {
1695        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, nullptr,
1696        VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT};
1697    VkExternalFenceProperties external_fence_properties = {};
1698
1699    for (VkExternalFenceHandleTypeFlagBits handle_type =
1700             VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
1701         handle_type <= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
1702         handle_type =
1703             static_cast<VkExternalFenceHandleTypeFlagBits>(handle_type << 1)) {
1704      external_fence_info.handleType = handle_type;
1705      vkGetPhysicalDeviceExternalFenceProperties(
1706          physical_device, &external_fence_info, &external_fence_properties);
1707      if (external_fence_properties.exportFromImportedHandleTypes ||
1708          external_fence_properties.compatibleHandleTypes ||
1709          external_fence_properties.externalFenceFeatures) {
1710        device.external_fence_properties.insert(
1711            std::make_pair(handle_type, external_fence_properties));
1712      }
1713    }
1714
1715    VkPhysicalDeviceExternalSemaphoreInfo external_semaphore_info = {
1716        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, nullptr,
1717        VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT};
1718    VkExternalSemaphoreProperties external_semaphore_properties = {};
1719
1720    for (VkExternalSemaphoreHandleTypeFlagBits handle_type =
1721             VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
1722         handle_type <= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
1723         handle_type = static_cast<VkExternalSemaphoreHandleTypeFlagBits>(
1724             handle_type << 1)) {
1725      external_semaphore_info.handleType = handle_type;
1726      vkGetPhysicalDeviceExternalSemaphoreProperties(
1727          physical_device, &external_semaphore_info,
1728          &external_semaphore_properties);
1729      if (external_semaphore_properties.exportFromImportedHandleTypes ||
1730          external_semaphore_properties.compatibleHandleTypes ||
1731          external_semaphore_properties.externalSemaphoreFeatures) {
1732        device.external_semaphore_properties.insert(
1733            std::make_pair(handle_type, external_semaphore_properties));
1734      }
1735    }
1736  }
1737
1738  if (device.properties.apiVersion >= VK_API_VERSION_1_2) {\n""")
1739
1740    cc_code_properties_11, cc_code_features_11 = generate_vk_core_structs_init_code("Core11")
1741    cc_code_properties_12, cc_code_features_12 = generate_vk_core_structs_init_code("Core12")
1742    cc_code_properties_13, cc_code_features_13 = generate_vk_core_structs_init_code("Core13")
1743    cc_code_properties_14, cc_code_features_14 = generate_vk_core_structs_init_code("Core14")
1744
1745    f.write(cc_code_properties_11)
1746    f.write(cc_code_properties_12)
1747    f.write(f"vkGetPhysicalDeviceProperties2(physical_device, &properties);\n\n")
1748    f.write(cc_code_features_11)
1749    f.write(cc_code_features_12)
1750    f.write(f"vkGetPhysicalDeviceFeatures2(physical_device, &features);\n\n")
1751    f.write("""\
1752  }
1753
1754  if (device.properties.apiVersion >= VK_API_VERSION_1_3) {\n""")
1755    f.write(cc_code_properties_13)
1756    f.write(f"vkGetPhysicalDeviceProperties2(physical_device, &properties);\n\n")
1757    f.write(cc_code_features_13)
1758    f.write(f"vkGetPhysicalDeviceFeatures2(physical_device, &features);\n\n")
1759    f.write("""\
1760  }
1761
1762  if (device.properties.apiVersion >= VK_API_VERSION_1_4) {\n""")
1763    f.write(cc_code_properties_14)
1764    f.write(f"vkGetPhysicalDeviceProperties2(physical_device, &properties);\n\n")
1765
1766    f.write("""\
1767if (device.core14.properties.copySrcLayoutCount > 0 || device.core14.properties.copyDstLayoutCount > 0 ) {
1768  if (device.core14.properties.copySrcLayoutCount > 0) {
1769    device.core14.copy_src_layouts.resize(device.core14.properties.copySrcLayoutCount);
1770    device.core14.properties.pCopySrcLayouts = device.core14.copy_src_layouts.data();
1771  }
1772  if (device.core14.properties.copyDstLayoutCount > 0) {
1773    device.core14.copy_dst_layouts.resize(device.core14.properties.copyDstLayoutCount);
1774    device.core14.properties.pCopyDstLayouts = device.core14.copy_dst_layouts.data();
1775  }
1776  vkGetPhysicalDeviceProperties2(physical_device, &properties);
1777}
1778    \n""")
1779
1780    f.write(cc_code_features_14)
1781    f.write(f"vkGetPhysicalDeviceFeatures2(physical_device, &features);\n\n")
1782    f.write("""\
1783  }
1784
1785  return device;
1786}
1787
1788VkJsonInstance VkJsonGetInstance() {
1789  VkJsonInstance instance;
1790  VkResult result;
1791  uint32_t count;
1792
1793  count = 0;
1794  result = vkEnumerateInstanceLayerProperties(&count, nullptr);
1795  if (result != VK_SUCCESS)
1796    return VkJsonInstance();
1797  if (count > 0) {
1798    std::vector<VkLayerProperties> layers(count);
1799    result = vkEnumerateInstanceLayerProperties(&count, layers.data());
1800    if (result != VK_SUCCESS)
1801      return VkJsonInstance();
1802    instance.layers.reserve(count);
1803    for (auto& layer : layers) {
1804      instance.layers.push_back(VkJsonLayer{layer, std::vector<VkExtensionProperties>()});
1805      if (!EnumerateExtensions(layer.layerName,
1806                               &instance.layers.back().extensions))
1807        return VkJsonInstance();
1808    }
1809  }
1810
1811  if (!EnumerateExtensions(nullptr, &instance.extensions))
1812    return VkJsonInstance();
1813
1814  const VkApplicationInfo app_info = {
1815      VK_STRUCTURE_TYPE_APPLICATION_INFO,
1816      nullptr,
1817      "vkjson_info",
1818      1,
1819      "",
1820      0,
1821      VK_API_VERSION_1_1,
1822  };
1823  VkInstanceCreateInfo instance_info = {
1824      VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
1825      nullptr,
1826      0,
1827      &app_info,
1828      0,
1829      nullptr,
1830      0,
1831      nullptr,
1832  };
1833  VkInstance vkinstance;
1834  result = vkCreateInstance(&instance_info, nullptr, &vkinstance);
1835  if (result != VK_SUCCESS)
1836    return VkJsonInstance();
1837
1838  count = 0;
1839  result = vkEnumeratePhysicalDevices(vkinstance, &count, nullptr);
1840  if (result != VK_SUCCESS) {
1841    vkDestroyInstance(vkinstance, nullptr);
1842    return VkJsonInstance();
1843  }
1844
1845  std::vector<VkPhysicalDevice> devices(count, VK_NULL_HANDLE);
1846  result = vkEnumeratePhysicalDevices(vkinstance, &count, devices.data());
1847  if (result != VK_SUCCESS) {
1848    vkDestroyInstance(vkinstance, nullptr);
1849    return VkJsonInstance();
1850  }
1851
1852  std::map<VkPhysicalDevice, uint32_t> device_map;
1853  const uint32_t sz = devices.size();
1854  instance.devices.reserve(sz);
1855  for (uint32_t i = 0; i < sz; ++i) {
1856    device_map.insert(std::make_pair(devices[i], i));
1857    instance.devices.emplace_back(VkJsonGetDevice(devices[i]));
1858  }
1859
1860  result = vkEnumerateInstanceVersion(&instance.api_version);
1861  if (result != VK_SUCCESS) {
1862    vkDestroyInstance(vkinstance, nullptr);
1863    return VkJsonInstance();
1864  }
1865
1866  count = 0;
1867  result = vkEnumeratePhysicalDeviceGroups(vkinstance, &count, nullptr);
1868  if (result != VK_SUCCESS) {
1869    vkDestroyInstance(vkinstance, nullptr);
1870    return VkJsonInstance();
1871  }
1872
1873  VkJsonDeviceGroup device_group;
1874  std::vector<VkPhysicalDeviceGroupProperties> group_properties;
1875  group_properties.resize(count);
1876  for (auto& properties : group_properties) {
1877    properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1878    properties.pNext = nullptr;
1879  }
1880  result = vkEnumeratePhysicalDeviceGroups(vkinstance, &count,
1881                                           group_properties.data());
1882  if (result != VK_SUCCESS) {
1883    vkDestroyInstance(vkinstance, nullptr);
1884    return VkJsonInstance();
1885  }
1886  for (auto properties : group_properties) {
1887    device_group.properties = properties;
1888    for (uint32_t i = 0; i < properties.physicalDeviceCount; ++i) {
1889      device_group.device_inds.push_back(
1890          device_map[properties.physicalDevices[i]]);
1891    }
1892    instance.device_groups.push_back(device_group);
1893  }
1894
1895  vkDestroyInstance(vkinstance, nullptr);
1896  return instance;
1897}
1898
1899\n""")
1900
1901    f.close()
1902  gencom.run_clang_format(genfile)