diff svk/api.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/api.nim	Sat May 03 01:03:01 2025 +0700
+++ b/svk/api.nim	Sat May 03 20:16:04 2025 +0700
@@ -1,8 +1,11 @@
 import std/strutils
 import std/logging
+import std/os
 
 include ./vkapi
 
+const VULKAN_VERSION = VK_MAKE_API_VERSION(0, 1, 3, 0)
+
 template checkVkResult*(call: untyped) =
   when defined(release):
     discard call
@@ -21,36 +24,91 @@
 
 type SVkInstance* = object
   vkInstance: VkInstance
+  debugMessenger: VkDebugUtilsMessengerEXT
 
 proc `=copy`(a: var SVkInstance, b: SVkInstance) {.error.}
 
 proc `=destroy`(a: SVkInstance) =
   if a.vkInstance.pointer != nil:
+    if a.debugMessenger.pointer != nil:
+      vkDestroyDebugUtilsMessengerEXT(a.vkInstance, a.debugMessenger, nil)
     a.vkInstance.vkDestroyInstance(nil)
 
+proc debugCallback(
+    messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT,
+    messageTypes: VkDebugUtilsMessageTypeFlagsEXT,
+    pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT,
+    userData: pointer,
+): VkBool32 {.cdecl.} =
+  const LOG_LEVEL_MAPPING = {
+    VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: lvlDebug,
+    VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: lvlInfo,
+    VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: lvlWarn,
+    VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: lvlError,
+  }.toTable
+  log LOG_LEVEL_MAPPING[messageSeverity]
+  if messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+    # stderr.write getStackTrace()
+    # stderr.writeLine LOG_LEVEL_MAPPING[messageSeverity], &"{toEnums messageTypes}: {pCallbackData.pMessage}"
+    let errorMsg = $pCallbackData.pMessage & ": " & getStackTrace()
+    raise newException(Exception, errorMsg)
+  return VK_FALSE
+
 proc svkCreateInstance*(
     applicationName: string,
     enabledLayers: openArray[string] = [],
-    enabledExtensions: openArray[string] = [],
+    enabledExtensions: openArray[string] =
+      if defined(release):
+        @["VK_KHR_surface"]
+      else:
+        @["VK_KHR_surface", "VK_EXT_debug_utils"],
     engineName = "semicongine",
-    majorVersion = 1'u32,
-    minorVersion = 3'u32,
+    withSwapchain = true,
 ): SVkInstance =
+  putEnv("VK_LOADER_LAYERS_ENABLE", "*validation")
+  putEnv(
+    "VK_LAYER_ENABLES",
+    "VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD,VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXTVK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT",
+  )
+  initVulkanLoader()
+
   let
     appinfo = VkApplicationInfo(
       pApplicationName: applicationName,
       pEngineName: engineName,
-      apiVersion: VK_MAKE_API_VERSION(0, majorVersion, minorVersion, 0),
+      apiVersion: VULKAN_VERSION,
     )
-    layersC = enabledLayers.allocCStringArray()
-    extensionsC = enabledLayers.allocCStringArray()
+    enabledLayersC = allocCStringArray(enabledLayers)
+    enabledExtensionsC = allocCStringArray(enabledExtensions)
     createinfo = VkInstanceCreateInfo(
       pApplicationInfo: addr appinfo,
       enabledLayerCount: enabledLayers.len.uint32,
-      ppEnabledLayerNames: layersC,
+      ppEnabledLayerNames: enabledLayersC,
       enabledExtensionCount: enabledExtensions.len.uint32,
-      ppEnabledExtensionNames: extensionsC,
+      ppEnabledExtensionNames: enabledExtensionsC,
     )
+  # this one we will load manually
   checkVkResult vkCreateInstance(addr createinfo, nil, addr result.vkInstance)
-  layersC.deallocCStringArray()
-  extensionsC.deallocCStringArray()
+
+  enabledLayersC.deallocCStringArray()
+  enabledExtensionsC.deallocCStringArray()
+
+  load_VK_VERSION_1_0(result.vkInstance)
+  load_VK_VERSION_1_1(result.vkInstance)
+  load_VK_VERSION_1_2(result.vkInstance)
+  load_VK_VERSION_1_3(result.vkInstance)
+
+  for extension in enabledExtensions:
+    loadExtension(result.vkInstance, extension)
+  if withSwapchain:
+    load_VK_KHR_swapchain(result.vkInstance)
+
+  when not defined(release):
+    var debugMessengerCreateInfo = VkDebugUtilsMessengerCreateInfoEXT(
+      messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT.items.toSeq.toBits,
+      messageType: VkDebugUtilsMessageTypeFlagBitsEXT.items.toSeq.toBits,
+      pfnUserCallback: debugCallback,
+    )
+    checkVkResult vkCreateDebugUtilsMessengerEXT(
+      result.vkInstance, addr debugMessengerCreateInfo, nil, addr result.debugMessenger
+    )