1479
|
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 ""
|