changeset 106:9c3e3dcb0328

add: render main loop structure
author Sam <sam@basx.dev>
date Sun, 26 Mar 2023 01:56:19 +0700
parents 4059aa0d689b
children 2d0351a68a4e
files src/semicongine/engine.nim src/semicongine/math/vector.nim src/semicongine/vulkan/commandbuffer.nim src/semicongine/vulkan/framebuffer.nim src/semicongine/vulkan/pipeline.nim src/semicongine/vulkan/renderpass.nim src/semicongine/vulkan/swapchain.nim src/semicongine/vulkan/syncing.nim tests/test_vulkan_wrapper.nim
diffstat 9 files changed, 198 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/engine.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/engine.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -651,11 +651,8 @@
     device.updateBufferData(buffer, data)
 
 
-proc runPipeline[VertexType; Uniforms](commandBuffer: VkCommandBuffer,
-    pipeline: var RenderPipeline[VertexType, Uniforms], currentFrame: int) =
-  vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
-      pipeline.pipeline)
-
+proc runPipeline[VertexType; Uniforms](commandBuffer: VkCommandBuffer, pipeline: var RenderPipeline[VertexType, Uniforms], currentFrame: int) =
+  vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline)
   vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 1, addr(pipeline.descriptors[currentFrame]), 0, nil)
 
   for (vertexBufferSet, indexed, indexBuffer, count, indexType) in pipeline.vertexBuffers:
@@ -671,8 +668,7 @@
       vkCmdBindIndexBuffer(commandBuffer, indexBuffer.vkBuffer, VkDeviceSize(0), indexType)
       vkCmdDrawIndexed(commandBuffer, count, 1, 0, 0, 0)
     else:
-      vkCmdDraw(commandBuffer, vertexCount = count, instanceCount = 1,
-          firstVertex = 0, firstInstance = 0)
+      vkCmdDraw(commandBuffer, vertexCount = count, instanceCount = 1, firstVertex = 0, firstInstance = 0)
 
 proc recordCommandBuffer(renderPass: VkRenderPass, pipeline: var RenderPipeline,
     commandBuffer: VkCommandBuffer, framebuffer: VkFramebuffer,
@@ -682,8 +678,7 @@
       sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
       pInheritanceInfo: nil,
     )
