changeset 1202:a8864fe6fe6e compiletime-tests

add: descriptor sets binding n stuff
author sam <sam@basx.dev>
date Mon, 15 Jul 2024 00:04:33 +0700
parents d4a206b5e5b0
children 6360c8d17ce0
files semicongine/rendering.nim semicongine/rendering/renderer.nim semicongine/rendering/shaders.nim test1.nim
diffstat 4 files changed, 133 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/rendering.nim	Sun Jul 14 21:30:52 2024 +0700
+++ b/semicongine/rendering.nim	Mon Jul 15 00:04:33 2024 +0700
@@ -65,6 +65,8 @@
 
 var vulkan*: VulkanGlobals
 
+func currentFiF*(swapchain: Swapchain): int = swapchain.currentFiF
+
 type
   # type aliases
   SupportedGPUType = float32 | float64 | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | TVec2[int32] | TVec2[int64] | TVec3[int32] | TVec3[int64] | TVec4[int32] | TVec4[int64] | TVec2[uint32] | TVec2[uint64] | TVec3[uint32] | TVec3[uint64] | TVec4[uint32] | TVec4[uint64] | TVec2[float32] | TVec2[float64] | TVec3[float32] | TVec3[float64] | TVec4[float32] | TVec4[float64] | TMat2[float32] | TMat2[float64] | TMat23[float32] | TMat23[float64] | TMat32[float32] | TMat32[float64] | TMat3[float32] | TMat3[float64] | TMat34[float32] | TMat34[float64] | TMat43[float32] | TMat43[float64] | TMat4[float32] | TMat4[float64]
@@ -114,8 +116,8 @@
     data*: seq[T]
   GPUArray*[T: SupportedGPUType, TBuffer: static BufferType] = object
     data*: seq[T]
-    buffer: Buffer
-    offset: uint64
+    buffer*: Buffer
+    offset*: uint64
   GPUValue*[T: object|array, TBuffer: static BufferType] = object
     data*: T
     buffer: Buffer
--- a/semicongine/rendering/renderer.nim	Sun Jul 14 21:30:52 2024 +0700
+++ b/semicongine/rendering/renderer.nim	Mon Jul 15 00:04:33 2024 +0700
@@ -86,14 +86,12 @@
   let flags = toEnums(physicalProperties.memoryTypes[memoryTypeIndex].propertyFlags)
   return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags
 
-proc GetLayoutFor*(pipeline: Pipeline, dType: DescriptorSetType): VkDescriptorSetLayout =
-  pipeline.descriptorSetLayouts[dType]
-
 proc InitDescriptorSet*(
   renderData: RenderData,
   layout: VkDescriptorSetLayout,
   descriptorSet: var DescriptorSet,
 ) =
+
   # santization checks
   for name, value in descriptorSet.data.fieldPairs:
     when typeof(value) is GPUValue:
@@ -185,13 +183,6 @@
     pDescriptorCopies = nil,
   )
 
