changeset 91:2e9823f9193f

Merge branch 'main' of github.com:saemideluxe/semicongine
author Sam <sam@basx.dev>
date Mon, 27 Feb 2023 00:05:26 +0700
parents 6e8037c1f655 (diff) 01ba9f715b7e (current diff)
children e872cf354110
files src/semicongine/shader.nim
diffstat 8 files changed, 286 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/engine.nim	Sat Feb 25 18:56:42 2023 +0700
+++ b/src/semicongine/engine.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -111,21 +111,17 @@
 proc getAllPhysicalDevices(instance: VkInstance, surface: VkSurfaceKHR): seq[
     PhysicalDevice] =
   for vulkanPhysicalDevice in getVulkanPhysicalDevices(instance):
-    var device = PhysicalDevice(device: vulkanPhysicalDevice,
-        extensions: getDeviceExtensions(vulkanPhysicalDevice))
+    var device = PhysicalDevice(device: vulkanPhysicalDevice, extensions: getDeviceExtensions(vulkanPhysicalDevice))
     vkGetPhysicalDeviceProperties(vulkanPhysicalDevice, addr(device.properties))
     vkGetPhysicalDeviceFeatures(vulkanPhysicalDevice, addr(device.features))
     device.formats = vulkanPhysicalDevice.getDeviceSurfaceFormats(surface)
     device.presentModes = vulkanPhysicalDevice.getDeviceSurfacePresentModes(surface)
 
     debug(&"Physical device nr {int(vulkanPhysicalDevice)} {cleanString(device.properties.deviceName)}")
-    for i, queueFamilyProperty in enumerate(getQueueFamilies(
-        vulkanPhysicalDevice)):
+    for i, queueFamilyProperty in enumerate(getQueueFamilies(vulkanPhysicalDevice)):
       var hasSurfaceSupport: VkBool32 = VK_FALSE
-      checkVkResult vkGetPhysicalDeviceSurfaceSupportKHR(vulkanPhysicalDevice,
-          uint32(i), surface, addr(hasSurfaceSupport))
-      device.queueFamilies.add(QueueFamily(properties: queueFamilyProperty,
-          hasSurfaceSupport: bool(hasSurfaceSupport)))
+      checkVkResult vkGetPhysicalDeviceSurfaceSupportKHR(vulkanPhysicalDevice, uint32(i), surface, addr(hasSurfaceSupport))
+      device.queueFamilies.add(QueueFamily(properties: queueFamilyProperty, hasSurfaceSupport: bool(hasSurfaceSupport)))
       debug(&"  Queue family {i} {queueFamilyProperty}")
 
     result.add(device)
@@ -182,11 +178,9 @@
       pfnUserCallback: debugCallback,
       pUserData: nil,
     )
-    checkVkResult instance.vkCreateDebugUtilsMessengerEXT(addr(createInfo), nil,
-        addr(result))
+    checkVkResult instance.vkCreateDebugUtilsMessengerEXT(addr(createInfo), nil, addr(result))
 
-proc setupVulkanDeviceAndQueues(instance: VkInstance,
-    surface: VkSurfaceKHR): Device =
+proc setupVulkanDeviceAndQueues(instance: VkInstance, surface: VkSurfaceKHR): Device =
   let usableDevices = instance.getAllPhysicalDevices(surface).filterForDevice()
   if len(usableDevices) == 0:
     raise newException(Exception, "No suitable graphics device found")
@@ -539,8 +533,7 @@
   when DEBUG_LOG:
     result.vulkan.debugMessenger = result.vulkan.instance.setupDebugLog()
   result.vulkan.surface = result.vulkan.instance.createVulkanSurface(result.window)
-  result.vulkan.device = result.vulkan.instance.setupVulkanDeviceAndQueues(
-      result.vulkan.surface)
+  result.vulkan.device = result.vulkan.instance.setupVulkanDeviceAndQueues(result.vulkan.surface)
 
   # get basic frame information
   result.vulkan.surfaceFormat = result.vulkan.device.physicalDevice.formats.getSuitableSurfaceFormat()
@@ -906,8 +899,7 @@
   engine.vulkan.instance.vkDestroySurfaceKHR(engine.vulkan.surface, nil)
   engine.vulkan.device.device.vkDestroyDevice(nil)
   when DEBUG_LOG:
-    engine.vulkan.instance.vkDestroyDebugUtilsMessengerEXT(
-        engine.vulkan.debugMessenger, nil)
+    engine.vulkan.instance.vkDestroyDebugUtilsMessengerEXT(engine.vulkan.debugMessenger, nil)
   engine.window.trash()
   engine.vulkan.instance.vkDestroyInstance(
       nil) # needs to happen after window is trashed as the driver might have a hook registered for the window destruction
--- a/src/semicongine/shader.nim	Sat Feb 25 18:56:42 2023 +0700
+++ b/src/semicongine/shader.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -58,7 +58,7 @@
       input = shaderSource
   )
 
-  when defined(mingw) and not defined(windows): # required for crosscompilation, path separators get messed up
+  when defined(mingw) and defined(linux): # required for crosscompilation, path separators get messed up
     let shaderbinary = staticRead shaderfile.replace("\\", "/")
   else:
     let shaderbinary = staticRead shaderfile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/semicongine/vulkan/buffers.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -0,0 +1,31 @@
