Mercurial > games > semicongine
comparison src/zamikongine/engine.nim @ 489:54a1f8ee208e
big refactoring, part1
| author | Sam <sam@basx.dev> |
|---|---|
| date | Sat, 14 Jan 2023 14:08:00 +0700 |
| parents | b4a972bd37d5 |
| children | 680c4b8ca28a |
comparison
equal
deleted
inserted
replaced
| 488:455f1a416fe7 | 489:54a1f8ee208e |
|---|---|
| 1 import std/times | |
| 1 import std/typetraits | 2 import std/typetraits |
| 2 import std/strformat | 3 import std/strformat |
| 3 import std/enumerate | 4 import std/enumerate |
| 4 import std/logging | 5 import std/logging |
| 5 | 6 |
| 11 import ./shader | 12 import ./shader |
| 12 import ./vertex | 13 import ./vertex |
| 13 import ./buffer | 14 import ./buffer |
| 14 import ./thing | 15 import ./thing |
| 15 import ./mesh | 16 import ./mesh |
| 17 import ./descriptor | |
| 16 | 18 |
| 17 const MAX_FRAMES_IN_FLIGHT = 2 | 19 const MAX_FRAMES_IN_FLIGHT = 2 |
| 18 const DEBUG_LOG = not defined(release) | 20 const DEBUG_LOG = not defined(release) |
| 19 | 21 |
| 20 var logger = newConsoleLogger() | 22 var logger = newConsoleLogger() |
| 33 presentationQueue: VkQueue | 35 presentationQueue: VkQueue |
| 34 Swapchain = object | 36 Swapchain = object |
| 35 swapchain: VkSwapchainKHR | 37 swapchain: VkSwapchainKHR |
| 36 images: seq[VkImage] | 38 images: seq[VkImage] |
| 37 imageviews: seq[VkImageView] | 39 imageviews: seq[VkImageView] |
| 38 RenderPipeline = object | 40 RenderPipeline[T] = object |
| 39 shaders*: seq[ShaderProgram] | 41 device*: VkDevice |
| 42 shaders*: seq[ShaderProgram[T]] | |
| 40 layout*: VkPipelineLayout | 43 layout*: VkPipelineLayout |
| 41 pipeline*: VkPipeline | 44 pipeline*: VkPipeline |
| 45 uniformLayout*: VkDescriptorSetLayout | |
| 46 vertexBuffers*: seq[(seq[Buffer], uint32)] | |
| 47 indexedVertexBuffers*: seq[(seq[Buffer], Buffer, uint32, VkIndexType)] | |
| 48 uniformBuffers*: array[MAX_FRAMES_IN_FLIGHT, Buffer] | |
| 42 QueueFamily = object | 49 QueueFamily = object |
| 43 properties*: VkQueueFamilyProperties | 50 properties*: VkQueueFamilyProperties |
| 44 hasSurfaceSupport*: bool | 51 hasSurfaceSupport*: bool |
| 45 PhysicalDevice = object | 52 PhysicalDevice = object |
| 46 device*: VkPhysicalDevice | 53 device*: VkPhysicalDevice |
| 49 features*: VkPhysicalDeviceFeatures | 56 features*: VkPhysicalDeviceFeatures |
| 50 queueFamilies*: seq[QueueFamily] | 57 queueFamilies*: seq[QueueFamily] |
| 51 formats: seq[VkSurfaceFormatKHR] | 58 formats: seq[VkSurfaceFormatKHR] |
| 52 presentModes: seq[VkPresentModeKHR] | 59 presentModes: seq[VkPresentModeKHR] |
| 53 Vulkan* = object | 60 Vulkan* = object |
| 54 debugMessenger: VkDebugUtilsMessengerEXT | 61 debugMessenger*: VkDebugUtilsMessengerEXT |
| 55 instance*: VkInstance | 62 instance*: VkInstance |
| 56 deviceList*: seq[PhysicalDevice] | 63 deviceList*: seq[PhysicalDevice] |
| 57 device*: Device | 64 device*: Device |
| 58 surface*: VkSurfaceKHR | 65 surface*: VkSurfaceKHR |
| 59 surfaceFormat: VkSurfaceFormatKHR | 66 surfaceFormat*: VkSurfaceFormatKHR |
| 60 frameDimension: VkExtent2D | 67 frameDimension*: VkExtent2D |
| 61 swapchain: Swapchain | 68 swapchain*: Swapchain |
| 62 framebuffers: seq[VkFramebuffer] | 69 framebuffers*: seq[VkFramebuffer] |
| 63 renderPass*: VkRenderPass | 70 renderPass*: VkRenderPass |
| 64 pipeline*: RenderPipeline | |
| 65 commandPool*: VkCommandPool | 71 commandPool*: VkCommandPool |
| 66 commandBuffers*: array[MAX_FRAMES_IN_FLIGHT, VkCommandBuffer] | 72 commandBuffers*: array[MAX_FRAMES_IN_FLIGHT, VkCommandBuffer] |
| 67 imageAvailableSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] | 73 imageAvailableSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] |
| 68 renderFinishedSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] | 74 renderFinishedSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] |
| 69 inFlightFences*: array[MAX_FRAMES_IN_FLIGHT, VkFence] | 75 inFlightFences*: array[MAX_FRAMES_IN_FLIGHT, VkFence] |
| 70 vertexBuffers: seq[(seq[Buffer], uint32)] | |
| 71 indexedVertexBuffers: seq[(seq[Buffer], Buffer, uint32, VkIndexType)] | |
| 72 Engine* = object | 76 Engine* = object |
| 73 vulkan: Vulkan | 77 vulkan*: Vulkan |
| 74 window: NativeWindow | 78 window*: NativeWindow |
| 75 currentscenedata: ref Thing | 79 currentscenedata*: ref Thing |
| 76 | 80 |
| 77 proc getAllPhysicalDevices(instance: VkInstance, surface: VkSurfaceKHR): seq[PhysicalDevice] = | 81 proc getAllPhysicalDevices(instance: VkInstance, surface: VkSurfaceKHR): seq[PhysicalDevice] = |
| 78 for vulkanPhysicalDevice in getVulkanPhysicalDevices(instance): | 82 for vulkanPhysicalDevice in getVulkanPhysicalDevices(instance): |
| 79 var device = PhysicalDevice(device: vulkanPhysicalDevice, extensions: getDeviceExtensions(vulkanPhysicalDevice)) | 83 var device = PhysicalDevice(device: vulkanPhysicalDevice, extensions: getDeviceExtensions(vulkanPhysicalDevice)) |
| 80 vkGetPhysicalDeviceProperties(vulkanPhysicalDevice, addr(device.properties)) | 84 vkGetPhysicalDeviceProperties(vulkanPhysicalDevice, addr(device.properties)) |
| 244 dependencyCount: 1, | 248 dependencyCount: 1, |
| 245 pDependencies: addr(dependency), | 249 pDependencies: addr(dependency), |
| 246 ) | 250 ) |
| 247 checkVkResult device.vkCreateRenderPass(addr(renderPassCreateInfo), nil, addr(result)) | 251 checkVkResult device.vkCreateRenderPass(addr(renderPassCreateInfo), nil, addr(result)) |
| 248 | 252 |
| 249 proc setupRenderPipeline[T](device: VkDevice, frameDimension: VkExtent2D, renderPass: VkRenderPass, vertexShader, fragmentShader: static string): RenderPipeline = | 253 proc initRenderPipeline[VertextType, T](device: VkDevice, frameDimension: VkExtent2D, renderPass: VkRenderPass, vertexShader, fragmentShader: static string): RenderPipeline[T] = |
| 250 # load shaders | 254 # load shaders |
| 251 result.shaders.add(device.initShaderProgram(VK_SHADER_STAGE_VERTEX_BIT, vertexShader)) | 255 result.device = device |
| 252 result.shaders.add(device.initShaderProgram(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShader)) | 256 result.shaders.add(initShaderProgram[T](device, VK_SHADER_STAGE_VERTEX_BIT, vertexShader)) |
| 257 result.shaders.add(initShaderProgram[T](device, VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShader)) | |
| 253 | 258 |
| 254 var | 259 var |
| 255 # define which parts can be dynamic (pipeline is fixed after setup) | 260 # define which parts can be dynamic (pipeline is fixed after setup) |
| 256 dynamicStates = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] | 261 dynamicStates = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] |
| 257 dynamicState = VkPipelineDynamicStateCreateInfo( | 262 dynamicState = VkPipelineDynamicStateCreateInfo( |
| 258 sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, | 263 sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, |
| 259 dynamicStateCount: uint32(dynamicStates.len), | 264 dynamicStateCount: uint32(dynamicStates.len), |
| 260 pDynamicStates: addr(dynamicStates[0]), | 265 pDynamicStates: addr(dynamicStates[0]), |
| 261 ) | 266 ) |
| 262 vertexbindings = generateInputVertexBinding[T]() | 267 vertexbindings = generateInputVertexBinding[VertextType]() |
| 263 attributebindings = generateInputAttributeBinding[T]() | 268 attributebindings = generateInputAttributeBinding[VertextType]() |
| 264 | 269 |
| 265 # define input data format | 270 # define input data format |
| 266 vertexInputInfo = VkPipelineVertexInputStateCreateInfo( | 271 vertexInputInfo = VkPipelineVertexInputStateCreateInfo( |
| 267 sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | 272 sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, |
| 268 vertexBindingDescriptionCount: uint32(vertexbindings.len), | 273 vertexBindingDescriptionCount: uint32(vertexbindings.len), |
| 329 attachmentCount: 1, | 334 attachmentCount: 1, |
| 330 pAttachments: addr(colorBlendAttachment), | 335 pAttachments: addr(colorBlendAttachment), |
| 331 blendConstants: [0.0'f, 0.0'f, 0.0'f, 0.0'f], | 336 blendConstants: [0.0'f, 0.0'f, 0.0'f, 0.0'f], |
| 332 ) | 337 ) |
| 333 | 338 |
| 334 # create pipeline | 339 result.uniformLayout = device.createUniformDescriptorLayout(VkShaderStageFlags(VK_SHADER_STAGE_VERTEX_BIT), 0) |
| 340 var | |
| 341 # "globals" that go into the shader, uniforms etc. | |
| 335 pipelineLayoutInfo = VkPipelineLayoutCreateInfo( | 342 pipelineLayoutInfo = VkPipelineLayoutCreateInfo( |
| 336 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | 343 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| 337 setLayoutCount: 0, | 344 setLayoutCount: 1, |
| 338 pSetLayouts: nil, | 345 pSetLayouts: addr(result.uniformLayout), |
| 339 pushConstantRangeCount: 0, | 346 pushConstantRangeCount: 0, |
| 340 pPushConstantRanges: nil, | 347 pPushConstantRanges: nil, |
| 341 ) | 348 ) |
| 342 checkVkResult vkCreatePipelineLayout(device, addr(pipelineLayoutInfo), nil, addr(result.layout)) | 349 checkVkResult vkCreatePipelineLayout(device, addr(pipelineLayoutInfo), nil, addr(result.layout)) |
| 343 | 350 |
| 441 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: | 448 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: |
| 442 checkVkResult device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result[0][i])) | 449 checkVkResult device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result[0][i])) |
| 443 checkVkResult device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result[1][i])) | 450 checkVkResult device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result[1][i])) |
| 444 checkVkResult device.vkCreateFence(addr(fenceInfo), nil, addr(result[2][i])) | 451 checkVkResult device.vkCreateFence(addr(fenceInfo), nil, addr(result[2][i])) |
| 445 | 452 |
| 446 proc igniteEngine*(): Engine = | 453 proc igniteEngine*(windowTitle: string): Engine = |
| 447 | 454 |
| 448 result.window = createWindow("Hello triangle") | 455 result.window = createWindow(windowTitle) |
| 449 | 456 |
| 450 # setup vulkan functions | 457 # setup vulkan functions |
| 451 vkLoad1_0() | 458 vkLoad1_0() |
| 452 vkLoad1_1() | 459 vkLoad1_1() |
| 453 vkLoad1_2() | 460 vkLoad1_2() |
| 486 result.vulkan.renderFinishedSemaphores, | 493 result.vulkan.renderFinishedSemaphores, |
| 487 result.vulkan.inFlightFences, | 494 result.vulkan.inFlightFences, |
| 488 ) = result.vulkan.device.device.setupSyncPrimitives() | 495 ) = result.vulkan.device.device.setupSyncPrimitives() |
| 489 | 496 |
| 490 | 497 |
| 491 proc setupPipeline*[T: object, U: uint16|uint32](engine: var Engine, scenedata: ref Thing, vertexShader, fragmentShader: static string) = | 498 proc setupPipeline*[VertexType, UniformType, T: object, IndexType: uint16|uint32](engine: var Engine, scenedata: ref Thing, vertexShader, fragmentShader: static string): RenderPipeline[T] = |
| 492 engine.currentscenedata = scenedata | 499 engine.currentscenedata = scenedata |
| 493 engine.vulkan.pipeline = setupRenderPipeline[T]( | 500 result = initRenderPipeline[VertexType, T]( |
| 494 engine.vulkan.device.device, | 501 engine.vulkan.device.device, |
| 495 engine.vulkan.frameDimension, | 502 engine.vulkan.frameDimension, |
| 496 engine.vulkan.renderPass, | 503 engine.vulkan.renderPass, |
| 497 vertexShader, | 504 vertexShader, |
| 498 fragmentShader, | 505 fragmentShader, |
| 499 ) | 506 ) |
| 500 var allmeshes: seq[Mesh[T]] | 507 # vertex buffers |
| 501 for mesh in partsOfType[ref Mesh[T]](engine.currentscenedata): | 508 var allmeshes: seq[Mesh[VertexType]] |
| 509 for mesh in partsOfType[ref Mesh[VertexType]](engine.currentscenedata): | |
| 502 allmeshes.add(mesh[]) | 510 allmeshes.add(mesh[]) |
| 503 if allmeshes.len > 0: | 511 if allmeshes.len > 0: |
| 504 var ubermesh = createUberMesh(allmeshes) | 512 var ubermesh = createUberMesh(allmeshes) |
| 505 engine.vulkan.vertexBuffers.add createVertexBuffers(ubermesh, engine.vulkan.device.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue) | 513 result.vertexBuffers.add createVertexBuffers(ubermesh, engine.vulkan.device.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue) |
| 506 | 514 |
| 507 var allindexedmeshes: seq[IndexedMesh[T, U]] | 515 # vertex buffers with indexes |
| 508 for mesh in partsOfType[ref IndexedMesh[T, U]](engine.currentscenedata): | 516 var allindexedmeshes: seq[IndexedMesh[VertexType, IndexType]] |
| 517 for mesh in partsOfType[ref IndexedMesh[VertexType, IndexType]](engine.currentscenedata): | |
| 509 allindexedmeshes.add(mesh[]) | 518 allindexedmeshes.add(mesh[]) |
| 510 if allindexedmeshes.len > 0: | 519 if allindexedmeshes.len > 0: |
| 511 var indexedubermesh = createUberMesh(allindexedmeshes) | 520 var indexedubermesh = createUberMesh(allindexedmeshes) |
| 512 engine.vulkan.indexedVertexBuffers.add createIndexedVertexBuffers(indexedubermesh, engine.vulkan.device.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue) | 521 result.indexedVertexBuffers.add createIndexedVertexBuffers(indexedubermesh, engine.vulkan.device.device, engine.vulkan.device.physicalDevice.device, engine.vulkan.commandPool, engine.vulkan.device.graphicsQueue) |
| 513 | 522 |
| 514 proc recordCommandBuffer(renderPass: VkRenderPass, pipeline: VkPipeline, commandBuffer: VkCommandBuffer, framebuffer: VkFramebuffer, frameDimension: VkExtent2D, engine: var Engine) = | 523 # uniform buffers |
| 524 result.uniformBuffers = createUniformBuffers[MAX_FRAMES_IN_FLIGHT, UniformType]( | |
| 525 engine.vulkan.device.device, | |
| 526 engine.vulkan.device.physicalDevice.device | |
| 527 ) | |
| 528 | |
| 529 | |
| 530 proc runPipeline(commandBuffer: VkCommandBuffer, pipeline: RenderPipeline) = | |
| 531 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline) | |
| 532 | |
| 533 for (vertexBufferSet, vertexCount) in pipeline.vertexBuffers: | |
| 534 var | |
| 535 vertexBuffers: seq[VkBuffer] | |
| 536 offsets: seq[VkDeviceSize] | |
| 537 for buffer in vertexBufferSet: | |
| 538 vertexBuffers.add buffer.vkBuffer | |
| 539 offsets.add VkDeviceSize(0) | |
| 540 | |
| 541 vkCmdBindVertexBuffers(commandBuffer, firstBinding=0'u32, bindingCount=2'u32, pBuffers=addr(vertexBuffers[0]), pOffsets=addr(offsets[0])) | |
| 542 vkCmdDraw(commandBuffer, vertexCount=vertexCount, instanceCount=1'u32, firstVertex=0'u32, firstInstance=0'u32) | |
| 543 | |
| 544 for (vertexBufferSet, indexBuffer, indicesCount, indexType) in pipeline.indexedVertexBuffers: | |
| 545 var | |
| 546 vertexBuffers: seq[VkBuffer] | |
| 547 offsets: seq[VkDeviceSize] | |
| 548 for buffer in vertexBufferSet: | |
| 549 vertexBuffers.add buffer.vkBuffer | |
| 550 offsets.add VkDeviceSize(0) | |
| 551 | |
| 552 vkCmdBindVertexBuffers(commandBuffer, firstBinding=0'u32, bindingCount=2'u32, pBuffers=addr(vertexBuffers[0]), pOffsets=addr(offsets[0])) | |
| 553 vkCmdBindIndexBuffer(commandBuffer, indexBuffer.vkBuffer, VkDeviceSize(0), indexType); | |
| 554 vkCmdDrawIndexed(commandBuffer, indicesCount, 1, 0, 0, 0); | |
| 555 | |
| 556 proc recordCommandBuffer(renderPass: VkRenderPass, pipeline: RenderPipeline, commandBuffer: VkCommandBuffer, framebuffer: VkFramebuffer, frameDimension: VkExtent2D) = | |
| 515 var | 557 var |
| 516 beginInfo = VkCommandBufferBeginInfo( | 558 beginInfo = VkCommandBufferBeginInfo( |
| 517 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | 559 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, |
| 518 pInheritanceInfo: nil, | 560 pInheritanceInfo: nil, |
| 519 ) | 561 ) |
| 539 ) | 581 ) |
| 540 scissor = VkRect2D( | 582 scissor = VkRect2D( |
| 541 offset: VkOffset2D(x: 0, y: 0), | 583 offset: VkOffset2D(x: 0, y: 0), |
| 542 extent: frameDimension | 584 extent: frameDimension |
| 543 ) | 585 ) |
| 544 checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo)) | 586 checkVkResult vkBeginCommandBuffer(commandBuffer, addr(beginInfo)) |
| 545 commandBuffer.vkCmdBeginRenderPass(addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) | 587 block: |
| 546 commandBuffer.vkCmdSetViewport(firstViewport=0, viewportCount=1, addr(viewport)) | 588 vkCmdBeginRenderPass(commandBuffer, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) |
| 547 commandBuffer.vkCmdSetScissor(firstScissor=0, scissorCount=1, addr(scissor)) | 589 vkCmdSetViewport(commandBuffer, firstViewport=0, viewportCount=1, addr(viewport)) |
| 548 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline) | 590 vkCmdSetScissor(commandBuffer, firstScissor=0, scissorCount=1, addr(scissor)) |
| 549 | 591 runPipeline(commandBuffer, pipeline) |
| 550 for (vertexBufferSet, vertexCount) in engine.vulkan.vertexBuffers: | 592 vkCmdEndRenderPass(commandBuffer) |
| 551 var | 593 checkVkResult vkEndCommandBuffer(commandBuffer) |
| 552 vertexBuffers: seq[VkBuffer] | 594 |
| 553 offsets: seq[VkDeviceSize] | 595 proc drawFrame(window: NativeWindow, vulkan: var Vulkan, currentFrame: int, resized: bool, pipeline: RenderPipeline) = |
| 554 for buffer in vertexBufferSet: | 596 checkVkResult vkWaitForFences(vulkan.device.device, 1, addr(vulkan.inFlightFences[currentFrame]), VK_TRUE, high(uint64)) |
| 555 vertexBuffers.add buffer.vkBuffer | |
| 556 offsets.add VkDeviceSize(0) | |
| 557 | |
| 558 commandBuffer.vkCmdBindVertexBuffers(firstBinding=0'u32, bindingCount=2'u32, pBuffers=addr(vertexBuffers[0]), pOffsets=addr(offsets[0])) | |
| 559 commandBuffer.vkCmdDraw(vertexCount=vertexCount, instanceCount=1'u32, firstVertex=0'u32, firstInstance=0'u32) | |
| 560 | |
| 561 for (vertexBufferSet, indexBuffer, indicesCount, indexType) in engine.vulkan.indexedVertexBuffers: | |
| 562 var | |
| 563 vertexBuffers: seq[VkBuffer] | |
| 564 offsets: seq[VkDeviceSize] | |
| 565 for buffer in vertexBufferSet: | |
| 566 vertexBuffers.add buffer.vkBuffer | |
| 567 offsets.add VkDeviceSize(0) | |
| 568 | |
| 569 commandBuffer.vkCmdBindVertexBuffers(firstBinding=0'u32, bindingCount=2'u32, pBuffers=addr(vertexBuffers[0]), pOffsets=addr(offsets[0])) | |
| 570 commandBuffer.vkCmdBindIndexBuffer(indexBuffer.vkBuffer, VkDeviceSize(0), indexType); | |
| 571 commandBuffer.vkCmdDrawIndexed(indicesCount, 1, 0, 0, 0); | |
| 572 commandBuffer.vkCmdEndRenderPass() | |
| 573 checkVkResult commandBuffer.vkEndCommandBuffer() | |
| 574 | |
| 575 proc drawFrame(window: NativeWindow, vulkan: var Vulkan, currentFrame: int, resized: bool, engine: var Engine) = | |
| 576 checkVkResult vulkan.device.device.vkWaitForFences(1, addr(vulkan.inFlightFences[currentFrame]), VK_TRUE, high(uint64)) | |
| 577 var bufferImageIndex: uint32 | 597 var bufferImageIndex: uint32 |
| 578 let nextImageResult = vulkan.device.device.vkAcquireNextImageKHR( | 598 let nextImageResult = vkAcquireNextImageKHR( |
| 599 vulkan.device.device, | |
| 579 vulkan.swapchain.swapchain, | 600 vulkan.swapchain.swapchain, |
| 580 high(uint64), | 601 high(uint64), |
| 581 vulkan.imageAvailableSemaphores[currentFrame], | 602 vulkan.imageAvailableSemaphores[currentFrame], |
| 582 VkFence(0), | 603 VkFence(0), |
| 583 addr(bufferImageIndex) | 604 addr(bufferImageIndex) |
| 585 if nextImageResult == VK_ERROR_OUT_OF_DATE_KHR: | 606 if nextImageResult == VK_ERROR_OUT_OF_DATE_KHR: |
| 586 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.device, vulkan.surface) | 607 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.device, vulkan.surface) |
| 587 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain() | 608 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain() |
| 588 elif not (nextImageResult in [VK_SUCCESS, VK_SUBOPTIMAL_KHR]): | 609 elif not (nextImageResult in [VK_SUCCESS, VK_SUBOPTIMAL_KHR]): |
| 589 raise newException(Exception, "Vulkan error: vkAcquireNextImageKHR returned " & $nextImageResult) | 610 raise newException(Exception, "Vulkan error: vkAcquireNextImageKHR returned " & $nextImageResult) |
| 590 checkVkResult vulkan.device.device.vkResetFences(1, addr(vulkan.inFlightFences[currentFrame])) | 611 checkVkResult vkResetFences(vulkan.device.device, 1, addr(vulkan.inFlightFences[currentFrame])) |
| 591 | 612 |
| 592 checkVkResult vulkan.commandBuffers[currentFrame].vkResetCommandBuffer(VkCommandBufferResetFlags(0)) | 613 checkVkResult vkResetCommandBuffer(vulkan.commandBuffers[currentFrame], VkCommandBufferResetFlags(0)) |
| 593 vulkan.renderPass.recordCommandBuffer(vulkan.pipeline.pipeline, vulkan.commandBuffers[currentFrame], vulkan.framebuffers[bufferImageIndex], vulkan.frameDimension, engine) | 614 vulkan.renderPass.recordCommandBuffer(pipeline, vulkan.commandBuffers[currentFrame], vulkan.framebuffers[bufferImageIndex], vulkan.frameDimension) |
| 594 var | 615 var |
| 595 waitSemaphores = [vulkan.imageAvailableSemaphores[currentFrame]] | 616 waitSemaphores = [vulkan.imageAvailableSemaphores[currentFrame]] |
| 596 waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)] | 617 waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)] |
| 597 signalSemaphores = [vulkan.renderFinishedSemaphores[currentFrame]] | 618 signalSemaphores = [vulkan.renderFinishedSemaphores[currentFrame]] |
| 598 submitInfo = VkSubmitInfo( | 619 submitInfo = VkSubmitInfo( |
| 621 if presentResult == VK_ERROR_OUT_OF_DATE_KHR or presentResult == VK_SUBOPTIMAL_KHR or resized: | 642 if presentResult == VK_ERROR_OUT_OF_DATE_KHR or presentResult == VK_SUBOPTIMAL_KHR or resized: |
| 622 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.device, vulkan.surface) | 643 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.device, vulkan.surface) |
| 623 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain() | 644 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain() |
| 624 | 645 |
| 625 | 646 |
| 626 proc fullThrottle*(engine: var Engine) = | 647 proc run*(engine: var Engine, pipeline: RenderPipeline, globalUpdate: proc(engine: var Engine, dt: Duration)) = |
| 627 var | 648 var |
| 628 killed = false | 649 killed = false |
| 629 currentFrame = 0 | 650 currentFrame = 0 |
| 630 resized = false | 651 resized = false |
| 652 lastUpdate = getTime() | |
| 631 | 653 |
| 632 while not killed: | 654 while not killed: |
| 655 | |
| 656 # process input | |
| 633 for event in engine.window.pendingEvents(): | 657 for event in engine.window.pendingEvents(): |
| 634 case event.eventType: | 658 case event.eventType: |
| 635 of Quit: | 659 of Quit: |
| 636 killed = true | 660 killed = true |
| 637 of ResizedWindow: | 661 of ResizedWindow: |
| 640 echo event | 664 echo event |
| 641 if event.key == Escape: | 665 if event.key == Escape: |
| 642 killed = true | 666 killed = true |
| 643 else: | 667 else: |
| 644 discard | 668 discard |
| 645 engine.window.drawFrame(engine.vulkan, currentFrame, resized, engine) | 669 |
| 670 # game logic update | |
| 671 let | |
| 672 now = getTime() | |
| 673 dt = now - lastUpdate | |
| 674 lastUpdate = now | |
| 675 engine.globalUpdate(dt) | |
| 676 for entity in allEntities(engine.currentscenedata): | |
| 677 entity.update(dt) | |
| 678 | |
| 679 # submit frame for drawing | |
| 680 engine.window.drawFrame(engine.vulkan, currentFrame, resized, pipeline) | |
| 646 resized = false | 681 resized = false |
| 647 currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT; | 682 currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT; |
| 648 checkVkResult engine.vulkan.device.device.vkDeviceWaitIdle() | 683 checkVkResult vkDeviceWaitIdle(engine.vulkan.device.device) |
| 649 | 684 |
| 650 proc trash*(engine: var Engine) = | 685 proc trash*(pipeline: var RenderPipeline) = |
| 651 for (bufferset, cnt) in engine.vulkan.vertexBuffers.mitems: | 686 vkDestroyDescriptorSetLayout(pipeline.device, pipeline.uniformLayout, nil); |
| 687 vkDestroyPipeline(pipeline.device, pipeline.pipeline, nil) | |
| 688 vkDestroyPipelineLayout(pipeline.device, pipeline.layout, nil) | |
| 689 for shader in pipeline.shaders: | |
| 690 vkDestroyShaderModule(pipeline.device, shader.shader.module, nil) | |
| 691 | |
| 692 for (bufferset, cnt) in pipeline.vertexBuffers.mitems: | |
| 652 for buffer in bufferset.mitems: | 693 for buffer in bufferset.mitems: |
| 653 buffer.trash() | 694 buffer.trash() |
| 654 for (bufferset, indexbuffer, cnt, t) in engine.vulkan.indexedVertexBuffers.mitems: | 695 for (bufferset, indexbuffer, cnt, t) in pipeline.indexedVertexBuffers.mitems: |
| 655 indexbuffer.trash() | 696 indexbuffer.trash() |
| 656 for buffer in bufferset.mitems: | 697 for buffer in bufferset.mitems: |
| 657 buffer.trash() | 698 buffer.trash() |
| 699 for buffer in pipeline.uniformBuffers.mitems: | |
| 700 buffer.trash() | |
| 701 | |
| 702 proc trash*(engine: var Engine) = | |
| 703 checkVkResult vkDeviceWaitIdle(engine.vulkan.device.device) | |
| 658 engine.vulkan.device.device.trash(engine.vulkan.swapchain, engine.vulkan.framebuffers) | 704 engine.vulkan.device.device.trash(engine.vulkan.swapchain, engine.vulkan.framebuffers) |
| 659 checkVkResult engine.vulkan.device.device.vkDeviceWaitIdle() | |
| 660 | 705 |
| 661 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: | 706 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: |
| 662 engine.vulkan.device.device.vkDestroySemaphore(engine.vulkan.imageAvailableSemaphores[i], nil) | 707 engine.vulkan.device.device.vkDestroySemaphore(engine.vulkan.imageAvailableSemaphores[i], nil) |
| 663 engine.vulkan.device.device.vkDestroySemaphore(engine.vulkan.renderFinishedSemaphores[i], nil) | 708 engine.vulkan.device.device.vkDestroySemaphore(engine.vulkan.renderFinishedSemaphores[i], nil) |
| 664 engine.vulkan.device.device.vkDestroyFence(engine.vulkan.inFlightFences[i], nil) | 709 engine.vulkan.device.device.vkDestroyFence(engine.vulkan.inFlightFences[i], nil) |
| 665 | 710 |
| 711 engine.vulkan.device.device.vkDestroyRenderPass(engine.vulkan.renderPass, nil) | |
| 666 engine.vulkan.device.device.vkDestroyCommandPool(engine.vulkan.commandPool, nil) | 712 engine.vulkan.device.device.vkDestroyCommandPool(engine.vulkan.commandPool, nil) |
| 667 engine.vulkan.device.device.vkDestroyPipeline(engine.vulkan.pipeline.pipeline, nil) | |
| 668 engine.vulkan.device.device.vkDestroyPipelineLayout(engine.vulkan.pipeline.layout, nil) | |
| 669 engine.vulkan.device.device.vkDestroyRenderPass(engine.vulkan.renderPass, nil) | |
| 670 | |
| 671 for shader in engine.vulkan.pipeline.shaders: | |
| 672 engine.vulkan.device.device.vkDestroyShaderModule(shader.shader.module, nil) | |
| 673 | 713 |
| 674 engine.vulkan.instance.vkDestroySurfaceKHR(engine.vulkan.surface, nil) | 714 engine.vulkan.instance.vkDestroySurfaceKHR(engine.vulkan.surface, nil) |
| 675 engine.vulkan.device.device.vkDestroyDevice(nil) | 715 engine.vulkan.device.device.vkDestroyDevice(nil) |
| 676 when DEBUG_LOG: | 716 when DEBUG_LOG: |
| 677 engine.vulkan.instance.vkDestroyDebugUtilsMessengerEXT(engine.vulkan.debugMessenger, nil) | 717 engine.vulkan.instance.vkDestroyDebugUtilsMessengerEXT(engine.vulkan.debugMessenger, nil) |
| 678 engine.window.trash() | 718 engine.window.trash() |
| 679 engine.vulkan.instance.vkDestroyInstance(nil) | 719 engine.vulkan.instance.vkDestroyInstance(nil) # needs to happen after window is trashed as the driver might have a hook registered for the window destruction |