-    clearColor = VkClearValue(color: VkClearColorValue(
-        float32: pipeline.clearColor))
+    clearColor = VkClearValue(color: VkClearColorValue(float32: pipeline.clearColor))
     renderPassInfo = VkRenderPassBeginInfo(
       sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
       renderPass: renderPass,
--- a/src/semicongine/math/vector.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/math/vector.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -15,6 +15,9 @@
   Vec2* = TVec2[float32]
   Vec3* = TVec3[float32]
   Vec4* = TVec4[float32]
+  Vec2I* = TVec2[uint32]
+  Vec3I* = TVec3[uint32]
+  Vec4I* = TVec4[uint32]
 
 converter toVec2*[T: SomeNumber](orig: TVec3[T]|TVec4[T]): TVec2[T] =
   TVec2[T]([orig[0], orig[1]])
--- a/src/semicongine/vulkan/commandbuffer.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/vulkan/commandbuffer.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -1,16 +1,20 @@
 import ./api
 import ./device
 import ./physicaldevice
+import ./renderpass
+import ./framebuffer
 import ./utils
 
+import ../math
+
 type
-  CommandPool = object
+  CommandBufferPool* = object
     vk*: VkCommandPool
     family*: QueueFamily
-    buffers: seq[VkCommandBuffer]
+    buffers*: seq[VkCommandBuffer]
     device: Device
 
-proc createCommandPool*(device: Device, family: QueueFamily, nBuffers: int): CommandPool =
+proc createCommandBufferPool*(device: Device, family: QueueFamily, nBuffers: uint32): CommandBufferPool =
   assert device.vk.valid
   var createInfo = VkCommandPoolCreateInfo(
     sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
@@ -25,12 +29,68 @@
     sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
     commandPool: result.vk,
     level: VK_COMMAND_BUFFER_LEVEL_PRIMARY,
-    commandBufferCount: uint32(nBuffers),
+    commandBufferCount: nBuffers,
   )
   result.buffers = newSeq[VkCommandBuffer](nBuffers)
   checkVkResult device.vk.vkAllocateCommandBuffers(addr(allocInfo), result.buffers.toCPointer)
 
-proc destroy*(commandpool: var CommandPool) =
+proc beginRenderCommands*(commandBuffer: VkCommandBuffer, renderpass: RenderPass, framebuffer: Framebuffer) =
+  assert commandBuffer.valid
+  assert renderpass.vk.valid
+  assert framebuffer.vk.valid
+  let
+    w = framebuffer.dimension.x
+    h = framebuffer.dimension.y
+
+
+  var clearColors: seq[VkClearValue]
+  for subpass in renderpass.subpasses:
+    clearColors.add(VkClearValue(color: VkClearColorValue(float32: subpass.clearColor)))
+  var
+    beginInfo = VkCommandBufferBeginInfo(
+      sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+      pInheritanceInfo: nil,
+    )
+    renderPassInfo = VkRenderPassBeginInfo(
+      sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+      renderPass: renderPass.vk,
+      framebuffer: framebuffer.vk,
+      renderArea: VkRect2D(
+        offset: VkOffset2D(x: 0, y: 0),
+        extent: VkExtent2D(width: w, height: h),
+      ),
+      clearValueCount: uint32(clearColors.len),
+      pClearValues: clearColors.toCPointer(),
+    )
+    viewport = VkViewport(
+      x: 0.0,
+      y: 0.0,
+      width: (float)w,
+      height: (float)h,
+      minDepth: 0.0,
+      maxDepth: 1.0,
+    )
+    scissor = VkRect2D(
+      offset: VkOffset2D(x: 0, y: 0),
+      extent: VkExtent2D(width: w, height: h)
+    )
+  checkVkResult commandBuffer.vkResetCommandBuffer(VkCommandBufferResetFlags(0))
+  checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo))
+  commandBuffer.vkCmdBeginRenderPass(addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE)
+  commandBuffer.vkCmdSetViewport(firstViewport=0, viewportCount=1, addr(viewport))
+  commandBuffer.vkCmdSetScissor(firstScissor=0, scissorCount=1, addr(scissor))
+
+proc endRenderCommands*(commandBuffer: VkCommandBuffer) =
+  commandBuffer.vkCmdEndRenderPass()
+  checkVkResult commandBuffer.vkEndCommandBuffer()
+
+template renderCommands*(commandBuffer: VkCommandBuffer, renderpass: RenderPass, framebuffer: Framebuffer, body: untyped) =
+  commandBuffer.beginRenderCommands(renderpass, framebuffer)
+  body
+  commandBuffer.endRenderCommands()
+
+
+proc destroy*(commandpool: var CommandBufferPool) =
   assert commandpool.device.vk.valid
   assert commandpool.vk.valid
   commandpool.device.vk.vkDestroyCommandPool(commandpool.vk, nil)
--- a/src/semicongine/vulkan/framebuffer.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/vulkan/framebuffer.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -10,10 +10,15 @@
   Framebuffer* = object
     device*: Device
     vk*: VkFramebuffer
+    dimension*: Vec2I
 
-proc createFramebuffer*(device: Device, renderPass: RenderPass, attachments: openArray[ImageView], dimension: TVec2[uint32]): Framebuffer =
+proc createFramebuffer*(device: Device, renderPass: RenderPass, attachments: openArray[ImageView], dimension: Vec2I): Framebuffer =
   assert device.vk.valid
   assert renderpass.vk.valid
+
+  result.device = device
+  result.dimension = dimension
+
   var theattachments: seq[VkImageView]
   for a in attachments:
     assert a.vk.valid
@@ -27,7 +32,6 @@
     height: dimension[1],
     layers: 1,
   )
-  result.device = device
   checkVkResult device.vk.vkCreateFramebuffer(addr(framebufferInfo), nil, addr(result.vk))
 
 proc destroy*(framebuffer: var Framebuffer) =
--- a/src/semicongine/vulkan/pipeline.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/vulkan/pipeline.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -38,14 +38,6 @@
     )
   result.descriptorSetLayout = renderPass.device.createDescriptorSetLayout(descriptors)
 
-  #[
-  Descriptor
-    thetype: VkDescriptorType
-    count: uint32
-    stages: seq[VkShaderStageFlagBits]
-    itemsize: uint32
-  ]#
-
   # TODO: Push constants
   # var pushConstant = VkPushConstantRange(
     # stageFlags: toBits shaderStage,
--- a/src/semicongine/vulkan/renderpass.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/vulkan/renderpass.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -3,9 +3,11 @@
 import ./api
 import ./utils
 import ./device
+import ../math
 
 type
   Subpass* = object
+    clearColor*: Vec4
     flags: VkSubpassDescriptionFlags
     pipelineBindPoint: VkPipelineBindPoint
     inputs: seq[VkAttachmentReference]
