Mercurial > games > semicongine
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svk/generate.nim Sun Apr 20 21:57:56 2025 +0700 @@ -0,0 +1,171 @@ +import std/strtabs +import std/xmltree +import std/tables +import std/options +import std/sequtils +import std/strutils +import std/strformat +import std/xmlparser +import std/os +import std/paths + +# helpers +func smartParseInt(value: string): int = + if value.startsWith("0x"): + parseHexInt(value) + else: + parseInt(value) + +const TYPEMAP = { + "void": "void", + "char": "char", + "float": "float32", + "double": "float64", + "int8_t": "int8", + "uint8_t": "uint8", + "int16_t": "int16", + "uint16_t": "uint16", + "int32_t": "int32", + "uint32_t": "uint32", + "uint64_t": "uint64", + "int64_t": "int64", + "size_t": "csize_t", + "int": "cint", + "void*": "pointer", + "char*": "cstring", + "ptr char": "cstring", + "ptr void": "pointer", + # "VK_DEFINE_HANDLE": "VkHandle", # not required, can directly defined as a distinct pointer, (in C is a pointer to an empty struct type) + # "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "VkNonDispatchableHandle", # same here +}.toTable + +# load xml +let xml = (system.currentSourcePath.parentDir() / "vk.xml").loadXml() +let platforms = xml.findAll("platforms")[0] +let types = xml.findAll("types")[0] +let xmlenums = xml.findAll("enums") +let commands = xml.findAll("commands")[0] +let features = xml.findAll("feature") # features has extends="<ENUM>" +let extensions = xml.findAll("extensions")[0] # extensions has extends="<ENUM>" +let formats = xml.findAll("formats")[0] + +# gather all enums + +type + EnumEntry = object + name: string + value: string + + EnumDef = object + name: string + values: seq[EnumEntry] + isBitmask: bool + + ConstantDef = object + name: string + datatype: string + value: string + +var consts: seq[ConstantDef] +var enums: Table[string, EnumDef] + +func addValue(edef: var EnumDef, n: XmlNode) = + if n.attr("deprecated") != "aliased" and n.attr("alias") == "": + if n.attr("name") in edef.values.mapIt(it.name): + return + if n.attr("name").endsWith("_EXT") and + n.attr("name")[0 ..< ^4] in edef.values.mapIt(it.name): + return + + var value = "" + if n.attr("value") != "": + value = n.attr("value") + elif n.attr("bitpos") != "": + value = $(1 shl parseInt(n.attr("bitpos"))) + elif n.attr("offset") != "": + var enumBase = 1000000000 + if n.attr("extnumber") != "": + enumBase += (smartParseInt(n.attr("extnumber")) - 1) * 1000 + var v = smartParseInt(n.attr("offset")) + enumBase + if n.attr("dir") == "-": + v = -v + value = $(v) + + edef.values.add EnumEntry(name: n.attr("name"), value: value) + +for e in xmlenums: + if e.attr("type") == "constants": + for c in e.findAll("enum"): + var value = c.attr("value").strip(chars = {'(', ')'}) + consts.add ConstantDef( + name: c.attr("name"), datatype: TYPEMAP[c.attr("type")], value: value + ) + elif e.attr("type") == "enum": + var edef = EnumDef(name: e.attr("name"), isBitmask: false) + for ee in e.findAll("enum"): + edef.addValue(ee) + enums[edef.name] = edef + elif e.attr("type") == "bitmask": + var edef = EnumDef(name: e.attr("name"), isBitmask: true) + for ee in e.findAll("enum"): + edef.addValue(ee) + enums[edef.name] = edef + +for f in features: + for extendenum in f.findAll("enum"): + if extendenum.attr("extends") != "": + enums[extendenum.attr("extends")].addValue(extendenum) + +for extension in extensions.findAll("extension"): + let extNum = extension.attr("number") + for extendenum in extension.findAll("enum"): + if extendenum.attr("extends") != "": + if extendenum.attr("extnumber") == "": + extendenum.attrs["extnumber"] = extNum + enums[extendenum.attr("extends")].addValue(extendenum) + +# generate core types =============================================================================== +# preamble, much easier to hardcode than to generate from xml +echo """ +when defined(linux): + include ./platform/xlib +when defined(windows): + include ./platform/win32 + +func VK_MAKE_API_VERSION*( + variant: uint32, major: uint32, minor: uint32, patch: uint32 +): uint32 {.compileTime.} = + (variant shl 29) or (major shl 22) or (minor shl 12) or patch + + +""" + +echo "type" + +for t in types: + if t.attr("deprecated") == "true": + continue + echo t +echo "" + +# generate consts =============================================================================== +echo "const" +for c in consts: + var value = c.value + if value.endsWith("U"): + value = value[0 ..^ 2] & "'u32" + elif value.endsWith("ULL"): + value = value[0 ..^ 4] & "'u64" + if value[0] == '~': + value = "not " & value[1 ..^ 1] + echo &" {c.name}*: {c.datatype} = {value}" +echo "" + +# generate enums =============================================================================== +echo "type" +for edef in enums.values(): + if edef.values.len > 0: + echo &" {edef.name}* {{.size: 4.}} = enum" + for ee in edef.values: + echo &" {ee.name} = {ee.value}" +echo ""