Mercurial > games > semicongine
comparison 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 |
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 |