Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45075eb3 authored by Anjana Sherin's avatar Anjana Sherin Committed by Android (Google) Code Review
Browse files

Merge "Extract pending vkjson_generator utility functions into separate file" into main

parents b3372d53 23c3e4f7
Loading
Loading
Loading
Loading
+225 −2
Original line number Diff line number Diff line
@@ -15,12 +15,13 @@
# limitations under the License.

"""
This file contains utility functions for vkjson_generator.py
that are reused in various parts of the same script.
This file contains all supporting utility functions for vkjson_generator.py
"""

import dataclasses
import re
import vk as VK
from typing import get_origin

COPYRIGHT_WARNINGS = """///////////////////////////////////////////////////////////////////////////////
//
@@ -122,6 +123,228 @@ def get_struct_name(struct_name):
    return special_cases.get(variable_name, variable_name)


def generate_extension_struct_definition(f):
    """Generates struct definition code for extension based structs
    Example:
    struct VkJsonKHRShaderFloatControls {
      VkJsonKHRShaderFloatControls() {
        reported = false;
        memset(&float_controls_properties_khr, 0,
              sizeof(VkPhysicalDeviceFloatControlsPropertiesKHR));
      }
      bool reported;
      VkPhysicalDeviceFloatControlsPropertiesKHR float_controls_properties_khr;
    };
    """
    vkjson_entries = []

    for extension_name, struct_list in (VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"]
            .items()):
        vkjson_struct_name = get_vkjson_struct_name(extension_name)
        vkjson_struct_variable_name = get_vkjson_struct_variable_name(extension_name)
        vkjson_entries.append(f"{vkjson_struct_name} {vkjson_struct_variable_name}")

        struct_entries = []

        f.write(f"struct {vkjson_struct_name} {{\n")
        f.write(f"  {vkjson_struct_name}() {{\n")
        f.write("    reported = false;\n")

        for struct_map in struct_list:
            for struct_name, _ in struct_map.items():
                variable_name = get_struct_name(struct_name)
                f.write(f"    memset(&{variable_name}, 0, sizeof({struct_name}));\n")
                struct_entries.append(f"{struct_name} {variable_name}")

        f.write("  }\n")  # End of constructor
        f.write("  bool reported;\n")

        for entry in struct_entries:
            f.write(f"  {entry};\n")

        f.write("};\n\n")  # End of struct

    return vkjson_entries


def generate_vk_core_struct_definition(f):
    """Generates struct definition code for vulkan cores
    Example:
    struct VkJsonCore11 {
      VkPhysicalDeviceVulkan11Properties properties;
      VkPhysicalDeviceVulkan11Features features;
    };
    """
    vkjson_core_entries = []

    for version, items in VK.VULKAN_CORES_AND_STRUCTS_MAPPING["versions"].items():
        struct_name = f"VkJson{version}"
        vkjson_core_entries.append(f"{struct_name} {version.lower()}")

        f.write(f"struct {struct_name} {{\n")
        f.write(f"  {struct_name}() {{\n")  # Start of constructor
        for item in items:
            for struct_type, _ in item.items():
                field_name = "properties" if "Properties" in struct_type else "features"
                f.write(f" memset(&{field_name}, 0, sizeof({struct_type}));\n")
        f.write("  }\n")  # End of constructor

        for item in items:
            for struct_type, _ in item.items():
                field_name = "properties" if "Properties" in struct_type else "features"
                f.write(f"  {struct_type} {field_name};\n")

        if version == "Core14":
            f.write(f"std::vector<VkImageLayout> copy_src_layouts;\n")
            f.write(f"std::vector<VkImageLayout> copy_dst_layouts;\n")

        f.write("};\n\n")

    return vkjson_core_entries


def generate_memset_statements(f):
    """Generates memset statements for all independent Vulkan structs and core Vulkan versions.
    This initializes struct instances to zero before use.

    Example:
      memset(&properties, 0, sizeof(VkPhysicalDeviceProperties));
      VkPhysicalDeviceProperties properties;
    """
    entries = []

    # Process independent structs
    for dataclass_type in VK.EXTENSION_INDEPENDENT_STRUCTS:
        class_name = dataclass_type.__name__
        variable_name = get_struct_name(class_name)
        f.write(f"memset(&{variable_name}, 0, sizeof({class_name}));\n")
        entries.append(f"{class_name} {variable_name}")

    return entries


def generate_extension_struct_template():
    """Generates templates for extensions
    Example:
      template <typename Visitor>
      inline bool Iterate(Visitor* visitor, VkJsonKHRVariablePointers* structs) {
        return visitor->Visit("variablePointerFeaturesKHR",
                              &structs->variable_pointer_features_khr) &&
              visitor->Visit("variablePointersFeaturesKHR",
                              &structs->variable_pointers_features_khr);
      }
    """
    template_code = []

    for extension, struct_mappings in (VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"]
            .items()):
        struct_type = get_vkjson_struct_name(extension)

        template_code.append(f"template <typename Visitor>")
        template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_type}* structs) {{")
        template_code.append("  return ")

        visitor_calls = []
        for struct_map in struct_mappings:
            for struct_name in struct_map:
                json_field_name = struct_name.replace("VkPhysicalDevice", "")
                json_field_name = json_field_name[0].lower() + json_field_name[1:]

                # Special case renaming
                if json_field_name == "8BitStorageFeaturesKHR":
                    json_field_name = "bit8StorageFeaturesKHR"

                visitor_calls.append(
                    f'visitor->Visit("{json_field_name}", &structs->{get_struct_name(struct_name)})'
                )

        template_code.append(" &&\n         ".join(visitor_calls) + ";")
        template_code.append("}\n")

    return "\n".join(template_code)


def generate_core_template():
    """Generates templates for vulkan cores.
    template <typename Visitor>
    inline bool Iterate(Visitor* visitor, VkJsonCore11* core) {
      return visitor->Visit("properties", &core->properties) &&
            visitor->Visit("features", &core->features);
    }
    """
    template_code = []

    for version, struct_list in VK.VULKAN_CORES_AND_STRUCTS_MAPPING["versions"].items():
        struct_type = f"VkJson{version}"

        template_code.append(f"template <typename Visitor>")
        template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_type}* core) {{")
        template_code.append("  return")

        visitor_calls = []
        for struct_map in struct_list:
            for struct_name in struct_map:
                member_name = "properties" if "Properties" in struct_name else "features"
                visitor_calls.append(f'visitor->Visit("{member_name}", &core->{member_name})')

        template_code.append(" &&\n         ".join(visitor_calls) + ";")
        template_code.append("}\n")

    return "\n".join(template_code)


def generate_struct_template(data_classes):
    """Generates templates for all the structs
    template <typename Visitor>
    inline bool Iterate(Visitor* visitor,
                        VkPhysicalDevicePointClippingProperties* properties) {
      return visitor->Visit("pointClippingBehavior",
                            &properties->pointClippingBehavior);
    }
    """
    template_code = []
    processed_classes = set()  # Track processed class names

    for dataclass_type in data_classes:
        struct_name = dataclass_type.__name__

        if struct_name in processed_classes:
            continue  # Skip already processed struct
        processed_classes.add(struct_name)

        struct_fields = dataclasses.fields(dataclass_type)
        template_code.append("template <typename Visitor>")

        # Determine the correct variable name based on the struct type
        struct_var = "properties" if "Properties" in struct_name else "features" if "Features" in struct_name else "limits" if "Limits" in struct_name else None

        if not struct_var:
            continue  # Skip structs that don't match expected patterns

        template_code.append(
            f"inline bool Iterate(Visitor* visitor, {struct_name}* {struct_var}) {{")
        template_code.append(f"return\n")

        visitor_calls = []
        for struct_field in struct_fields:
            field_name = struct_field.name
            field_type = struct_field.type

            if get_origin(field_type) is list:
                # Handle list types (VisitArray)
                size_field_name = VK.LIST_TYPE_FIELD_AND_SIZE_MAPPING[field_name]
                visitor_calls.append(
                    f'visitor->VisitArray("{field_name}", {struct_var}->{size_field_name}, &{struct_var}->{field_name})')
            else:
                # Handle other types (Visit)
                visitor_calls.append(f'visitor->Visit("{field_name}", &{struct_var}->{field_name})')

        template_code.append(" &&\n         ".join(visitor_calls) + ";")
        template_code.append("}\n\n")

    return "\n".join(template_code)


def emit_struct_visits_by_vk_version(f, version):
    """Emits visitor calls for Vulkan version structs
    """
+5 −226
Original line number Diff line number Diff line
@@ -16,114 +16,12 @@

"""Generates the vkjson files.
"""
import dataclasses
import os
from typing import get_origin

import generator_common as gencom
import vkjson_gen_util as util
import vk as VK

dataclass_field = dataclasses.field

def generate_extension_struct_definition(f):
  """Generates struct definition code for extension based structs
  Example:
  struct VkJsonKHRShaderFloatControls {
    VkJsonKHRShaderFloatControls() {
      reported = false;
      memset(&float_controls_properties_khr, 0,
            sizeof(VkPhysicalDeviceFloatControlsPropertiesKHR));
    }
    bool reported;
    VkPhysicalDeviceFloatControlsPropertiesKHR float_controls_properties_khr;
  };
  """
  vkJson_entries = []

  for extension_name, struct_list in VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"].items():
    vkjson_struct_name = util.get_vkjson_struct_name(extension_name)
    vkjson_struct_variable_name = util.get_vkjson_struct_variable_name(extension_name)
    vkJson_entries.append(f"{vkjson_struct_name} {vkjson_struct_variable_name}")

    struct_entries = []

    f.write(f"struct {vkjson_struct_name} {{\n")
    f.write(f"  {vkjson_struct_name}() {{\n")
    f.write("    reported = false;\n")

    for struct_map in struct_list:
      for struct_name, _ in struct_map.items():
        variable_name = util.get_struct_name(struct_name)
        f.write(f"    memset(&{variable_name}, 0, sizeof({struct_name}));\n")
        struct_entries.append(f"{struct_name} {variable_name}")

    f.write("  }\n")  # End of constructor
    f.write("  bool reported;\n")

    for entry in struct_entries:
      f.write(f"  {entry};\n")

    f.write("};\n\n")  # End of struct

  return vkJson_entries


def generate_vk_core_struct_definition(f):
  """Generates struct definition code for vulkan cores
  Example:
  struct VkJsonCore11 {
    VkPhysicalDeviceVulkan11Properties properties;
    VkPhysicalDeviceVulkan11Features features;
  };
  """
  vkJson_core_entries = []

  for version, items in VK.VULKAN_CORES_AND_STRUCTS_MAPPING["versions"].items():
    struct_name = f"VkJson{version}"
    vkJson_core_entries.append(f"{struct_name} {version.lower()}")

    f.write(f"struct {struct_name} {{\n")
    f.write(f"  {struct_name}() {{\n") # Start of constructor
    for item in items:
      for struct_type, _ in item.items():
        field_name = "properties" if "Properties" in struct_type else "features"
        f.write(f" memset(&{field_name}, 0, sizeof({struct_type}));\n")
    f.write("  }\n")  # End of constructor

    for item in items:
      for struct_type, _ in item.items():
        field_name = "properties" if "Properties" in struct_type else "features"
        f.write(f"  {struct_type} {field_name};\n")

    if version == "Core14":
      f.write(f"std::vector<VkImageLayout> copy_src_layouts;\n")
      f.write(f"std::vector<VkImageLayout> copy_dst_layouts;\n")

    f.write("};\n\n")

  return vkJson_core_entries


def generate_memset_statements(f):
  """Generates memset statements for all independent Vulkan structs and core Vulkan versions.
  This initializes struct instances to zero before use.

  Example:
    memset(&properties, 0, sizeof(VkPhysicalDeviceProperties));
    VkPhysicalDeviceProperties properties;
  """
  entries = []

  # Process independent structs
  for dataclass_type in VK.EXTENSION_INDEPENDENT_STRUCTS:
    class_name = dataclass_type.__name__
    variable_name = util.get_struct_name(class_name)
    f.write(f"memset(&{variable_name}, 0, sizeof({class_name}));\n")
    entries.append(f"{class_name} {variable_name}")

  return entries


def gen_h():
  """Generates vkjson.h file.
