changeset 342:8c67f67b62fb

fix: attributes with same name but different gpu memory lead to wrong results
author Sam <sam@basx.dev>
date Mon, 11 Sep 2023 18:23:15 +0700
parents 6cc16b62e497
children c9b34b41a5a2
files src/semicongine/core/gpu_data.nim src/semicongine/engine.nim src/semicongine/mesh.nim src/semicongine/renderer.nim src/semicongine/text.nim src/semicongine/vulkan/drawable.nim
diffstat 6 files changed, 47 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/core/gpu_data.nim	Fri Sep 08 00:34:24 2023 +0700
+++ b/src/semicongine/core/gpu_data.nim	Mon Sep 11 18:23:15 2023 +0700
@@ -507,20 +507,20 @@
     of Mat4F64: result.mat4f64 = new seq[TMat4[float64]]
     of Sampler2D: discard
 
-func newDataList*[T: GPUType](len=0): DataList =
+proc newDataList*[T: GPUType](len=0): DataList =
   result = newDataList(getDataType[T]())
   if len > 0:
     result.initData(len)
 
-func newDataList*[T: GPUType](data: seq[T]): DataList =
+proc newDataList*[T: GPUType](data: seq[T]): DataList =
   result = newDataList(getDataType[T]())
   setValues[T](result, data)
 
-func toGPUValue*[T: GPUType](value: T): DataValue =
+proc toGPUValue*[T: GPUType](value: T): DataValue =
   result = DataValue(theType: getDataType[T]())
   result.setValue(value)
 
-func toGPUValue*[T: GPUType](value: seq[T]): DataList =
+proc toGPUValue*[T: GPUType](value: seq[T]): DataList =
   result = newDataList[T](value.len)
   result.setValue(value)
 
--- a/src/semicongine/engine.nim	Fri Sep 08 00:34:24 2023 +0700
+++ b/src/semicongine/engine.nim	Mon Sep 11 18:23:15 2023 +0700
@@ -103,16 +103,15 @@
   )
   startMixerThread()
 
-proc initRenderer*(engine: var Engine, shaders: Table[string, ShaderConfiguration], clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32])) =
+proc initRenderer*(engine: var Engine, shaders: openArray[(string, ShaderConfiguration)], clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32])) =
 
   assert not engine.renderer.isSome
-  var materialShaderMap = shaders
-  materialShaderMap[TEXT_MATERIAL] = TEXT_SHADER
-  engine.renderer = some(engine.device.initRenderer(shaders=materialShaderMap, clearColor=clearColor))
+  var allShaders = @shaders
+  allShaders.add (TEXT_MATERIAL, TEXT_SHADER)
+  engine.renderer = some(engine.device.initRenderer(shaders=allShaders.toTable, clearColor=clearColor))
 
 proc initRenderer*(engine: var Engine, clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32])) =
-  var materialShaderMap: Table[string, ShaderConfiguration]
-  engine.initRenderer(materialShaderMap, clearColor)
+  engine.initRenderer(@[], clearColor)
 
 proc addScene*(engine: var Engine, scene: var Scene) =
   assert engine.renderer.isSome
--- a/src/semicongine/mesh.nim	Fri Sep 08 00:34:24 2023 +0700
+++ b/src/semicongine/mesh.nim	Mon Sep 11 18:23:15 2023 +0700
@@ -315,6 +315,16 @@
     mesh[attribute] = currentTransforms
     mesh.transformCache = currentTransforms
 
+proc renameAttribute*(mesh: var MeshObject, oldname, newname: string) =
+  if mesh.vertexData.contains(oldname):
+    mesh.vertexData[newname] = mesh.vertexData[oldname]
+    mesh.vertexData.del oldname
+  elif mesh.instanceData.contains(oldname):
+    mesh.instanceData[newname] = mesh.vertexData[oldname]
+    mesh.instanceData.del oldname
+  else:
+    raise newException(Exception, &"Attribute {oldname} is not defined for mesh {mesh}")
+
 func dirtyAttributes*(mesh: MeshObject): seq[string] =
   mesh.dirtyAttributes
 
--- a/src/semicongine/renderer.nim	Fri Sep 08 00:34:24 2023 +0700
+++ b/src/semicongine/renderer.nim	Mon Sep 11 18:23:15 2023 +0700
@@ -66,9 +66,10 @@
       if scene.usesMaterial(materialName):
         for input in pipeline.inputs:
           if found.contains(input.name):
-            assert input.name == found[input.name].name, &"{input.name} != {found[input.name].name}"
-            assert input.theType == found[input.name].theType, &"{input.theType} != {found[input.name].theType}"
-            assert input.arrayCount == found[input.name].arrayCount, &"{input.arrayCount} != {found[input.name].arrayCount}"
+            assert input.name == found[input.name].name, &"{input.name}: {input.name} != {found[input.name].name}"
+            assert input.theType == found[input.name].theType, &"{input.name}: {input.theType} != {found[input.name].theType}"
+            assert input.arrayCount == found[input.name].arrayCount, &"{input.name}: {input.arrayCount} != {found[input.name].arrayCount}"
+            assert input.memoryPerformanceHint == found[input.name].memoryPerformanceHint, &"{input.name}: {input.memoryPerformanceHint} != {found[input.name].memoryPerformanceHint}"
           else:
             result.add input
             found[input.name] = input