+import ./api
+
+type
+  Buffer = object
+    device: VkDevice
+    vk: VkBuffer
+    size: uint64
+
+# currently no support for extended structure and concurrent/shared use
+# (shardingMode = VK_SHARING_MODE_CONCURRENT not supported)
+proc createBuffer(device: VkDevice, size: uint64, flags: openArray[VkBufferCreateFlagBits], usage: openArray[VkBufferUsageFlagBits]): Buffer =
+  result.device = device
+  result.size = size
+  var createInfo = VkBufferCreateInfo(
+    sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+    flags: toBits(flags),
+    size: size,
+    usage: toBits(usage),
+    sharingMode: VK_SHARING_MODE_EXCLUSIVE,
+  )
+
+  checkVkResult vkCreateBuffer(
+    device=device,
+    pCreateInfo=addr createInfo,
+    pAllocator=nil,
+    pBuffer=addr result.vk
+  )
+
+proc destroy(buffer: Buffer) =
+  if uint(buffer.vk) != 0:
+    vkDestroyBuffer(buffer.device, buffer.vk, nil)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/semicongine/vulkan/device.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -0,0 +1,80 @@
+import ./api
+import ./utils
+import ./instance
+
+type
+  PhysicalDevice = object
+    vk: VkPhysicalDevice
+  Device = object
+    physicalDevice: PhysicalDevice
+    vk: VkDevice
+  QueueFamily = object
+    vk: VkQueueFamilyProperties
+    index: uint32
+  Queue = object
+    vk: VkQueue
+
+proc getDeviceExtensions*(device: VkPhysicalDevice): seq[string] =
+  var extensionCount: uint32
+  checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), nil)
+  if extensionCount > 0:
+    var extensions = newSeq[VkExtensionProperties](extensionCount)
+    checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), addr extensions[0])
+    for extension in extensions:
+      result.add(cleanString(extension.extensionName))
+
+proc getVulkanPhysicalDevices*(instance: Instance): seq[PhysicalDevice] =
+  var nDevices: uint32
+  checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), nil)
+  var devices = newSeq[VkPhysicalDevice](nDevices)
+  checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), addr devices[0])
+  for i in 0 ..< nDevices:
+    result.add PhysicalDevice(vk: devices[i])
+
+proc getQueueFamilies*(device: PhysicalDevice): seq[QueueFamily] =
+  var nQueuefamilies: uint32
+  vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies, nil)
+  var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies)
+  vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies , addr queuFamilies[0])
+  for i in 0 ..< nQueuefamilies:
+    result.add QueueFamily(vk: queuFamilies[i], index: i)
+
+proc createDevice(
+  physicalDevice: PhysicalDevice,
+  enabledLayers: openArray[string],
+  enabledExtensions: openArray[string],
+  queueFamilies: openArray[QueueFamily],
+): Device =
+  result.physicalDevice = physicalDevice
+  var
+    enabledLayersC = allocCStringArray(enabledLayers)
+    enabledExtensionsC = allocCStringArray(enabledExtensions)
+    priority = 1'f32
+  var deviceQueues: seq[VkDeviceQueueCreateInfo]
+  for family in queueFamilies:
+    deviceQueues.add VkDeviceQueueCreateInfo(
+      sType: VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+      queueFamilyIndex: family.index,
+      queueCount: 1,
+      pQueuePriorities: addr(priority),
+    )
+
+  var createInfo = VkDeviceCreateInfo(
+    sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+    queueCreateInfoCount: uint32(deviceQueues.len),
+    pQueueCreateInfos: addr deviceQueues[0],
+    enabledLayerCount: uint32(enabledLayers.len),
+    ppEnabledLayerNames: enabledLayersC,
+    enabledExtensionCount: uint32(enabledExtensions.len),
+    ppEnabledExtensionNames: enabledExtensionsC,
+    pEnabledFeatures: nil,
+  )
+
+  checkVkResult vkCreateDevice(
+    physicalDevice=physicalDevice.vk,
+    pCreateInfo=addr createInfo,
+    pAllocator=nil,
+    pDevice=addr result.vk
+  )
+  deallocCStringArray(enabledLayersC)
+  deallocCStringArray(enabledExtensionsC)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/semicongine/vulkan/instance.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -0,0 +1,105 @@
+import std/strformat
+
+import ./api
+import ./utils
+
+type
+  Instance* = object
+    vk*: VkInstance
+  Debugger = object
+    instance: VkInstance
+    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), addr extensions[0])
+    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), addr layers[0])
+    for layer in layers:
+      result.add(cleanString(layer.layerName))
+
+proc createInstance*(
+  vulkanVersion: uint32,
+  instanceExtensions: seq[string],
+  layers: seq[string],
+  name = "defaultVulkanInstance",
+  engine = "defaultEngine",
+): Instance =
+  for i in layers: assert i in getLayers()
+  for i in instanceExtensions: assert i in getInstanceExtensions()
+  var
+    layersC = allocCStringArray(layers)
+    instanceExtensionsC = allocCStringArray(instanceExtensions)
+    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: layers.len.uint32,
+      ppEnabledLayerNames: layersC,
+      enabledExtensionCount: instanceExtensions.len.uint32,
+      ppEnabledExtensionNames: instanceExtensionsC
+    )
+  checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result.vk))
+  deallocCStringArray(layersC)
+  deallocCStringArray(instanceExtensionsC)
+  for extension in instanceExtensions:
+    result.vk.loadExtension($extension)
+
+proc destroy(instance: Instance) =
+  # needs to happen after window is trashed as the driver might have a hook registered for the window destruction
+  instance.vk.vkDestroyInstance(nil)
+
+proc defaultDebugCallback(
+  messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT,
+  messageTypes: VkDebugUtilsMessageTypeFlagsEXT,
+  pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT,
+  userData: pointer
+): VkBool32 {.cdecl.} =
+  echo &"{messageSeverity}: {toEnums messageTypes}: {pCallbackData.pMessage}"
+  return false
+
+proc createDebugMessenger(
+  instance: VkInstance,
+  severityLevels: openArray[VkDebugUtilsMessageSeverityFlagBitsEXT] = @[],
+  types: openArray[VkDebugUtilsMessageTypeFlagBitsEXT] = @[],
+  callback: DebugCallback=defaultDebugCallback
+): Debugger =
+  result.instance = instance
+  var severityLevelBits = high(VkDebugUtilsMessageSeverityFlagsEXT)
+  var typeBits = high(VkDebugUtilsMessageTypeFlagsEXT)
+  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.vkCreateDebugUtilsMessengerEXT(addr(createInfo), nil, addr(result.messenger))
+
+proc destroy(debugger: Debugger) =
+  debugger.instance.vkDestroyDebugUtilsMessengerEXT(debugger.messenger, nil)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/semicongine/vulkan/memory.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -0,0 +1,51 @@
+import ./api
+
+type
+  MemoryHeap = object
+    size: uint64
+    flags: seq[VkMemoryHeapFlagBits]
+    index: uint32
+  MemoryType = object
+    heap: MemoryHeap
+    flags: seq[VkMemoryPropertyFlagBits]
+    index: uint32
+  PhyscialDeviceMemoryProperties = object
+    heaps: seq[MemoryHeap]
+    types: seq[MemoryType]
+  DeviceMemory = object
+    device: VkDevice
+    size: uint64
+    vk: VkDeviceMemory
+
+proc getPhysicalDeviceMemoryProperties(physicalDevice: VkPhysicalDevice): PhyscialDeviceMemoryProperties =
+  var physicalProperties: VkPhysicalDeviceMemoryProperties
+  vkGetPhysicalDeviceMemoryProperties(physicalDevice, addr physicalProperties)
+  for i in 0 ..< physicalProperties.memoryHeapCount:
+    result.heaps.add MemoryHeap(
+      size: physicalProperties.memoryHeaps[i].size,
+      flags: toEnums(physicalProperties.memoryHeaps[i].flags),
+      index: i,
+    )
+  for i in 0 ..< physicalProperties.memoryTypeCount:
+    result.types.add MemoryType(
+      heap: result.heaps[physicalProperties.memoryTypes[i].heapIndex],
+      flags: toEnums(physicalProperties.memoryTypes[i].propertyFlags),
+      index: i,
+    )
+
+proc allocateMemory(device: VkDevice, size: uint64, memoryType: MemoryType): DeviceMemory =
+  result.device = device
+  result.size = size
+
+  var allocationInfo = VkMemoryAllocateInfo(
+    sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+    allocationSize: size,
+    memoryTypeIndex: memoryType.index,
+  )
+
+  checkVkResult vkAllocateMemory(
+    device,
+    addr allocationInfo,
+    nil,
+    addr result.vk
+  )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/semicongine/vulkan/utils.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -0,0 +1,8 @@
+import std/strutils
+
+func cleanString*(str: openArray[char]): string =
+  for i in 0 ..< len(str):
+    if str[i] == char(0):
+      result = join(str[0 ..< i])
+      break
+
--- a/src/semicongine/vulkan_helpers.nim	Sat Feb 25 18:56:42 2023 +0700
+++ b/src/semicongine/vulkan_helpers.nim	Mon Feb 27 00:05:26 2023 +0700
@@ -40,11 +40,9 @@
 
 proc getInstanceExtensions*(): seq[string] =
   var extensionCount: uint32
-  checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(
-      extensionCount), nil)
+  checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr( extensionCount), nil)
   var extensions = newSeq[VkExtensionProperties](extensionCount)
-  checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(
-      extensionCount), addrOrNil(extensions))
+  checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr( extensionCount), addrOrNil(extensions))
 
   for extension in extensions:
     result.add(cleanString(extension.extensionName))
@@ -177,7 +175,6 @@
   for extension in requiredExtensions & other_extensions:
     result.loadExtension($extension)
 
-
 proc getVulcanDevice*(
   physicalDevice: var VkPhysicalDevice,
   features: var VkPhysicalDeviceFeatures,