changeset 658:8549373571aa

did: improve stability for configuration without uniforms and settings the engine renderer
author Sam <sam@basx.dev>
date Sun, 07 May 2023 17:41:45 +0700
parents c04425caeab5
children 8599b84f0563
files src/semicongine/engine.nim src/semicongine/entity.nim src/semicongine/mesh.nim src/semicongine/renderer.nim src/semicongine/resources.nim src/semicongine/vulkan/descriptor.nim src/semicongine/vulkan/pipeline.nim src/semicongine/vulkan/shader.nim
diffstat 8 files changed, 32 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/engine.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/engine.nim	Sun May 07 17:41:45 2023 +0700
@@ -1,4 +1,5 @@
 import std/sequtils
+import std/options
 import std/strutils
 import std/logging
 import std/os
@@ -41,7 +42,7 @@
     debugger: Debugger
     instance: Instance
     window: NativeWindow
-    renderer: Renderer
+    renderer: Option[Renderer]
     input: Input
     exitHandler: proc(engine: var Engine)
     resizeHandler: proc(engine: var Engine)
@@ -50,7 +51,8 @@
 
 proc destroy*(engine: var Engine) =
   checkVkResult engine.device.vk.vkDeviceWaitIdle()
-  engine.renderer.destroy()
+  if engine.renderer.isSome:
+    engine.renderer.get.destroy()
   engine.device.destroy()
   if engine.debugger.messenger.valid:
     engine.debugger.destroy()
@@ -105,19 +107,22 @@
 
 proc setRenderer*(engine: var Engine, renderPass: RenderPass) =
   assert engine.state != Destroyed
-  engine.renderer = engine.device.initRenderer(renderPass)
+  if engine.renderer.isSome:
+    engine.renderer.get.destroy()
+  engine.renderer = some(engine.device.initRenderer(renderPass))
 
 proc addScene*(engine: var Engine, scene: Scene, vertexInput: seq[ShaderAttribute], transformAttribute="") =
   assert engine.state != Destroyed
   assert transformAttribute == "" or transformAttribute in map(vertexInput, proc(a: ShaderAttribute): string = a.name)
-  engine.renderer.setupDrawableBuffers(scene, vertexInput, transformAttribute=transformAttribute)
+  assert engine.renderer.isSome
+  engine.renderer.get.setupDrawableBuffers(scene, vertexInput, transformAttribute=transformAttribute)
 
 proc renderScene*(engine: var Engine, scene: var Scene) =
   assert engine.state == Running
-  assert engine.renderer.valid
+  assert engine.renderer.isSome
   if engine.state == Running:
-    engine.renderer.refreshMeshData(scene)
-    engine.renderer.render(scene)
+    engine.renderer.get.refreshMeshData(scene)
+    engine.renderer.get.render(scene)
 
 proc updateInputs*(engine: var Engine): EngineState =
   assert engine.state in [Starting, Running]
@@ -171,7 +176,7 @@
 func mouseWasReleased*(engine: Engine, button: MouseButton): auto = button in engine.input.mouseWasReleased
 func mousePosition*(engine: Engine): auto = engine.input.mousePosition
 func eventsProcessed*(engine: Engine): auto = engine.input.eventsProcessed
-func framesRendered*(engine: Engine): auto = engine.renderer.framesRendered
+func framesRendered*(engine: Engine): uint64 = (if engine.renderer.isSome: engine.renderer.get.framesRendered else: 0)
 func gpuDevice*(engine: Engine): Device = engine.device
 func getWindow*(engine: Engine): auto = engine.window
 func windowWasResized*(engine: Engine): auto = engine.input.windowWasResized
--- a/src/semicongine/entity.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/entity.nim	Sun May 07 17:41:45 2023 +0700
@@ -23,11 +23,11 @@
     children*: seq[Entity]
     components*: seq[Component]
 
+  Pixel* = array[4, uint8]
   TextureImage* = ref object of RootObj
-    name*: string
     width*: uint32
     height*: uint32
-    imagedata*: seq[array[4, uint8]]
+    imagedata*: seq[Pixel]
 
 func addShaderGlobal*[T](scene: var Scene, name: string, data: T) =
   var value = DataValue(thetype: getDataType[T]())
--- a/src/semicongine/mesh.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/mesh.nim	Sun May 07 17:41:45 2023 +0700
@@ -44,10 +44,12 @@
   positions: openArray[Vec3f],
   indices: openArray[array[3, uint32|int32|uint16|int16|int]],
   colors: openArray[Vec3f]=[],
+  uvs: openArray[Vec2f]=[],
   instanceCount=1'u32,
   autoResize=true
 ): auto =
   assert colors.len == 0 or colors.len == positions.len
+  assert uvs.len == 0 or uvs.len == positions.len
 
   result = new Mesh
   result.vertexCount = uint32(positions.len)
@@ -58,6 +60,9 @@
   if colors.len > 0:
     result.data["color"] = DataList(thetype: Vec3F32)
     setValues(result.data["color"], colors.toSeq)
+  if uvs.len > 0:
+    result.data["uv"] = DataList(thetype: Vec2F32)
+    setValues(result.data["uv"], colors.toSeq)
 
   for i in indices:
     assert uint32(i[0]) < result.vertexCount