-converter toVkIndexType(indexType: IndexType): VkIndexType =
-  case indexType:
-    of None: VK_INDEX_TYPE_NONE_KHR
-    of UInt8: VK_INDEX_TYPE_UINT8_EXT
-    of UInt16: VK_INDEX_TYPE_UINT16
-    of UInt32: VK_INDEX_TYPE_UINT32
-
 proc AllocateNewMemoryBlock(size: uint64, mType: uint32): MemoryBlock =
   result = MemoryBlock(
     vk: svkAllocateMemory(size, mType),
@@ -536,6 +527,22 @@
         assert typeof(shaderAttribute) is TMaterial, "Shader has materialdescriptor type '" & typetraits.name(get(genericParams(typeof(shaderAttribute)), 0)) & "' but provided type is " & typetraits.name(TMaterial)
 
 
+
+template WithBind*[A, B](commandBuffer: VkCommandBuffer, globalDescriptorSet: DescriptorSet[A, GlobalSet], materialDescriptorSet: DescriptorSet[B, MaterialSet], pipeline: Pipeline, currentFiF: int, body: untyped): untyped =
+  block:
+    let sets = [globalDescriptorSet.vk[currentFiF], materialDescriptorSet.vk[currentFiF]]
+    vkCmdBindDescriptorSets(
+      commandBuffer = commandBuffer,
+      pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+      layout = pipeline.layout,
+      firstSet = 0,
+      descriptorSetCount = sets.len.uint32,
+      pDescriptorSets = sets.ToCPointer,
+      dynamicOffsetCount = 0,
+      pDynamicOffsets = nil
+    )
+    body
+
 proc Render*[TShader, TGlobals, TMaterial, TMesh, TInstance](
   commandBuffer: VkCommandBuffer,
   pipeline: Pipeline[TShader],
@@ -544,33 +551,91 @@
   mesh: TMesh,
   instances: TInstance,
 ) =
-  static: AssertCompatible(TShader, TMesh, TInstance, TGlobals, TMaterial)
-  #[
-  if renderable.vertexBuffers.len > 0:
-    commandBuffer.vkCmdBindVertexBuffers(
+  when not defined(release):
+    static: AssertCompatible(TShader, TMesh, TInstance, TGlobals, TMaterial)
+
+  var vertexBuffers: seq[VkBuffer]
+  var vertexBuffersOffsets: seq[uint64]
+  var elementCount = 0'u32
+  var instanceCount = 1'u32
+
+  for shaderAttributeName, shaderAttribute in default(TShader).fieldPairs:
+    when hasCustomPragma(shaderAttribute, VertexAttribute):
+      for meshName, meshValue in mesh.fieldPairs:
+        when meshName == shaderAttributeName:
+          vertexBuffers.add meshValue.buffer.vk
+          vertexBuffersOffsets.add meshValue.offset
+          elementCount = meshValue.data.len.uint32
+    elif hasCustomPragma(shaderAttribute, InstanceAttribute):
+      for instanceName, instanceValue in instances.fieldPairs:
+        when instanceName == shaderAttributeName:
+          vertexBuffers.add instanceValue.buffer.vk
+          vertexBuffersOffsets.add instanceValue.offset
+          instanceCount = instanceValue.data.len.uint32
+
+  if vertexBuffers.len > 0:
+    vkCmdBindVertexBuffers(
+      commandBuffer = commandBuffer,
       firstBinding = 0'u32,
-      bindingCount = uint32(renderable.vertexBuffers.len),
-      pBuffers = renderable.vertexBuffers.ToCPointer(),
-      pOffsets = renderable.bufferOffsets.ToCPointer()
+      bindingCount = uint32(vertexBuffers.len),
+      pBuffers = vertexBuffers.ToCPointer(),
+      pOffsets = vertexBuffersOffsets.ToCPointer()
     )
-  if renderable.indexType != None:
-    commandBuffer.vkCmdBindIndexBuffer(
-      renderable.indexBuffer,
-      renderable.indexBufferOffset,
-      renderable.indexType,
+
+  var indexBuffer: VkBuffer
+  var indexBufferOffset: uint64
+  var indexType = VK_INDEX_TYPE_NONE_KHR
+
+  for meshName, meshValue in mesh.fieldPairs:
+    when typeof(meshValue) is GPUArray[uint8, IndexBuffer]:
+      indexBuffer = meshValue.buffer.vk
+      indexBufferOffset = meshValue.offset
+      indexType = VK_INDEX_TYPE_UINT8_EXT
+      elementCount = meshValue.data.len.uint32
+    elif typeof(meshValue) is GPUArray[uint16, IndexBuffer]:
+      indexBuffer = meshValue.buffer.vk
+      indexBufferOffset = meshValue.offset
+      indexType = VK_INDEX_TYPE_UINT16
+      elementCount = meshValue.data.len.uint32
+    elif typeof(meshValue) is GPUArray[uint32, IndexBuffer]:
+      indexBuffer = meshValue.buffer.vk
+      indexBufferOffset = meshValue.offset
+      indexType = VK_INDEX_TYPE_UINT32
+      elementCount = meshValue.data.len.uint32
+
+  assert elementCount > 0
+
+  if indexType != VK_INDEX_TYPE_NONE_KHR:
+    vkCmdBindIndexBuffer(
+      commandBuffer,
+      indexBuffer,
+      indexBufferOffset,
+      indexType,
     )
-    commandBuffer.vkCmdDrawIndexed(
-      indexCount = renderable.indexCount,
-      instanceCount = renderable.instanceCount,
+    vkCmdDrawIndexed(
+      commandBuffer = commandBuffer,
+      indexCount = elementCount,
+      instanceCount = instanceCount,
       firstIndex = 0,
       vertexOffset = 0,
       firstInstance = 0
     )
   else:
-    commandBuffer.vkCmdDraw(
-      vertexCount = renderable.vertexCount,
-      instanceCount = renderable.instanceCount,
+    vkCmdDraw(
+      commandBuffer = commandBuffer,
+      vertexCount = elementCount,
+      instanceCount = instanceCount,
       firstVertex = 0,
       firstInstance = 0
     )
-  ]#
+
+type EMPTY = object
+
+proc Render*[TShader, TGlobals, TMaterial, TMesh](
+  commandBuffer: VkCommandBuffer,
+  pipeline: Pipeline[TShader],
+  globalSet: TGlobals,
+  materialSet: TMaterial,
+  mesh: TMesh,
+) =
+  Render(commandBuffer, pipeline, globalSet, materialSet, mesh, EMPTY())
--- a/semicongine/rendering/shaders.nim	Sun Jul 14 21:30:52 2024 +0700
+++ b/semicongine/rendering/shaders.nim	Mon Jul 15 00:04:33 2024 +0700
@@ -460,6 +460,15 @@
     addr(result.vk)
   )
 
+proc GetLayoutFor*(pipeline: Pipeline, dType: DescriptorSetType): VkDescriptorSetLayout =
+  pipeline.descriptorSetLayouts[dType]
+
+
+template WithPipeline*(commandbuffer: VkCommandBuffer, pipeline: Pipeline, body: untyped): untyped =
+  block:
+    vkCmdBindPipeline(commandbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.vk)
+    body
+
 proc DestroyPipeline*(pipeline: Pipeline) =
 
   for descriptorSetLayout in pipeline.descriptorSetLayouts:
--- a/test1.nim	Sun Jul 14 21:30:52 2024 +0700
+++ b/test1.nim	Mon Jul 15 00:04:33 2024 +0700
@@ -29,8 +29,8 @@
   ShaderA = object
     # vertex input
     position {.VertexAttribute.}: Vec3f
-    objPosition {.InstanceAttribute.}: Vec3f
-    rotation {.InstanceAttribute.}: Vec4f
+    # objPosition {.InstanceAttribute.}: Vec3f
+    # rotation {.InstanceAttribute.}: Vec4f
     # intermediate
     test {.Pass.}: float32
     test1 {.PassFlat.}: Vec3f
@@ -40,14 +40,16 @@
     globals: DescriptorSet[GlobalsA, GlobalSet]
     uniforms: DescriptorSet[UniformsA, MaterialSet]
     # code
-    vertexCode: string = "void main() {}"
-    fragmentCode: string = "void main() {}"
-
-let frameWidth = 100'u32
-let frameHeight = 100'u32
+    vertexCode: string = """void main() {
+    gl_Position = vec4(position, 1);
+}"""
+    fragmentCode: string = """void main() {
+    color = vec4(1, 0, 0, 1);
+}"""
 
 var myMesh1 = MeshA(
-  position: GPUArray[Vec3f, VertexBuffer](data: @[NewVec3f(0, 0, ), NewVec3f(0, 0, ), NewVec3f(0, 0, )]),
+  position: GPUArray[Vec3f, VertexBuffer](data: @[NewVec3f(-0.5, 0.5, ), NewVec3f(0, -0.5, ), NewVec3f(0.5, 0.5, )]),
+  indices: GPUArray[uint16, IndexBuffer](data: @[0'u16, 1'u16, 2'u16])
 )
 var uniforms1 = DescriptorSet[UniformsA, MaterialSet](
   data: UniformsA(
@@ -76,12 +78,7 @@
 )
 
 let mainRenderpass = CreatePresentationRenderPass()
-var swapchainResult = InitSwapchain(renderpass = mainRenderpass)
-
-assert swapchainResult.isSome()
-var swapchain = swapchainResult.get()
-
-# shaders
+var swapchain = InitSwapchain(renderpass = mainRenderpass).get()
 var pipeline1 = CreatePipeline[ShaderA](renderPass = mainRenderpass)
 
 var renderdata = InitRenderData()
@@ -111,24 +108,25 @@
 InitDescriptorSet(renderdata, pipeline1.GetLayoutFor(MaterialSet), uniforms1)
 
 
-# start command buffer
+# main loop
 var t = getMonoTime()
 while UpdateInputs():
   WithNextFrame(swapchain, framebuffer, commandbuffer):
-    WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(1, 0, 0, 0)):
-      vkCmdBindPipeline(commandbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline1.vk)
+    WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)):
+      WithPipeline(commandbuffer, pipeline1):
+        WithBind(commandBuffer, myGlobals, uniforms1, pipeline1, swapchain.currentFiF.int):
+          Render(
+            commandbuffer = commandbuffer,
+            pipeline = pipeline1,
+            globalSet = myGlobals,
+            materialSet = uniforms1,
+            mesh = myMesh1,
+            # instances = instances1,
+          )
+  echo (getMonoTime() - t).inMicroseconds.float / 1000.0
+  t = getMonoTime()
 
-      Render(
-        commandbuffer = commandbuffer,
-        pipeline = pipeline1,
-        globalSet = myGlobals,
-        materialSet = uniforms1,
-        mesh = myMesh1,
-        instances = instances1,
-      )
-      echo (getMonoTime() - t).inMicroseconds.float / 1000.0
-      t = getMonoTime()
-
+# cleanup
 checkVkResult vkDeviceWaitIdle(vulkan.device)
 DestroyPipeline(pipeline1)
 vkDestroyRenderPass(vulkan.device, mainRenderpass, nil)