@@ -16,6 +18,7 @@
   RenderPass* = object
     vk*: VkRenderPass
     device*: Device
+    subpasses*: seq[Subpass]
 
 proc createRenderPass*(
   device: Device,
@@ -50,6 +53,7 @@
       pDependencies: dependencies.toCPointer,
     )
   result.device = device
+  result.subpasses = subpasses
   checkVkResult device.vk.vkCreateRenderPass(addr(createInfo), nil, addr(result.vk))
 
 proc createRenderAttachment(
@@ -75,7 +79,7 @@
     finalLayout: finalLayout,
   )
 
-proc simpleForwardRenderPass*(device: Device, format: VkFormat): RenderPass =
+proc simpleForwardRenderPass*(device: Device, format: VkFormat, clearColor=Vec4([0.5'f32, 0.5'f32, 0.5'f32, 1'f32])): RenderPass =
   assert device.vk.valid
   var
     attachments = @[createRenderAttachment(
@@ -91,7 +95,8 @@
     subpasses = @[
       Subpass(
         pipelineBindPoint: VK_PIPELINE_BIND_POINT_GRAPHICS,
-        outputs: @[VkAttachmentReference(attachment: 0, layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)]
+        outputs: @[VkAttachmentReference(attachment: 0, layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)],
+        clearColor: clearColor
       )
     ]
     dependencies = @[
@@ -104,7 +109,7 @@
         dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT],
       )
     ]
-  device.createRenderPass(attachments = attachments, subpasses = subpasses, dependencies = dependencies)
+  device.createRenderPass(attachments=attachments, subpasses=subpasses, dependencies=dependencies)
 
 proc destroy*(renderpass: var RenderPass) =
   assert renderpass.device.vk.valid
--- a/src/semicongine/vulkan/swapchain.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/vulkan/swapchain.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -1,3 +1,5 @@
+import std/options
+
 import ./api
 import ./utils
 import ./device
@@ -5,6 +7,8 @@
 import ./image
 import ./renderpass
 import ./framebuffer
+import ./commandbuffer
+import ./pipeline
 import ./syncing
 
 import ../math
@@ -15,19 +19,23 @@
     vk*: VkSwapchainKHR
     format*: VkFormat
     dimension*: TVec2[uint32]
+    renderPass*: RenderPass
     nImages*: uint32
     imageviews*: seq[ImageView]
     framebuffers*: seq[Framebuffer]
     nInFlight*: uint32
-    inFlightFences: seq[Fence]
-    imageAvailableSemaphores*: seq[Semaphore]
-    renderFinishedSemaphores*: seq[Semaphore]
+    currentInFlight*: uint32
+    queueFinishedFence: seq[Fence]
+    imageAvailableSemaphore*: seq[Semaphore]
+    renderFinishedSemaphore*: seq[Semaphore]
+    commandBufferPool: CommandBufferPool
 
 
 proc createSwapchain*(
   device: Device,
   renderPass: RenderPass,
   surfaceFormat: VkSurfaceFormatKHR,
+  queueFamily: QueueFamily,
   desiredNumberOfImages=3'u32,
   framesInFlight=2'u32,
   presentationMode: VkPresentModeKHR=VK_PRESENT_MODE_MAILBOX_KHR
@@ -35,6 +43,7 @@
   assert device.vk.valid
   assert device.physicalDevice.vk.valid
   assert renderPass.vk.valid
+  assert framesInFlight > 0
 
   var capabilities = device.physicalDevice.getSurfaceCapabilities()
 
@@ -68,7 +77,8 @@
       device: device,
       format: surfaceFormat.format,
       nInFlight: framesInFlight,
-      dimension: TVec2[uint32]([capabilities.currentExtent.width, capabilities.currentExtent.height])
+      dimension: TVec2[uint32]([capabilities.currentExtent.width, capabilities.currentExtent.height]),
+      renderPass: renderPass,
     )
     createResult = device.vk.vkCreateSwapchainKHR(addr(createInfo), nil, addr(swapchain.vk))
 
@@ -84,33 +94,96 @@
       swapChain.imageviews.add imageview
       swapChain.framebuffers.add swapchain.device.createFramebuffer(renderPass, [imageview], swapchain.dimension)
     for i in 0 ..< swapchain.nInFlight:
-      swapchain.inFlightFences.add device.createFence()
-      swapchain.imageAvailableSemaphores.add device.createSemaphore()
-      swapchain.renderFinishedSemaphores.add device.createSemaphore()
+      swapchain.queueFinishedFence.add device.createFence()
+      swapchain.imageAvailableSemaphore.add device.createSemaphore()
+      swapchain.renderFinishedSemaphore.add device.createSemaphore()
+    swapchain.commandBufferPool = device.createCommandBufferPool(queueFamily, swapchain.nInFlight)
 
   return (swapchain, createResult)
 
