diff semiconginev2/old/vulkan/instance.nim @ 1218:56781cc0fc7c compiletime-tests

did: renamge main package
author sam <sam@basx.dev>
date Wed, 17 Jul 2024 21:01:37 +0700
parents semicongine/old/vulkan/instance.nim@a3eb305bcac2
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/semiconginev2/old/vulkan/instance.nim	Wed Jul 17 21:01:37 2024 +0700
@@ -0,0 +1,143 @@
+import std/strformat
+import std/tables
+import std/sequtils
+import std/logging
+
+import ../core
+
+import ../platform/vulkanExtensions
+import ../platform/window
+import ../platform/surface
+
+type
+  Instance* = object
+    vk*: VkInstance
+    window*: NativeWindow
+    surface*: VkSurfaceKHR
+  Debugger* = object
+    instance*: Instance
+    messenger*: VkDebugUtilsMessengerEXT
+  DebugCallback* = proc (
+    messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT,
+    messageTypes: VkDebugUtilsMessageTypeFlagsEXT,
+    pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT,
+    userData: pointer
+  ): VkBool32 {.cdecl.}
+
+proc GetInstanceExtensions*(): seq[string] =
+  var extensionCount: uint32
+  checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), nil)
+  if extensionCount > 0:
+    var extensions = newSeq[VkExtensionProperties](extensionCount)
+    checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), extensions.ToCPointer)
+    for extension in extensions:
+      result.add(CleanString(extension.extensionName))
+
+proc GetLayers*(): seq[string] =
+  var n_layers: uint32
+  checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), nil)
+  if n_layers > 0:
+    var layers = newSeq[VkLayerProperties](n_layers)
+    checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), layers.ToCPointer)
+    for layer in layers:
+      result.add(CleanString(layer.layerName))
+
+proc CreateInstance*(
+  window: NativeWindow,
+  vulkanVersion: uint32,
+  instanceExtensions: seq[string],
+  layers: seq[string],
+  name = "defaultVulkanInstance",
+  engine = "defaultEngine",
+): Instance =
+
+  let requiredExtensions = REQUIRED_PLATFORM_EXTENSIONS & @["VK_KHR_surface"] & instanceExtensions
+  for i in requiredExtensions:
+    assert i in GetInstanceExtensions(), $i
+  var availableLayers: seq[string]
+  for i in layers:
+    if i in GetLayers():
+      availableLayers.add i
+  debug "Enabled layers: " & $availableLayers
+  var
+    layersC = allocCStringArray(availableLayers)
+    instanceExtensionsC = allocCStringArray(requiredExtensions)
+    appinfo = VkApplicationInfo(
+      sType: VK_STRUCTURE_TYPE_APPLICATION_INFO,
+      pApplicationName: name,
+      pEngineName: engine,
+      apiVersion: vulkanVersion,
+    )
+    createinfo = VkInstanceCreateInfo(
+      sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+      pApplicationInfo: addr(appinfo),
+      enabledLayerCount: availableLayers.len.uint32,
+      ppEnabledLayerNames: layersC,
+      enabledExtensionCount: requiredExtensions.len.uint32,
+      ppEnabledExtensionNames: instanceExtensionsC
+    )
+  checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result.vk))
+  result.vk.loadVulkan()
+  deallocCStringArray(layersC)
+  deallocCStringArray(instanceExtensionsC)
+  for extension in requiredExtensions:
+    result.vk.loadExtension($extension)
+  result.surface = result.vk.CreateNativeSurface(window)
+
+proc Destroy*(instance: var Instance) =
+  assert instance.vk.Valid
+  assert instance.surface.Valid
+  # needs to happen after window is trashed as the driver might have a hook registered for the window destruction
+  instance.vk.vkDestroySurfaceKHR(instance.surface, nil)
+  instance.surface.Reset()
+  instance.vk.vkDestroyInstance(nil)
+  instance.vk.Reset()
+
+const 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
+
+proc defaultDebugCallback(
+  messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT,
+  messageTypes: VkDebugUtilsMessageTypeFlagsEXT,
+  pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT,
+  userData: pointer
+): VkBool32 {.cdecl.} =
+
+  log LEVEL_MAPPING[messageSeverity], &"{toEnums messageTypes}: {pCallbackData.pMessage}"
+  if messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+    let errorMsg = getStackTrace() & &"\n{toEnums messageTypes}: {pCallbackData.pMessage}"
+    raise newException(Exception, errorMsg)
+  return false
+
+proc CreateDebugMessenger*(
+  instance: Instance,
+  severityLevels: openArray[VkDebugUtilsMessageSeverityFlagBitsEXT] = @[],
+  types: openArray[VkDebugUtilsMessageTypeFlagBitsEXT] = @[],
+  callback: DebugCallback = defaultDebugCallback
+): Debugger =
+  assert instance.vk.Valid
+  result.instance = instance
+  var severityLevelBits = VkDebugUtilsMessageSeverityFlagBitsEXT.items.toSeq.toBits
+  var typeBits = VkDebugUtilsMessageTypeFlagBitsEXT.items.toSeq.toBits
+  if severityLevels.len > 0:
+    severityLevelBits = toBits severityLevels
+  if types.len > 0:
+    typeBits = toBits types
+  var createInfo = VkDebugUtilsMessengerCreateInfoEXT(
+    sType: VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
+    messageSeverity: severityLevelBits,
+    messageType: typeBits,
+    pfnUserCallback: callback,
+    pUserData: nil,
+  )
+  checkVkResult instance.vk.vkCreateDebugUtilsMessengerEXT(addr(createInfo), nil, addr(result.messenger))
+
+proc Destroy*(debugger: var Debugger) =
+  assert debugger.messenger.Valid
+  assert debugger.instance.vk.Valid
+  debugger.instance.vk.vkDestroyDebugUtilsMessengerEXT(debugger.messenger, nil)
+  debugger.messenger.Reset()