Mercurial > games > semicongine
comparison semiconginev2/rendering/swapchain.nim @ 1229:5dcb503ef0c0
did: refactor renderpass a bit, enable depth buffering and msaa on offscreen-rendering
| author | sam <sam@basx.dev> |
|---|---|
| date | Thu, 18 Jul 2024 21:32:41 +0700 |
| parents | 56781cc0fc7c |
| children | 69489a678141 |
comparison
equal
deleted
inserted
replaced
| 1228:4e465583ea32 | 1229:5dcb503ef0c0 |
|---|---|
| 1 const N_FRAMEBUFFERS = 3'u32 | 1 const N_FRAMEBUFFERS = 3'u32 |
| 2 | 2 |
| 3 proc InitSwapchain*( | 3 proc InitSwapchain*( |
| 4 renderPass: VkRenderPass, | 4 renderPass: RenderPass, |
| 5 vSync: bool = false, | 5 vSync: bool = false, |
| 6 samples = VK_SAMPLE_COUNT_1_BIT, | 6 oldSwapchain: Swapchain = nil, |
| 7 oldSwapchain: ref Swapchain = nil, | |
| 8 ): Option[Swapchain] = | 7 ): Option[Swapchain] = |
| 9 assert vulkan.instance.Valid, "Vulkan not initialized" | 8 assert vulkan.instance.Valid, "Vulkan not initialized" |
| 10 | 9 |
| 11 var capabilities: VkSurfaceCapabilitiesKHR | 10 var capabilities: VkSurfaceCapabilitiesKHR |
| 12 checkVkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vulkan.physicalDevice, vulkan.surface, addr(capabilities)) | 11 checkVkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vulkan.physicalDevice, vulkan.surface, addr(capabilities)) |
| 13 let | 12 let |
| 14 format = DefaultSurfaceFormat() | |
| 15 width = capabilities.currentExtent.width | 13 width = capabilities.currentExtent.width |
| 16 height = capabilities.currentExtent.height | 14 height = capabilities.currentExtent.height |
| 17 | 15 |
| 18 if width == 0 or height == 0: | 16 if width == 0 or height == 0: |
| 19 return none(Swapchain) | 17 return none(Swapchain) |
| 28 let hasTripleBuffering = VK_PRESENT_MODE_MAILBOX_KHR in svkGetPhysicalDeviceSurfacePresentModesKHR() | 26 let hasTripleBuffering = VK_PRESENT_MODE_MAILBOX_KHR in svkGetPhysicalDeviceSurfacePresentModesKHR() |
| 29 var swapchainCreateInfo = VkSwapchainCreateInfoKHR( | 27 var swapchainCreateInfo = VkSwapchainCreateInfoKHR( |
| 30 sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, | 28 sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, |
| 31 surface: vulkan.surface, | 29 surface: vulkan.surface, |
| 32 minImageCount: minFramebufferCount, | 30 minImageCount: minFramebufferCount, |
| 33 imageFormat: format, | 31 imageFormat: SURFACE_FORMAT, |
| 34 imageColorSpace: VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, # only one supported without special extensions | 32 imageColorSpace: VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, # only one supported without special extensions |
| 35 imageExtent: capabilities.currentExtent, | 33 imageExtent: capabilities.currentExtent, |
| 36 imageArrayLayers: 1, | 34 imageArrayLayers: 1, |
| 37 imageUsage: toBits [VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT], | 35 imageUsage: toBits [VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT], |
| 38 imageSharingMode: VK_SHARING_MODE_EXCLUSIVE, | 36 imageSharingMode: VK_SHARING_MODE_EXCLUSIVE, |
| 40 compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, # only used for blending with other windows, can be opaque | 38 compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, # only used for blending with other windows, can be opaque |
| 41 presentMode: if (vSync or not hasTripleBuffering): VK_PRESENT_MODE_FIFO_KHR else: VK_PRESENT_MODE_MAILBOX_KHR, | 39 presentMode: if (vSync or not hasTripleBuffering): VK_PRESENT_MODE_FIFO_KHR else: VK_PRESENT_MODE_MAILBOX_KHR, |
| 42 clipped: true, | 40 clipped: true, |
| 43 oldSwapchain: if oldSwapchain != nil: oldSwapchain.vk else: VkSwapchainKHR(0), | 41 oldSwapchain: if oldSwapchain != nil: oldSwapchain.vk else: VkSwapchainKHR(0), |
| 44 ) | 42 ) |
| 45 var swapchain: Swapchain | 43 var swapchain = Swapchain( |
| 44 width: width, | |
| 45 height: height, | |
| 46 renderPass: renderPass, | |
| 47 vSync: vSync, | |
| 48 oldSwapchain: oldSwapchain, | |
| 49 ) | |
| 50 | |
| 46 if vkCreateSwapchainKHR(vulkan.device, addr(swapchainCreateInfo), nil, addr(swapchain.vk)) != VK_SUCCESS: | 51 if vkCreateSwapchainKHR(vulkan.device, addr(swapchainCreateInfo), nil, addr(swapchain.vk)) != VK_SUCCESS: |
| 47 return none(Swapchain) | 52 return none(Swapchain) |
| 48 | 53 |
| 49 swapchain.width = width | |
| 50 swapchain.height = height | |
| 51 swapchain.renderPass = renderPass | |
| 52 swapchain.vSync = vSync | |
| 53 swapchain.samples = samples | |
| 54 swapchain.oldSwapchain = oldSwapchain | |
| 55 if swapchain.oldSwapchain != nil: | 54 if swapchain.oldSwapchain != nil: |
| 56 swapchain.oldSwapchainCounter = INFLIGHTFRAMES.int * 2 | 55 swapchain.oldSwapchainCounter = INFLIGHTFRAMES.int * 2 |
| 57 | 56 |
| 57 # create depth buffer image+view if desired | |
| 58 if renderPass.depthBuffer: | |
| 59 swapchain.depthImage = svkCreate2DImage( | |
| 60 width = width, | |
| 61 height = height, | |
| 62 format = DEPTH_FORMAT, | |
| 63 usage = [VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT], | |
| 64 samples = renderPass.samples, | |
| 65 ) | |
| 66 let requirements = svkGetImageMemoryRequirements(swapchain.depthImage) | |
| 67 swapchain.depthMemory = svkAllocateMemory( | |
| 68 requirements.size, | |
| 69 BestMemory(mappable = false, filter = requirements.memoryTypes) | |
| 70 ) | |
| 71 checkVkResult vkBindImageMemory( | |
| 72 vulkan.device, | |
| 73 swapchain.depthImage, | |
| 74 swapchain.depthMemory, | |
| 75 0, | |
| 76 ) | |
| 77 swapchain.depthImageView = svkCreate2DImageView( | |
| 78 image = swapchain.depthImage, | |
| 79 format = DEPTH_FORMAT, | |
| 80 aspect = VK_IMAGE_ASPECT_DEPTH_BIT | |
| 81 ) | |
| 82 | |
| 58 # create msaa image+view if desired | 83 # create msaa image+view if desired |
| 59 if samples != VK_SAMPLE_COUNT_1_BIT: | 84 if renderPass.samples != VK_SAMPLE_COUNT_1_BIT: |
| 60 swapchain.msaaImage = svkCreate2DImage( | 85 swapchain.msaaImage = svkCreate2DImage( |
| 61 width = width, | 86 width = width, |
| 62 height = height, | 87 height = height, |
| 63 format = format, | 88 format = SURFACE_FORMAT, |
| 64 usage = [VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT], | 89 usage = [VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT], |
| 65 samples = samples, | 90 samples = renderPass.samples, |
| 66 ) | 91 ) |
| 67 let requirements = svkGetImageMemoryRequirements(swapchain.msaaImage) | 92 let requirements = svkGetImageMemoryRequirements(swapchain.msaaImage) |
| 68 swapchain.msaaMemory = svkAllocateMemory( | 93 swapchain.msaaMemory = svkAllocateMemory( |
| 69 requirements.size, | 94 requirements.size, |
| 70 BestMemory(mappable = false, filter = requirements.memoryTypes) | 95 BestMemory(mappable = false, filter = requirements.memoryTypes) |
| 73 vulkan.device, | 98 vulkan.device, |
| 74 swapchain.msaaImage, | 99 swapchain.msaaImage, |
| 75 swapchain.msaaMemory, | 100 swapchain.msaaMemory, |
| 76 0, | 101 0, |
| 77 ) | 102 ) |
| 78 swapchain.msaaImageView = svkCreate2DImageView(swapchain.msaaImage, format) | 103 swapchain.msaaImageView = svkCreate2DImageView(image = swapchain.msaaImage, format = SURFACE_FORMAT) |
| 79 | 104 |
| 80 # create framebuffers | 105 # create framebuffers |
| 81 var actualNFramebuffers: uint32 | 106 var actualNFramebuffers: uint32 |
| 82 checkVkResult vkGetSwapchainImagesKHR(vulkan.device, swapchain.vk, addr(actualNFramebuffers), nil) | 107 checkVkResult vkGetSwapchainImagesKHR(vulkan.device, swapchain.vk, addr(actualNFramebuffers), nil) |
| 83 var framebuffers = newSeq[VkImage](actualNFramebuffers) | 108 var framebuffers = newSeq[VkImage](actualNFramebuffers) |
| 84 checkVkResult vkGetSwapchainImagesKHR(vulkan.device, swapchain.vk, addr(actualNFramebuffers), framebuffers.ToCPointer) | 109 checkVkResult vkGetSwapchainImagesKHR(vulkan.device, swapchain.vk, addr(actualNFramebuffers), framebuffers.ToCPointer) |
| 85 | 110 |
| 86 for framebuffer in framebuffers: | 111 for framebuffer in framebuffers: |
| 87 swapchain.framebufferViews.add svkCreate2DImageView(framebuffer, format) | 112 swapchain.framebufferViews.add svkCreate2DImageView(framebuffer, SURFACE_FORMAT) |
| 88 if samples == VK_SAMPLE_COUNT_1_BIT: | 113 var attachments: seq[VkImageView] |
| 89 swapchain.framebuffers.add svkCreateFramebuffer(renderPass, width, height, [swapchain.framebufferViews[^1]]) | 114 if renderPass.samples == VK_SAMPLE_COUNT_1_BIT: |
| 115 if renderPass.depthBuffer: | |
| 116 attachments = @[swapchain.framebufferViews[^1], swapchain.depthImageView] | |
| 117 else: | |
| 118 attachments = @[swapchain.framebufferViews[^1]] | |
| 90 else: | 119 else: |
| 91 swapchain.framebuffers.add svkCreateFramebuffer(renderPass, width, height, [swapchain.msaaImageView, swapchain.framebufferViews[^1]]) | 120 if renderPass.depthBuffer: |
| 121 attachments = @[swapchain.msaaImageView, swapchain.depthImageView, swapchain.framebufferViews[^1]] | |
| 122 else: | |
| 123 attachments = @[swapchain.msaaImageView, swapchain.framebufferViews[^1]] | |
| 124 | |
| 125 swapchain.framebuffers.add svkCreateFramebuffer( | |
| 126 renderpass = renderPass.vk, | |
| 127 width = width, | |
| 128 height = height, | |
| 129 attachments = attachments, | |
| 130 ) | |
| 92 | 131 |
| 93 # create sync primitives | 132 # create sync primitives |
| 94 for i in 0 ..< INFLIGHTFRAMES: | 133 for i in 0 ..< INFLIGHTFRAMES: |
| 95 swapchain.queueFinishedFence[i] = svkCreateFence(signaled = true) | 134 swapchain.queueFinishedFence[i] = svkCreateFence(signaled = true) |
| 96 swapchain.imageAvailableSemaphore[i] = svkCreateSemaphore() | 135 swapchain.imageAvailableSemaphore[i] = svkCreateSemaphore() |
| 113 | 152 |
| 114 return some(swapchain) | 153 return some(swapchain) |
| 115 | 154 |
| 116 proc DestroySwapchain*(swapchain: Swapchain) = | 155 proc DestroySwapchain*(swapchain: Swapchain) = |
| 117 | 156 |
| 118 if swapchain.samples != VK_SAMPLE_COUNT_1_BIT: | 157 if swapchain.msaaImage.Valid: |
| 119 vkDestroyImageView(vulkan.device, swapchain.msaaImageView, nil) | 158 vkDestroyImageView(vulkan.device, swapchain.msaaImageView, nil) |
| 120 vkDestroyImage(vulkan.device, swapchain.msaaImage, nil) | 159 vkDestroyImage(vulkan.device, swapchain.msaaImage, nil) |
| 121 vkFreeMemory(vulkan.device, swapchain.msaaMemory, nil) | 160 vkFreeMemory(vulkan.device, swapchain.msaaMemory, nil) |
| 122 | 161 |
| 162 if swapchain.depthImage.Valid: | |
| 163 vkDestroyImageView(vulkan.device, swapchain.depthImageView, nil) | |
| 164 vkDestroyImage(vulkan.device, swapchain.depthImage, nil) | |
| 165 vkFreeMemory(vulkan.device, swapchain.depthMemory, nil) | |
| 166 | |
| 123 for fence in swapchain.queueFinishedFence: | 167 for fence in swapchain.queueFinishedFence: |
| 124 vkDestroyFence(vulkan.device, fence, nil) | 168 vkDestroyFence(vulkan.device, fence, nil) |
| 125 | 169 |
| 126 for semaphore in swapchain.imageAvailableSemaphore: | 170 for semaphore in swapchain.imageAvailableSemaphore: |
| 127 vkDestroySemaphore(vulkan.device, semaphore, nil) | 171 vkDestroySemaphore(vulkan.device, semaphore, nil) |
| 137 | 181 |
| 138 vkDestroyCommandPool(vulkan.device, swapchain.commandBufferPool, nil) | 182 vkDestroyCommandPool(vulkan.device, swapchain.commandBufferPool, nil) |
| 139 | 183 |
| 140 vkDestroySwapchainKHR(vulkan.device, swapchain.vk, nil) | 184 vkDestroySwapchainKHR(vulkan.device, swapchain.vk, nil) |
| 141 | 185 |
| 142 proc TryAcquireNextImage(swapchain: var Swapchain): Option[VkFramebuffer] = | 186 proc TryAcquireNextImage(swapchain: Swapchain): Option[VkFramebuffer] = |
| 143 if not swapchain.queueFinishedFence[swapchain.currentFiF].Await(100_000_000): | 187 if not swapchain.queueFinishedFence[swapchain.currentFiF].Await(100_000_000): |
| 144 return none(VkFramebuffer) | 188 return none(VkFramebuffer) |
| 145 | 189 |
| 146 let nextImageResult = vkAcquireNextImageKHR( | 190 let nextImageResult = vkAcquireNextImageKHR( |
| 147 vulkan.device, | 191 vulkan.device, |
| 156 | 200 |
| 157 if nextImageResult != VK_SUCCESS: | 201 if nextImageResult != VK_SUCCESS: |
| 158 return none(VkFramebuffer) | 202 return none(VkFramebuffer) |
| 159 return some(swapchain.framebuffers[swapchain.currentFramebufferIndex]) | 203 return some(swapchain.framebuffers[swapchain.currentFramebufferIndex]) |
| 160 | 204 |
| 161 proc Swap(swapchain: var Swapchain, commandBuffer: VkCommandBuffer): bool = | 205 proc Swap(swapchain: Swapchain, commandBuffer: VkCommandBuffer): bool = |
| 162 var | 206 var |
| 163 waitStage = VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) | 207 waitStage = VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) |
| 164 submitInfo = VkSubmitInfo( | 208 submitInfo = VkSubmitInfo( |
| 165 sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, | 209 sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, |
| 166 waitSemaphoreCount: 1, | 210 waitSemaphoreCount: 1, |
| 190 let presentResult = vkQueuePresentKHR(vulkan.graphicsQueue, addr(presentInfo)) | 234 let presentResult = vkQueuePresentKHR(vulkan.graphicsQueue, addr(presentInfo)) |
| 191 | 235 |
| 192 if swapchain.oldSwapchain != nil: | 236 if swapchain.oldSwapchain != nil: |
| 193 dec swapchain.oldSwapchainCounter | 237 dec swapchain.oldSwapchainCounter |
| 194 if swapchain.oldSwapchainCounter <= 0: | 238 if swapchain.oldSwapchainCounter <= 0: |
| 195 DestroySwapchain(swapchain.oldSwapchain[]) | 239 DestroySwapchain(swapchain.oldSwapchain) |
| 196 swapchain.oldSwapchain = nil | 240 swapchain.oldSwapchain = nil |
| 197 | 241 |
| 198 if presentResult != VK_SUCCESS: | 242 if presentResult != VK_SUCCESS: |
| 199 return false | 243 return false |
| 200 | 244 |
| 201 swapchain.currentFiF = (uint32(swapchain.currentFiF) + 1) mod INFLIGHTFRAMES | 245 swapchain.currentFiF = (uint32(swapchain.currentFiF) + 1) mod INFLIGHTFRAMES |
| 202 return true | 246 return true |
| 203 | 247 |
| 204 proc Recreate(swapchain: Swapchain): Option[Swapchain] = | 248 proc Recreate(swapchain: Swapchain): Option[Swapchain] = |
| 205 var oldSwapchain = new Swapchain | |
| 206 oldSwapchain[] = swapchain | |
| 207 InitSwapchain( | 249 InitSwapchain( |
| 208 renderPass = swapchain.renderPass, | 250 renderPass = swapchain.renderPass, |
| 209 vSync = swapchain.vSync, | 251 vSync = swapchain.vSync, |
| 210 samples = swapchain.samples, | 252 oldSwapchain = swapchain, |
| 211 oldSwapchain = oldSwapchain, | 253 ) |
| 212 ) | 254 |
| 213 | 255 template WithNextFrame*(theSwapchain: var Swapchain, framebufferName, commandBufferName, body: untyped): untyped = |
| 214 template WithNextFrame*(swapchain: var Swapchain, framebufferName, commandBufferName, body: untyped): untyped = | 256 var maybeFramebuffer = TryAcquireNextImage(theSwapchain) |
| 215 var maybeFramebuffer = TryAcquireNextImage(swapchain) | |
| 216 if maybeFramebuffer.isSome: | 257 if maybeFramebuffer.isSome: |
| 217 block: | 258 block: |
| 218 let `framebufferName` {.inject.} = maybeFramebuffer.get | 259 let `framebufferName` {.inject.} = maybeFramebuffer.get |
| 219 let `commandBufferName` {.inject.} = swapchain.commandBuffers[swapchain.currentFiF] | 260 let `commandBufferName` {.inject.} = theSwapchain.commandBuffers[theSwapchain.currentFiF] |
| 220 let beginInfo = VkCommandBufferBeginInfo( | 261 let beginInfo = VkCommandBufferBeginInfo( |
| 221 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | 262 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, |
| 222 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), | 263 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), |
| 223 ) | 264 ) |
| 224 checkVkResult vkResetCommandBuffer(`commandBufferName`, VkCommandBufferResetFlags(0)) | 265 checkVkResult vkResetCommandBuffer(`commandBufferName`, VkCommandBufferResetFlags(0)) |
| 225 checkVkResult vkBeginCommandBuffer(`commandBufferName`, addr(beginInfo)) | 266 checkVkResult vkBeginCommandBuffer(`commandBufferName`, addr(beginInfo)) |
| 226 | 267 |
| 227 body | 268 body |
| 228 | 269 |
| 229 checkVkResult vkEndCommandBuffer(`commandBufferName`) | 270 checkVkResult vkEndCommandBuffer(`commandBufferName`) |
| 230 discard Swap(swapchain = swapchain, commandBuffer = `commandBufferName`) | 271 discard Swap(swapchain = theSwapchain, commandBuffer = `commandBufferName`) |
| 231 else: | 272 else: |
| 232 let maybeNewSwapchain = Recreate(swapchain) | 273 let maybeNewSwapchain = Recreate(theSwapchain) |
| 233 if maybeNewSwapchain.isSome: | 274 if maybeNewSwapchain.isSome: |
| 234 swapchain = maybeNewSwapchain.get | 275 theSwapchain = maybeNewSwapchain.get |
| 235 | 276 |