--- a/src/semicongine/text.nim	Fri Sep 08 00:34:24 2023 +0700
+++ b/src/semicongine/text.nim	Mon Sep 11 18:23:15 2023 +0700
@@ -1,10 +1,12 @@
 import std/tables
 import std/unicode
+import std/strformat
 
 import ./core
 import ./mesh
 import ./vulkan/shader
 
+const SHADER_ATTRIB_PREFIX = "semicon_text_"
 type
   TextAlignment = enum
     Left
@@ -19,18 +21,21 @@
     mesh*: Mesh
 
 const
+  TRANSFORM_ATTRIB = "transform"
+  POSITION_ATTRIB = SHADER_ATTRIB_PREFIX & "position"
+  UV_ATTRIB = SHADER_ATTRIB_PREFIX & "uv"
   TEXT_MATERIAL* = "default-text"
   TEXT_SHADER* = createShaderConfiguration(
     inputs=[
-      attr[Mat4]("transform", memoryPerformanceHint=PreferFastWrite, perInstance=true),
-      attr[Vec3f]("position", memoryPerformanceHint=PreferFastWrite),
-      attr[Vec2f]("uv", memoryPerformanceHint=PreferFastWrite),
+      attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint=PreferFastWrite, perInstance=true),
+      attr[Vec3f](POSITION_ATTRIB, memoryPerformanceHint=PreferFastWrite),
+      attr[Vec2f](UV_ATTRIB, memoryPerformanceHint=PreferFastWrite),
     ],
     intermediates=[attr[Vec2f]("uvFrag")],
     outputs=[attr[Vec4f]("color")],
     samplers=[attr[Texture]("fontAtlas")],
-    vertexCode="""gl_Position = vec4(position, 1.0) * transform; uvFrag = uv;""",
-    fragmentCode="""color = texture(fontAtlas, uvFrag);""",
+    vertexCode= &"""gl_Position = vec4({POSITION_ATTRIB}, 1.0) * {TRANSFORM_ATTRIB}; uvFrag = {UV_ATTRIB};""",
+    fragmentCode= &"""color = texture(fontAtlas, uvFrag);""",
   )
 
 proc updateMesh(textbox: var Textbox) =
@@ -56,24 +61,24 @@
         top = glyph.topOffset
         bottom = glyph.topOffset + glyph.dimension.y
 
-      textbox.mesh["position", vertexOffset + 0] = newVec3f(left - centerX, bottom + centerY)
-      textbox.mesh["position", vertexOffset + 1] = newVec3f(left - centerX, top + centerY)
-      textbox.mesh["position", vertexOffset + 2] = newVec3f(right - centerX, top + centerY)
-      textbox.mesh["position", vertexOffset + 3] = newVec3f(right - centerX, bottom + centerY)
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f(left - centerX, bottom + centerY)
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f(left - centerX, top + centerY)
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f(right - centerX, top + centerY)
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f(right - centerX, bottom + centerY)
 
-      textbox.mesh["uv", vertexOffset + 0] = glyph.uvs[0]
-      textbox.mesh["uv", vertexOffset + 1] = glyph.uvs[1]
-      textbox.mesh["uv", vertexOffset + 2] = glyph.uvs[2]
-      textbox.mesh["uv", vertexOffset + 3] = glyph.uvs[3]
+      textbox.mesh[UV_ATTRIB, vertexOffset + 0] = glyph.uvs[0]
+      textbox.mesh[UV_ATTRIB, vertexOffset + 1] = glyph.uvs[1]
+      textbox.mesh[UV_ATTRIB, vertexOffset + 2] = glyph.uvs[2]
+      textbox.mesh[UV_ATTRIB, vertexOffset + 3] = glyph.uvs[3]
 
       offsetX += glyph.advance
       if i < textbox.text.len - 1:
         offsetX += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])]
     else:
-      textbox.mesh["position", vertexOffset + 0] = newVec3f()
-      textbox.mesh["position", vertexOffset + 1] = newVec3f()
-      textbox.mesh["position", vertexOffset + 2] = newVec3f()
-      textbox.mesh["position", vertexOffset + 3] = newVec3f()
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f()
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f()
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f()
+      textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f()
 
 
 func text*(textbox: Textbox): seq[Rune] =
@@ -99,6 +104,8 @@
 
   result = Textbox(maxLen: maxLen, text: text, font: font, dirty: true)
   result.mesh = newMesh(positions = positions, indices = indices, uvs = uvs)
+  result.mesh[].renameAttribute("position", POSITION_ATTRIB)
+  result.mesh[].renameAttribute("uv", UV_ATTRIB)
   result.mesh.material = Material(
     name: TEXT_MATERIAL,
     textures: {"fontAtlas": font.fontAtlas}.toTable,
--- a/src/semicongine/vulkan/drawable.nim	Fri Sep 08 00:34:24 2023 +0700
+++ b/src/semicongine/vulkan/drawable.nim	Mon Sep 11 18:23:15 2023 +0700
@@ -34,9 +34,6 @@
       buffers.add vertexBuffers[performanceHint].vk
       offsets.add VkDeviceSize(offset)
 
-      # echo "####### ", name
-      # echo "####### ", (cast[ptr array[4, Vec3f]](vertexBuffers[performanceHint].memory.data))[]
-
     commandBuffer.vkCmdBindVertexBuffers(
       firstBinding=0'u32,
       bindingCount=uint32(buffers.len),