-proc getImages*(device: VkDevice, swapChain: VkSwapchainKHR): seq[VkImage] =
-  var n_images: uint32
-  checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), nil)
-  result = newSeq[VkImage](n_images)
-  checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), addr(
-      result[0]))
+proc drawNextFrame*(swapchain: var Swapchain, pipeline: Pipeline): bool =
+  assert swapchain.device.vk.valid
+  assert swapchain.vk.valid
+  assert swapchain.device.firstGraphicsQueue().isSome
+  assert swapchain.device.firstPresentationQueue().isSome
+
+  swapchain.currentInFlight = (swapchain.currentInFlight + 1) mod swapchain.nInFlight
+  swapchain.queueFinishedFence[swapchain.currentInFlight].wait()
+
+  var currentFramebufferIndex: uint32
+
+  let nextImageResult = swapchain.device.vk.vkAcquireNextImageKHR(
+    swapchain.vk,
+    high(uint64),
+    swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk,
+    VkFence(0),
+    addr(currentFramebufferIndex)
+  )
+  if not (nextImageResult in [VK_SUCCESS, VK_TIMEOUT, VK_NOT_READY, VK_SUBOPTIMAL_KHR]):
+    return false
+
+  swapchain.queueFinishedFence[swapchain.currentInFlight].reset()
+
+  renderCommands(
+    swapchain.commandBufferPool.buffers[swapchain.currentInFlight],
+    swapchain.renderpass,
+    swapchain.framebuffers[swapChain.currentInFlight]
+  ):
+    echo "TODO: Draw calls here"
+
+  var
+    waitSemaphores = [swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk]
+    waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)]
+    submitInfo = VkSubmitInfo(
+      sType: VK_STRUCTURE_TYPE_SUBMIT_INFO,
+      waitSemaphoreCount: 1,
+      pWaitSemaphores: addr(waitSemaphores[0]),
+      pWaitDstStageMask: addr(waitStages[0]),
+      commandBufferCount: 1,
+      pCommandBuffers: addr(swapchain.commandBufferPool.buffers[swapchain.currentInFlight]),
+      signalSemaphoreCount: 1,
+      pSignalSemaphores: addr(swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk),
+    )
+  checkVkResult vkQueueSubmit(
+    swapchain.device.firstGraphicsQueue().get.vk,
+    1,
+    addr(submitInfo),
+    swapchain.queueFinishedFence[swapchain.currentInFlight].vk
+  )
+
+  var presentInfo = VkPresentInfoKHR(
+    sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+    waitSemaphoreCount: 1,
+    pWaitSemaphores: addr(swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk),
+    swapchainCount: 1,
+    pSwapchains: addr(swapchain.vk),
+    pImageIndices: addr(currentFramebufferIndex),
+    pResults: nil,
+  )
+  let presentResult = vkQueuePresentKHR(swapchain.device.firstPresentationQueue().get().vk, addr(presentInfo))
+  if not (presentResult in [VK_SUCCESS, VK_SUBOPTIMAL_KHR]):
+    return false
+
+  return true
+
 
 proc destroy*(swapchain: var Swapchain) =
   assert swapchain.vk.valid
+  assert swapchain.commandBufferPool.vk.valid
+
   for imageview in swapchain.imageviews.mitems:
     assert imageview.vk.valid
     imageview.destroy()
   for framebuffer in swapchain.framebuffers.mitems:
     assert framebuffer.vk.valid
     framebuffer.destroy()
+  swapchain.commandBufferPool.destroy()
   for i in 0 ..< swapchain.nInFlight:
-    assert swapchain.inFlightFences[i].vk.valid
-    assert swapchain.imageAvailableSemaphores[i].vk.valid
-    assert swapchain.renderFinishedSemaphores[i].vk.valid
-    swapchain.inFlightFences[i].destroy()
-    swapchain.imageAvailableSemaphores[i].destroy()
-    swapchain.renderFinishedSemaphores[i].destroy()
+    assert swapchain.queueFinishedFence[i].vk.valid
+    assert swapchain.imageAvailableSemaphore[i].vk.valid
+    assert swapchain.renderFinishedSemaphore[i].vk.valid
+    swapchain.queueFinishedFence[i].destroy()
+    swapchain.imageAvailableSemaphore[i].destroy()
+    swapchain.renderFinishedSemaphore[i].destroy()
   swapchain.device.vk.vkDestroySwapchainKHR(swapchain.vk, nil)
   swapchain.vk.reset()
