diff svk/generate.nim @ 1486:0ba3f0b2be2e default tip main

did: more
author sam <sam@basx.dev>
date Sat, 03 May 2025 20:16:04 +0700
parents 6e062a84c157
children
line wrap: on
line diff
--- a/svk/generate.nim	Sat May 03 01:03:01 2025 +0700
+++ b/svk/generate.nim	Sat May 03 20:16:04 2025 +0700
@@ -213,8 +213,15 @@
     if extendenum.attr("extends") != "":
       enums[extendenum.attr("extends")].addValue(extendenum)
 
+var extensionLoaders: seq[(string, seq[string])]
+
 for extension in extensions.findAll("extension"):
   let extNum = extension.attr("number")
+  extensionLoaders.add (extension.attr("name"), newSeq[string]())
+  for c in extension.findAll("command"):
+    if "Video" notin c.attr("name"):
+      extensionLoaders[^1][1].add c.attr("name")
+
   for extendenum in extension.findAll("enum"):
     if extendenum.attr("extends") != "":
       if extendenum.attr("extnumber") == "":
@@ -229,6 +236,8 @@
 outFile.writeLine """
 
 import std/dynlib
+import std/strutils
+import std/tables
 
 import ../semicongine/thirdparty/winim/winim/inc/winbase
 import ../semicongine/thirdparty/winim/winim/inc/windef
@@ -311,7 +320,10 @@
     value = value[0 ..^ 4] & "'u64"
   if value[0] == '~':
     value = "not " & value[1 ..^ 1]
-  outFile.writeLine &"  {c.name}*: {c.datatype} = {value}"
+  if c.name in ["VK_TRUE", "VK_FALSE"]:
+    outFile.writeLine &"  {c.name}*: VkBool32 = VkBool32({value})"
+  else:
+    outFile.writeLine &"  {c.name}*: {c.datatype} = {value}"
 outFile.writeLine ""
 
 # generate enums ===============================================================================
@@ -335,6 +347,7 @@
 outFile.writeLine ""
 
 # generate types ===============================================================================
+var stringConverters: seq[string]
 for t in types:
   let category = t.attr("category")
   let tName = t.attr("name")
@@ -357,13 +370,14 @@
     outFile.writeLine &"  {tName}* = {a}"
   elif category == "bitmask":
     if t.len > 0 and t[0].text.startsWith("typedef"):
-      outFile.writeLine &"  {t[2][0].text}* = distinct {t[1][0].text}"
+      outFile.writeLine &"  {t[2][0].text.strip()}* = distinct {t[1][0].text.strip()}"
   elif category == "union":
     outFile.writeLine &"  {tName}* {{.union.}} = object"
     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.strip()} = distinct pointer"
+    stringConverters.add t[2][0].text.strip()
   elif category == "struct":
     outFile.writeLine &"  {tName}* = object"
     for member in t.findAll("member"):
@@ -451,27 +465,37 @@
   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"))
 
 proc loadFunc[T](instance: VkInstance, f: var T, name: string) =
   f = cast[T](vkGetInstanceProcAddr(instance, name))
 
+proc initVulkanLoader*() =
+  if vkGetInstanceProcAddr != nil:
+    return
+
+  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")
+
+  # init two global functions
+  vkGetInstanceProcAddr = cast[proc(instance: VkInstance, pName: cstring, ): PFN_vkVoidFunction {.stdcall.}](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr"))
+
+  loadFunc(VkInstance(nil), vkCreateInstance, "vkCreateInstance")
+
 """
 
 for f in features:
   let name = f.attr("name").replace(",", "_")
   if f.attr("struct") != "":
     continue
-  outFile.writeLine &"proc loadFeature_{name}(instance: VkInstance) ="
+  outFile.writeLine &"proc load_{name}(instance: VkInstance) ="
   var hasEntries = false
   for cmd in f.findAll("command"):
+    if cmd.attr("name") == "vkCreateInstance":
+      continue
     hasEntries = true
     let cName = cmd.attr("name")
     outFile.writeLine &"  loadFunc(instance, {cName}, \"{cName}\")"
@@ -479,6 +503,32 @@
     outFile.writeLine "  discard"
   outFile.writeLine ""
 
+for (extName, commands) in extensionLoaders:
+  outFile.writeLine &"proc load_{extName}(instance: VkInstance) ="
+  for c in commands:
+    outFile.writeLine &"  loadFunc(instance, {c}, \"{c}\")"
+  if commands.len == 0:
+    outFile.writeLine &"  discard"
+outFile.writeLine ""
+
+outFile.writeLine "const EXTENSION_LOADERS = {"
+for (extName, commands) in extensionLoaders:
+  outFile.writeLine &"  \"{extName}\": load_{extName},"
+outFile.writeLine "}.toTable"
+outFile.writeLine ""
+
+outFile.writeLine "proc loadExtension*(instance: VkInstance, name: string) ="
+outFile.writeLine "  assert name in EXTENSION_LOADERS"
+outFile.writeLine "  EXTENSION_LOADERS[name](instance)"
+outFile.writeLine ""
+
+for strCon in stringConverters:
+  outFile.writeLine &"""proc `$`*(v: {strCon}): string = "0x" & cast[uint](v).toHex()"""
+outFile.writeLine ""
+
+# we preload the vkCreateInstance function, so we can create an instance
+outFile.writeLine ""
+
 outFile.close()
 
 assert execCmd("nim c " & outPath) == 0