Mercurial > games > semicongine
diff src/vulkan_api/vulkan_api_generator.nim @ 92:e872cf354110
add: more stuff for the vulkan API wrappers
author | Sam <sam@basx.dev> |
---|---|
date | Tue, 28 Feb 2023 00:08:28 +0700 |
parents | 8412f433dc46 |
children | f036546f5ea2 |
line wrap: on
line diff
--- a/src/vulkan_api/vulkan_api_generator.nim Mon Feb 27 00:05:26 2023 +0700 +++ b/src/vulkan_api/vulkan_api_generator.nim Tue Feb 28 00:08:28 2023 +0700 @@ -127,7 +127,8 @@ result = &"array[{arraylen}, {result}]" # serializers -func serializeEnum(node: XmlNode, api: XmlNode): seq[string] = +# return values and whether this is a bitfield +func serializeEnum(node: XmlNode, api: XmlNode): (seq[string], string) = let name = node.attr("name") if name == "": return result @@ -206,13 +207,13 @@ else: values[smartParseInt(value.attr("value"))] = value.attr("name") if values.len > 0: - result.add " " & name & "* {.size: sizeof(cint).} = enum" + result[0].add " " & name & "* {.size: sizeof(cint).} = enum" for (value, name) in tableSorted(values): var thename = name if name.replace("_", "").toLower() in reservedNames: thename = thename & "_ENUM" let enumEntry = &" {thename} = {value}" - result.add enumEntry + result[0].add enumEntry # generate bitsets (normal enums in the C API, but bitfield-enums in Nim) elif node.attr("type") == "bitmask": @@ -226,41 +227,42 @@ predefined_enum_sets.add &" {value.attr(\"name\")}* = {value.attr(\"value\")}" if values.len > 0: + let cApiName = name.replace("FlagBits", "Flags") + result[1] = cApiName if node.hasAttr("bitwidth"): - result.add " " & name & "* {.size: 8.} = enum" + result[0].add " " & name & "* {.size: 8.} = enum" else: - result.add " " & name & "* {.size: sizeof(cint).} = enum" + result[0].add " " & name & "* {.size: sizeof(cint).} = enum" for (bitpos, enumvalue) in tableSorted(values): var value = "00000000000000000000000000000000"# makes the bit mask nicely visible if node.hasAttr("bitwidth"): # assumes this is always 64 value = value & value value[^(bitpos + 1)] = '1' let enumEntry = &" {enumvalue} = 0b{value}" - if not (enumEntry in result): # the specs define duplicate entries for backwards compat - result.add enumEntry - let cApiName = name.replace("FlagBits", "Flags") + if not (enumEntry in result[0]): # the specs define duplicate entries for backwards compat + result[0].add enumEntry if node.hasAttr("bitwidth"): # assuming this attribute is always 64 if values.len > 0: - result.add &"""converter BitsetToNumber*(flags: openArray[{name}]): {cApiName} = + result[0].add &"""func toBits*(flags: openArray[{name}]): {cApiName} = for flag in flags: - result = {cApiName}(int64(result) or int64(flag))""" - result.add &"""converter NumberToBitset*(number: {cApiName}): seq[{name}] = - for value in {name}.items: - if (value.ord and int64(number)) > 0: - result.add value""" + result = {cApiName}(uint64(result) or uint64(flag))""" + result[0].add &"""func toEnums*(number: {cApiName}): seq[{name}] = + for value in {name}.items: + if (cast[uint64](value) and uint64(number)) > 0: + result.add value""" else: if values.len > 0: - result.add &"""func toBits*(flags: openArray[{name}]): {cApiName} = + result[0].add &"""func toBits*(flags: openArray[{name}]): {cApiName} = for flag in flags: result = {cApiName}(uint(result) or uint(flag))""" - result.add &"""func toEnums*(number: {cApiName}): seq[{name}] = + result[0].add &"""func toEnums*(number: {cApiName}): seq[{name}] = for value in {name}.items: if (value.ord and cint(number)) > 0: result.add value""" if predefined_enum_sets.len > 0: - result.add "const" - result.add predefined_enum_sets - result.add "type" + result[0].add "const" + result[0].add predefined_enum_sets + result[0].add "type" func serializeStruct(node: XmlNode): seq[string] = @@ -416,6 +418,7 @@ "import std/tables", "import std/strutils", "import std/logging", + "import std/typetraits", "import std/macros", "import std/private/digitsutils", "from typetraits import HoleyEnum", @@ -465,10 +468,24 @@ if thetype.attr("category") == "bitmask" and not thetype.hasAttr("alias") and (not thetype.hasAttr("api") or thetype.attr("api") == "vulkan"): let name = thetype.child("name")[0].text outputFiles["enums"].add &" {name}* = distinct VkFlags" + + var bitfields: Table[string, string] outputFiles["enums"].add "let vkGetInstanceProcAddr = cast[proc(instance: VkInstance, name: cstring): pointer {.stdcall.}](checkedSymAddr(vulkanLib, \"vkGetInstanceProcAddr\"))" outputFiles["enums"].add "type" for theenum in api.findAll("enums"): - outputFiles["enums"].add serializeEnum(theenum, api) + let (enums, bitFieldName) = serializeEnum(theenum, api) + outputFiles["enums"].add enums + if bitFieldName != "": + bitfields[theenum.attr("name")] = bitFieldName + + # bitmask-to-string functions + for thetype in api.findAll("type"): + if thetype.attr("name") in bitfields: + let name = bitfields[thetype.attr("name")] + let stringfunc = &"proc `$`*(bitset: {name}): string = $toEnums(bitset)" + if not (stringfunc in outputFiles["enums"]): + outputFiles["enums"].add stringfunc + outputFiles["enums"].add "type" # structs and function types need to be in same "type" block to avoid forward-declarations outputFiles["structs"].add serializeFunctiontypes(api) @@ -494,6 +511,15 @@ for thetype in typesgroup.findAll("type"): outputFiles.update serializeType(thetype, headerTypes) + for typesgroup in api.findAll("types"): + for node in typesgroup.findAll("type"): + if node.attr("category") == "handle": + if not node.hasAttr("alias"): + let name = node.child("name")[0].text + outputFiles["basetypes"].add &"proc `$`*(handle: {name}): string = \"{name}(\" & $(uint(handle)) & \")\"" + outputFiles["basetypes"].add &"proc valid*(handle: {name}): bool = uint(handle) != 0" + outputFiles["basetypes"].add &"proc reset*(handle: var {name}) = handle = {name}(0)" + # commands aka functions var varDecls: Table[string, string] var procLoads: Table[string, string] # procloads need to be packed into feature/extension loader procs