changeset 690:fe20f8013d12

add: support for struct members to be array
author Sam <sam@basx.dev>
date Tue, 16 May 2023 15:35:43 +0700
parents 473e6069692d
children 9182a5d2ea3a
files src/semicongine/core/gpu_data.nim src/semicongine/core/vulkanapi.nim src/semicongine/entity.nim src/semicongine/vulkan/descriptor.nim src/semicongine/vulkan/device.nim src/semicongine/vulkan/physicaldevice.nim src/semicongine/vulkan/pipeline.nim src/semicongine/vulkan/shader.nim
diffstat 8 files changed, 45 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/core/gpu_data.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/core/gpu_data.nim	Tue May 16 15:35:43 2023 +0700
@@ -1020,7 +1020,7 @@
   if group.len == 0:
     return @[]
   # currently only a single uniform block supported, therefore binding = 0
-  result.add(&"layout(binding = {binding}) uniform T{blockName} {{")
+  result.add(&"layout(std430, binding = {binding}) uniform T{blockName} {{")
   for attribute in group:
     var arrayDecl = ""
     if attribute.arrayCount > 0:
--- a/src/semicongine/core/vulkanapi.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/core/vulkanapi.nim	Tue May 16 15:35:43 2023 +0700
@@ -12052,7 +12052,9 @@
   include ../vulkan/platform/screen
   EXTENSION_LOADERS["VK_QNX_screen_surface"] = loadVK_QNX_screen_surface
 
-proc loadExtension*(instance: VkInstance, extension: string) = EXTENSION_LOADERS[extension](instance)
+proc loadExtension*(instance: VkInstance, extension: string) =
+  if extension in EXTENSION_LOADERS:
+    EXTENSION_LOADERS[extension](instance)
 
 # load global functions immediately
 block globalFunctions:
--- a/src/semicongine/entity.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/entity.nim	Tue May 16 15:35:43 2023 +0700
@@ -12,7 +12,7 @@
   Scene* = object
     name*: string
     root*: Entity
-    shaderGlobals*: Table[string, DataValue]
+    shaderGlobals*: Table[string, DataList]
     textures*: Table[string, (seq[Image], VkFilter)]
 
   Entity* = ref object of RootObj
@@ -23,15 +23,24 @@
     components*: seq[Component]
 
 func addShaderGlobal*[T](scene: var Scene, name: string, data: T) =
-  var value = DataValue(thetype: getDataType[T]())
-  value.setValue(data)
-  scene.shaderGlobals[name] = value
+  scene.shaderGlobals[name] = newDataList(thetype=getDataType[T]())
+  setValues(scene.shaderGlobals[name], @[data])
+
+func addShaderGlobalArray*[T](scene: var Scene, name: string, data: seq[T]) =
+  scene.shaderGlobals[name] = newDataList(thetype=getDataType[T]())
+  setValues(scene.shaderGlobals[name], data)
 
 func getShaderGlobal*[T](scene: Scene, name: string): T =
-  getValue[T](scene.shaderGlobals[name])
+  getValues[T](scene.shaderGlobals[name])[0]
+
+func getShaderGlobalArray*[T](scene: Scene, name: string): seq[T] =
+  getValues[T](scene.shaderGlobals[name])
 
 func setShaderGlobal*[T](scene: var Scene, name: string, value: T) =
-  setValue[T](scene.shaderGlobals[name], value)
+  setValues[T](scene.shaderGlobals[name], @[value])
+
+func setShaderGlobalArray*[T](scene: var Scene, name: string, value: seq[T]) =
+  setValues[T](scene.shaderGlobals[name], value)
 
 func addTextures*(scene: var Scene, name: string, texture: seq[Image], interpolation=VK_FILTER_LINEAR) =
   scene.textures[name] = (texture, interpolation)
--- a/src/semicongine/vulkan/descriptor.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/vulkan/descriptor.nim	Tue May 16 15:35:43 2023 +0700
@@ -13,7 +13,6 @@
     name*: string
     count*: uint32
     stages*: seq[VkShaderStageFlagBits]
-    itemsize*: uint32
     case thetype*: DescriptorType
     of Uniform:
       buffer*: Buffer
--- a/src/semicongine/vulkan/device.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/vulkan/device.nim	Tue May 16 15:35:43 2023 +0700
@@ -33,7 +33,7 @@
   assert queueFamilies.len > 0
 
   result.physicalDevice = physicalDevice
-  var allExtensions = enabledExtensions & @["VK_KHR_swapchain"]
+  var allExtensions = enabledExtensions & @["VK_KHR_swapchain", "VK_KHR_uniform_buffer_standard_layout"]
   for extension in allExtensions:
     instance.vk.loadExtension(extension)
   var
@@ -49,6 +49,16 @@
       pQueuePriorities: addr(priority),
     )
   var queueList = deviceQueues.values.toSeq
