Mercurial > games > semicongine
annotate src/vulkan_api/vulkan_api_generator.nim @ 547:c3b6981764a5
fix: type mismatch
author | Sam <sam@basx.dev> |
---|---|
date | Sat, 25 Feb 2023 01:13:42 +0700 |
parents | 39aed3128be7 |
children | e872cf354110 |
rev | line source |
---|---|
539 | 1 import std/os |
2 import std/sugar | |
3 import std/algorithm | |
4 import std/strformat | |
5 import std/strutils | |
6 import std/sequtils | |
7 import std/streams | |
8 import std/tables | |
9 import httpClient | |
10 import std/xmlparser | |
11 import std/xmltree | |
12 | |
13 const | |
14 TYPEMAP = { | |
15 "void": "void", | |
16 "char": "char", | |
17 "float": "float32", | |
18 "double": "float64", | |
19 "int8_t": "int8", | |
20 "uint8_t": "uint8", | |
21 "int16_t": "int16", | |
22 "uint16_t": "uint16", | |
23 "int32_t": "int32", | |
24 "uint32_t": "uint32", | |
25 "uint64_t": "uint64", | |
26 "int64_t": "int64", | |
27 "size_t": "csize_t", | |
28 "int": "cint", | |
29 "void*": "pointer", | |
30 "char*": "cstring", | |
31 "ptr char": "cstring", | |
32 "ptr void": "pointer", | |
33 "VK_DEFINE_HANDLE": "VkHandle", | |
34 "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "VkNonDispatchableHandle", | |
35 }.toTable | |
36 PLATFORM_HEADER_MAP = { | |
540 | 37 "X11/Xlib.h": @["xlib", "xlib_xrandr"], |
38 "X11/extensions/Xrandr.h": @["xlib_xrandr"], | |
39 "wayland-client.h": @["wayland"], | |
40 "windows.h": @["win32"], | |
41 "xcb/xcb.h": @["xcb"], | |
42 "directfb.h": @["directfb"], | |
43 "zircon/types.h": @["fuchsia"], | |
44 "ggp_c/vulkan_types.h": @["ggp"], | |
45 "screen/screen.h": @["screen"], | |
46 "nvscisync.h": @["sci"], | |
47 "nvscibuf.h": @["sci"], | |
48 "vk_video/vulkan_video_codec_h264std.h": @["provisional"], | |
49 "vk_video/vulkan_video_codec_h264std_decode.h": @["provisional"], | |
50 "vk_video/vulkan_video_codec_h264std_encode.h": @["provisional"], | |
51 "vk_video/vulkan_video_codec_h265std.h": @["provisional"], | |
52 "vk_video/vulkan_video_codec_h265std_decode.h": @["provisional"], | |
53 "vk_video/vulkan_video_codec_h265std_encode.h": @["provisional"], | |
539 | 54 }.toTable |
55 MAP_KEYWORD = { | |
56 "object": "theobject", | |
57 "type": "thetype", | |
58 }.toTable | |
540 | 59 SPECIAL_DEPENDENCIES = { |
60 "VK_NV_ray_tracing": "VK_KHR_ray_tracing_pipeline", | |
61 }.toTable | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
62 # will be directly loaded at startup |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
63 IGNORED_COMMANDS = @["vkGetInstanceProcAddr"] |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
64 # can be loaded without a vulkan instance |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
65 GLOBAL_COMMANDS = @[ |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
66 "vkEnumerateInstanceVersion", |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
67 "vkEnumerateInstanceExtensionProperties", |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
68 "vkEnumerateInstanceLayerProperties", |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
69 "vkCreateInstance", |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
70 ] |
539 | 71 |
72 # helpers | |
73 func mapType(typename: string): auto = | |
74 TYPEMAP.getOrDefault(typename.strip(), typename.strip()).strip(chars={'_'}) | |
75 func mapName(thename: string): auto = | |
76 MAP_KEYWORD.getOrDefault(thename.strip(), thename.strip()).strip(chars={'_'}) | |
77 func smartParseInt(value: string): int = | |
78 if value.startsWith("0x"): | |
79 parseHexInt(value) | |
80 else: | |
81 parseInt(value) | |
82 func hasAttr(node: XmlNode, attr: string): bool = node.attr(attr) != "" | |
83 func tableSorted(table: Table[int, string]): seq[(int, string)] = | |
84 result = toSeq(table.pairs) | |
85 result.sort((a, b) => cmp(a[0], b[0])) | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
86 func findType(declNode: XmlNode): string = |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
87 # examples: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
88 # char** -> cstringArray |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
89 # void* -> pointer |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
90 # char* -> cstring |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
91 # |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
92 # int* -> ptr int |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
93 # void** -> ptr pointer |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
94 # int** -> ptr ptr int |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
95 var basetype = "" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
96 var apointer = "" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
97 var arraylen = "" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
98 for child in declNode: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
99 if child.kind == xnText: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
100 if "[" in child.text: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
101 if "[" in child.text and "]" in child.text: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
102 arraylen = child.text.strip(chars={'[', ']'}).replace("][", "*") |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
103 else: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
104 arraylen = declNode.child("enum")[0].text |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
105 else: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
106 for i in 0 ..< child.text.count('*'): |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
107 apointer = apointer & "ptr " |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
108 elif child.tag == "type": |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
109 basetype = mapType(child[0].text) |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
110 if basetype == "void": |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
111 if apointer.count("ptr ") > 0: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
112 basetype = "pointer" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
113 apointer = apointer[0 ..< ^4] |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
114 elif basetype == "char": |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
115 if apointer.count("ptr ") == 1: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
116 basetype = "cstring" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
117 apointer = "" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
118 elif apointer.count("ptr ") == 2: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
119 basetype = "cstringArray" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
120 apointer = "" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
121 elif apointer.count("ptr ") > 2: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
122 basetype = "cstringArray" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
123 apointer = apointer[0 ..< ^8] |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
124 |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
125 result = &"{apointer}{basetype}" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
126 if arraylen != "": |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
127 result = &"array[{arraylen}, {result}]" |
539 | 128 |
129 # serializers | |
541 | 130 func serializeEnum(node: XmlNode, api: XmlNode): seq[string] = |
539 | 131 let name = node.attr("name") |
132 if name == "": | |
133 return result | |
134 | |
541 | 135 var reservedNames: seq[string] |
136 for t in api.findAll("type"): | |
137 reservedNames.add t.attr("name").replace("_", "").toLower() | |
138 | |
539 | 139 # find additional enum defintion in feature definitions |
140 var values: Table[int, string] | |
541 | 141 for feature in api.findAll("feature"): |
539 | 142 for require in feature.findAll("require"): |
143 for theenum in require.findAll("enum"): | |
144 if theenum.attr("extends") == name: | |
145 if theenum.hasAttr("offset"): | |
146 let enumBase = 1000000000 + (smartParseInt(theenum.attr("extnumber")) - 1) * 1000 | |
147 var value = smartParseInt(theenum.attr("offset")) + enumBase | |
148 if theenum.attr("dir") == "-": | |
149 value = -value | |
150 values[value] = theenum.attr("name") | |
151 elif theenum.hasAttr("value"): | |
152 var value = smartParseInt(theenum.attr("value")) | |
153 if theenum.attr("dir") == "-": | |
154 value = -value | |
155 values[value] = theenum.attr("name") | |
156 elif theenum.hasAttr("bitpos"): | |
157 var value = smartParseInt(theenum.attr("bitpos")) | |
158 if theenum.attr("dir") == "-": | |
159 value = -value | |
160 values[value] = theenum.attr("name") | |
161 elif theenum.hasAttr("alias"): | |
162 discard | |
163 else: | |
164 raise newException(Exception, &"Unknown extension value: {feature}\nvalue:{theenum}") | |
165 # find additional enum defintion in extension definitions | |
541 | 166 for extension in api.findAll("extension"): |
539 | 167 let extensionNumber = parseInt(extension.attr("number")) |
168 let enumBase = 1000000000 + (extensionNumber - 1) * 1000 | |
169 for require in extension.findAll("require"): | |
170 for theenum in require.findAll("enum"): | |
171 if theenum.attr("extends") == name: | |
172 if theenum.hasAttr("offset"): | |
173 if theenum.hasAttr("extnumber"): | |
174 let otherBase = 1000000000 + (smartParseInt(theenum.attr("extnumber")) - 1) * 1000 | |
175 var value = smartParseInt(theenum.attr("offset")) + otherBase | |
176 if theenum.attr("dir") == "-": | |
177 value = -value | |
178 values[value] = theenum.attr("name") | |
179 else: | |
180 var value = smartParseInt(theenum.attr("offset")) + enumBase | |
181 if theenum.attr("dir") == "-": | |
182 value = -value | |
183 values[value] = theenum.attr("name") | |
184 elif theenum.hasAttr("value"): | |
185 var value = smartParseInt(theenum.attr("value")) | |
186 if theenum.attr("dir") == "-": | |
187 value = -value | |
188 values[value] = theenum.attr("name") | |
189 elif theenum.hasAttr("bitpos"): | |
190 var value = smartParseInt(theenum.attr("bitpos")) | |
191 if theenum.attr("dir") == "-": | |
192 value = -value | |
193 values[value] = theenum.attr("name") | |
194 elif theenum.hasAttr("alias"): | |
195 discard | |
196 else: | |
197 raise newException(Exception, &"Unknown extension value: {extension}\nvalue:{theenum}") | |
198 | |
199 # generate enums | |
200 if node.attr("type") == "enum": | |
201 for value in node.findAll("enum"): | |
202 if value.hasAttr("alias"): | |
203 continue | |
204 if value.attr("value").startsWith("0x"): | |
205 values[parseHexInt(value.attr("value"))] = value.attr("name") | |
206 else: | |
207 values[smartParseInt(value.attr("value"))] = value.attr("name") | |
208 if values.len > 0: | |
209 result.add " " & name & "* {.size: sizeof(cint).} = enum" | |
210 for (value, name) in tableSorted(values): | |
541 | 211 var thename = name |
212 if name.replace("_", "").toLower() in reservedNames: | |
213 thename = thename & "_ENUM" | |
214 let enumEntry = &" {thename} = {value}" | |
539 | 215 result.add enumEntry |
216 | |
217 # generate bitsets (normal enums in the C API, but bitfield-enums in Nim) | |
218 elif node.attr("type") == "bitmask": | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
219 var predefined_enum_sets: seq[string] |
539 | 220 for value in node.findAll("enum"): |
540 | 221 if value.hasAttr("bitpos"): |
222 values[smartParseInt(value.attr("bitpos"))] = value.attr("name") | |
223 elif node.attr("name") == "VkVideoEncodeRateControlModeFlagBitsKHR": # special exception, for some reason this has values instead of bitpos | |
224 values[smartParseInt(value.attr("value"))] = value.attr("name") | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
225 elif value.hasAttr("value"): # create a const that has multiple bits set |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
226 predefined_enum_sets.add &" {value.attr(\"name\")}* = {value.attr(\"value\")}" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
227 |
539 | 228 if values.len > 0: |
229 if node.hasAttr("bitwidth"): | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
230 result.add " " & name & "* {.size: 8.} = enum" |
539 | 231 else: |
232 result.add " " & name & "* {.size: sizeof(cint).} = enum" | |
233 for (bitpos, enumvalue) in tableSorted(values): | |
234 var value = "00000000000000000000000000000000"# makes the bit mask nicely visible | |
235 if node.hasAttr("bitwidth"): # assumes this is always 64 | |
236 value = value & value | |
237 value[^(bitpos + 1)] = '1' | |
238 let enumEntry = &" {enumvalue} = 0b{value}" | |
239 if not (enumEntry in result): # the specs define duplicate entries for backwards compat | |
240 result.add enumEntry | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
241 let cApiName = name.replace("FlagBits", "Flags") |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
242 if node.hasAttr("bitwidth"): # assuming this attribute is always 64 |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
243 if values.len > 0: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
244 result.add &"""converter BitsetToNumber*(flags: openArray[{name}]): {cApiName} = |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
245 for flag in flags: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
246 result = {cApiName}(int64(result) or int64(flag))""" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
247 result.add &"""converter NumberToBitset*(number: {cApiName}): seq[{name}] = |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
248 for value in {name}.items: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
249 if (value.ord and int64(number)) > 0: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
250 result.add value""" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
251 else: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
252 if values.len > 0: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
253 result.add &"""func toBits*(flags: openArray[{name}]): {cApiName} = |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
254 for flag in flags: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
255 result = {cApiName}(uint(result) or uint(flag))""" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
256 result.add &"""func toEnums*(number: {cApiName}): seq[{name}] = |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
257 for value in {name}.items: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
258 if (value.ord and cint(number)) > 0: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
259 result.add value""" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
260 if predefined_enum_sets.len > 0: |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
261 result.add "const" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
262 result.add predefined_enum_sets |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
263 result.add "type" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
264 |
539 | 265 |
541 | 266 func serializeStruct(node: XmlNode): seq[string] = |
539 | 267 let name = node.attr("name") |
268 var union = "" | |
269 if node.attr("category") == "union": | |
540 | 270 union = "{.union.} " |
271 result.add &" {name}* {union}= object" | |
539 | 272 for member in node.findAll("member"): |
273 if not member.hasAttr("api") or member.attr("api") == "vulkan": | |
274 let fieldname = member.child("name")[0].text.strip(chars={'_'}) | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
275 result.add &" {mapName(fieldname)}*: {findType(member)}" |
539 | 276 |
277 func serializeFunctiontypes(api: XmlNode): seq[string] = | |
278 for node in api.findAll("type"): | |
279 if node.attr("category") == "funcpointer": | |
280 let name = node[1][0] | |
281 let returntype = mapType(node[0].text[8 .. ^1].split('(', 1)[0]) | |
282 var params: seq[string] | |
283 for i in countup(3, node.len - 1, 2): | |
284 var paramname = node[i + 1].text.split(',', 1)[0].split(')', 1)[0] | |
285 var paramtype = node[i][0].text | |
286 if paramname[0] == '*': | |
287 paramname = paramname.rsplit(" ", 1)[1] | |
288 paramtype = "ptr " & paramtype | |
289 paramname = mapName(paramname) | |
290 params.add &"{paramname}: {mapType(paramtype)}" | |
291 let paramsstr = params.join(", ") | |
540 | 292 result.add(&" {name}* = proc({paramsstr}): {returntype} {{.cdecl.}}") |
539 | 293 |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
294 func serializeConsts(api: XmlNode): seq[string] = |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
295 result = @["const"] |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
296 for enums in api.findAll("enums"): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
297 if enums.attr("name") == "API Constants": |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
298 for theenum in enums.findAll("enum"): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
299 if theenum.hasAttr("alias"): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
300 result.add &" {theenum.attr(\"name\")}* = {theenum.attr(\"alias\")}" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
301 else: |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
302 var value = theenum.attr("value").strip(chars={'(', ')'}) |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
303 if value.endsWith("U"): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
304 value = value[0..^2] & "'u32" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
305 elif value.endsWith("ULL"): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
306 value = value[0..^4] & "'u64" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
307 if value[0] == '~': |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
308 value = "not " & value[1..^1] |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
309 result.add &" {theenum.attr(\"name\")}*: {mapType(theenum.attr(\"type\"))} = {value}" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
310 |
540 | 311 func serializeType(node: XmlNode, headerTypes: Table[string, string]): Table[string, seq[string]] = |
539 | 312 if node.attrsLen == 0: |
313 return | |
314 if node.attr("requires") == "vk_platform" or node.attr("category") == "include": | |
315 return | |
316 result["basetypes"] = @[] | |
317 result["enums"] = @[] | |
318 | |
319 # include-defined types (in platform headers) | |
540 | 320 if node.attr("name") in headerTypes: |
321 for platform in PLATFORM_HEADER_MAP[node.attr("requires")]: | |
322 let platformfile = "platform/" & platform | |
323 if not result.hasKey(platformfile): | |
324 result[platformfile] = @[] | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
325 result[platformfile].add " " & node.attr("name").strip(chars={'_'}) & " *{.header: \"" & node.attr("requires") & "\".} = object" |
539 | 326 # generic base types |
327 elif node.attr("category") == "basetype": | |
328 let typechild = node.child("type") | |
329 let namechild = node.child("name") | |
330 if typechild != nil and namechild != nil: | |
331 var typename = typechild[0].text | |
332 if node[2].kind == xnText and node[2].text.strip() == "*": | |
333 typename = &"ptr {typename}" | |
334 result["basetypes"].add &" {namechild[0].text}* = {mapType(typename)}" | |
335 elif namechild != nil: | |
336 result["basetypes"].add &" {namechild[0].text}* = object" | |
337 # function pointers need to be handled with structs | |
338 elif node.attr("category") == "funcpointer": | |
339 discard | |
340 # preprocessor defines, ignored | |
341 elif node.attr("category") == "define": | |
342 discard | |
343 # bitmask aliases | |
344 elif node.attr("category") == "bitmask": | |
345 if node.hasAttr("alias"): | |
346 let name = node.attr("name") | |
347 let alias = node.attr("alias") | |
348 result["enums"].add &" {name}* = {alias}" | |
349 # distinct resource ID types aka handles | |
350 elif node.attr("category") == "handle": | |
351 if not node.hasAttr("alias"): | |
352 let name = node.child("name")[0].text | |
353 var thetype = mapType(node.child("type")[0].text) | |
354 result["basetypes"].add &" {name}* = distinct {thetype}" | |
355 # enum aliases | |
356 elif node.attr("category") == "enum": | |
357 if node.hasAttr("alias"): | |
358 let name = node.attr("name") | |
359 let alias = node.attr("alias") | |
360 result["enums"].add &" {name}* = {alias}" | |
361 else: | |
362 discard | |
363 | |
540 | 364 func serializeCommand(node: XmlNode): (string, string) = |
365 let | |
366 proto = node.child("proto") | |
367 resulttype = mapType(proto.child("type")[0].text) | |
368 name = proto.child("name")[0].text | |
369 var params: seq[string] | |
370 for param in node: | |
371 if param.tag == "param" and param.attr("api") in ["", "vulkan"]: | |
372 let fieldname = param.child("name")[0].text.strip(chars={'_'}) | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
373 params.add &"{mapName(fieldname)}: {findType(param)}" |
540 | 374 let allparams = params.join(", ") |
375 return (name, &"proc({allparams}): {resulttype} {{.stdcall.}}") | |
376 | |
539 | 377 |
378 proc update(a: var Table[string, seq[string]], b: Table[string, seq[string]]) = | |
379 for k, v in b.pairs: | |
380 if not a.hasKey(k): | |
381 a[k] = @[] | |
382 a[k].add v | |
383 | |
384 | |
385 proc main() = | |
542 | 386 let file = getTempDir() / "vk.xml" |
387 if not os.fileExists(file): | |
539 | 388 let client = newHttpClient() |
389 let glUrl = "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Docs/main/xml/vk.xml" | |
542 | 390 client.downloadFile(glUrl, file) |
539 | 391 |
542 | 392 let api = loadXml(file) |
539 | 393 |
394 const outdir = "src/vulkan_api/output" | |
395 removeDir outdir | |
396 createDir outdir | |
397 createDir outdir / "platform" | |
398 | |
399 # index all names that are only available on certain platforms | |
400 var platformTypes: Table[string, string] | |
401 for extension in api.findAll("extension"): | |
402 if extension.hasAttr("platform"): | |
403 for thetype in extension.findAll("type"): | |
404 platformTypes[thetype.attr("name")] = extension.attr("platform") | |
405 for command in extension.findAll("command"): | |
406 platformTypes[command.attr("name")] = extension.attr("platform") | |
407 elif extension.attr("name").startsWith("VK_KHR_video"): | |
408 for thetype in extension.findAll("type"): | |
540 | 409 platformTypes[thetype.attr("name")] = "provisional" |
539 | 410 for command in extension.findAll("command"): |
540 | 411 platformTypes[command.attr("name")] = "provisional" |
539 | 412 |
413 var outputFiles = { | |
540 | 414 "basetypes": @[ |
415 "import std/dynlib", | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
416 "import std/tables", |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
417 "import std/strutils", |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
418 "import std/logging", |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
419 "import std/macros", |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
420 "import std/private/digitsutils", |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
421 "from typetraits import HoleyEnum", |
540 | 422 "type", |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
423 " VkHandle* = distinct uint", |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
424 " VkNonDispatchableHandle* = distinct uint", |
540 | 425 "when defined(linux):", |
426 " let vulkanLib* = loadLib(\"libvulkan.so.1\")", | |
427 "when defined(windows):", | |
428 " let vulkanLib* = loadLib(\"vulkan-1.dll\")", | |
429 "if vulkanLib == nil:", | |
430 " raise newException(Exception, \"Unable to load vulkan library\")", | |
541 | 431 "func VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} =", |
432 " (variant shl 29) or (major shl 22) or (minor shl 12) or patch", | |
433 "", | |
542 | 434 """template checkVkResult*(call: untyped) = |
435 when defined(release): | |
436 discard call | |
437 else: | |
438 # yes, a bit cheap, but this is only for nice debug output | |
439 var callstr = astToStr(call).replace("\n", "") | |
440 while callstr.find(" ") >= 0: | |
441 callstr = callstr.replace(" ", " ") | |
442 debug "CALLING vulkan: ", callstr | |
443 let value = call | |
444 if value != VK_SUCCESS: | |
445 error "Vulkan error: ", astToStr(call), " returned ", $value | |
446 raise newException(Exception, "Vulkan error: " & astToStr(call) & | |
447 " returned " & $value)""", | |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
448 """ |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
449 # custom enum iteration (for enum values > 2^16) |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
450 macro enumFullRange(a: typed): untyped = |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
451 newNimNode(nnkBracket).add(a.getType[1][1..^1]) |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
452 |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
453 iterator items[T: HoleyEnum](E: typedesc[T]): T = |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
454 for a in enumFullRange(E): yield a""", |
540 | 455 ], |
456 "structs": @["type"], | |
457 "enums": @["type"], | |
458 "commands": @[], | |
539 | 459 }.toTable |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
460 outputFiles["basetypes"].add serializeConsts(api) |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
461 outputFiles["basetypes"].add "type" |
539 | 462 |
463 # enums | |
464 for thetype in api.findAll("type"): | |
465 if thetype.attr("category") == "bitmask" and not thetype.hasAttr("alias") and (not thetype.hasAttr("api") or thetype.attr("api") == "vulkan"): | |
466 let name = thetype.child("name")[0].text | |
467 outputFiles["enums"].add &" {name}* = distinct VkFlags" | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
468 outputFiles["enums"].add "let vkGetInstanceProcAddr = cast[proc(instance: VkInstance, name: cstring): pointer {.stdcall.}](checkedSymAddr(vulkanLib, \"vkGetInstanceProcAddr\"))" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
469 outputFiles["enums"].add "type" |
539 | 470 for theenum in api.findAll("enums"): |
471 outputFiles["enums"].add serializeEnum(theenum, api) | |
472 | |
473 # structs and function types need to be in same "type" block to avoid forward-declarations | |
474 outputFiles["structs"].add serializeFunctiontypes(api) | |
475 for thetype in api.findAll("type"): | |
476 if thetype.attr("category") == "struct" or thetype.attr("category") == "union": | |
477 var outfile = "structs" | |
478 if thetype.attr("name") in platformTypes: | |
479 outfile = "platform/" & platformTypes[thetype.attr("name")] | |
480 if not (outfile in outputFiles): | |
481 outputFiles[outfile] = @[] | |
541 | 482 outputFiles[outfile].add serializeStruct(thetype) |
539 | 483 |
484 # types | |
540 | 485 var headerTypes: Table[string, string] |
486 for types in api.findAll("types"): | |
487 for thetype in types.findAll("type"): | |
488 if thetype.attrsLen == 2 and thetype.hasAttr("requires") and thetype.hasAttr("name") and thetype.attr("requires") != "vk_platform": | |
489 let name = thetype.attr("name") | |
490 let incld = thetype.attr("requires") | |
491 headerTypes[name] = &"{name} {{.header: \"{incld}\".}} = object" | |
492 | |
539 | 493 for typesgroup in api.findAll("types"): |
494 for thetype in typesgroup.findAll("type"): | |
540 | 495 outputFiles.update serializeType(thetype, headerTypes) |
496 | |
497 # commands aka functions | |
498 var varDecls: Table[string, string] | |
499 var procLoads: Table[string, string] # procloads need to be packed into feature/extension loader procs | |
500 for commands in api.findAll("commands"): | |
501 for command in commands.findAll("command"): | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
502 if command.attr("api") != "vulkansc" and not (command.attr("name") in IGNORED_COMMANDS): |
540 | 503 if command.hasAttr("alias"): |
504 let name = command.attr("name") | |
505 let alias = command.attr("alias") | |
506 let thetype = varDecls[alias].split(":", 1)[1].strip() | |
507 varDecls[name] = &" {name}*: {thetype}" | |
508 procLoads[name] = &" {name} = {alias}" | |
509 else: | |
510 let (name, thetype) = serializeCommand(command) | |
511 varDecls[name] = &" {name}*: {thetype}" | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
512 procLoads[name] = &" {name} = cast[{thetype}](vkGetInstanceProcAddr(instance, \"{name}\"))" |
540 | 513 var declared: seq[string] |
514 var featureloads: seq[string] | |
515 for feature in api.findAll("feature"): | |
516 if feature.attr("api") in ["vulkan", "vulkan,vulkansc"]: | |
517 let name = feature.attr("name") | |
518 outputFiles["commands"].add &"# feature {name}" | |
519 outputFiles["commands"].add "var" | |
520 for command in feature.findAll("command"): | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
521 if not (command.attr("name") in declared) and not (command.attr("name") in IGNORED_COMMANDS): |
540 | 522 outputFiles["commands"].add varDecls[command.attr("name")] |
523 declared.add command.attr("name") | |
524 featureloads.add &"load{name}" | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
525 outputFiles["commands"].add &"proc load{name}*(instance: VkInstance) =" |
540 | 526 for command in feature.findAll("command"): |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
527 if not (command.attr("name") in IGNORED_COMMANDS & GLOBAL_COMMANDS): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
528 outputFiles["commands"].add procLoads[command.attr("name")] |
540 | 529 outputFiles["commands"].add "" |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
530 outputFiles["commands"].add ["proc loadVulkan*(instance: VkInstance) ="] |
540 | 531 for l in featureloads: |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
532 outputFiles["commands"].add [&" {l}(instance)"] |
540 | 533 outputFiles["commands"].add "" |
534 | |
535 # for promoted extensions, dependants need to call the load-function of the promoted feature/extension | |
536 # use table to store promotions | |
537 var promotions: Table[string, string] | |
538 for extensions in api.findAll("extensions"): | |
539 for extension in extensions.findAll("extension"): | |
540 if extension.hasAttr("promotedto"): | |
541 promotions[extension.attr("name")] = extension.attr("promotedto") | |
542 | |
543 var extensionDependencies: Table[string, (seq[string], XmlNode)] | |
544 var features: seq[string] | |
545 for feature in api.findAll("feature"): | |
546 features.add feature.attr("name") | |
547 for extensions in api.findAll("extensions"): | |
548 for extension in extensions.findAll("extension"): | |
549 let name = extension.attr("name") | |
550 extensionDependencies[name] = (@[], extension) | |
551 if extension.hasAttr("depends"): | |
552 extensionDependencies[name] = (extension.attr("depends").split("+"), extension) | |
553 if extension.attr("depends").startsWith("("): # no need for full tree parser, only single place where we can use a feature | |
554 let dependencies = extension.attr("depends").rsplit({')'}, 1)[1][1 .. ^1].split("+") | |
555 extensionDependencies[name] = (dependencies, extension) | |
556 if name in SPECIAL_DEPENDENCIES: | |
557 extensionDependencies[name][0].add SPECIAL_DEPENDENCIES[name] | |
558 | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
559 # order dependencies to generate them in correct order |
540 | 560 var dependencyOrderedExtensions: OrderedTable[string, XmlNode] |
561 while extensionDependencies.len > 0: | |
562 var delkeys: seq[string] | |
563 for extensionName, (dependencies, extension) in extensionDependencies.pairs: | |
564 var missingExtension = false | |
565 for dep in dependencies: | |
566 let realdep = promotions.getOrDefault(dep, dep) | |
567 if not (realdep in dependencyOrderedExtensions) and not (realdep in features): | |
568 missingExtension = true | |
569 break | |
570 if not missingExtension: | |
571 dependencyOrderedExtensions[extensionName] = extension | |
572 delkeys.add extensionName | |
573 for key in delkeys: | |
574 extensionDependencies.del key | |
575 | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
576 var extensionLoaderMap: Table[string, Table[string, string]] |
540 | 577 for extension in dependencyOrderedExtensions.values: |
578 if extension.hasAttr("promotedto"): # will be loaded in promoted place | |
579 continue | |
580 if extension.attr("supported") in ["", "vulkan", "vulkan,vulkansc"]: | |
581 var file = "commands" | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
582 var platform = extension.attr("platform") |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
583 if extension.attr("name").startsWith("VK_KHR_video"): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
584 platform = "provisional" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
585 if platform != "": |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
586 file = "platform/" & platform |
540 | 587 let name = extension.attr("name") |
588 if extension.findAll("command").len > 0: | |
589 outputFiles[file].add &"# extension {name}" | |
590 outputFiles[file].add "var" | |
591 for command in extension.findAll("command"): | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
592 if not (command.attr("name") in declared) and not (command.attr("name") in IGNORED_COMMANDS): |
540 | 593 outputFiles[file].add varDecls[command.attr("name")] |
594 declared.add command.attr("name") | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
595 outputFiles[file].add &"proc load{name}*(instance: VkInstance) =" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
596 if not (platform in extensionLoaderMap): |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
597 extensionLoaderMap[platform] = Table[string, string]() |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
598 extensionLoaderMap[platform][name] = &"load{name}" |
540 | 599 var addedFunctionBody = false |
600 if extension.hasAttr("depends"): | |
601 for dependency in extension.attr("depends").split("+"): | |
602 # need to check since some extensions have no commands and therefore no load-function | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
603 outputFiles[file].add &" load{promotions.getOrDefault(dependency, dependency)}(instance)" |
540 | 604 addedFunctionBody = true |
605 for command in extension.findAll("command"): | |
606 outputFiles[file].add procLoads[command.attr("name")] | |
607 addedFunctionBody = true | |
608 if not addedFunctionBody: | |
609 outputFiles[file].add " discard" | |
610 outputFiles[file].add "" | |
611 | |
612 var mainout: seq[string] | |
613 for section in ["basetypes", "enums", "structs", "commands"]: | |
614 mainout.add outputFiles[section] | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
615 mainout.add "var EXTENSION_LOADERS = {" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
616 for extension, loader in extensionLoaderMap[""].pairs: |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
617 mainout.add &" \"{extension}\": {loader}," |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
618 mainout.add "}.toTable" |
541 | 619 for platform in api.findAll("platform"): |
620 mainout.add &"when defined({platform.attr(\"protect\")}):" | |
621 mainout.add &" include platform/{platform.attr(\"name\")}" | |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
622 if platform.attr("name") in extensionLoaderMap: |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
623 for extension, loader in extensionLoaderMap[platform.attr("name")].pairs: |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
624 mainout.add &" EXTENSION_LOADERS[\"{extension}\"] = {loader}" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
625 |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
626 mainout.add "" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
627 mainout.add "proc loadExtension*(instance: VkInstance, extension: string) = EXTENSION_LOADERS[extension](instance)" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
628 mainout.add "" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
629 mainout.add "# load global functions immediately" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
630 mainout.add "block globalFunctions:" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
631 mainout.add " let instance = VkInstance(0)" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
632 for l in GLOBAL_COMMANDS: |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
633 mainout.add procLoads[l] |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
634 mainout.add "" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
635 mainout.add "converter VkBool2NimBool*(a: VkBool32): bool = a > 0" |
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
636 mainout.add "converter NimBool2VkBool*(a: bool): VkBool32 = VkBool32(a)" |
545
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
637 mainout.add "proc `$`*(x: uint32): string {.raises: [].} = addInt(result, x)" |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
638 |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
639 writeFile outdir / &"api.nim", mainout.join("\n") |
39aed3128be7
fix: tons of errors in wrapper generator, can now compile, extension function not loaded yet it seems
Sam <sam@basx.dev>
parents:
544
diff
changeset
|
640 |
544
c3c772512e7c
add: new vulkan api wrapper, not done yet
Sam <sam@basx.dev>
parents:
542
diff
changeset
|
641 |
539 | 642 for filename, filecontent in outputFiles.pairs: |
540 | 643 if filename.startsWith("platform/"): |
644 writeFile outdir / &"{filename}.nim", (@[ | |
645 "type" | |
646 ] & filecontent).join("\n") | |
539 | 647 |
648 when isMainModule: | |
649 main() |