diff semiconginev2/rendering/renderer.nim @ 1239:69489a678141

add: better syncing, better swapchain access, correct font offset, two font-rendering tests
author sam <sam@basx.dev>
date Mon, 22 Jul 2024 00:46:10 +0700
parents 176383220123
children 42eeb59f3a43
line wrap: on
line diff
--- a/semiconginev2/rendering/renderer.nim	Sun Jul 21 11:31:11 2024 +0700
+++ b/semiconginev2/rendering/renderer.nim	Mon Jul 22 00:46:10 2024 +0700
@@ -4,11 +4,11 @@
 func usage(bType: BufferType): seq[VkBufferUsageFlagBits] =
   case bType:
     of VertexBuffer: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
-    of VertexBufferMapped: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
+    of VertexBufferMapped: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT]
     of IndexBuffer: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
-    of IndexBufferMapped: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
+    of IndexBufferMapped: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT]
     of UniformBuffer: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
-    of UniformBufferMapped: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
+    of UniformBufferMapped: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT]
 
 proc GetVkFormat(grayscale: bool, usage: openArray[VkImageUsageFlagBits]): VkFormat =
   let formats = if grayscale: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM]
@@ -279,9 +279,10 @@
   result.rawPointer = selectedBlock.rawPointer.pointerAddOffset(selectedBlock.offsetNextFree)
   renderData.memory[memoryType][selectedBlockI].offsetNextFree += memoryRequirements.size
 
-proc UpdateGPUBuffer*(gpuData: GPUData, flush = false) =
+proc UpdateGPUBuffer*(gpuData: GPUData, flush = false, allFrames = false) =
   if gpuData.size == 0:
     return
+
   when NeedsMapping(gpuData):
     copyMem(pointerAddOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size)
     if flush:
@@ -290,47 +291,57 @@
     WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.size, stagingPtr):
       copyMem(stagingPtr, gpuData.rawPointer, gpuData.size)
 
-proc UpdateAllGPUBuffers*[T](value: T, flush = false) =
+proc UpdateAllGPUBuffers*[T](value: T, flush = false, allFrames = false) =
   for name, fieldvalue in value.fieldPairs():
     when typeof(fieldvalue) is GPUData:
-      UpdateGPUBuffer(fieldvalue, flush = flush)
+      UpdateGPUBuffer(fieldvalue, flush = flush, allFrames = allFrames)
     when typeof(fieldvalue) is array:
       when elementType(fieldvalue) is GPUData:
         for entry in fieldvalue:
-          UpdateGPUBuffer(entry, flush = flush)
+          UpdateGPUBuffer(entry, flush = flush, allFrames = allFrames)
 
-proc AssignGPUData(renderdata: var RenderData, value: var GPUData) =
+proc AllocateGPUData(
+  renderdata: var RenderData,
+  bufferType: BufferType,
+  size: uint64,
+  needsFrameInFlight = -1
+): (Buffer, uint64) =
+
   # find buffer that has space
   var selectedBufferI = -1
 
-  for i in 0 ..< renderData.buffers[value.bufferType].len:
-    let buffer = renderData.buffers[value.bufferType][i]
-    if buffer.size - alignedTo(buffer.offsetNextFree, BUFFER_ALIGNMENT) >= value.size:
-      selectedBufferI = i
+  for i in 0 ..< renderData.buffers[bufferType].len:
+    let buffer = renderData.buffers[bufferType][i]
+    if needsFrameInFlight == -1 or buffer.useForFrameInFlight == needsFrameInFlight:
+      if buffer.size - alignedTo(buffer.offsetNextFree, BUFFER_ALIGNMENT) >= size:
+        selectedBufferI = i
 
   # otherwise create new buffer
   if selectedBufferI < 0:
-    selectedBufferI = renderdata.buffers[value.bufferType].len
-    renderdata.buffers[value.bufferType].add renderdata.AllocateNewBuffer(
-      size = max(value.size, BUFFER_ALLOCATION_SIZE),
-      bufferType = value.bufferType,
+    selectedBufferI = renderdata.buffers[bufferType].len
+    renderdata.buffers[bufferType].add renderdata.AllocateNewBuffer(
+      size = max(size, BUFFER_ALLOCATION_SIZE),
+      bufferType = bufferType,
     )
+    if needsFrameInFlight >= 0:
+      renderdata.buffers[bufferType][selectedBufferI].useForFrameInFlight = needsFrameInFlight
 
   # assigne value
-  let selectedBuffer = renderdata.buffers[value.bufferType][selectedBufferI]
-  renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree = alignedTo(
+  let selectedBuffer = renderdata.buffers[bufferType][selectedBufferI]
+  renderdata.buffers[bufferType][selectedBufferI].offsetNextFree = alignedTo(
     selectedBuffer.offsetNextFree,
     BUFFER_ALIGNMENT
   )
-  value.buffer = selectedBuffer
-  value.offset = renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree
-  renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree += value.size
+
+  result[0] = selectedBuffer
+  result[1] = renderdata.buffers[bufferType][selectedBufferI].offsetNextFree
+  renderdata.buffers[bufferType][selectedBufferI].offsetNextFree += size
 
 proc AssignBuffers*[T](renderdata: var RenderData, data: var T, uploadData = true) =
   for name, value in fieldPairs(data):
 
     when typeof(value) is GPUData:
-      AssignGPUData(renderdata, value)
+      (value.buffer, value.offset) = AllocateGPUData(renderdata, value.bufferType, value.size)
 
     elif typeof(value) is DescriptorSet:
       AssignBuffers(renderdata, value.data, uploadData = uploadData)
@@ -338,10 +349,10 @@
     elif typeof(value) is array:
       when elementType(value) is GPUValue:
         for v in value.mitems:
-          AssignGPUData(renderdata, v)
+          (v.buffer, v.offset) = AllocateGPUData(renderdata, v.bufferType, v.size)
 
   if uploadData:
-    UpdateAllGPUBuffers(data)
+    UpdateAllGPUBuffers(data, flush = true, allFrames = true)
 
 proc AssignBuffers*(renderdata: var RenderData, descriptorSet: var DescriptorSet, uploadData = true) =
   AssignBuffers(renderdata, descriptorSet.data, uploadData = uploadData)
@@ -534,36 +545,36 @@
         let `fieldvalue` {.inject.} = value
         body
 
-template WithBind*[A, B, C, D](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C], DescriptorSet[D]), pipeline: Pipeline, currentFiF: int, body: untyped): untyped =
+template WithBind*[A, B, C, D](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C], DescriptorSet[D]), pipeline: Pipeline, body: untyped): untyped =
   block:
     var descriptorSets: seq[VkDescriptorSet]
     for dSet in sets.fields:
-      assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
-      descriptorSets.add dSet.vk[currentFiF]
+      assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
+      descriptorSets.add dSet.vk[currentFiF()]
     svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
     body
-template WithBind*[A, B, C](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C]), pipeline: Pipeline, currentFiF: int, body: untyped): untyped =
+template WithBind*[A, B, C](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C]), pipeline: Pipeline, body: untyped): untyped =
   block:
     var descriptorSets: seq[VkDescriptorSet]
     for dSet in sets.fields:
-      assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
-      descriptorSets.add dSet.vk[currentFiF]
+      assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
+      descriptorSets.add dSet.vk[currentFiF()]
     svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
     body
-template WithBind*[A, B](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B]), pipeline: Pipeline, currentFiF: int, body: untyped): untyped =
+template WithBind*[A, B](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B]), pipeline: Pipeline, body: untyped): untyped =
   block:
     var descriptorSets: seq[VkDescriptorSet]
     for dSet in sets.fields:
-      assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
-      descriptorSets.add dSet.vk[currentFiF]
+      assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
+      descriptorSets.add dSet.vk[currentFiF()]
     svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
     body
-template WithBind*[A](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], ), pipeline: Pipeline, currentFiF: int, body: untyped): untyped =
+template WithBind*[A](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], ), pipeline: Pipeline, body: untyped): untyped =
   block:
     var descriptorSets: seq[VkDescriptorSet]
     for dSet in sets.fields:
-      assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
-      descriptorSets.add dSet.vk[currentFiF]
+      assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
+      descriptorSets.add dSet.vk[currentFiF()]
     svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
     body