--- a/src/semicongine/vulkan/syncing.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/src/semicongine/vulkan/syncing.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -24,6 +24,18 @@
   result.device = device
   checkVkResult device.vk.vkCreateFence(addr(fenceInfo), nil, addr(result.vk))
 
+proc wait*(fence: Fence) =
+  assert fence.device.vk.valid
+  assert fence.vk.valid
+  var varFence = fence.vk
+  checkVkResult vkWaitForFences(fence.device.vk, 1, addr(varFence), false, high(uint64))
+
+proc reset*(fence: Fence) =
+  assert fence.device.vk.valid
+  assert fence.vk.valid
+  var varFence = fence.vk
+  checkVkResult vkResetFences(fence.device.vk, 1, addr(varFence))
+
 proc destroy*(semaphore: var Semaphore) =
   assert semaphore.device.vk.valid
   assert semaphore.vk.valid
--- a/tests/test_vulkan_wrapper.nim	Fri Mar 24 00:11:42 2023 +0700
+++ b/tests/test_vulkan_wrapper.nim	Sun Mar 26 01:56:19 2023 +0700
@@ -67,30 +67,22 @@
   # setup render pipeline
   var surfaceFormat = device.physicalDevice.getSurfaceFormats().filterSurfaceFormat()
   var renderpass = device.simpleForwardRenderPass(surfaceFormat.format)
-  var (swapchain, res) = device.createSwapchain(renderpass, surfaceFormat)
+  var (swapchain, res) = device.createSwapchain(renderpass, surfaceFormat, device.firstGraphicsQueue().get().family)
   if res != VK_SUCCESS:
     raise newException(Exception, "Unable to create swapchain")
-  # var framebuffers: seq[Framebuffer]
-  # for imageview in swapchain.imageviews:
-    # framebuffers.add device.createFramebuffer(renderpass, [imageview], swapchain.dimension)
 
   # todo: could be create inside "device", but it would be nice to have nim v2 with support for circular dependencies first
-  var
-    commandPool = device.createCommandPool(family=device.firstGraphicsQueue().get().family, nBuffers=1)
-    imageAvailable = device.createSemaphore()
-    renderFinished = device.createSemaphore()
-    inflight = device.createFence()
-
   const vertexBinary = shaderCode[Vertex, Uniforms, FragmentInput](stage=VK_SHADER_STAGE_VERTEX_BIT, version=450, entrypoint="main", "fragpos = pos;")
   const fragmentBinary = shaderCode[FragmentInput, void, Pixel](stage=VK_SHADER_STAGE_FRAGMENT_BIT, version=450, entrypoint="main", "color = vec4(1, 1, 1, 0);")
-  var vertexshader = createShader[Vertex, Uniforms, FragmentInput](device, VK_SHADER_STAGE_VERTEX_BIT, "main", vertexBinary)
-  var fragmentshader = createShader[FragmentInput, void, Pixel](device, VK_SHADER_STAGE_FRAGMENT_BIT, "main", fragmentBinary)
-
-  var pipeline = renderpass.createPipeline(vertexshader, fragmentshader)
-  var descriptorPool = device.createDescriptorSetPool(@[(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1'u32)])
-  var descriptorSet = descriptorPool.allocateDescriptorSet(pipeline.descriptorSetLayout, 1)
+  var
+    vertexshader = createShader[Vertex, Uniforms, FragmentInput](device, VK_SHADER_STAGE_VERTEX_BIT, "main", vertexBinary)
+    fragmentshader = createShader[FragmentInput, void, Pixel](device, VK_SHADER_STAGE_FRAGMENT_BIT, "main", fragmentBinary)
+    pipeline = renderpass.createPipeline(vertexshader, fragmentshader)
+    descriptorPool = device.createDescriptorSetPool(@[(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1'u32)])
+    descriptorSet = descriptorPool.allocateDescriptorSet(pipeline.descriptorSetLayout, 1)
 
   echo "All successfull"
+  echo swapchain.drawNextFrame(pipeline)
   echo "Start cleanup"
 
   # cleanup
@@ -99,10 +91,6 @@
   vertexshader.destroy()
   fragmentshader.destroy()
   pipeline.destroy()
-  inflight.destroy()
-  imageAvailable.destroy()
-  renderFinished.destroy()
-  commandPool.destroy()
   renderpass.destroy()
   swapchain.destroy()
   device.destroy()