comparison svk/generate.nim @ 1479:172ac338f820 main

add: prep to add new vulkan api
author sam <sam@basx.dev>
date Sun, 20 Apr 2025 21:57:56 +0700
parents
children 0b302531f5c5
comparison
equal deleted inserted replaced
1478:6b389ac08e5e 1479:172ac338f820
1 import std/strtabs
2 import std/xmltree
3 import std/tables
4 import std/options
5 import std/sequtils
6 import std/strutils
7 import std/strformat
8 import std/xmlparser
9 import std/os
10 import std/paths
11
12 # helpers
13 func smartParseInt(value: string): int =
14 if value.startsWith("0x"):
15 parseHexInt(value)
16 else:
17 parseInt(value)
18
19 const TYPEMAP = {
20 "void": "void",
21 "char": "char",
22 "float": "float32",
23 "double": "float64",
24 "int8_t": "int8",
25 "uint8_t": "uint8",
26 "int16_t": "int16",
27 "uint16_t": "uint16",
28 "int32_t": "int32",
29 "uint32_t": "uint32",
30 "uint64_t": "uint64",
31 "int64_t": "int64",
32 "size_t": "csize_t",
33 "int": "cint",
34 "void*": "pointer",
35 "char*": "cstring",
36 "ptr char": "cstring",
37 "ptr void": "pointer",
38 # "VK_DEFINE_HANDLE": "VkHandle", # not required, can directly defined as a distinct pointer, (in C is a pointer to an empty struct type)
39 # "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "VkNonDispatchableHandle", # same here
40 }.toTable
41
42 # load xml
43 let xml = (system.currentSourcePath.parentDir() / "vk.xml").loadXml()
44 let platforms = xml.findAll("platforms")[0]
45 let types = xml.findAll("types")[0]
46 let xmlenums = xml.findAll("enums")
47 let commands = xml.findAll("commands")[0]
48 let features = xml.findAll("feature") # features has extends="<ENUM>"
49 let extensions = xml.findAll("extensions")[0] # extensions has extends="<ENUM>"
50 let formats = xml.findAll("formats")[0]
51
52 # gather all enums
53
54 type
55 EnumEntry = object
56 name: string
57 value: string
58
59 EnumDef = object
60 name: string
61 values: seq[EnumEntry]
62 isBitmask: bool
63
64 ConstantDef = object
65 name: string
66 datatype: string
67 value: string
68
69 var consts: seq[ConstantDef]
70 var enums: Table[string, EnumDef]
71
72 func addValue(edef: var EnumDef, n: XmlNode) =
73 if n.attr("deprecated") != "aliased" and n.attr("alias") == "":
74 if n.attr("name") in edef.values.mapIt(it.name):
75 return
76 if n.attr("name").endsWith("_EXT") and
77 n.attr("name")[0 ..< ^4] in edef.values.mapIt(it.name):
78 return
79
80 var value = ""
81 if n.attr("value") != "":
82 value = n.attr("value")
83 elif n.attr("bitpos") != "":
84 value = $(1 shl parseInt(n.attr("bitpos")))
85 elif n.attr("offset") != "":
86 var enumBase = 1000000000
87 if n.attr("extnumber") != "":
88 enumBase += (smartParseInt(n.attr("extnumber")) - 1) * 1000
89 var v = smartParseInt(n.attr("offset")) + enumBase
90 if n.attr("dir") == "-":
91 v = -v
92 value = $(v)
93
94 edef.values.add EnumEntry(name: n.attr("name"), value: value)
95
96 for e in xmlenums:
97 if e.attr("type") == "constants":
98 for c in e.findAll("enum"):
99 var value = c.attr("value").strip(chars = {'(', ')'})
100 consts.add ConstantDef(
101 name: c.attr("name"), datatype: TYPEMAP[c.attr("type")], value: value
102 )
103 elif e.attr("type") == "enum":
104 var edef = EnumDef(name: e.attr("name"), isBitmask: false)
105 for ee in e.findAll("enum"):
106 edef.addValue(ee)
107 enums[edef.name] = edef
108 elif e.attr("type") == "bitmask":
109 var edef = EnumDef(name: e.attr("name"), isBitmask: true)
110 for ee in e.findAll("enum"):
111 edef.addValue(ee)
112 enums[edef.name] = edef
113
114 for f in features:
115 for extendenum in f.findAll("enum"):
116 if extendenum.attr("extends") != "":
117 enums[extendenum.attr("extends")].addValue(extendenum)
118
119 for extension in extensions.findAll("extension"):
120 let extNum = extension.attr("number")
121 for extendenum in extension.findAll("enum"):
122 if extendenum.attr("extends") != "":
123 if extendenum.attr("extnumber") == "":
124 extendenum.attrs["extnumber"] = extNum
125 enums[extendenum.attr("extends")].addValue(extendenum)
126
127 # generate core types ===============================================================================
128 # preamble, much easier to hardcode than to generate from xml
129 echo """
130 when defined(linux):
131 include ./platform/xlib
132 when defined(windows):
133 include ./platform/win32
134
135 func VK_MAKE_API_VERSION*(
136 variant: uint32, major: uint32, minor: uint32, patch: uint32
137 ): uint32 {.compileTime.} =
138 (variant shl 29) or (major shl 22) or (minor shl 12) or patch
139
140
141 """
142
143 echo "type"
144
145 for t in types:
146 if t.attr("deprecated") == "true":
147 continue
148 echo t
149 echo ""
150
151 # generate consts ===============================================================================
152 echo "const"
153 for c in consts:
154 var value = c.value
155 if value.endsWith("U"):
156 value = value[0 ..^ 2] & "'u32"
157 elif value.endsWith("ULL"):
158 value = value[0 ..^ 4] & "'u64"
159 if value[0] == '~':
160 value = "not " & value[1 ..^ 1]
161 echo &" {c.name}*: {c.datatype} = {value}"
162 echo ""
163
164 # generate enums ===============================================================================
165 echo "type"
166 for edef in enums.values():
167 if edef.values.len > 0:
168 echo &" {edef.name}* {{.size: 4.}} = enum"
169 for ee in edef.values:
170 echo &" {ee.name} = {ee.value}"
171 echo ""