Mercurial > games > semicongine
comparison svk/generate.nim @ 1480:0b302531f5c5 default tip
did: continue on vulkan nim api generator
author | sam <sam@basx.dev> |
---|---|
date | Mon, 21 Apr 2025 01:31:55 +0700 |
parents | 172ac338f820 |
children |
comparison
equal
deleted
inserted
replaced
1479:172ac338f820 | 1480:0b302531f5c5 |
---|---|
1 import std/strtabs | 1 import std/strtabs |
2 import std/syncio | |
2 import std/xmltree | 3 import std/xmltree |
3 import std/tables | 4 import std/tables |
4 import std/options | 5 import std/options |
5 import std/sequtils | 6 import std/sequtils |
6 import std/strutils | 7 import std/strutils |
7 import std/strformat | 8 import std/strformat |
8 import std/xmlparser | 9 import std/xmlparser |
9 import std/os | 10 import std/os |
11 import std/osproc | |
10 import std/paths | 12 import std/paths |
11 | 13 |
12 # helpers | 14 # helpers |
13 func smartParseInt(value: string): int = | 15 func smartParseInt(value: string): int = |
14 if value.startsWith("0x"): | 16 if value.startsWith("0x"): |
91 v = -v | 93 v = -v |
92 value = $(v) | 94 value = $(v) |
93 | 95 |
94 edef.values.add EnumEntry(name: n.attr("name"), value: value) | 96 edef.values.add EnumEntry(name: n.attr("name"), value: value) |
95 | 97 |
98 func memberDecl(n: XmlNode): string = | |
99 for i in 0 ..< n.len: | |
100 if n[i].kind == xnElement and n[i].tag == "comment": | |
101 n.delete(i) | |
102 break | |
103 assert n.tag == "member" | |
104 debugecho n.toSeq, " ", n.len | |
105 if n.len == 2: | |
106 return &"{n[1][0].text}: {n[0][0]}" | |
107 elif n.len == 3: | |
108 if n[1].kind == xnElement and n[1].tag == "name": | |
109 return | |
110 &"{n[1][0].text}: array[{n[2].text[1 ..< ^1]}, {TYPEMAP.getOrDefault(n[0][0].text, n[0][0].text)}]]" | |
111 else: | |
112 assert n[1].text.strip() == "*" | |
113 return &"{n[2][0].text}: ptr {n[0][0].text}" | |
114 elif n.len == 4: | |
115 if n[0].text.strip() in ["struct", "const struct"]: | |
116 return &"{n[3][0].text}: ptr {n[1][0].text}" | |
117 else: | |
118 assert n[2].text.strip() in ["*", "* const *", "* const*"] | |
119 return &"?" | |
120 elif n.len in [5, 6]: | |
121 return &"{n[1][0].text}: array[{n[3][0].text}, {n[0][0].text}]" | |
122 assert false | |
123 | |
96 for e in xmlenums: | 124 for e in xmlenums: |
97 if e.attr("type") == "constants": | 125 if e.attr("type") == "constants": |
98 for c in e.findAll("enum"): | 126 for c in e.findAll("enum"): |
99 var value = c.attr("value").strip(chars = {'(', ')'}) | 127 var value = c.attr("value").strip(chars = {'(', ')'}) |
100 consts.add ConstantDef( | 128 consts.add ConstantDef( |
122 if extendenum.attr("extends") != "": | 150 if extendenum.attr("extends") != "": |
123 if extendenum.attr("extnumber") == "": | 151 if extendenum.attr("extnumber") == "": |
124 extendenum.attrs["extnumber"] = extNum | 152 extendenum.attrs["extnumber"] = extNum |
125 enums[extendenum.attr("extends")].addValue(extendenum) | 153 enums[extendenum.attr("extends")].addValue(extendenum) |
126 | 154 |
155 let outPath = (system.currentSourcePath.parentDir() / "api.nim") | |
156 let outFile = open(outPath, fmWrite) | |
157 | |
127 # generate core types =============================================================================== | 158 # generate core types =============================================================================== |
128 # preamble, much easier to hardcode than to generate from xml | 159 # preamble, much easier to hardcode than to generate from xml |
129 echo """ | 160 outFile.writeLine """ |
130 when defined(linux): | |
131 include ./platform/xlib | |
132 when defined(windows): | |
133 include ./platform/win32 | |
134 | |
135 func VK_MAKE_API_VERSION*( | 161 func VK_MAKE_API_VERSION*( |
136 variant: uint32, major: uint32, minor: uint32, patch: uint32 | 162 variant: uint32, major: uint32, minor: uint32, patch: uint32 |
137 ): uint32 {.compileTime.} = | 163 ): uint32 {.compileTime.} = |
138 (variant shl 29) or (major shl 22) or (minor shl 12) or patch | 164 (variant shl 29) or (major shl 22) or (minor shl 12) or patch |
139 | |
140 | |
141 """ | 165 """ |
142 | 166 |
143 echo "type" | 167 outFile.writeLine "type" |
168 outFile.writeLine """ | |
169 VkSampleMask = distinct uint32 | |
170 VkBool32 = distinct uint32 | |
171 VkFlags = distinct uint32 | |
172 VkFlags64 = distinct uint64 | |
173 VkDeviceSize = distinct uint64 | |
174 VkDeviceAddress = distinct uint64 | |
175 VkRemoteAddressNV = pointer | |
176 """ | |
144 | 177 |
145 for t in types: | 178 for t in types: |
179 if t.attr("api") == "vulkansc": | |
180 continue | |
181 if t.attr("alias") != "": | |
182 continue | |
146 if t.attr("deprecated") == "true": | 183 if t.attr("deprecated") == "true": |
147 continue | 184 continue |
148 echo t | 185 if t.attr("category") == "include": |
149 echo "" | 186 continue |
187 if t.attr("category") == "define": | |
188 continue | |
189 if t.attr("category") == "bitmask": | |
190 if t.len > 0 and t[0].text.startsWith("typedef"): | |
191 outFile.writeLine &" {t[2][0].text} = distinct {t[1][0].text}" | |
192 elif t.attr("category") == "union": | |
193 let n = t.attr("name") | |
194 outFile.writeLine &" {n}* {{.union.}} = object" | |
195 for member in t.findAll("member"): | |
196 outFile.writeLine &" {member.memberDecl()}" | |
197 elif t.attr("category") == "handle": | |
198 outFile.writeLine &" {t[2][0].text} = distinct pointer" | |
199 elif t.attr("category") == "struct": | |
200 let n = t.attr("name") | |
201 outFile.writeLine &" {n}* = object" | |
202 for member in t.findAll("member"): | |
203 outFile.writeLine &" {member.memberDecl()}" | |
204 # TODO: funcpointer | |
205 | |
206 outFile.writeLine "" | |
150 | 207 |
151 # generate consts =============================================================================== | 208 # generate consts =============================================================================== |
152 echo "const" | 209 outFile.writeLine "const" |
153 for c in consts: | 210 for c in consts: |
154 var value = c.value | 211 var value = c.value |
155 if value.endsWith("U"): | 212 if value.endsWith("U"): |
156 value = value[0 ..^ 2] & "'u32" | 213 value = value[0 ..^ 2] & "'u32" |
157 elif value.endsWith("ULL"): | 214 elif value.endsWith("ULL"): |
158 value = value[0 ..^ 4] & "'u64" | 215 value = value[0 ..^ 4] & "'u64" |
159 if value[0] == '~': | 216 if value[0] == '~': |
160 value = "not " & value[1 ..^ 1] | 217 value = "not " & value[1 ..^ 1] |
161 echo &" {c.name}*: {c.datatype} = {value}" | 218 outFile.writeLine &" {c.name}*: {c.datatype} = {value}" |
162 echo "" | 219 outFile.writeLine "" |
163 | 220 |
164 # generate enums =============================================================================== | 221 # generate enums =============================================================================== |
165 echo "type" | 222 outFile.writeLine "type" |
166 for edef in enums.values(): | 223 for edef in enums.values(): |
167 if edef.values.len > 0: | 224 if edef.values.len > 0: |
168 echo &" {edef.name}* {{.size: 4.}} = enum" | 225 outFile.writeLine &" {edef.name}* {{.size: 4.}} = enum" |
169 for ee in edef.values: | 226 for ee in edef.values: |
170 echo &" {ee.name} = {ee.value}" | 227 outFile.writeLine &" {ee.name} = {ee.value}" |
171 echo "" | 228 outFile.writeLine "" |
229 | |
230 outFile.writeLine """ | |
231 when defined(linux): | |
232 include ../semicongine/rendering/vulkan/platform/xlib | |
233 when defined(windows): | |
234 include ../semicongine/rendering/vulkan/platform/win32 | |
235 """ | |
236 | |
237 outFile.close() | |
238 | |
239 assert execCmd("nim c " & outPath) == 0 |