comparison src/zamikongine/engine.nim @ 32:9edca5dc4e93

add: working implementation of uniforms
author Sam <sam@basx.dev>
date Sat, 14 Jan 2023 23:34:50 +0700
parents b1b05d4efb52
children 94c38e4b5782
comparison
equal deleted inserted replaced
31:0996104ad066 32:9edca5dc4e93
22 var logger = newConsoleLogger() 22 var logger = newConsoleLogger()
23 addHandler(logger) 23 addHandler(logger)
24 24
25 25
26 const VULKAN_VERSION = VK_MAKE_API_VERSION(0'u32, 1'u32, 2'u32, 0'u32) 26 const VULKAN_VERSION = VK_MAKE_API_VERSION(0'u32, 1'u32, 2'u32, 0'u32)
27 const ENGINE_NAME = "zamkongine"
28 const ENGINE_VERSION = "0.1"
29 const BUILD_VERSION = ENGINE_VERSION & '-' & gorge("git log -1 --format=format:'%H'")
30 echo "Engine: " & ENGINE_NAME & " " & BUILD_VERSION
27 31
28 type 32 type
29 Device = object 33 Device = object
30 device: VkDevice 34 device: VkDevice
31 physicalDevice: PhysicalDevice 35 physicalDevice: PhysicalDevice
35 presentationQueue: VkQueue 39 presentationQueue: VkQueue
36 Swapchain = object 40 Swapchain = object
37 swapchain: VkSwapchainKHR 41 swapchain: VkSwapchainKHR
38 images: seq[VkImage] 42 images: seq[VkImage]
39 imageviews: seq[VkImageView] 43 imageviews: seq[VkImageView]
40 RenderPipeline[T] = object 44 RenderPipeline*[VertexType, Uniforms] = object
41 device*: VkDevice 45 device*: VkDevice
42 shaders*: seq[ShaderProgram[T]] 46 shaders*: seq[ShaderProgram[VertexType, Uniforms]]
43 layout*: VkPipelineLayout 47 layout*: VkPipelineLayout
44 pipeline*: VkPipeline 48 pipeline*: VkPipeline
45 uniformLayout*: VkDescriptorSetLayout
46 vertexBuffers*: seq[(seq[Buffer], uint32)] 49 vertexBuffers*: seq[(seq[Buffer], uint32)]
47 indexedVertexBuffers*: seq[(seq[Buffer], Buffer, uint32, VkIndexType)] 50 indexedVertexBuffers*: seq[(seq[Buffer], Buffer, uint32, VkIndexType)]
51 descriptorSetLayout*: VkDescriptorSetLayout
48 uniformBuffers*: array[MAX_FRAMES_IN_FLIGHT, Buffer] 52 uniformBuffers*: array[MAX_FRAMES_IN_FLIGHT, Buffer]
53 descriptorPool*: VkDescriptorPool
54 descriptors: array[MAX_FRAMES_IN_FLIGHT, VkDescriptorSet]
49 QueueFamily = object 55 QueueFamily = object
50 properties*: VkQueueFamilyProperties 56 properties*: VkQueueFamilyProperties
51 hasSurfaceSupport*: bool 57 hasSurfaceSupport*: bool
52 PhysicalDevice = object 58 PhysicalDevice = object
53 device*: VkPhysicalDevice 59 device*: VkPhysicalDevice
248 dependencyCount: 1, 254 dependencyCount: 1,
249 pDependencies: addr(dependency), 255 pDependencies: addr(dependency),
250 ) 256 )
251 checkVkResult device.vkCreateRenderPass(addr(renderPassCreateInfo), nil, addr(result)) 257 checkVkResult device.vkCreateRenderPass(addr(renderPassCreateInfo), nil, addr(result))
252 258
253 proc initRenderPipeline[VertextType, T](device: VkDevice, frameDimension: VkExtent2D, renderPass: VkRenderPass, vertexShader, fragmentShader: static string): RenderPipeline[T] = 259 proc initRenderPipeline[VertexType, Uniforms](device: VkDevice, frameDimension: VkExtent2D, renderPass: VkRenderPass, vertexShader, fragmentShader: static string): RenderPipeline[VertexType, Uniforms] =
254 # load shaders 260 # load shaders
255 result.device = device 261 result.device = device
256 result.shaders.add(initShaderProgram[T](device, VK_SHADER_STAGE_VERTEX_BIT, vertexShader)) 262 result.shaders.add(initShaderProgram[VertexType, Uniforms](device, VK_SHADER_STAGE_VERTEX_BIT, vertexShader))
257 result.shaders.add(initShaderProgram[T](device, VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShader)) 263 result.shaders.add(initShaderProgram[VertexType, Uniforms](device, VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShader))
258 264
259 var 265 var
260 # define which parts can be dynamic (pipeline is fixed after setup) 266 # define which parts can be dynamic (pipeline is fixed after setup)
261 dynamicStates = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] 267 dynamicStates = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR]
262 dynamicState = VkPipelineDynamicStateCreateInfo( 268 dynamicState = VkPipelineDynamicStateCreateInfo(
263 sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 269 sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
264 dynamicStateCount: uint32(dynamicStates.len), 270 dynamicStateCount: uint32(dynamicStates.len),
265 pDynamicStates: addr(dynamicStates[0]), 271 pDynamicStates: addr(dynamicStates[0]),
266 ) 272 )
267 vertexbindings = generateInputVertexBinding[VertextType]() 273 vertexbindings = generateInputVertexBinding[VertexType]()
268 attributebindings = generateInputAttributeBinding[VertextType]() 274 attributebindings = generateInputAttributeBinding[VertexType]()
269 275
270 # define input data format 276 # define input data format
271 vertexInputInfo = VkPipelineVertexInputStateCreateInfo( 277 vertexInputInfo = VkPipelineVertexInputStateCreateInfo(
272 sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 278 sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
273 vertexBindingDescriptionCount: uint32(vertexbindings.len), 279 vertexBindingDescriptionCount: uint32(vertexbindings.len),
334 attachmentCount: 1, 340 attachmentCount: 1,
335 pAttachments: addr(colorBlendAttachment), 341 pAttachments: addr(colorBlendAttachment),
336 blendConstants: [0.0'f, 0.0'f, 0.0'f, 0.0'f], 342 blendConstants: [0.0'f, 0.0'f, 0.0'f, 0.0'f],
337 ) 343 )
338 344
339 result.uniformLayout = device.createUniformDescriptorLayout(VkShaderStageFlags(VK_SHADER_STAGE_VERTEX_BIT), 0) 345 result.descriptorSetLayout = device.createUniformDescriptorLayout(VkShaderStageFlags(VK_SHADER_STAGE_VERTEX_BIT), 0)
340 var 346 var
341 # "globals" that go into the shader, uniforms etc. 347 # "globals" that go into the shader, uniforms etc.
342 pipelineLayoutInfo = VkPipelineLayoutCreateInfo( 348 pipelineLayoutInfo = VkPipelineLayoutCreateInfo(
343 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 349 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
344 setLayoutCount: 1, 350 setLayoutCount: 1,
345 pSetLayouts: addr(result.uniformLayout), 351 pSetLayouts: addr(result.descriptorSetLayout),
346 pushConstantRangeCount: 0, 352 pushConstantRangeCount: 0,
347 pPushConstantRanges: nil, 353 pPushConstantRanges: nil,
348 ) 354 )
349 checkVkResult vkCreatePipelineLayout(device, addr(pipelineLayoutInfo), nil, addr(result.layout)) 355 checkVkResult vkCreatePipelineLayout(device, addr(pipelineLayoutInfo), nil, addr(result.layout))
350 356
493 result.vulkan.renderFinishedSemaphores, 499 result.vulkan.renderFinishedSemaphores,
494 result.vulkan.inFlightFences, 500 result.vulkan.inFlightFences,
495 ) = result.vulkan.device.device.setupSyncPrimitives() 501 ) = result.vulkan.device.device.setupSyncPrimitives()
496 502
497 503
498 proc setupPipeline*[VertexType, UniformType, T: object, IndexType: uint16|uint32](engine: var Engine, scenedata: ref Thing, vertexShader, fragmentShader: static string): RenderPipeline[T] = 504 proc setupPipeline*[VertexType, UniformType: object, IndexType: uint16|uint32](engine: var Engine, scenedata: ref Thing, vertexShader, fragmentShader: static string): RenderPipeline[VertexType, UniformType] =
499 engine.currentscenedata = scenedata 505 engine.currentscenedata = scenedata
500 result = initRenderPipeline[VertexType, T]( 506 result = initRenderPipeline[VertexType, UniformType](
501 engine.vulkan.device.device, 507 engine.vulkan.device.device,
502 engine.vulkan.frameDimension, 508 engine.vulkan.frameDimension,
503 engine.vulkan.renderPass, 509 engine.vulkan.renderPass,
504 vertexShader, 510 vertexShader,
505 fragmentShader, 511 fragmentShader,
508 var allmeshes: seq[Mesh[VertexType]] 514 var allmeshes: seq[Mesh[VertexType]]
509 for mesh in partsOfType[ref Mesh[VertexType]](engine.currentscenedata): 515 for mesh in partsOfType[ref Mesh[VertexType]](engine.currentscenedata):
510 allmeshes.add(mesh[]) 516 allmeshes.add(mesh[])
511 if allmeshes.len > 0: 517 if allmeshes.len > 0:
512 var ubermesh = createUberMesh(allmeshes) 518 var ubermesh = createUberMesh(allmeshes)
513 result.vertexBuffers.add createVertexBuffers(ubermesh, engine.vulkan.device.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue) 519 result.vertexBuffers.add createVertexBuffers(ubermesh, result.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue)
514 520
515 # vertex buffers with indexes 521 # vertex buffers with indexes
516 var allindexedmeshes: seq[IndexedMesh[VertexType, IndexType]] 522 var allindexedmeshes: seq[IndexedMesh[VertexType, IndexType]]
517 for mesh in partsOfType[ref IndexedMesh[VertexType, IndexType]](engine.currentscenedata): 523 for mesh in partsOfType[ref IndexedMesh[VertexType, IndexType]](engine.currentscenedata):
518 allindexedmeshes.add(mesh[]) 524 allindexedmeshes.add(mesh[])
519 if allindexedmeshes.len > 0: 525 if allindexedmeshes.len > 0:
520 var indexedubermesh = createUberMesh(allindexedmeshes) 526 var indexedubermesh = createUberMesh(allindexedmeshes)
521 result.indexedVertexBuffers.add createIndexedVertexBuffers(indexedubermesh, engine.vulkan.device.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue) 527 result.indexedVertexBuffers.add createIndexedVertexBuffers(indexedubermesh, result.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue)
522 528
523 # uniform buffers 529 # uniform buffers
524 result.uniformBuffers = createUniformBuffers[MAX_FRAMES_IN_FLIGHT, UniformType]( 530 result.uniformBuffers = createUniformBuffers[MAX_FRAMES_IN_FLIGHT, UniformType](
525 engine.vulkan.device.device, 531 result.device,
526 engine.vulkan.device.physicalDevice.device 532 engine.vulkan.device.physicalDevice.device
527 ) 533 )
528 534
529 535 var
530 proc runPipeline(commandBuffer: VkCommandBuffer, pipeline: RenderPipeline) = 536 poolSize = VkDescriptorPoolSize(
537 `type`: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
538 descriptorCount: uint32(MAX_FRAMES_IN_FLIGHT),
539 )
540 poolInfo = VkDescriptorPoolCreateInfo(
541 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
542 poolSizeCount: 1,
543 pPoolSizes: addr(poolSize),
544 maxSets: uint32(MAX_FRAMES_IN_FLIGHT),
545 )
546 checkVkResult vkCreateDescriptorPool(result.device, addr(poolInfo), nil, addr(result.descriptorPool))
547
548 var layouts: array[MAX_FRAMES_IN_FLIGHT, VkDescriptorSetLayout]
549 for i in 0 ..< MAX_FRAMES_IN_FLIGHT:
550 layouts[i] = result.descriptorSetLayout
551 var allocInfo = VkDescriptorSetAllocateInfo(
552 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
553 descriptorPool: result.descriptorPool,
554 descriptorSetCount: uint32(MAX_FRAMES_IN_FLIGHT),
555 pSetLayouts: addr(layouts[0]),
556 )
557
558 checkVkResult vkAllocateDescriptorSets(result.device, addr(allocInfo), addr(result.descriptors[0]))
559
560 var bufferInfos: array[MAX_FRAMES_IN_FLIGHT, array[1, VkDescriptorBufferInfo]] # because we use only one Uniform atm
561 for i in 0 ..< MAX_FRAMES_IN_FLIGHT:
562 bufferInfos[i][0] = VkDescriptorBufferInfo(
563 buffer: result.uniformBuffers[i].vkBuffer,
564 offset: VkDeviceSize(0),
565 range: VkDeviceSize(sizeof(UniformType)),
566 )
567 var descriptorWrite = VkWriteDescriptorSet(
568 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
569 dstSet: result.descriptors[i],
570 dstBinding: 0,
571 dstArrayElement: 0,
572 descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
573 descriptorCount: 1,
574 pBufferInfo: cast[ptr ptr VkDescriptorBufferInfo](addr(bufferInfos[i][0])),
575 )
576 vkUpdateDescriptorSets(result.device, 1, addr(descriptorWrite), 0, nil)
577
578
579 proc runPipeline(commandBuffer: VkCommandBuffer, pipeline: var RenderPipeline, currentFrame: int) =
531 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline) 580 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline)
532 581
582 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 1, addr(pipeline.descriptors[currentFrame]), 0, nil)
533 for (vertexBufferSet, vertexCount) in pipeline.vertexBuffers: 583 for (vertexBufferSet, vertexCount) in pipeline.vertexBuffers:
534 var 584 var
535 vertexBuffers: seq[VkBuffer] 585 vertexBuffers: seq[VkBuffer]
536 offsets: seq[VkDeviceSize] 586 offsets: seq[VkDeviceSize]
537 for buffer in vertexBufferSet: 587 for buffer in vertexBufferSet:
548 for buffer in vertexBufferSet: 598 for buffer in vertexBufferSet:
549 vertexBuffers.add buffer.vkBuffer 599 vertexBuffers.add buffer.vkBuffer
550 offsets.add VkDeviceSize(0) 600 offsets.add VkDeviceSize(0)
551 601
552 vkCmdBindVertexBuffers(commandBuffer, firstBinding=0'u32, bindingCount=2'u32, pBuffers=addr(vertexBuffers[0]), pOffsets=addr(offsets[0])) 602 vkCmdBindVertexBuffers(commandBuffer, firstBinding=0'u32, bindingCount=2'u32, pBuffers=addr(vertexBuffers[0]), pOffsets=addr(offsets[0]))
553 vkCmdBindIndexBuffer(commandBuffer, indexBuffer.vkBuffer, VkDeviceSize(0), indexType); 603 vkCmdBindIndexBuffer(commandBuffer, indexBuffer.vkBuffer, VkDeviceSize(0), indexType)
554 vkCmdDrawIndexed(commandBuffer, indicesCount, 1, 0, 0, 0); 604 vkCmdDrawIndexed(commandBuffer, indicesCount, 1, 0, 0, 0)
555 605
556 proc recordCommandBuffer(renderPass: VkRenderPass, pipeline: RenderPipeline, commandBuffer: VkCommandBuffer, framebuffer: VkFramebuffer, frameDimension: VkExtent2D) = 606 proc recordCommandBuffer(renderPass: VkRenderPass, pipeline: var RenderPipeline, commandBuffer: VkCommandBuffer, framebuffer: VkFramebuffer, frameDimension: VkExtent2D, currentFrame: int) =
557 var 607 var
558 beginInfo = VkCommandBufferBeginInfo( 608 beginInfo = VkCommandBufferBeginInfo(
559 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 609 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
560 pInheritanceInfo: nil, 610 pInheritanceInfo: nil,
561 ) 611 )
586 checkVkResult vkBeginCommandBuffer(commandBuffer, addr(beginInfo)) 636 checkVkResult vkBeginCommandBuffer(commandBuffer, addr(beginInfo))
587 block: 637 block:
588 vkCmdBeginRenderPass(commandBuffer, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) 638 vkCmdBeginRenderPass(commandBuffer, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE)
589 vkCmdSetViewport(commandBuffer, firstViewport=0, viewportCount=1, addr(viewport)) 639 vkCmdSetViewport(commandBuffer, firstViewport=0, viewportCount=1, addr(viewport))
590 vkCmdSetScissor(commandBuffer, firstScissor=0, scissorCount=1, addr(scissor)) 640 vkCmdSetScissor(commandBuffer, firstScissor=0, scissorCount=1, addr(scissor))
591 runPipeline(commandBuffer, pipeline) 641 runPipeline(commandBuffer, pipeline, currentFrame)
592 vkCmdEndRenderPass(commandBuffer) 642 vkCmdEndRenderPass(commandBuffer)
593 checkVkResult vkEndCommandBuffer(commandBuffer) 643 checkVkResult vkEndCommandBuffer(commandBuffer)
594 644
595 proc drawFrame(window: NativeWindow, vulkan: var Vulkan, currentFrame: int, resized: bool, pipeline: RenderPipeline) = 645 proc drawFrame(window: NativeWindow, vulkan: var Vulkan, currentFrame: int, resized: bool, pipeline: var RenderPipeline) =
596 checkVkResult vkWaitForFences(vulkan.device.device, 1, addr(vulkan.inFlightFences[currentFrame]), VK_TRUE, high(uint64)) 646 checkVkResult vkWaitForFences(vulkan.device.device, 1, addr(vulkan.inFlightFences[currentFrame]), VK_TRUE, high(uint64))
597 var bufferImageIndex: uint32 647 var bufferImageIndex: uint32
598 let nextImageResult = vkAcquireNextImageKHR( 648 let nextImageResult = vkAcquireNextImageKHR(
599 vulkan.device.device, 649 vulkan.device.device,
600 vulkan.swapchain.swapchain, 650 vulkan.swapchain.swapchain,
609 elif not (nextImageResult in [VK_SUCCESS, VK_SUBOPTIMAL_KHR]): 659 elif not (nextImageResult in [VK_SUCCESS, VK_SUBOPTIMAL_KHR]):
610 raise newException(Exception, "Vulkan error: vkAcquireNextImageKHR returned " & $nextImageResult) 660 raise newException(Exception, "Vulkan error: vkAcquireNextImageKHR returned " & $nextImageResult)
611 checkVkResult vkResetFences(vulkan.device.device, 1, addr(vulkan.inFlightFences[currentFrame])) 661 checkVkResult vkResetFences(vulkan.device.device, 1, addr(vulkan.inFlightFences[currentFrame]))
612 662
613 checkVkResult vkResetCommandBuffer(vulkan.commandBuffers[currentFrame], VkCommandBufferResetFlags(0)) 663 checkVkResult vkResetCommandBuffer(vulkan.commandBuffers[currentFrame], VkCommandBufferResetFlags(0))
614 vulkan.renderPass.recordCommandBuffer(pipeline, vulkan.commandBuffers[currentFrame], vulkan.framebuffers[bufferImageIndex], vulkan.frameDimension) 664 vulkan.renderPass.recordCommandBuffer(pipeline, vulkan.commandBuffers[currentFrame], vulkan.framebuffers[bufferImageIndex], vulkan.frameDimension, currentFrame)
615 var 665 var
616 waitSemaphores = [vulkan.imageAvailableSemaphores[currentFrame]] 666 waitSemaphores = [vulkan.imageAvailableSemaphores[currentFrame]]
617 waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)] 667 waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)]
618 signalSemaphores = [vulkan.renderFinishedSemaphores[currentFrame]] 668 signalSemaphores = [vulkan.renderFinishedSemaphores[currentFrame]]
619 submitInfo = VkSubmitInfo( 669 submitInfo = VkSubmitInfo(
642 if presentResult == VK_ERROR_OUT_OF_DATE_KHR or presentResult == VK_SUBOPTIMAL_KHR or resized: 692 if presentResult == VK_ERROR_OUT_OF_DATE_KHR or presentResult == VK_SUBOPTIMAL_KHR or resized:
643 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.device, vulkan.surface) 693 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.device, vulkan.surface)
644 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain() 694 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain()
645 695
646 696
647 proc run*(engine: var Engine, pipeline: RenderPipeline, globalUpdate: proc(engine: var Engine, dt: Duration)) = 697 proc run*(engine: var Engine, pipeline: var RenderPipeline, globalUpdate: proc(engine: var Engine, dt: float32)) =
648 var 698 var
649 killed = false 699 killed = false
650 currentFrame = 0 700 currentFrame = 0
651 resized = false 701 resized = false
652 lastUpdate = getTime() 702 lastUpdate = getTime()
668 discard 718 discard
669 719
670 # game logic update 720 # game logic update
671 let 721 let
672 now = getTime() 722 now = getTime()
673 dt = now - lastUpdate 723 dt = float32(float64((now - lastUpdate).inNanoseconds) / 1_000_000_000'f64)
674 lastUpdate = now 724 lastUpdate = now
675 engine.globalUpdate(dt) 725 engine.globalUpdate(dt)
676 for entity in allEntities(engine.currentscenedata): 726 for entity in allEntities(engine.currentscenedata):
677 entity.update(dt) 727 entity.update(dt)
678 728
679 # submit frame for drawing 729 # submit frame for drawing
680 engine.window.drawFrame(engine.vulkan, currentFrame, resized, pipeline) 730 engine.window.drawFrame(engine.vulkan, currentFrame, resized, pipeline)
681 resized = false 731 resized = false
682 currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT; 732 currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT
683 checkVkResult vkDeviceWaitIdle(engine.vulkan.device.device) 733 checkVkResult vkDeviceWaitIdle(engine.vulkan.device.device)
684 734
685 proc trash*(pipeline: var RenderPipeline) = 735 proc trash*(pipeline: var RenderPipeline) =
686 vkDestroyDescriptorSetLayout(pipeline.device, pipeline.uniformLayout, nil); 736 vkDestroyDescriptorPool(pipeline.device, pipeline.descriptorPool, nil)
737 vkDestroyDescriptorSetLayout(pipeline.device, pipeline.descriptorSetLayout, nil)
687 vkDestroyPipeline(pipeline.device, pipeline.pipeline, nil) 738 vkDestroyPipeline(pipeline.device, pipeline.pipeline, nil)
688 vkDestroyPipelineLayout(pipeline.device, pipeline.layout, nil) 739 vkDestroyPipelineLayout(pipeline.device, pipeline.layout, nil)
689 for shader in pipeline.shaders: 740 for shader in pipeline.shaders:
690 vkDestroyShaderModule(pipeline.device, shader.shader.module, nil) 741 vkDestroyShaderModule(pipeline.device, shader.shader.module, nil)
691 742