@@ -83,9 +88,10 @@
 func newMesh*(
   positions: openArray[Vec3f],
   colors: openArray[Vec3f]=[],
+  uvs: openArray[Vec2f]=[],
   instanceCount=1'u32,
 ): auto =
-  newMesh(positions, newSeq[array[3, int]](), colors, instanceCount)
+  newMesh(positions, newSeq[array[3, int]](), colors, uvs, instanceCount)
 
 func availableAttributes*(mesh: Mesh): seq[string] =
   mesh.data.keys.toSeq
@@ -169,6 +175,7 @@
   result.instanceCount = 1
   result.data["position"] = DataList(thetype: Vec3F32)
   result.data["color"] = DataList(thetype: Vec3F32)
+  result.data["uv"] = DataList(thetype: Vec2F32)
   result.indexType = Small
   result.smallIndices = @[[0'u16, 1'u16, 2'u16], [2'u16, 3'u16, 0'u16]]
 
@@ -180,6 +187,7 @@
 
   setValues(result.data["position"], v.toSeq)
   setValues(result.data["color"], @[c, c, c, c])
+  setValues(result.data["uv"], @[newVec2f(0, 0), newVec2f(1, 0), newVec2f(1, 1), newVec2f(0, 1)])
 
 func tri*(width=1'f32, height=1'f32, color="ffffff"): Mesh =
   result = new Mesh
--- a/src/semicongine/renderer.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/renderer.nim	Sun May 07 17:41:45 2023 +0700
@@ -250,7 +250,6 @@
     for pipeline in subpass.pipelines:
       var mpipeline = pipeline
       commandBuffer.vkCmdBindPipeline(subpass.pipelineBindPoint, mpipeline.vk)
-      echo "############## ", mpipeline.descriptorSets[renderer.swapchain.currentInFlight]
       commandBuffer.vkCmdBindDescriptorSets(subpass.pipelineBindPoint, mpipeline.layout, 0, 1, addr(mpipeline.descriptorSets[renderer.swapchain.currentInFlight].vk), 0, nil)
 
       debug "Scene buffers:"
--- a/src/semicongine/resources.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/resources.nim	Sun May 07 17:41:45 2023 +0700
@@ -1,5 +1,3 @@
-{. error: "do resources" .}
-
 import std/strutils
 import std/os
 
--- a/src/semicongine/vulkan/descriptor.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/vulkan/descriptor.nim	Sun May 07 17:41:45 2023 +0700
@@ -170,7 +170,4 @@
           pImageInfo: addr imageInfos[^1],
         )
     inc i
-  echo "wrote descriptors:"
-  for w in descriptorSetWrites:
-    echo "  ", w
   descriptorSet.layout.device.vk.vkUpdateDescriptorSets(uint32(descriptorSetWrites.len), descriptorSetWrites.toCPointer, 0, nil)
--- a/src/semicongine/vulkan/pipeline.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/vulkan/pipeline.nim	Sun May 07 17:41:45 2023 +0700
@@ -38,15 +38,14 @@
 
 proc setupDescriptors*(pipeline: var Pipeline, buffers: seq[Buffer], textures: Table[string, Texture], inFlightFrames: int) =
   assert pipeline.vk.valid
-  assert buffers.len == 0 or buffers.len == inFlightFrames
+  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
-    assert pipeline.descriptorSets[i].layout.descriptors[0].thetype == Uniform
     for descriptor in pipeline.descriptorSets[i].layout.descriptors.mitems:
-      if descriptor.thetype == Uniform:
+      if descriptor.thetype == Uniform and buffers.len > 0:
         let size = VkDeviceSize(descriptor.itemsize * descriptor.count)
         descriptor.buffer = buffers[i]
         descriptor.offset = offset
@@ -74,15 +73,16 @@
   result.device = device
   result.shaders = @[vertexShader, fragmentShader]
   
-  var descriptors = @[
-    Descriptor(
+  var descriptors: seq[Descriptor]
+
+  if vertexCode.uniforms.len > 0:
+    descriptors.add Descriptor(
       name: "Uniforms",
       thetype: Uniform,
       count: 1,
       stages: @[VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT],
       itemsize: vertexShader.uniforms.size(),
-    ),
-  ]
+    )
   for sampler in vertexShader.samplers:
     descriptors.add Descriptor(
       name: sampler.name,
--- a/src/semicongine/vulkan/shader.nim	Sun May 07 01:30:38 2023 +0700
+++ b/src/semicongine/vulkan/shader.nim	Sun May 07 17:41:45 2023 +0700
@@ -101,7 +101,7 @@
   # var code = @[&"#version {version}", "layout(row_major) uniform;", ""] &
     (if inputs.len > 0: inputs.glslInput() & @[""] else: @[]) &
     (if uniforms.len > 0: uniforms.glslUniforms(binding=0) & @[""] else: @[]) &
-    (if samplers.len > 0: samplers.glslSamplers(basebinding=1) & @[""] else: @[]) &
+    (if samplers.len > 0: samplers.glslSamplers(basebinding=if uniforms.len > 0: 1 else: 0) & @[""] else: @[]) &
     (if outputs.len > 0: outputs.glslOutput() & @[""] else: @[]) &
     @[&"void {entrypoint}(){{"] &
     main &