Files
raven/scripts/generate-vulkan-chains.py
T

81 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Generate the table of Vulkan feature, property and format query structures that can travel in a pNext chain.
Every structure named VkPhysicalDevice...Features or ...Properties, or Vk...Format...Properties (any vendor suffix), whose members hold no pointers except
pNext is a plain block of bytes: it can be copied between guest and host without translating handles. The table pairs each
structure type value with the size of the host structure.
usage: generate-vulkan-chains.py /usr/include/vulkan/vulkan_core.h native/graphics/vulkan_chain_table.inc
"""
import os
import re
import subprocess
import sys
import tempfile
def snake(name):
text = re.sub(r"(?<=[a-z0-9])(?=[A-Z])", "_", name)
text = re.sub(r"(?<=[A-Z])(?=[A-Z][a-z])", "_", text)
return text.upper()
def main():
header = open(sys.argv[1]).read()
enumerators = set(re.findall(r"\b(VK_STRUCTURE_TYPE_[A-Z0-9_]+)\b", header))
entries = []
for match in re.finditer(r"typedef struct (Vk\w+) \{(.*?)\} \1;", header, re.S):
name, body = match.groups()
device_structure = re.match(r"VkPhysicalDevice\w*(Features|Properties)\w*$", name)
# Format and image format query results (VkFormatProperties3, external and Ycbcr image format answers) also travel in chains.
format_answer = re.match(r"Vk(?!PhysicalDevice|Video)\w*Format\w*Properties\w*$", name) and name not in ("VkFormatProperties2", "VkImageFormatProperties2")
if not (device_structure or format_answer) or "sType" not in body:
continue
members = [line.strip() for line in body.split(";") if line.strip()]
if any("*" in member and "pNext" not in member for member in members):
continue
suffix = re.search(r"(KHR|EXT|NV|NVX|AMD|INTEL|QCOM|ARM|HUAWEI|VALVE|MESA|IMG|ANDROID|FUCHSIA|GOOGLE|SEC|QNX|MSFT|EXT_PRIVATE)$", name)
stem = name[:-len(suffix.group(1))] if suffix else name
base = snake(stem[2:])
tail = ("_" + suffix.group(1)) if suffix else ""
# The enumerator spelling of digits varies: Vulkan11 is VULKAN_1_1, Robustness2 is ROBUSTNESS_2, Int64 stays INT64.
candidates = [
base,
re.sub(r"(?<=[A-Z])(\d)", r"_\1", base),
re.sub(r"VULKAN(\d)(\d)", r"VULKAN_\1_\2", base),
re.sub(r"VULKAN(\d)(\d)", r"VULKAN_\1_\2", re.sub(r"(?<=[A-Z])(\d)", r"_\1", base)),
]
candidate = next((("VK_STRUCTURE_TYPE_" + item + tail) for item in candidates if ("VK_STRUCTURE_TYPE_" + item + tail) in enumerators), None)
if not candidate:
continue
entries.append((candidate, name))
entries.sort()
# Beta-only structures are declared behind preprocessor switches; keep what the plain headers really provide.
include_root = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[1])))
for _ in range(8):
with tempfile.TemporaryDirectory() as directory:
probe = os.path.join(directory, "probe.c")
with open(probe, "w") as handle:
handle.write("#include <vulkan/vulkan.h>\nstatic const struct { int type; unsigned long size; } probe[] = {\n")
for enumerator, name in entries:
handle.write(f"{{{enumerator}, sizeof({name})}},\n")
handle.write("};\n")
result = subprocess.run(["cc", "-fsyntax-only", "-I" + include_root, probe], capture_output=True, text=True)
missing = set(re.findall(r"[‘'](VK_STRUCTURE_TYPE_\w+)[’']", result.stderr)) | set(re.findall(r"[‘'](Vk\w+)[’']", result.stderr))
if result.returncode == 0:
break
before = len(entries)
entries = [(e, n) for e, n in entries if e not in missing and n not in missing]
if len(entries) == before:
raise SystemExit(result.stderr)
print("// Generated by scripts/generate-vulkan-chains.py from the Vulkan headers; do not edit.", file=open(sys.argv[2], "w"))
with open(sys.argv[2], "a") as output:
for enumerator, name in entries:
print(f"{{{enumerator}, sizeof({name})}},", file=output)
print(len(entries), "structures")
if __name__ == "__main__":
main()