Mercurial > games > semicongine
changeset 1484:a2af327f19df default tip
add: final raw wrapper
author | sam <sam@basx.dev> |
---|---|
date | Thu, 01 May 2025 00:59:40 +0700 |
parents | 55911f736a5a |
children | |
files | svk/generate.nim svk/test.nim |
diffstat | 2 files changed, 91 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/svk/generate.nim Tue Apr 29 00:17:33 2025 +0700 +++ b/svk/generate.nim Thu May 01 00:59:40 2025 +0700 @@ -86,30 +86,36 @@ if value notin edef.values.mapIt(it.value): edef.values.add EnumEntry(name: n.attr("name"), value: value) -func doTypename(typename: string, isPointer: bool): string = +func doTypename(typename: string, pointerType: int): string = + ## pointerType == 0: no pointer + ## pointerType == 1: normal pointer (e.g. char *) + ## pointerType == 2: double pointer (e.g. void **) + assert pointerType in [0, 1, 2] result = TYPEMAP.getOrDefault(typename.strip(), typename.strip()).strip(chars = {'_'}) if typename == "void": - assert isPointer + assert pointerType > 0 - if isPointer: + if pointerType > 0: if typename == "void": result = "pointer" elif typename == "char": result = "cstring" else: result = "ptr " & result + if pointerType == 2: + result = "ptr " & result func doIdentifier(typename: string): string = if typename in ["type", "object"]: return &"`{typename}`" return typename.strip() -func doMember(typename, theType: string, isPointer: bool, value: string): string = +func doMember(typename, theType: string, pointerType: int, value: string): string = if value == "": - &"{doIdentifier(typename)}: {doTypename(theType, isPointer)}" + &"{doIdentifier(typename)}: {doTypename(theType, pointerType)}" else: - &"{doIdentifier(typename)}: {doTypename(theType, isPointer)} = {value}" + &"{doIdentifier(typename)}: {doTypename(theType, pointerType)} = {value}" func memberDecl(n: XmlNode): string = for i in 0 ..< n.len: @@ -118,14 +124,14 @@ break assert n.tag == "member" if n.len == 2: - return doMember(n[1][0].text, n[0][0].text, false, n.attr("values")) + return doMember(n[1][0].text, n[0][0].text, 0, n.attr("values")) elif n.len == 3: assert "*" notin n[0][0].text.strip() if n[1].kind == xnElement and n[1].tag == "name": # bitfield if n[2].text.strip().startsWith(":"): return - &"{doIdentifier(n[1][0].text)} {{.bitsize:{n[2].text.strip()[1 .. ^1]}.}}: {doTypename(n[0][0].text, false)}" + &"{doIdentifier(n[1][0].text)} {{.bitsize:{n[2].text.strip()[1 .. ^1]}.}}: {doTypename(n[0][0].text, 0)}" # array definition elif n[2].text.strip().startsWith("["): let arrayDim = n[2].text[1 ..< ^1] @@ -134,15 +140,15 @@ let (dim1, dim2) = (dims[0], dims[1]) return doMember( n[1][0].text, - &"array[{dim1}, array[{dim2}, {doTypename(n[0][0].text, false)}]]", - false, + &"array[{dim1}, array[{dim2}, {doTypename(n[0][0].text, 0)}]]", + 0, n.attr("values"), ) else: return doMember( n[1][0].text, - &"array[{arrayDim}, {doTypename(n[0][0].text, false)}]", - false, + &"array[{arrayDim}, {doTypename(n[0][0].text, 0)}]", + 0, n.attr("values"), ) else: @@ -151,10 +157,10 @@ else: # pointer definition assert n[1].text.strip() == "*" - return doMember(n[2][0].text, n[0][0].text, true, n.attr("values")) + return doMember(n[2][0].text, n[0][0].text, 1, n.attr("values")) elif n.len == 4: if n[0].text.strip() in ["struct", "const struct"]: - return doMember(n[3][0].text, n[1][0].text, true, n.attr("values")) + return doMember(n[3][0].text, n[1][0].text, 1, n.attr("values")) else: assert n[0].text.strip() == "const" # can be ignored assert n[1].tag == "type" @@ -163,7 +169,7 @@ assert n[3].tag == "name" assert n[1].len == 1 assert n[3].len == 1 - return doMember(n[3][0].text, n[1][0].text, true, n.attr("values")) + return doMember(n[3][0].text, n[1][0].text, 1, n.attr("values")) elif n.len in [5, 6]: # array definition, using const-value for array length # <type>uint8_t</type>,<name>pipelineCacheUUID</name>[<enum>VK_UUID_SIZE</enum>] @@ -171,8 +177,8 @@ assert n[4].text.strip() == "]" return doMember( n[1][0].text, - &"array[{n[3][0].text}, {doTypename(n[0][0].text, false)}]", - false, + &"array[{n[3][0].text}, {doTypename(n[0][0].text, 0)}]", + 0, n.attr("values"), ) assert false @@ -215,6 +221,8 @@ # preamble, much easier to hardcode than to generate from xml outFile.writeLine """ +import std/dynlib + import ../semicongine/thirdparty/winim/winim/inc/winbase import ../semicongine/thirdparty/winim/winim/inc/windef import ../semicongine/thirdparty/x11/xlib @@ -348,7 +356,7 @@ for member in t.findAll("member"): outFile.writeLine &" {member.memberDecl()}" elif category == "handle": - outFile.writeLine &" {t[2][0].text}* = distinct pointer" + outFile.writeLine &" {t[2][0].text} = distinct pointer" elif category == "struct": outFile.writeLine &" {tName}* = object" for member in t.findAll("member"): @@ -356,51 +364,42 @@ continue outFile.writeLine &" {member.memberDecl()}" elif category == "funcpointer": - #[ - <type category="funcpointer">typedef void* (VKAPI_PTR *<name>PFN_vkAllocationFunction</name>)( - <type>void</type>* pUserData, - <type>size_t</type> size, - <type>size_t</type> alignment, - <type>VkSystemAllocationScope</type> allocationScope); - </type> - ]# assert t[0].text.startsWith("typedef ") let retName = t[0].text[8 ..< ^13].strip() let funcName = t.findAll("name")[0][0].text outFile.write &" {funcname}* = proc(" - for i in 3 ..< t.len: - # TODO: params + let nParams = (t.len - 3) div 2 + for i in 0 ..< nParams: + assert t[i * 2 + 3].tag == "type" + let typename = t[i * 2 + 3][0].text.strip() + var identifier = t[i * 2 + 4].text.strip(chars = {' ', ')', ';', ',', '\n'}) + var pointerType = if identifier.startsWith("*"): 1 else: 0 + if pointerType > 0: + identifier = identifier[1 .. ^1].strip(chars = {' ', ')', ';', ',', '\n'}) + if identifier.endsWith("const"): + identifier = identifier[0 .. ^6].strip(chars = {' ', ')', ';', ',', '\n'}) + identifier = identifier.strip(chars = {','}) + outFile.write &"{doIdentifier(identifier)}: {doTypename(typename, pointerType)}, " - if retName == "void" + if retName == "void": outFile.writeLine &") {{.cdecl.}}" - elif retName == "void*" + elif retName == "void*": outFile.writeLine &"): pointer {{.cdecl.}}" else: - outFile.writeLine &"): {doTypename(retName, false)} {{.cdecl.}}" - + outFile.writeLine &"): {doTypename(retName, 0)} {{.cdecl.}}" else: doAssert category in ["", "basetype", "enum"], "unknown type category: " & category outFile.writeLine "" +outFile.write &"var\n" for command in commands: - #[ - <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_LAYER_NOT_PRESENT,VK_ERROR_EXTENSION_NOT_PRESENT,VK_ERROR_INCOMPATIBLE_DRIVER"> - <proto> - <type>VkResult</type> - <name>vkCreateInstance</name> - </proto> - <param>const <type>VkInstanceCreateInfo</type>* <name>pCreateInfo</name></param> - <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param> - <param><type>VkInstance</type>* <name>pInstance</name></param> - </command> - ]# if command.attr("api") == "vulkansc": continue if command.attr("alias") != "": let funcName = command.attr("name") let funcAlias = command.attr("alias") - outFile.write &"var {funcName}* = {funcAlias}\n" + outFile.write &" {funcName}* = {funcAlias}\n" continue let proto = command.findAll("proto")[0] @@ -410,7 +409,7 @@ if "Video" in funcName: # Video API not supported at this time continue - outFile.write &"var {funcName}*: proc(" + outFile.write &" {funcName}*: proc(" for param in command: if param.tag != "param": continue @@ -420,17 +419,42 @@ let paramType = param.findAll("type")[0][0].text let paramName = param.findAll("name")[0][0].text assert "*" notin paramType, $param - if paramType == "void": - outFile.write &"{doIdentifier(paramName)}: {doTypename(paramType, true)}, " - else: - outFile.write &"{doIdentifier(paramName)}: {doTypename(paramType, false)}, " + + if param.len == 4: + param.delete(0) + + var pointerType = 0 + + if param.len == 3: + if param[param.len - 1].kind == xnText: + assert param[param.len - 1].text[^1] == ']' + else: + assert param[0].tag == "type" + assert param[param.len - 1].tag == "name" + if param[1].text.strip() == "*": + pointerType = 1 + elif param[1].text.strip() == "**": + pointerType = 2 + # echo "3: ", param[1].text, " ", paramType, " ", paramName + outFile.write &"{doIdentifier(paramName)}: {doTypename(paramType, pointerType)}, " outFile.write &")" if retType != "void": assert "*" notin retType - outFile.write &": {doTypename(retType, false)}" + outFile.write &": {doTypename(retType, 0)}" outFile.write " {.stdcall.}\n" +outFile.write """ +when defined(linux): + let vulkanLib = loadLib("libvulkan.so.1") +when defined(windows): + let vulkanLib = loadLib("vulkan-1.dll") +if vulkanLib == nil: + raise newException(Exception, "Unable to load vulkan library") + +vkGetInstanceProcAddr = cast[proc(instance: VkInstance, pName: cstring, ): PFN_vkVoidFunction {.stdcall.}](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr")) + """ + outFile.close() assert execCmd("nim c " & outPath) == 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svk/test.nim Thu May 01 00:59:40 2025 +0700 @@ -0,0 +1,17 @@ +import ./vkapi + +var + appinfo = VkApplicationInfo( + pApplicationName: appName, + pEngineName: "semicongine", + apiVersion: VK_MAKE_API_VERSION(0, 1, 3, 0), + ) + createinfo = VkInstanceCreateInfo( + pApplicationInfo: addr appinfo, + enabledLayerCount: layers.len.uint32, + ppEnabledLayerNames: layersC, + enabledExtensionCount: requiredExtensions.len.uint32, + ppEnabledExtensionNames: instanceExtensionsC, + ) +checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result.instance)) +loadVulkan(result.instance)