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