Mercurial > games > semicongine
comparison svk/generate.nim @ 1486:0ba3f0b2be2e
did: more
| author | sam <sam@basx.dev> |
|---|---|
| date | Sat, 03 May 2025 20:16:04 +0700 |
| parents | 6e062a84c157 |
| children | f786797a0cbe |
comparison
equal
deleted
inserted
replaced
| 1485:6e062a84c157 | 1486:0ba3f0b2be2e |
|---|---|
| 211 for f in features: | 211 for f in features: |
| 212 for extendenum in f.findAll("enum"): | 212 for extendenum in f.findAll("enum"): |
| 213 if extendenum.attr("extends") != "": | 213 if extendenum.attr("extends") != "": |
| 214 enums[extendenum.attr("extends")].addValue(extendenum) | 214 enums[extendenum.attr("extends")].addValue(extendenum) |
| 215 | 215 |
| 216 var extensionLoaders: seq[(string, seq[string])] | |
| 217 | |
| 216 for extension in extensions.findAll("extension"): | 218 for extension in extensions.findAll("extension"): |
| 217 let extNum = extension.attr("number") | 219 let extNum = extension.attr("number") |
| 220 extensionLoaders.add (extension.attr("name"), newSeq[string]()) | |
| 221 for c in extension.findAll("command"): | |
| 222 if "Video" notin c.attr("name"): | |
| 223 extensionLoaders[^1][1].add c.attr("name") | |
| 224 | |
| 218 for extendenum in extension.findAll("enum"): | 225 for extendenum in extension.findAll("enum"): |
| 219 if extendenum.attr("extends") != "": | 226 if extendenum.attr("extends") != "": |
| 220 if extendenum.attr("extnumber") == "": | 227 if extendenum.attr("extnumber") == "": |
| 221 extendenum.attrs["extnumber"] = extNum | 228 extendenum.attrs["extnumber"] = extNum |
| 222 enums[extendenum.attr("extends")].addValue(extendenum) | 229 enums[extendenum.attr("extends")].addValue(extendenum) |
| 227 # generate core types =============================================================================== | 234 # generate core types =============================================================================== |
| 228 # preamble, much easier to hardcode than to generate from xml | 235 # preamble, much easier to hardcode than to generate from xml |
| 229 outFile.writeLine """ | 236 outFile.writeLine """ |
| 230 | 237 |
| 231 import std/dynlib | 238 import std/dynlib |
| 239 import std/strutils | |
| 240 import std/tables | |
| 232 | 241 |
| 233 import ../semicongine/thirdparty/winim/winim/inc/winbase | 242 import ../semicongine/thirdparty/winim/winim/inc/winbase |
| 234 import ../semicongine/thirdparty/winim/winim/inc/windef | 243 import ../semicongine/thirdparty/winim/winim/inc/windef |
| 235 import ../semicongine/thirdparty/x11/xlib | 244 import ../semicongine/thirdparty/x11/xlib |
| 236 import ../semicongine/thirdparty/x11/x | 245 import ../semicongine/thirdparty/x11/x |
| 309 value = value[0 ..^ 2] & "'u32" | 318 value = value[0 ..^ 2] & "'u32" |
| 310 elif value.endsWith("ULL"): | 319 elif value.endsWith("ULL"): |
| 311 value = value[0 ..^ 4] & "'u64" | 320 value = value[0 ..^ 4] & "'u64" |
| 312 if value[0] == '~': | 321 if value[0] == '~': |
| 313 value = "not " & value[1 ..^ 1] | 322 value = "not " & value[1 ..^ 1] |
| 314 outFile.writeLine &" {c.name}*: {c.datatype} = {value}" | 323 if c.name in ["VK_TRUE", "VK_FALSE"]: |
| 324 outFile.writeLine &" {c.name}*: VkBool32 = VkBool32({value})" | |
| 325 else: | |
| 326 outFile.writeLine &" {c.name}*: {c.datatype} = {value}" | |
| 315 outFile.writeLine "" | 327 outFile.writeLine "" |
| 316 | 328 |
| 317 # generate enums =============================================================================== | 329 # generate enums =============================================================================== |
| 318 const nameCollisions = [ | 330 const nameCollisions = [ |
| 319 "VK_PIPELINE_CACHE_HEADER_VERSION_ONE", | 331 "VK_PIPELINE_CACHE_HEADER_VERSION_ONE", |
| 333 outFile.writeLine &" {ee.name} = {ee.value}" | 345 outFile.writeLine &" {ee.name} = {ee.value}" |
| 334 | 346 |
| 335 outFile.writeLine "" | 347 outFile.writeLine "" |
| 336 | 348 |
| 337 # generate types =============================================================================== | 349 # generate types =============================================================================== |
| 350 var stringConverters: seq[string] | |
| 338 for t in types: | 351 for t in types: |
| 339 let category = t.attr("category") | 352 let category = t.attr("category") |
| 340 let tName = t.attr("name") | 353 let tName = t.attr("name") |
| 341 if tName.startsWith("VkVideo"): # we are not doing the video API, sorry | 354 if tName.startsWith("VkVideo"): # we are not doing the video API, sorry |
| 342 continue | 355 continue |
| 355 elif t.attr("alias") != "": | 368 elif t.attr("alias") != "": |
| 356 let a = t.attr("alias") | 369 let a = t.attr("alias") |
| 357 outFile.writeLine &" {tName}* = {a}" | 370 outFile.writeLine &" {tName}* = {a}" |
| 358 elif category == "bitmask": | 371 elif category == "bitmask": |
| 359 if t.len > 0 and t[0].text.startsWith("typedef"): | 372 if t.len > 0 and t[0].text.startsWith("typedef"): |
| 360 outFile.writeLine &" {t[2][0].text}* = distinct {t[1][0].text}" | 373 outFile.writeLine &" {t[2][0].text.strip()}* = distinct {t[1][0].text.strip()}" |
| 361 elif category == "union": | 374 elif category == "union": |
| 362 outFile.writeLine &" {tName}* {{.union.}} = object" | 375 outFile.writeLine &" {tName}* {{.union.}} = object" |
| 363 for member in t.findAll("member"): | 376 for member in t.findAll("member"): |
| 364 outFile.writeLine &" {member.memberDecl()}" | 377 outFile.writeLine &" {member.memberDecl()}" |
| 365 elif category == "handle": | 378 elif category == "handle": |
| 366 outFile.writeLine &" {t[2][0].text} = distinct pointer" | 379 outFile.writeLine &" {t[2][0].text.strip()} = distinct pointer" |
| 380 stringConverters.add t[2][0].text.strip() | |
| 367 elif category == "struct": | 381 elif category == "struct": |
| 368 outFile.writeLine &" {tName}* = object" | 382 outFile.writeLine &" {tName}* = object" |
| 369 for member in t.findAll("member"): | 383 for member in t.findAll("member"): |
| 370 if member.attr("api") == "vulkansc": | 384 if member.attr("api") == "vulkansc": |
| 371 continue | 385 continue |
| 449 assert "*" notin retType | 463 assert "*" notin retType |
| 450 outFile.write &": {doTypename(retType, 0)}" | 464 outFile.write &": {doTypename(retType, 0)}" |
| 451 outFile.write " {.stdcall.}\n" | 465 outFile.write " {.stdcall.}\n" |
| 452 | 466 |
| 453 outFile.write """ | 467 outFile.write """ |
| 454 when defined(linux): | |
| 455 let vulkanLib = loadLib("libvulkan.so.1") | |
| 456 when defined(windows): | |
| 457 let vulkanLib = loadLib("vulkan-1.dll") | |
| 458 if vulkanLib == nil: | |
| 459 raise newException(Exception, "Unable to load vulkan library") | |
| 460 | |
| 461 vkGetInstanceProcAddr = cast[proc(instance: VkInstance, pName: cstring, ): PFN_vkVoidFunction {.stdcall.}](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr")) | |
| 462 | 468 |
| 463 proc loadFunc[T](instance: VkInstance, f: var T, name: string) = | 469 proc loadFunc[T](instance: VkInstance, f: var T, name: string) = |
| 464 f = cast[T](vkGetInstanceProcAddr(instance, name)) | 470 f = cast[T](vkGetInstanceProcAddr(instance, name)) |
| 471 | |
| 472 proc initVulkanLoader*() = | |
| 473 if vkGetInstanceProcAddr != nil: | |
| 474 return | |
| 475 | |
| 476 when defined(linux): | |
| 477 let vulkanLib = loadLib("libvulkan.so.1") | |
| 478 when defined(windows): | |
| 479 let vulkanLib = loadLib("vulkan-1.dll") | |
| 480 if vulkanLib == nil: | |
| 481 raise newException(Exception, "Unable to load vulkan library") | |
| 482 | |
| 483 # init two global functions | |
| 484 vkGetInstanceProcAddr = cast[proc(instance: VkInstance, pName: cstring, ): PFN_vkVoidFunction {.stdcall.}](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr")) | |
| 485 | |
| 486 loadFunc(VkInstance(nil), vkCreateInstance, "vkCreateInstance") | |
| 465 | 487 |
| 466 """ | 488 """ |
| 467 | 489 |
| 468 for f in features: | 490 for f in features: |
| 469 let name = f.attr("name").replace(",", "_") | 491 let name = f.attr("name").replace(",", "_") |
| 470 if f.attr("struct") != "": | 492 if f.attr("struct") != "": |
| 471 continue | 493 continue |
| 472 outFile.writeLine &"proc loadFeature_{name}(instance: VkInstance) =" | 494 outFile.writeLine &"proc load_{name}(instance: VkInstance) =" |
| 473 var hasEntries = false | 495 var hasEntries = false |
| 474 for cmd in f.findAll("command"): | 496 for cmd in f.findAll("command"): |
| 497 if cmd.attr("name") == "vkCreateInstance": | |
| 498 continue | |
| 475 hasEntries = true | 499 hasEntries = true |
| 476 let cName = cmd.attr("name") | 500 let cName = cmd.attr("name") |
| 477 outFile.writeLine &" loadFunc(instance, {cName}, \"{cName}\")" | 501 outFile.writeLine &" loadFunc(instance, {cName}, \"{cName}\")" |
| 478 if not hasEntries: | 502 if not hasEntries: |
| 479 outFile.writeLine " discard" | 503 outFile.writeLine " discard" |
| 480 outFile.writeLine "" | 504 outFile.writeLine "" |
| 481 | 505 |
| 506 for (extName, commands) in extensionLoaders: | |
| 507 outFile.writeLine &"proc load_{extName}(instance: VkInstance) =" | |
| 508 for c in commands: | |
| 509 outFile.writeLine &" loadFunc(instance, {c}, \"{c}\")" | |
| 510 if commands.len == 0: | |
| 511 outFile.writeLine &" discard" | |
| 512 outFile.writeLine "" | |
| 513 | |
| 514 outFile.writeLine "const EXTENSION_LOADERS = {" | |
| 515 for (extName, commands) in extensionLoaders: | |
| 516 outFile.writeLine &" \"{extName}\": load_{extName}," | |
| 517 outFile.writeLine "}.toTable" | |
| 518 outFile.writeLine "" | |
| 519 | |
| 520 outFile.writeLine "proc loadExtension*(instance: VkInstance, name: string) =" | |
| 521 outFile.writeLine " assert name in EXTENSION_LOADERS" | |
| 522 outFile.writeLine " EXTENSION_LOADERS[name](instance)" | |
| 523 outFile.writeLine "" | |
| 524 | |
| 525 for strCon in stringConverters: | |
| 526 outFile.writeLine &"""proc `$`*(v: {strCon}): string = "0x" & cast[uint](v).toHex()""" | |
| 527 outFile.writeLine "" | |
| 528 | |
| 529 # we preload the vkCreateInstance function, so we can create an instance | |
| 530 outFile.writeLine "" | |
| 531 | |
| 482 outFile.close() | 532 outFile.close() |
| 483 | 533 |
| 484 assert execCmd("nim c " & outPath) == 0 | 534 assert execCmd("nim c " & outPath) == 0 |