@@ -160,14 +58,14 @@ struct VkJsonLayer {

\n""")

    vkjson_extension_structs = generate_extension_struct_definition(f)
    vkjson_core_structs = generate_vk_core_struct_definition(f)
    vkjson_extension_structs = util.generate_extension_struct_definition(f)
    vkjson_core_structs = util.generate_vk_core_struct_definition(f)

    f.write("""\
struct VkJsonDevice {
  VkJsonDevice() {""")

    feature_property_structs = generate_memset_statements(f)
    feature_property_structs = util.generate_memset_statements(f)

    f.write("""\
  }\n""")
@@ -243,125 +141,6 @@ inline bool VkJsonAllPropertiesFromJson(const std::string& json,
  gencom.run_clang_format(genfile)


def generate_extension_struct_template():
  """Generates templates for extensions
  Example:
    template <typename Visitor>
    inline bool Iterate(Visitor* visitor, VkJsonKHRVariablePointers* structs) {
      return visitor->Visit("variablePointerFeaturesKHR",
                            &structs->variable_pointer_features_khr) &&
            visitor->Visit("variablePointersFeaturesKHR",
                            &structs->variable_pointers_features_khr);
    }
  """
  template_code = []

  for extension, struct_mappings in VK.VULKAN_EXTENSIONS_AND_STRUCTS_MAPPING["extensions"].items():
    struct_type = util.get_vkjson_struct_name(extension)

    template_code.append(f"template <typename Visitor>")
    template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_type}* structs) {{")
    template_code.append("  return ")

    visitor_calls = []
    for struct_map in struct_mappings:
      for struct_name in struct_map:
        json_field_name = struct_name.replace("VkPhysicalDevice", "")
        json_field_name = json_field_name[0].lower() + json_field_name[1:]

        # Special case renaming
        if json_field_name == "8BitStorageFeaturesKHR":
          json_field_name = "bit8StorageFeaturesKHR"

        visitor_calls.append(
            f'visitor->Visit("{json_field_name}", &structs->{util.get_struct_name(struct_name)})'
        )

    template_code.append(" &&\n         ".join(visitor_calls) + ";")
    template_code.append("}\n")

  return "\n".join(template_code)


def generate_core_template():
  """Generates templates for vulkan cores.
  template <typename Visitor>
  inline bool Iterate(Visitor* visitor, VkJsonCore11* core) {
    return visitor->Visit("properties", &core->properties) &&
          visitor->Visit("features", &core->features);
  }
  """
  template_code = []

  for version, struct_list in VK.VULKAN_CORES_AND_STRUCTS_MAPPING["versions"].items():
    struct_type = f"VkJson{version}"

    template_code.append(f"template <typename Visitor>")
    template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_type}* core) {{")
    template_code.append("  return")

    visitor_calls = []
    for struct_map in struct_list:
      for struct_name in struct_map:
        member_name = "properties" if "Properties" in struct_name else "features"
        visitor_calls.append(f'visitor->Visit("{member_name}", &core->{member_name})')

    template_code.append(" &&\n         ".join(visitor_calls) + ";")
    template_code.append("}\n")

  return "\n".join(template_code)


def generate_struct_template(data_classes):
  """Generates templates for all the structs
  template <typename Visitor>
  inline bool Iterate(Visitor* visitor,
                      VkPhysicalDevicePointClippingProperties* properties) {
    return visitor->Visit("pointClippingBehavior",
                          &properties->pointClippingBehavior);
  }
  """
  template_code = []
  processed_classes = set()  # Track processed class names

  for dataclass_type in data_classes:
    struct_name = dataclass_type.__name__

    if struct_name in processed_classes:
      continue  # Skip already processed struct
    processed_classes.add(struct_name)

    struct_fields = dataclasses.fields(dataclass_type)
    template_code.append("template <typename Visitor>")

    # Determine the correct variable name based on the struct type
    struct_var = "properties" if "Properties" in struct_name else "features" if "Features" in struct_name else "limits" if "Limits" in struct_name else None

    if not struct_var:
      continue  # Skip structs that don't match expected patterns

    template_code.append(f"inline bool Iterate(Visitor* visitor, {struct_name}* {struct_var}) {{")
    template_code.append(f"return\n")

    visitor_calls = []
    for struct_field in struct_fields:
      field_name = struct_field.name
      field_type = struct_field.type

      if get_origin(field_type) is list:
        # Handle list types (VisitArray)
        size_field_name = VK.LIST_TYPE_FIELD_AND_SIZE_MAPPING[field_name]
        visitor_calls.append(f'visitor->VisitArray("{field_name}", {struct_var}->{size_field_name}, &{struct_var}->{field_name})')
      else:
        # Handle other types (Visit)
        visitor_calls.append(f'visitor->Visit("{field_name}", &{struct_var}->{field_name})')

    template_code.append(" &&\n         ".join(visitor_calls) + ";")
    template_code.append("}\n\n")

  return "\n".join(template_code)


def gen_cc():
  """Generates vkjson.cc file.
  """
@@ -870,8 +649,8 @@ inline bool Iterate(Visitor* visitor, VkMemoryHeap* heap) {
    visitor->Visit("flags", &heap->flags);
}\n\n""")

    f.write(f"{generate_core_template()}\n\n{generate_extension_struct_template()}\n\n")
    f.write(generate_struct_template(VK.ALL_STRUCTS))
    f.write(f"{util.generate_core_template()}\n\n{util.generate_extension_struct_template()}\n\n")
    f.write(util.generate_struct_template(VK.ALL_STRUCTS))

    f.write("""\
template <typename Visitor>