comparison semiconginev2/old/vulkan/swapchain.nim @ 1218:56781cc0fc7c compiletime-tests

did: renamge main package
author sam <sam@basx.dev>
date Wed, 17 Jul 2024 21:01:37 +0700
parents semicongine/old/vulkan/swapchain.nim@397c681f9c0c
children
comparison
equal deleted inserted replaced
1217:f819a874058f 1218:56781cc0fc7c
1 import std/options
2 import std/strformat
3 import std/logging
4
5 import ../core
6 import ./device
7 import ./physicaldevice
8 import ./image
9 import ./framebuffer
10 import ./syncing
11
12 type
13 Swapchain* = object
14 device*: Device
15 vk*: VkSwapchainKHR
16 dimension*: TVec2[uint32]
17 nFramebuffers*: uint32
18 currentInFlight*: int
19 currentFramebufferIndex: uint32
20 samples: VkSampleCountFlagBits
21 colorImage: VulkanImage
22 colorImageView: ImageView
23 framebufferViews*: seq[ImageView]
24 framebuffers*: seq[Framebuffer]
25 queueFinishedFence*: seq[Fence]
26 imageAvailableSemaphore*: seq[Semaphore]
27 renderFinishedSemaphore*: seq[Semaphore]
28 # required for recreation:
29 renderPass: VkRenderPass
30 surfaceFormat: VkSurfaceFormatKHR
31 inFlightFrames*: int
32 presentQueue: Queue
33 vSync: bool
34
35
36 proc CreateSwapchain*(
37 device: Device,
38 renderPass: VkRenderPass,
39 surfaceFormat: VkSurfaceFormatKHR,
40 inFlightFrames: int,
41 samples: VkSampleCountFlagBits,
42 desiredFramebufferCount = 3'u32,
43 oldSwapchain = VkSwapchainKHR(0),
44 vSync = false,
45 ): Option[Swapchain] =
46 assert device.vk.Valid
47 assert device.physicalDevice.vk.Valid
48 assert renderPass.Valid
49 assert inFlightFrames > 0
50
51 var capabilities = device.physicalDevice.GetSurfaceCapabilities()
52 if capabilities.currentExtent.width == 0 or capabilities.currentExtent.height == 0:
53 return none(Swapchain)
54
55 var minFramebufferCount = desiredFramebufferCount
56
57 # following is according to vulkan specs
58 minFramebufferCount = max(minFramebufferCount, capabilities.minImageCount)
59 if capabilities.maxImageCount != 0:
60 minFramebufferCount = min(minFramebufferCount, capabilities.maxImageCount)
61 let hasTripleBuffering = VK_PRESENT_MODE_MAILBOX_KHR in device.physicalDevice.GetSurfacePresentModes()
62 var createInfo = VkSwapchainCreateInfoKHR(
63 sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
64 surface: device.physicalDevice.surface,
65 minImageCount: minFramebufferCount,
66 imageFormat: surfaceFormat.format,
67 imageColorSpace: surfaceFormat.colorSpace,
68 imageExtent: capabilities.currentExtent,
69 imageArrayLayers: 1,
70 imageUsage: toBits [VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT],
71 # VK_SHARING_MODE_CONCURRENT no supported currently
72 imageSharingMode: VK_SHARING_MODE_EXCLUSIVE,
73 preTransform: capabilities.currentTransform,
74 compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, # only used for blending with other windows, can be opaque
75 presentMode: if (vSync or not hasTripleBuffering): VK_PRESENT_MODE_FIFO_KHR else: VK_PRESENT_MODE_MAILBOX_KHR,
76 clipped: true,
77 oldSwapchain: oldSwapchain,
78 )
79 var
80 swapchain = Swapchain(
81 device: device,
82 surfaceFormat: surfaceFormat,
83 dimension: TVec2[uint32]([capabilities.currentExtent.width, capabilities.currentExtent.height]),
84 inFlightFrames: inFlightFrames,
85 renderPass: renderPass,
86 vSync: vSync,
87 samples: samples,
88 )
89
90 if samples != VK_SAMPLE_COUNT_1_BIT:
91 swapchain.colorImage = device.CreateImage(
92 width = capabilities.currentExtent.width,
93 height = capabilities.currentExtent.height,
94 depth = 4,
95 samples = samples,
96 format = surfaceFormat.format,
97 usage = [VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT],
98 )
99 swapchain.colorImageView = swapchain.colorImage.CreateImageView()
100
101 if device.vk.vkCreateSwapchainKHR(addr createInfo, nil, addr swapchain.vk) == VK_SUCCESS:
102
103 checkVkResult device.vk.vkGetSwapchainImagesKHR(swapchain.vk, addr swapchain.nFramebuffers, nil)
104 var framebuffers = newSeq[VkImage](swapchain.nFramebuffers)
105 checkVkResult device.vk.vkGetSwapchainImagesKHR(swapchain.vk, addr swapchain.nFramebuffers, framebuffers.ToCPointer)
106 for framebuffer in framebuffers:
107 let framebufferView = VulkanImage(vk: framebuffer, format: surfaceFormat.format, device: device).CreateImageView()
108 swapchain.framebufferViews.add framebufferView
109 if samples == VK_SAMPLE_COUNT_1_BIT:
110 swapchain.framebuffers.add device.CreateFramebuffer(renderPass, [framebufferView], swapchain.dimension)
111 else:
112 swapchain.framebuffers.add device.CreateFramebuffer(renderPass, [swapchain.colorImageView, framebufferView], swapchain.dimension)
113 for i in 0 ..< swapchain.inFlightFrames:
114 swapchain.queueFinishedFence.add device.CreateFence()
115 swapchain.imageAvailableSemaphore.add device.CreateSemaphore()
116 swapchain.renderFinishedSemaphore.add device.CreateSemaphore()
117 debug &"Created swapchain with: {swapchain.nFramebuffers} framebuffers, {inFlightFrames} in-flight frames, {swapchain.dimension.x}x{swapchain.dimension.y}"
118 assert device.FirstPresentationQueue().isSome, "No present queue found"
119 swapchain.presentQueue = device.FirstPresentationQueue().get
120
121 result = some(swapchain)
122 else:
123 result = none(Swapchain)
124
125 proc CurrentFramebuffer*(swapchain: Swapchain): Framebuffer =
126 assert swapchain.device.vk.Valid
127 assert swapchain.vk.Valid
128 swapchain.framebuffers[swapchain.currentFramebufferIndex]
129
130 proc AcquireNextFrame*(swapchain: var Swapchain): bool =
131 assert swapchain.device.vk.Valid
132 assert swapchain.vk.Valid
133
134 swapchain.queueFinishedFence[swapchain.currentInFlight].Await()
135
136 let nextImageResult = swapchain.device.vk.vkAcquireNextImageKHR(
137 swapchain.vk,
138 high(uint64),
139 swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk,
140 VkFence(0),
141 addr swapchain.currentFramebufferIndex,
142 )
143
144 swapchain.queueFinishedFence[swapchain.currentInFlight].Reset()
145
146 return nextImageResult == VK_SUCCESS
147
148 proc Swap*(swapchain: var Swapchain, queue: Queue, commandBuffer: VkCommandBuffer): bool =
149 assert swapchain.device.vk.Valid
150 assert swapchain.vk.Valid
151 assert queue.vk.Valid
152
153 var
154 waitSemaphores = [swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk]
155 waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)]
156 submitInfo = VkSubmitInfo(
157 sType: VK_STRUCTURE_TYPE_SUBMIT_INFO,
158 waitSemaphoreCount: 1,
159 pWaitSemaphores: waitSemaphores.ToCPointer,
160 pWaitDstStageMask: waitStages.ToCPointer,
161 commandBufferCount: 1,
162 pCommandBuffers: addr commandBuffer,
163 signalSemaphoreCount: 1,
164 pSignalSemaphores: addr swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk,
165 )
166 checkVkResult queue.vk.vkQueueSubmit(
167 submitCount = 1,
168 pSubmits = addr submitInfo,
169 fence = swapchain.queueFinishedFence[swapchain.currentInFlight].vk
170 )
171
172 var presentInfo = VkPresentInfoKHR(
173 sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
174 waitSemaphoreCount: 1,
175 pWaitSemaphores: addr swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk,
176 swapchainCount: 1,
177 pSwapchains: addr swapchain.vk,
178 pImageIndices: addr swapchain.currentFramebufferIndex,
179 pResults: nil,
180 )
181 let presentResult = vkQueuePresentKHR(swapchain.presentQueue.vk, addr presentInfo)
182 if presentResult != VK_SUCCESS:
183 return false
184
185 return true
186
187
188 proc Destroy*(swapchain: var Swapchain) =
189 assert swapchain.vk.Valid
190
191 for imageview in swapchain.framebufferViews.mitems:
192 assert imageview.vk.Valid
193 imageview.Destroy()
194 for framebuffer in swapchain.framebuffers.mitems:
195 assert framebuffer.vk.Valid
196 framebuffer.Destroy()
197 if swapchain.colorImage.vk.Valid:
198 swapchain.colorImage.Destroy()
199 if swapchain.colorImageView.vk.Valid:
200 swapchain.colorImageView.Destroy()
201 for i in 0 ..< swapchain.inFlightFrames:
202 assert swapchain.queueFinishedFence[i].vk.Valid
203 assert swapchain.imageAvailableSemaphore[i].vk.Valid
204 assert swapchain.renderFinishedSemaphore[i].vk.Valid
205 swapchain.queueFinishedFence[i].Destroy()
206 swapchain.imageAvailableSemaphore[i].Destroy()
207 swapchain.renderFinishedSemaphore[i].Destroy()
208
209 swapchain.device.vk.vkDestroySwapchainKHR(swapchain.vk, nil)
210 swapchain.vk.Reset()
211
212 proc Recreate*(swapchain: var Swapchain): Option[Swapchain] =
213 assert swapchain.vk.Valid
214 assert swapchain.device.vk.Valid
215 result = CreateSwapchain(
216 device = swapchain.device,
217 renderPass = swapchain.renderPass,
218 surfaceFormat = swapchain.surfaceFormat,
219 desiredFramebufferCount = swapchain.nFramebuffers,
220 inFlightFrames = swapchain.inFlightFrames,
221 oldSwapchain = swapchain.vk,
222 vSync = swapchain.vSync,
223 samples = swapchain.samples,
224 )