diff tests/test_rendering.nim @ 1204:e2901100a596 compiletime-tests

add: tests, some fixes, some helpers
author sam <sam@basx.dev>
date Mon, 15 Jul 2024 23:51:17 +0700
parents 6360c8d17ce0
children f7530247a21f
line wrap: on
line diff
--- a/tests/test_rendering.nim	Mon Jul 15 20:06:42 2024 +0700
+++ b/tests/test_rendering.nim	Mon Jul 15 23:51:17 2024 +0700
@@ -1,11 +1,13 @@
 import std/options
+import std/random
+
 import ../semicongine
 
 var
   mainRenderpass: VkRenderPass
   swapchain: Swapchain
 
-proc test_01_gl_triangle() =
+proc test_01_triangle(nFrames: int) =
   var renderdata = InitRenderData()
 
   type
@@ -23,41 +25,188 @@
     TriangleMesh = object
       position: GPUArray[Vec3f, VertexBuffer]
       color: GPUArray[Vec3f, VertexBuffer]
-    Empty = object
   var mesh = TriangleMesh(
-    position: asGPUArray([NewVec3f(-0.5, -0.5), NewVec3f(-0.5, 0.5), NewVec3f(0.5, -0.5)], VertexBuffer),
+    position: asGPUArray([NewVec3f(-0.5, -0.5), NewVec3f(0, 0.5), NewVec3f(0.5, -0.5)], VertexBuffer),
     color: asGPUArray([NewVec3f(0, 0, 1), NewVec3f(0, 1, 0), NewVec3f(1, 0, 0)], VertexBuffer),
   )
+  AssignBuffers(renderdata, mesh)
+  renderdata.FlushAllMemory()
 
   var
-    pipeline = CreatePipeline[TrianglShader](renderPass = mainRenderpass)
-    a, b: Empty
+    pipeline = CreatePipeline[TrianglShader](renderPass = mainRenderpass, samples = swapchain.samples)
 
-  while UpdateInputs():
+  var c = 0
+  while UpdateInputs() and c < nFrames:
     WithNextFrame(swapchain, framebuffer, commandbuffer):
       WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)):
         WithPipeline(commandbuffer, pipeline):
-          # WithBind(commandBuffer, a, b, pipeline, swapchain.currentFiF.int):
-            Render(
-              commandbuffer = commandbuffer,
-              pipeline = pipeline,
-              globalSet = a,
-              materialSet = b,
-              mesh = mesh,
-            )
+          Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = mesh)
+    inc c
 
   # cleanup
+  checkVkResult vkDeviceWaitIdle(vulkan.device)
   DestroyPipeline(pipeline)
   DestroyRenderData(renderdata)
 
 
-when isMainModule:
-  mainRenderpass = CreatePresentationRenderPass()
-  swapchain = InitSwapchain(renderpass = mainRenderpass).get()
+proc test_02_triangle_quad_instanced(nFrames: int) =
+  var renderdata = InitRenderData()
+
+  type
+    SomeShader = object
+      position {.VertexAttribute.}: Vec3f
+      color {.VertexAttribute.}: Vec3f
+      pos {.InstanceAttribute.}: Vec3f
+      scale {.InstanceAttribute.}: float32
+      fragmentColor {.Pass.}: Vec3f
+      outColor {.ShaderOutput.}: Vec4f
+      # code
+      vertexCode: string = """void main() {
+      fragmentColor = color;
+      gl_Position = vec4((position * scale) + pos, 1);}"""
+      fragmentCode: string = """void main() {
+      outColor = vec4(fragmentColor, 1);}"""
+    TriangleMesh = object
+      position: GPUArray[Vec3f, VertexBuffer]
+      color: GPUArray[Vec3f, VertexBuffer]
+    QuadMesh = object
+      position: GPUArray[Vec3f, VertexBuffer]
+      color: GPUArray[Vec3f, VertexBuffer]
+      indices: GPUArray[uint16, IndexBuffer]
+    Instances = object
+      pos: GPUArray[Vec3f, VertexBuffer]
+      scale: GPUArray[float32, VertexBuffer]
+  var tri = TriangleMesh(
+    position: asGPUArray([NewVec3f(-0.5, -0.5), NewVec3f(0, 0.5), NewVec3f(0.5, -0.5)], VertexBuffer),
+    color: asGPUArray([NewVec3f(0, 0, 1), NewVec3f(0, 1, 0), NewVec3f(1, 0, 0)], VertexBuffer),
+  )
+  var quad = QuadMesh(
+    position: asGPUArray([NewVec3f(-0.3, -0.3), NewVec3f(-0.3, 0.3), NewVec3f(0.3, 0.3), NewVec3f(0.3, -0.3)], VertexBuffer),
+    indices: asGPUArray([0'u16, 1'u16, 2'u16, 2'u16, 3'u16, 0'u16], IndexBuffer),
+    color: asGPUArray([NewVec3f(1, 1, 1), NewVec3f(1, 1, 1), NewVec3f(1, 1, 1), NewVec3f(1, 1, 1)], VertexBuffer),
+  )
+
+  var instancesA: Instances
+  for n in 1..100:
+    instancesA.pos.data.add NewVec3f(rand(-0.8'f32 .. 0.8'f32), rand(-0.8'f32 .. 0'f32))
+    instancesA.scale.data.add rand(0.3'f32 .. 0.4'f32)
+  var instancesB: Instances
+  for n in 1..100:
+    instancesB.pos.data.add NewVec3f(rand(-0.8'f32 .. 0.8'f32), rand(0'f32 .. 0.8'f32))
+    instancesB.scale.data.add rand(0.1'f32 .. 0.2'f32)
+
+  AssignBuffers(renderdata, tri)
+  AssignBuffers(renderdata, quad)
+  AssignBuffers(renderdata, instancesA)
+  AssignBuffers(renderdata, instancesB)
+  renderdata.FlushAllMemory()
+
+  var pipeline = CreatePipeline[SomeShader](renderPass = mainRenderpass, samples = swapchain.samples)
+
+  var c = 0
+  while UpdateInputs() and c < nFrames:
+    WithNextFrame(swapchain, framebuffer, commandbuffer):
+      WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)):
+        WithPipeline(commandbuffer, pipeline):
+          Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad, instances = instancesA)
+          Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad, instances = instancesB)
+          Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = tri, instances = instancesA)
+          Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = tri, instances = instancesB)
+    inc c
+
+  # cleanup
+  checkVkResult vkDeviceWaitIdle(vulkan.device)
+  DestroyPipeline(pipeline)
+  DestroyRenderData(renderdata)
+
+proc test_03_global_descriptorset(nFrames: int) =
+  var renderdata = InitRenderData()
 