+
+  var uniformBufferLayoutFeature = VkPhysicalDeviceUniformBufferStandardLayoutFeatures(
+    stype:VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES,
+    uniformBufferStandardLayout: true,
+  )
+  var features2 = VkPhysicalDeviceFeatures2(
+    stype: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+    pnext: addr uniformBufferLayoutFeature,
+    features: result.enabledFeatures,
+  )
   var createInfo = VkDeviceCreateInfo(
     sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
     queueCreateInfoCount: uint32(queueList.len),
@@ -57,7 +67,8 @@
     ppEnabledLayerNames: enabledLayersC,
     enabledExtensionCount: uint32(allExtensions.len),
     ppEnabledExtensionNames: enabledExtensionsC,
-    pEnabledFeatures: addr result.enabledFeatures,
+    pEnabledFeatures: nil,
+    pnext: addr features2,
   )
 
   checkVkResult vkCreateDevice(
--- a/src/semicongine/vulkan/physicaldevice.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/vulkan/physicaldevice.nim	Tue May 16 15:35:43 2023 +0700
@@ -12,7 +12,7 @@
     devicetype*: VkPhysicalDeviceType
     surface*: VkSurfaceKHR
     properties*: VkPhysicalDeviceProperties
-    features*: VkPhysicalDeviceFeatures
+    features*: VkPhysicalDeviceFeatures2
   QueueFamily* = object
     device: PhysicalDevice
     properties*: VkQueueFamilyProperties
@@ -32,7 +32,8 @@
   for i in 0 ..< nDevices:
     var device = PhysicalDevice(vk: devices[i], surface: instance.surface)
     device.vk.vkGetPhysicalDeviceProperties(addr device.properties)
-    device.vk.vkGetPhysicalDeviceFeatures(addr device.features)
+    device.features.stype = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
+    device.vk.vkGetPhysicalDeviceFeatures2(addr device.features)
     device.name = device.properties.deviceName.cleanString()
     device.devicetype = device.properties.deviceType
     result.add device
--- a/src/semicongine/vulkan/pipeline.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/vulkan/pipeline.nim	Tue May 16 15:35:43 2023 +0700
@@ -25,26 +25,26 @@
       return shader.inputs
 
 func uniforms*(pipeline: Pipeline): seq[ShaderAttribute] =
-  var uniformList: Table[string, ShaderAttribute]
+  var visitedUniforms: Table[string, ShaderAttribute]
   for shader in pipeline.shaders:
     for attribute in shader.uniforms:
-      if attribute.name in uniformList:
-        assert uniformList[attribute.name] == attribute
+      if attribute.name in visitedUniforms:
+        assert visitedUniforms[attribute.name] == attribute
       else:
-        uniformList[attribute.name] = attribute
-  result = uniformList.values.toSeq
+        result.add attribute
+        visitedUniforms[attribute.name] = attribute
 
 proc setupDescriptors*(pipeline: var Pipeline, buffers: seq[Buffer], textures: Table[string, seq[Texture]], inFlightFrames: int) =
   assert pipeline.vk.valid
   assert buffers.len == 0 or buffers.len == inFlightFrames # need to guard against this in case we have no uniforms, then we also create no buffers
   assert pipeline.descriptorSets.len > 0
-
+  
   for i in 0 ..< inFlightFrames:
     var offset = 0'u64
     # first descriptor is always uniform for globals, match should be better somehow
     for descriptor in pipeline.descriptorSets[i].layout.descriptors.mitems:
       if descriptor.thetype == Uniform and buffers.len > 0:
-        let size = VkDeviceSize(descriptor.itemsize * descriptor.count)
+        let size = VkDeviceSize(descriptor.size)
         descriptor.buffer = buffers[i]
         descriptor.offset = offset
         descriptor.size = size
@@ -75,24 +75,20 @@
   result.shaders = @[vertexShader, fragmentShader]
   
   var descriptors: seq[Descriptor]
-
   if vertexCode.uniforms.len > 0:
-    for uniform in vertexCode.uniforms:
-      assert uniform.arrayCount == 0, "arrays not yet supported for uniforms"
     descriptors.add Descriptor(
       name: "Uniforms",
       thetype: Uniform,
       count: 1,
       stages: @[VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT],
-      itemsize: vertexShader.uniforms.size(),
+      size: vertexShader.uniforms.size(),
     )
   for sampler in vertexShader.samplers:
     descriptors.add Descriptor(
       name: sampler.name,
       thetype: ImageSampler,
-      count: (if sampler.arrayCount == 0: 1 else: sampler.arrayCount),
+      count: (if sampler.arrayCount == 0: 1'u32 else: sampler.arrayCount),
       stages: @[VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT],
-      itemsize: 0,
     )
   result.descriptorSetLayout = device.createDescriptorSetLayout(descriptors)
 
--- a/src/semicongine/vulkan/shader.nim	Mon May 15 23:51:21 2023 +0700
+++ b/src/semicongine/vulkan/shader.nim	Tue May 16 15:35:43 2023 +0700
@@ -94,7 +94,7 @@
   main: seq[string]
 ): ShaderCode {.compileTime.} =
 
-  var code = @[&"#version {version}", ""] &
+  var code = @[&"#version {version}", "#extension GL_EXT_scalar_block_layout : require", ""] &
   # var code = @[&"#version {version}", "layout(row_major) uniform;", ""] &
     (if inputs.len > 0: inputs.glslInput() & @[""] else: @[]) &
     (if uniforms.len > 0: uniforms.glslUniforms(binding=0) & @[""] else: @[]) &