create_vulkan_odin_wrapper.py 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. import re
  2. import urllib.request as req
  3. from tokenize import tokenize
  4. from io import BytesIO
  5. import string
  6. import os.path
  7. import math
  8. file_and_urls = [
  9. ("vk_platform.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vk_platform.h', True),
  10. ("vulkan_core.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_core.h', False),
  11. ("vk_layer.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vk_layer.h', True),
  12. ("vk_icd.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vk_icd.h', True),
  13. ("vulkan_win32.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_win32.h', False),
  14. ("vulkan_metal.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_metal.h', False),
  15. ("vulkan_macos.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_macos.h', False),
  16. ("vulkan_ios.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_ios.h', False),
  17. ("vulkan_wayland.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_wayland.h', False),
  18. ("vulkan_xlib.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xlib.h', False),
  19. ("vulkan_xcb.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xcb.h', False),
  20. # Vulkan Video
  21. ("vulkan_video_codec_av1std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std.h', False),
  22. ("vulkan_video_codec_av1std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std_decode.h', False),
  23. ("vulkan_video_codec_av1std_encode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std_encode.h', False),
  24. ("vulkan_video_codec_h264std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h264std.h', False),
  25. ("vulkan_video_codec_h264std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h264std_decode.h', False),
  26. ("vulkan_video_codec_h264std_encode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h264std_encode.h', False),
  27. ("vulkan_video_codec_h265std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h265std.h', False),
  28. ("vulkan_video_codec_h265std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h265std_decode.h', False),
  29. ("vulkan_video_codec_h265std_encode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h265std_encode.h', False),
  30. ]
  31. for file, url, _ in file_and_urls:
  32. if not os.path.isfile(file):
  33. with open(file, 'w', encoding='utf-8') as f:
  34. f.write(req.urlopen(url).read().decode('utf-8'))
  35. src = ""
  36. for file, _, skip in file_and_urls:
  37. if skip: continue
  38. with open(file, 'r', encoding='utf-8') as f:
  39. src += f.read()
  40. def no_vk(t):
  41. t = t.replace('PFN_vk_icd', 'Procicd')
  42. t = t.replace('PFN_vk', 'Proc')
  43. t = t.replace('PFN_', 'Proc')
  44. t = t.replace('PFN_', 'Proc')
  45. t = re.sub('(?:Vk|VK_)?(\\w+)', '\\1', t)
  46. # Vulkan Video
  47. t = re.sub('(?:Std|STD_|VK_STD)?(\\w+)', '\\1', t)
  48. return t
  49. OPAQUE_STRUCTS = """
  50. wl_surface :: struct {} // Opaque struct defined by Wayland
  51. wl_display :: struct {} // Opaque struct defined by Wayland
  52. xcb_connection_t :: struct {} // Opaque struct defined by xcb
  53. IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
  54. """
  55. def convert_type(t, prev_name, curr_name):
  56. table = {
  57. "Bool32": 'b32',
  58. "float": 'f32',
  59. "double": 'f64',
  60. "uint32_t": 'u32',
  61. "uint64_t": 'u64',
  62. "size_t": 'int',
  63. 'int16_t': 'i16',
  64. 'int32_t': 'i32',
  65. 'int64_t': 'i64',
  66. 'int': 'c.int',
  67. 'uint8_t': 'u8',
  68. 'int8_t': 'i8',
  69. "uint16_t": 'u16',
  70. "char": "byte",
  71. "void": "void",
  72. "void*": "rawptr",
  73. "void *": "rawptr",
  74. "char*": 'cstring',
  75. "const uint32_t* const*": "^[^]u32",
  76. "const void*": 'rawptr',
  77. "const char*": 'cstring',
  78. "const char* const*": '[^]cstring',
  79. "const ObjectTableEntryNVX* const*": "^^ObjectTableEntryNVX",
  80. "const void* const *": "[^]rawptr",
  81. "const AccelerationStructureGeometryKHR* const*": "^[^]AccelerationStructureGeometryKHR",
  82. "const AccelerationStructureBuildRangeInfoKHR* const*": "^[^]AccelerationStructureBuildRangeInfoKHR",
  83. "const MicromapUsageEXT* const*": "^[^]MicromapUsageEXT",
  84. "struct BaseOutStructure": "BaseOutStructure",
  85. "struct BaseInStructure": "BaseInStructure",
  86. "struct wl_display": "wl_display",
  87. "struct wl_surface": "wl_surface",
  88. "Display": "XlibDisplay",
  89. "Window": "XlibWindow",
  90. "VisualID": "XlibVisualID",
  91. 'v': '',
  92. }
  93. if t in table.keys():
  94. return table[t]
  95. if t == "":
  96. return t
  97. if t.startswith("const"):
  98. t = convert_type(t[6:], prev_name, curr_name)
  99. elif t.endswith("*"):
  100. pointer = "^"
  101. ttype = t[:len(t)-1]
  102. elem = convert_type(ttype, prev_name, curr_name)
  103. if curr_name.endswith("s") or curr_name.endswith("Table"):
  104. if prev_name.endswith("Count") or prev_name.endswith("Counts"):
  105. pointer = "[^]"
  106. elif curr_name.startswith("pp"):
  107. if elem.startswith("[^]"):
  108. pass
  109. else:
  110. pointer = "[^]"
  111. elif curr_name.startswith("p"):
  112. pointer = "[^]"
  113. if curr_name and elem.endswith("Flags"):
  114. pointer = "[^]"
  115. return "{}{}".format(pointer, elem)
  116. elif t[0].isupper():
  117. return t
  118. return t
  119. def parse_array(n, t):
  120. name, length = n.split('[', 1)
  121. length = no_vk(length[:-1])
  122. type_ = "[{}]{}".format(length, do_type(t))
  123. return name, type_
  124. def remove_prefix(text, prefix):
  125. if text.startswith(prefix):
  126. return text[len(prefix):]
  127. return text
  128. def remove_suffix(text, suffix):
  129. if text.endswith(suffix):
  130. return text[:-len(suffix)]
  131. return text
  132. def to_snake_case(name):
  133. s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
  134. return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
  135. ext_suffixes = ["KHR", "EXT", "AMD", "NV", "NVX", "GOOGLE", "KHX"]
  136. ext_suffixes_title = [ext.title() for ext in ext_suffixes]
  137. def fix_arg(arg):
  138. name = arg
  139. # Remove useless pointer identifier in field name
  140. for p in ('s_', 'p_', 'pp_', 'pfn_'):
  141. if name.startswith(p):
  142. name = name[len(p)::]
  143. name = name.replace("__", "_")
  144. return name
  145. def fix_ext_suffix(name):
  146. for ext in ext_suffixes_title:
  147. if name.endswith(ext):
  148. start = name[:-len(ext)]
  149. end = name[-len(ext):].upper()
  150. return start+end
  151. return name
  152. def to_int(x):
  153. if x.startswith('0x'):
  154. return int(x, 16)
  155. return int(x)
  156. def is_int(x):
  157. try:
  158. int(x)
  159. return True
  160. except ValueError:
  161. return False
  162. def fix_enum_arg(name, is_flag_bit=False):
  163. # name = name.title()
  164. name = fix_ext_suffix(name)
  165. if len(name) > 0 and name[0].isdigit() and not name.startswith("0x") and not is_int(name):
  166. if name[1] == "D":
  167. name = name[1] + name[0] + (name[2:] if len(name) > 2 else "")
  168. else:
  169. name = "_"+name
  170. if is_flag_bit:
  171. name = name.replace("_BIT", "")
  172. return name
  173. def do_type(t, prev_name="", name=""):
  174. return convert_type(no_vk(t), prev_name, name).replace("FlagBits", "Flags")
  175. def parse_handles_def(f):
  176. f.write("// Handles types\n")
  177. handles = [h for h in re.findall(r"VK_DEFINE_HANDLE\(Vk(\w+)\)", src, re.S)]
  178. max_len = max(len(h) for h in handles)
  179. for h in handles:
  180. f.write("{} :: distinct Handle\n".format(h.ljust(max_len)))
  181. handles_non_dispatchable = [h for h in re.findall(r"VK_DEFINE_NON_DISPATCHABLE_HANDLE\(Vk(\w+)\)", src, re.S)]
  182. max_len = max(len(h) for h in handles_non_dispatchable)
  183. for h in handles_non_dispatchable:
  184. f.write("{} :: distinct NonDispatchableHandle\n".format(h.ljust(max_len)))
  185. flags_defs = set()
  186. def parse_flags_def(f):
  187. names = [n for n in re.findall(r"typedef VkFlags Vk(\w+?);", src)]
  188. global flags_defs
  189. flags_defs = set(names)
  190. class FlagError(ValueError):
  191. pass
  192. class IgnoreFlagError(ValueError):
  193. pass
  194. def fix_enum_name(name, prefix, suffix, is_flag_bit):
  195. name = remove_prefix(name, prefix)
  196. if suffix:
  197. name = remove_suffix(name, suffix)
  198. if name.startswith("0x"):
  199. if is_flag_bit:
  200. i = int(name, 16)
  201. if i == 0:
  202. raise IgnoreFlagError(i)
  203. v = int(math.log2(i))
  204. if 2**v != i:
  205. raise FlagError(i)
  206. return str(v)
  207. return name
  208. elif is_flag_bit:
  209. ignore = False
  210. try:
  211. if int(name) == 0:
  212. ignore = True
  213. except:
  214. pass
  215. if ignore:
  216. raise IgnoreFlagError()
  217. return fix_enum_arg(name, is_flag_bit)
  218. def fix_enum_value(value, prefix, suffix, is_flag_bit):
  219. v = no_vk(value)
  220. g = tokenize(BytesIO(v.encode('utf-8')).readline)
  221. tokens = [val for _, val, _, _, _ in g]
  222. assert len(tokens) > 2
  223. token = ''.join([t for t in tokens[1:-1] if t])
  224. token = fix_enum_name(token, prefix, suffix, is_flag_bit)
  225. return token
  226. def parse_constants(f):
  227. f.write("// General Constants\n")
  228. all_data = re.findall(r"#define VK_(\w+)\s*(.*?)U?\n", src, re.S)
  229. allowed_names = (
  230. "HEADER_VERSION",
  231. "MAX_DRIVER_NAME_SIZE",
  232. "MAX_DRIVER_INFO_SIZE",
  233. )
  234. allowed_data = [nv for nv in all_data if nv[0] in allowed_names]
  235. max_len = max(len(name) for name, value in allowed_data)
  236. for name, value in allowed_data:
  237. f.write("{}{} :: {}\n".format(name, "".rjust(max_len-len(name)), value))
  238. f.write("\n// Vulkan Video Constants\n")
  239. vulkan_video_data = re.findall(r"#define STD_(\w+)\s*(.*?)U?\n", src, re.S)
  240. max_len = max(len(name) for name, value in vulkan_video_data)
  241. for name, value in vulkan_video_data:
  242. f.write("{}{} :: {}\n".format(name, "".rjust(max_len-len(name)), value))
  243. f.write("\n// Vulkan Video Codec Constants\n")
  244. vulkan_video_codec_allowed_suffixes = (
  245. "_EXTENSION_NAME",
  246. )
  247. vulkan_video_codec_data = re.findall(r"#define VK_STD_(\w+)\s*(.*?)U?\n", src, re.S)
  248. vulkan_video_codec_allowed_data = [nv for nv in vulkan_video_codec_data if nv[0].endswith(vulkan_video_codec_allowed_suffixes)]
  249. max_len = max(len(name) for name, value in vulkan_video_codec_allowed_data)
  250. for name, value in vulkan_video_codec_allowed_data:
  251. f.write("{}{} :: {}\n".format(name, "".rjust(max_len-len(name)), value))
  252. f.write("\n// Vendor Constants\n")
  253. fixes = '|'.join(ext_suffixes)
  254. inner = r"((?:(?:" + fixes + r")\w+)|(?:\w+" + fixes + r"))"
  255. pattern = r"#define\s+VK_" + inner + r"\s*(.*?)\n"
  256. data = re.findall(pattern, src, re.S)
  257. number_suffix_re = re.compile(r"(\d+)[UuLlFf]")
  258. max_len = max(len(name) for name, value in data)
  259. for name, value in data:
  260. value = remove_prefix(value, 'VK_')
  261. v = number_suffix_re.findall(value)
  262. if v:
  263. value = v[0]
  264. f.write("{}{} :: {}\n".format(name, "".rjust(max_len-len(name)), value))
  265. f.write("\n")
  266. def parse_enums(f):
  267. f.write("import \"core:c\"\n\n")
  268. f.write("// Enums\n")
  269. data = re.findall(r"typedef enum (\w+) {(.+?)} \w+;", src, re.S)
  270. data = [(no_vk(n), f) for n, f in data]
  271. data.sort(key=lambda x: x[0])
  272. generated_flags = set()
  273. for name, fields in data:
  274. enum_name = name
  275. is_flag_bit = False
  276. if "FlagBits" in enum_name:
  277. is_flag_bit = True
  278. flags_name = enum_name.replace("FlagBits", "Flags")
  279. enum_name = enum_name.replace("FlagBits", "Flag")
  280. generated_flags.add(flags_name)
  281. f.write("{} :: distinct bit_set[{}; Flags]\n".format(flags_name, enum_name))
  282. if is_flag_bit:
  283. f.write("{} :: enum Flags {{\n".format(name.replace("FlagBits", "Flag")))
  284. else:
  285. f.write("{} :: enum c.int {{\n".format(name))
  286. prefix = to_snake_case(name).upper()
  287. suffix = None
  288. for ext in ext_suffixes:
  289. prefix_new = remove_suffix(prefix, "_"+ext)
  290. assert suffix is None
  291. if prefix_new != prefix:
  292. suffix = "_"+ext
  293. prefix = prefix_new
  294. break
  295. prefix = prefix.replace("_FLAG_BITS", "")
  296. prefix += "_"
  297. ff = []
  298. names_and_values = re.findall(r"VK_(\w+?) = (.*?)(?:,|})", fields, re.S)
  299. groups = []
  300. flags = {}
  301. for name, value in names_and_values:
  302. n = fix_enum_name(name, prefix, suffix, is_flag_bit)
  303. try:
  304. v = fix_enum_value(value, prefix, suffix, is_flag_bit)
  305. except FlagError as e:
  306. v = int(str(e))
  307. groups.append((n, v))
  308. continue
  309. except IgnoreFlagError as e:
  310. groups.append((n, 0))
  311. continue
  312. if n == v:
  313. continue
  314. try:
  315. flags[int(v)] = n
  316. except ValueError as e:
  317. pass
  318. if v == "NONE":
  319. continue
  320. ff.append((n, v))
  321. max_flag_value = max([int(v) for n, v in ff if is_int(v)] + [0])
  322. max_group_value = max([int(v) for n, v in groups if is_int(v)] + [0])
  323. if max_flag_value < max_group_value:
  324. if (1<<max_flag_value)+1 < max_group_value:
  325. ff.append(('_MAX', 31))
  326. flags[31] = '_MAX'
  327. pass
  328. max_len = max([len(n) for n, v in ff] + [0])
  329. flag_names = set([n for n, v in ff])
  330. for n, v in ff:
  331. if is_flag_bit and not is_int(v) and v not in flag_names:
  332. print("Ignoring", n, "=", v)
  333. continue
  334. f.write("\t{} = {},".format(n.ljust(max_len), v))
  335. if n == "_MAX":
  336. f.write(" // Needed for the *_ALL bit set")
  337. f.write("\n")
  338. f.write("}\n\n")
  339. for n, v in groups:
  340. used_flags = []
  341. for i in range(0, 32):
  342. if 1<<i & v != 0:
  343. if i in flags:
  344. used_flags.append('.'+flags[i])
  345. else:
  346. used_flags.append('{}({})'.format(enum_name, i))
  347. # Make sure the 's' is after Flags and not the extension name.
  348. ext_suffix = ''
  349. for suffix in ext_suffixes:
  350. if not enum_name.endswith(suffix):
  351. continue
  352. ext_suffix = suffix
  353. enum_name = remove_suffix(enum_name, ext_suffix)
  354. break
  355. s = "{enum_name}s{ext_suffix}_{n} :: {enum_name}s{ext_suffix}{{".format(enum_name=enum_name, ext_suffix=ext_suffix, n=n)
  356. s += ', '.join(used_flags)
  357. s += "}\n"
  358. f.write(s)
  359. if len(groups) > 0:
  360. f.write("\n\n")
  361. unused_flags = [flag for flag in flags_defs if flag not in generated_flags]
  362. unused_flags.sort()
  363. max_len = max(len(flag) for flag in unused_flags)
  364. for flag in unused_flags:
  365. flag_name = flag.replace("Flags", "Flag")
  366. f.write("{} :: distinct bit_set[{}; Flags]\n".format(flag.ljust(max_len), flag_name))
  367. f.write("{} :: enum u32 {{}}\n".format(flag_name.ljust(max_len)))
  368. def parse_fake_enums(f):
  369. data = re.findall(r"static const Vk(\w+FlagBits2) VK_(\w+?) = (\w+);", src, re.S)
  370. data.sort(key=lambda x: x[0])
  371. fake_enums = {}
  372. for type_name, name, value in data:
  373. if type_name in fake_enums:
  374. fake_enums[type_name].append((name,value))
  375. else:
  376. fake_enums[type_name] = [(name, value)]
  377. for name in fake_enums.keys():
  378. flags_name = name.replace("FlagBits", "Flags")
  379. enum_name = name.replace("FlagBits", "Flag")
  380. f.write("{} :: distinct bit_set[{}; Flags64]\n".format(flags_name, enum_name))
  381. f.write("{} :: enum Flags64 {{\n".format(name.replace("FlagBits", "Flag")))
  382. prefix = to_snake_case(name).upper()
  383. suffix = None
  384. for ext in ext_suffixes:
  385. prefix_new = remove_suffix(prefix, "_"+ext)
  386. assert suffix is None
  387. if prefix_new != prefix:
  388. suffix = "_"+ext
  389. prefix = prefix_new
  390. break
  391. prefix = prefix.replace("_FLAG_BITS2", "_2")
  392. prefix += "_"
  393. ff = []
  394. groups = []
  395. flags = {}
  396. names_and_values = fake_enums[name]
  397. for name, value in names_and_values:
  398. value = value.replace("ULL", "")
  399. n = fix_enum_name(name, prefix, suffix, True)
  400. try:
  401. v = fix_enum_value(value, prefix, suffix, True)
  402. except FlagError as e:
  403. v = int(str(e))
  404. groups.append((n, v))
  405. continue
  406. except IgnoreFlagError as e:
  407. groups.append((n, 0))
  408. continue
  409. if n == v:
  410. continue
  411. try:
  412. flags[int(v)] = n
  413. except ValueError as e:
  414. pass
  415. if v == "NONE":
  416. continue
  417. ff.append((n, v))
  418. max_flag_value = max([int(v) for n, v in ff if is_int(v)] + [0])
  419. max_group_value = max([int(v) for n, v in groups if is_int(v)] + [0])
  420. if max_flag_value < max_group_value:
  421. if (1<<max_flag_value)+1 < max_group_value:
  422. ff.append(('_MAX', 31))
  423. flags[31] = '_MAX'
  424. pass
  425. max_len = max([len(n) for n, v in ff] + [0])
  426. flag_names = set([n for n, v in ff])
  427. for n, v in ff:
  428. if not is_int(v) and v not in flag_names:
  429. print("Ignoring", n, "=", v)
  430. continue
  431. f.write("\t{} = {},".format(n.ljust(max_len), v))
  432. if n == "_MAX":
  433. f.write(" // Needed for the *_ALL bit set")
  434. f.write("\n")
  435. f.write("}\n\n")
  436. class BitfieldError(ValueError):
  437. pass
  438. def bitfield_type_to_size(type_):
  439. if type_ == 'u8':
  440. return 8
  441. if type_ == 'u16':
  442. return 16
  443. if type_ == 'u32':
  444. return 32
  445. if type_ == 'u64':
  446. return 64
  447. if 'Flags' in type_:
  448. return 32
  449. else:
  450. raise BitfieldError(f"Invalid type for bitfield: {type_}")
  451. def bitfield_size_to_type(size):
  452. if size == 8:
  453. return 'u8'
  454. if size == 16:
  455. return 'u16'
  456. if size == 32:
  457. return 'u32'
  458. if size == 64:
  459. return 'u64'
  460. else:
  461. raise BitfieldError(f"Invalid size for bitfield: {size}")
  462. class Bitfield:
  463. class Field:
  464. def __init__(self, name, type_, bitsize):
  465. self.name = name
  466. self.type = type_
  467. self.bitsize = bitsize
  468. def __init__(self, type_):
  469. self.bitsize = bitfield_type_to_size(type_)
  470. self.type = bitfield_size_to_type(self.bitsize)
  471. self.fields_bitsize = 0
  472. self.fields = []
  473. def add_field(self, name, type_, bitsize):
  474. self.fields.append(Bitfield.Field(name, type_, bitsize))
  475. self.fields_bitsize += bitsize
  476. def write(self, f, name=None, indent=0, justify=True):
  477. max_name = 1 if not justify else max([len(f.name) for f in self.fields], default=0)
  478. max_type = 1 if not justify else max([len(f.type) for f in self.fields], default=0)
  479. is_bit_set = all([f.bitsize == 1 or f.name == "reserved" for f in self.fields])
  480. if is_bit_set and name is None:
  481. raise BitfieldError(f"bit_set can not be anonymous")
  482. if is_bit_set:
  483. if not name.endswith("Flags"):
  484. raise BitfieldError(f"bit_set name should end with 'Flags': {name}")
  485. enum_name = re.sub('Flags$', 'Flag', name)
  486. f.write("{}{} :: distinct bit_set[{}; {}]\n".format('\t' * indent, name, enum_name, self.type))
  487. f.write("{}{} :: enum {} {{\n".format('\t' * indent, enum_name, self.type))
  488. for field in self.fields:
  489. if field.name != "reserved":
  490. f.write("{}{},\n".format('\t' * (indent + 1), field.name))
  491. f.write(('\t' * indent) + "}\n")
  492. else:
  493. f.write("{}{} bit_field {} {{\n".format('\t' * indent, name + ' ::' if name else 'using _:', self.type))
  494. for field in self.fields:
  495. type_ = field.type.replace("Flags", "Flag")
  496. f.write("{}{} {} | {},\n".format(
  497. '\t' * (indent + 1),
  498. (field.name + ":").ljust(max_name + 1),
  499. type_.ljust(max_type),
  500. field.bitsize))
  501. f.write(('\t' * indent) + "}" + ("," if name is None else "") + "\n")
  502. def parse_structs(f):
  503. data = re.findall(r"typedef (struct|union) Vk(\w+?) {(.+?)} \w+?;", src, re.S)
  504. data += re.findall(r"typedef (struct|union) Std(\w+?) {(.+?)} \w+?;", src, re.S)
  505. for _type, struct_name, fields in data:
  506. fields = re.findall(r"\s+(.+?)[\s:]+([_a-zA-Z0-9[\]]+);", fields)
  507. prev_name = ""
  508. ffields = []
  509. bitfield = None
  510. for type_, fname in fields:
  511. # If the field name only has a number in it, then it is a C bit field.
  512. # We will collect all the bit fields and then create either a bit_field or a bit_set.
  513. if is_int(fname):
  514. bf_field = type_.split(' ')
  515. # Get rid of empty spaces
  516. bf_field = list(filter(bool, bf_field))
  517. # [type, fieldname]
  518. assert len(bf_field) == 2, "Failed to parse the bit field!"
  519. field_type = do_type(bf_field[0])
  520. bitsize = int(fname)
  521. # Close the set because the field size is greater than the bitfield type
  522. if bitfield and (bitfield.fields_bitsize + bitsize) > bitfield_type_to_size(field_type):
  523. ffields.append(tuple([None, bitfield]))
  524. bitfield = None
  525. # Raise an error if the field type size is greater than the bitfield type size
  526. if bitfield is not None and bitfield_type_to_size(bitfield.type) < bitfield_type_to_size(field_type):
  527. raise BitfieldError(f"field will not fit in the bitfield: {bitfield.type} < {field_type}")
  528. # Create a new bitfield if we don't have one
  529. if not bitfield:
  530. bitfield = Bitfield(field_type)
  531. # Add the field to the bitfield
  532. bitfield.add_field(bf_field[1], field_type, bitsize)
  533. continue
  534. # Close the bitfield because this is not a field
  535. elif bitfield:
  536. ffields.append(tuple([None, bitfield]))
  537. bitfield = None
  538. if '[' in fname:
  539. fname, type_ = parse_array(fname, type_)
  540. n = fix_arg(fname)
  541. if "Flag_Bits" in type_:
  542. # comment = " // only single bit set"
  543. raise BitfieldError("only single bit set")
  544. t = do_type(type_, prev_name, fname)
  545. if n == "matrix":
  546. n = "mat"
  547. ffields.append(tuple([n, t]))
  548. prev_name = fname
  549. # Close the bitfield because we have no more fields
  550. if bitfield:
  551. ffields.append(tuple([None, bitfield]))
  552. # Write the struct as a bitfield if it only has bit fields
  553. if len(ffields) == 1 and ffields[0][0] is None:
  554. ffields[0][1].write(f, struct_name, 0, True)
  555. f.write("\n")
  556. # Write as a normal struct (or union) if it has other fields
  557. # and inject anonymous bitfields into the struct if there are any
  558. else:
  559. has_anon_bitfield = any(name is None for name, _ in ffields)
  560. max_len = 1 if has_anon_bitfield else max([len(n) for n, _ in ffields], default=0)
  561. f.write("{} :: struct ".format(struct_name))
  562. if _type == "union":
  563. f.write("#raw_union ")
  564. f.write("{\n")
  565. for name, type_ in ffields:
  566. if name is None:
  567. # Inject an anonymous bitfield into the struct
  568. type_.write(f, None, indent=1, justify=True)
  569. else:
  570. f.write("\t{} {},\n".format((name + ":").ljust(max_len + 1), type_))
  571. f.write("}\n\n")
  572. f.write("// Opaque structs\n")
  573. f.write(OPAQUE_STRUCTS)
  574. f.write("// Aliases\n")
  575. data = re.findall(r"typedef Vk(\w+?) Vk(\w+?);", src, re.S)
  576. aliases = []
  577. for _type, name in data:
  578. if _type == "Flags":
  579. continue
  580. name = name.replace("FlagBits", "Flag")
  581. _type = _type.replace("FlagBits", "Flag")
  582. if name.endswith("Flag2") or name.endswith("Flags2"):
  583. continue
  584. aliases.append((name, _type))
  585. max_len = max([len(n) for n, _ in aliases] + [0])
  586. for n, t in aliases:
  587. k = max_len
  588. f.write("{} :: {}\n".format(n.ljust(k), t))
  589. procedure_map = {}
  590. def parse_procedures(f):
  591. data = re.findall(r"typedef (\w+\*?) \(\w+ \*(\w+)\)\((.+?)\);", src, re.S)
  592. group_ff = {"Loader":[], "Misc":[], "Instance":[], "Device":[]}
  593. for rt, name, fields in data:
  594. proc_name = no_vk(name)
  595. pf = []
  596. prev_name = ""
  597. for type_, fname, array_len in re.findall(r"(?:\s*|)(.+?)\s*(\w+)(?:\[(\d+)\])?(?:,|$)", fields):
  598. curr_name = fix_arg(fname)
  599. ty = do_type(type_, prev_name, curr_name)
  600. if array_len != "":
  601. ty = f"^[{array_len}]{ty}"
  602. pf.append((ty, curr_name))
  603. prev_name = curr_name
  604. data_fields = ', '.join(["{}: {}".format(n, t) for t, n in pf if t != ""])
  605. ts = "proc \"c\" ({})".format(data_fields)
  606. rt_str = do_type(rt)
  607. if rt_str != "void":
  608. ts += " -> {}".format(rt_str)
  609. procedure_map[proc_name] = ts
  610. fields_types_name = [do_type(t) for t in re.findall(r"(?:\s*|)(.+?)\s*\w+(?:,|$)", fields)]
  611. table_name = fields_types_name[0]
  612. nn = (proc_name, ts)
  613. if table_name in ('Device', 'Queue', 'CommandBuffer') and proc_name != 'GetDeviceProcAddr':
  614. group_ff["Device"].append(nn)
  615. elif table_name in ('Instance', 'PhysicalDevice') or proc_name == 'GetDeviceProcAddr':
  616. group_ff["Instance"].append(nn)
  617. elif table_name in ('rawptr', '', 'DebugReportFlagsEXT') or proc_name == 'GetInstanceProcAddr':
  618. group_ff["Misc"].append(nn)
  619. else:
  620. group_ff["Loader"].append(nn)
  621. f.write("import \"core:c\"\n\n")
  622. for group_name, ff in group_ff.items():
  623. ff.sort()
  624. f.write("// {} Procedure Types\n".format(group_name))
  625. max_len = max(len(n) for n, t in ff)
  626. for n, t in ff:
  627. f.write("{} :: #type {}\n".format(n.ljust(max_len), t.replace('"c"', '"system"')))
  628. f.write("\n")
  629. def group_functions(f):
  630. data = re.findall(r"typedef (\w+\*?) \(\w+ \*(\w+)\)\((.+?)\);", src, re.S)
  631. group_map = {"Loader":[], "Instance":[], "Device":[]}
  632. for rt, vkname, fields in data:
  633. fields_types_name = [do_type(t) for t in re.findall(r"(?:\s*|)(.+?)\s*\w+(?:,|$)", fields)]
  634. table_name = fields_types_name[0]
  635. name = no_vk(vkname)
  636. nn = (fix_arg(name), fix_ext_suffix(name))
  637. if table_name in ('Device', 'Queue', 'CommandBuffer') and name != 'GetDeviceProcAddr':
  638. group_map["Device"].append(nn)
  639. elif table_name in ('Instance', 'PhysicalDevice') and name != 'ProcGetInstanceProcAddr' or name == 'GetDeviceProcAddr':
  640. group_map["Instance"].append(nn)
  641. elif table_name in ('rawptr', '', 'DebugReportFlagsEXT') or name == 'GetInstanceProcAddr':
  642. # Skip the allocation function and the dll entry point
  643. pass
  644. else:
  645. group_map["Loader"].append(nn)
  646. for _, group in group_map.items():
  647. group.sort()
  648. for group_name, group_lines in group_map.items():
  649. f.write("// {} Procedures\n".format(group_name))
  650. max_len = max(len(name) for name, _ in group_lines)
  651. for name, vk_name in group_lines:
  652. type_str = procedure_map[vk_name]
  653. f.write('{}: {}\n'.format(remove_prefix(name, "Proc"), name.rjust(max_len)))
  654. f.write("\n")
  655. f.write("load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {\n")
  656. for group_name, group_lines in group_map.items():
  657. f.write("\t// {} Procedures\n".format(group_name))
  658. max_len = max(len(name) for name, _ in group_lines)
  659. for name, vk_name in group_lines:
  660. k = max_len - len(name)
  661. f.write('\tset_proc_address(&{}, {}"vk{}")\n'.format(
  662. remove_prefix(name, 'Proc'),
  663. "".ljust(k),
  664. remove_prefix(vk_name, 'Proc'),
  665. ))
  666. f.write("\n")
  667. f.write("}\n\n")
  668. f.write("// Device Procedure VTable\n")
  669. f.write("Device_VTable :: struct {\n")
  670. max_len = max(len(name) for name, _ in group_map["Device"])
  671. for name, vk_name in group_map["Device"]:
  672. f.write('\t{}: {},\n'.format(remove_prefix(name, "Proc"), name.rjust(max_len)))
  673. f.write("}\n\n")
  674. f.write("load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable) {\n")
  675. for name, vk_name in group_map["Device"]:
  676. k = max_len - len(name)
  677. f.write('\tvtable.{}{} = auto_cast GetDeviceProcAddr(device, "vk{}")\n'.format(
  678. remove_prefix(name, 'Proc'),
  679. "".ljust(k),
  680. remove_prefix(vk_name, 'Proc'),
  681. ))
  682. f.write("}\n\n")
  683. f.write("load_proc_addresses_device :: proc(device: Device) {\n")
  684. max_len = max(len(name) for name, _ in group_map["Device"])
  685. for name, vk_name in group_map["Device"]:
  686. k = max_len - len(name)
  687. f.write('\t{}{} = auto_cast GetDeviceProcAddr(device, "vk{}")\n'.format(
  688. remove_prefix(name, 'Proc'),
  689. "".ljust(k),
  690. remove_prefix(vk_name, 'Proc'),
  691. ))
  692. f.write("}\n\n")
  693. f.write("load_proc_addresses_instance :: proc(instance: Instance) {\n")
  694. max_len = max(len(name) for name, _ in group_map["Instance"])
  695. for name, vk_name in group_map["Instance"]:
  696. k = max_len - len(name)
  697. f.write('\t{}{} = auto_cast GetInstanceProcAddr(instance, "vk{}")\n'.format(
  698. remove_prefix(name, 'Proc'),
  699. "".ljust(k),
  700. remove_prefix(vk_name, 'Proc'),
  701. ))
  702. f.write("\n\t// Device Procedures (may call into dispatch)\n")
  703. max_len = max(len(name) for name, _ in group_map["Device"])
  704. for name, vk_name in group_map["Device"]:
  705. k = max_len - len(name)
  706. f.write('\t{}{} = auto_cast GetInstanceProcAddr(instance, "vk{}")\n'.format(
  707. remove_prefix(name, 'Proc'),
  708. "".ljust(k),
  709. remove_prefix(vk_name, 'Proc'),
  710. ))
  711. f.write("}\n\n")
  712. f.write("load_proc_addresses_global :: proc(vk_get_instance_proc_addr: rawptr) {\n")
  713. f.write("\tGetInstanceProcAddr = auto_cast vk_get_instance_proc_addr\n\n")
  714. max_len = max(len(name) for name, _ in group_map["Loader"])
  715. for name, vk_name in group_map["Loader"]:
  716. k = max_len - len(name)
  717. f.write('\t{}{} = auto_cast GetInstanceProcAddr(nil, "vk{}")\n'.format(
  718. remove_prefix(name, 'Proc'),
  719. "".ljust(k),
  720. remove_prefix(vk_name, 'Proc'),
  721. ))
  722. f.write("}\n\n")
  723. f.write("""
  724. load_proc_addresses :: proc{
  725. \tload_proc_addresses_global,
  726. \tload_proc_addresses_instance,
  727. \tload_proc_addresses_device,
  728. \tload_proc_addresses_device_vtable,
  729. \tload_proc_addresses_custom,
  730. }\n
  731. """[1::])
  732. BASE = """
  733. //
  734. // Vulkan wrapper generated from "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h"
  735. //
  736. package vulkan
  737. """[1::]
  738. with open("../core.odin", 'w', encoding='utf-8') as f:
  739. f.write(BASE)
  740. f.write("""
  741. // Core API
  742. API_VERSION_1_0 :: (1<<22) | (0<<12) | (0)
  743. API_VERSION_1_1 :: (1<<22) | (1<<12) | (0)
  744. API_VERSION_1_2 :: (1<<22) | (2<<12) | (0)
  745. API_VERSION_1_3 :: (1<<22) | (3<<12) | (0)
  746. API_VERSION_1_4 :: (1<<22) | (4<<12) | (0)
  747. MAKE_VERSION :: proc(major, minor, patch: u32) -> u32 {
  748. \treturn (major<<22) | (minor<<12) | (patch)
  749. }
  750. // Base types
  751. Flags :: distinct u32
  752. Flags64 :: distinct u64
  753. DeviceSize :: distinct u64
  754. DeviceAddress :: distinct u64
  755. SampleMask :: distinct u32
  756. Handle :: distinct rawptr
  757. NonDispatchableHandle :: distinct u64
  758. SetProcAddressType :: #type proc(p: rawptr, name: cstring)
  759. RemoteAddressNV :: distinct rawptr // Declared inline before MemoryGetRemoteAddressInfoNV
  760. // Base constants
  761. LOD_CLAMP_NONE :: 1000.0
  762. REMAINING_MIP_LEVELS :: ~u32(0)
  763. REMAINING_ARRAY_LAYERS :: ~u32(0)
  764. WHOLE_SIZE :: ~u64(0)
  765. ATTACHMENT_UNUSED :: ~u32(0)
  766. TRUE :: 1
  767. FALSE :: 0
  768. QUEUE_FAMILY_IGNORED :: ~u32(0)
  769. SUBPASS_EXTERNAL :: ~u32(0)
  770. MAX_PHYSICAL_DEVICE_NAME_SIZE :: 256
  771. MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT :: 32
  772. UUID_SIZE :: 16
  773. MAX_MEMORY_TYPES :: 32
  774. MAX_MEMORY_HEAPS :: 16
  775. MAX_EXTENSION_NAME_SIZE :: 256
  776. MAX_DESCRIPTION_SIZE :: 256
  777. MAX_DEVICE_GROUP_SIZE :: 32
  778. LUID_SIZE_KHX :: 8
  779. LUID_SIZE :: 8
  780. MAX_QUEUE_FAMILY_EXTERNAL :: ~u32(1)
  781. MAX_GLOBAL_PRIORITY_SIZE :: 16
  782. MAX_GLOBAL_PRIORITY_SIZE_EXT :: MAX_GLOBAL_PRIORITY_SIZE
  783. QUEUE_FAMILY_EXTERNAL :: MAX_QUEUE_FAMILY_EXTERNAL
  784. // Vulkan Video API Constants
  785. VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_1_0_0 :: (1<<22) | (0<<12) | (0)
  786. VULKAN_VIDEO_CODEC_AV1_ENCODE_API_VERSION_1_0_0 :: (1<<22) | (0<<12) | (0)
  787. VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_1_0_0 :: (1<<22) | (0<<12) | (0)
  788. VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 :: (1<<22) | (0<<12) | (0)
  789. VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 :: (1<<22) | (0<<12) | (0)
  790. VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_1_0_0 :: (1<<22) | (0<<12) | (0)
  791. VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_1_0_0
  792. VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_AV1_ENCODE_API_VERSION_1_0_0
  793. VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_1_0_0
  794. VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0
  795. VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0
  796. VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_1_0_0
  797. MAKE_VIDEO_STD_VERSION :: MAKE_VERSION
  798. """[1::])
  799. parse_constants(f)
  800. parse_handles_def(f)
  801. f.write("\n\n")
  802. parse_flags_def(f)
  803. with open("../enums.odin", 'w', encoding='utf-8') as f:
  804. f.write(BASE)
  805. f.write("\n")
  806. parse_enums(f)
  807. parse_fake_enums(f)
  808. f.write("\n\n")
  809. with open("../structs.odin", 'w', encoding='utf-8') as f:
  810. f.write(BASE)
  811. f.write("""
  812. import "core:c"
  813. import win32 "core:sys/windows"
  814. _ :: win32
  815. import "vendor:x11/xlib"
  816. _ :: xlib
  817. when ODIN_OS == .Windows {
  818. \tHINSTANCE :: win32.HINSTANCE
  819. \tHWND :: win32.HWND
  820. \tHMONITOR :: win32.HMONITOR
  821. \tHANDLE :: win32.HANDLE
  822. \tLPCWSTR :: win32.LPCWSTR
  823. \tSECURITY_ATTRIBUTES :: win32.SECURITY_ATTRIBUTES
  824. \tDWORD :: win32.DWORD
  825. \tLONG :: win32.LONG
  826. \tLUID :: win32.LUID
  827. } else {
  828. \tHINSTANCE :: distinct rawptr
  829. \tHWND :: distinct rawptr
  830. \tHMONITOR :: distinct rawptr
  831. \tHANDLE :: distinct rawptr
  832. \tLPCWSTR :: ^u16
  833. \tSECURITY_ATTRIBUTES :: struct {}
  834. \tDWORD :: u32
  835. \tLONG :: c.long
  836. \tLUID :: struct {
  837. \t\tLowPart: DWORD,
  838. \t\tHighPart: LONG,
  839. \t}
  840. }
  841. when xlib.IS_SUPPORTED {
  842. \tXlibDisplay :: xlib.Display
  843. \tXlibWindow :: xlib.Window
  844. \tXlibVisualID :: xlib.VisualID
  845. } else {
  846. \tXlibDisplay :: struct {} // Opaque struct defined by Xlib
  847. \tXlibWindow :: c.ulong
  848. \tXlibVisualID :: c.ulong
  849. }
  850. xcb_visualid_t :: u32
  851. xcb_window_t :: u32
  852. CAMetalLayer :: struct {}
  853. MTLBuffer_id :: rawptr
  854. MTLTexture_id :: rawptr
  855. MTLSharedEvent_id :: rawptr
  856. MTLDevice_id :: rawptr
  857. MTLCommandQueue_id :: rawptr
  858. /********************************/
  859. """)
  860. f.write("\n")
  861. parse_structs(f)
  862. f.write("\n\n")
  863. with open("../procedures.odin", 'w', encoding='utf-8') as f:
  864. f.write(BASE)
  865. f.write("\n")
  866. parse_procedures(f)
  867. f.write("\n")
  868. group_functions(f)