-  test_01_gl_triangle()
+  type
+    RenderSettings = object
+      gamma: float32
+    FirstDS = object
+      settings: GPUValue[RenderSettings, UniformBuffer]
+    QuadShader = object
+      position {.VertexAttribute.}: Vec3f
+      color {.VertexAttribute.}: Vec3f
+      fragmentColor {.Pass.}: Vec3f
+      outColor {.ShaderOutput.}: Vec4f
+      firstDS: DescriptorSet[FirstDS, First]
+      # code
+      vertexCode: string = """void main() {
+      fragmentColor = vec3(pow(color.r, settings.gamma), pow(color.g, settings.gamma), pow(color.b, settings.gamma));
+      gl_Position = vec4(position, 1);}"""
+      fragmentCode: string = """void main() {
+      outColor = vec4(fragmentColor, 1);}"""
+    QuadMesh = object
+      position: GPUArray[Vec3f, VertexBuffer]
+      color: GPUArray[Vec3f, VertexBuffer]
+      indices: GPUArray[uint16, IndexBuffer]
 
+  var quad = QuadMesh(
+    position: asGPUArray([NewVec3f(-0.3, -0.3), NewVec3f(-0.3, 0.3), NewVec3f(0.3, 0.3), NewVec3f(0.3, -0.3)], VertexBuffer),
+    indices: asGPUArray([0'u16, 1'u16, 2'u16, 2'u16, 3'u16, 0'u16], IndexBuffer),
+    color: asGPUArray([NewVec3f(1, 1, 1), NewVec3f(1, 1, 1), NewVec3f(1, 1, 1), NewVec3f(1, 1, 1)], VertexBuffer),
+  )
+  var firstDs = DescriptorSet[FirstDS, First](
+    data: FirstDS(
+      settings: asGPUValue(RenderSettings(
+          gamma: 1.0'f32
+    ), UniformBuffer)
+  )
+  )
+  AssignBuffers(renderdata, quad)
+  AssignBuffers(renderdata, firstDs)
+  renderdata.FlushAllMemory()
+
+  var pipeline = CreatePipeline[QuadShader](renderPass = mainRenderpass, samples = swapchain.samples)
+
+  var c = 0
+  while UpdateInputs() and c < nFrames:
+    WithNextFrame(swapchain, framebuffer, commandbuffer):
+      WithBind(commandbuffer, firstDs, pipeline, swapchain.currentFiF):
+        WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)):
+          WithPipeline(commandbuffer, pipeline):
+            Render(commandbuffer = commandbuffer, pipeline = pipeline, firstSet = firstDs, mesh = quad)
+    inc c
+
+  # cleanup
   checkVkResult vkDeviceWaitIdle(vulkan.device)
-  vkDestroyRenderPass(vulkan.device, mainRenderpass, nil)
-  DestroySwapchain(swapchain)
+  DestroyPipeline(pipeline)
+  DestroyRenderData(renderdata)
+
+when isMainModule:
+  var nFrames = 100
+  InitVulkan()
+
+  # test normal
+  block:
+    mainRenderpass = CreatePresentationRenderPass()
+    swapchain = InitSwapchain(renderpass = mainRenderpass).get()
+
+    # tests a simple triangle with minimalistic shader and vertex format
+    test_01_triangle(nFrames)
+
+    # tests instanced triangles and quads, mixing meshes and instances
+    test_02_triangle_quad_instanced(nFrames)
+
+    # tests
+    test_03_global_descriptorset(nFrames)
+
+    checkVkResult vkDeviceWaitIdle(vulkan.device)
+    vkDestroyRenderPass(vulkan.device, mainRenderpass, nil)
+    DestroySwapchain(swapchain)
+
+  # test MSAA
+  block:
+    mainRenderpass = CreatePresentationRenderPass(samples = VK_SAMPLE_COUNT_4_BIT)
+    swapchain = InitSwapchain(renderpass = mainRenderpass, samples = VK_SAMPLE_COUNT_4_BIT).get()
+
+    test_01_triangle(nFrames)
+
+    checkVkResult vkDeviceWaitIdle(vulkan.device)
+    vkDestroyRenderPass(vulkan.device, mainRenderpass, nil)
+    DestroySwapchain(swapchain)
+
   DestroyVulkan()