Mercurial > games > semicongine
comparison src/engine.nim @ 4:af9183acb173
did: refactor, add resizing, proper cleanup
author | Sam <sam@basx.dev> |
---|---|
date | Tue, 20 Dec 2022 00:28:05 +0700 |
parents | 213fdf8d31dd |
children | 4ed9cb098315 |
comparison
equal
deleted
inserted
replaced
3:5d54ef652619 | 4:af9183acb173 |
---|---|
1 import std/typetraits | |
1 import std/strformat | 2 import std/strformat |
2 import std/enumerate | 3 import std/enumerate |
3 import std/logging | 4 import std/logging |
4 | 5 |
5 | 6 |
44 x11/x | 45 x11/x |
45 | 46 |
46 const VULKAN_VERSION = VK_MAKE_API_VERSION(0'u32, 1'u32, 2'u32, 0'u32) | 47 const VULKAN_VERSION = VK_MAKE_API_VERSION(0'u32, 1'u32, 2'u32, 0'u32) |
47 | 48 |
48 type | 49 type |
49 GraphicsPipeline = object | 50 Device = object |
51 physicalDevice: PhysicalDevice | |
52 graphicsQueueFamily: uint32 | |
53 presentationQueueFamily: uint32 | |
54 device: VkDevice | |
55 graphicsQueue: VkQueue | |
56 presentationQueue: VkQueue | |
57 Swapchain = object | |
58 swapchain: VkSwapchainKHR | |
59 images: seq[VkImage] | |
60 imageviews: seq[VkImageView] | |
61 RenderPipeline = object | |
50 shaderStages*: seq[VkPipelineShaderStageCreateInfo] | 62 shaderStages*: seq[VkPipelineShaderStageCreateInfo] |
51 layout*: VkPipelineLayout | 63 layout*: VkPipelineLayout |
52 renderPass*: VkRenderPass | |
53 pipeline*: VkPipeline | 64 pipeline*: VkPipeline |
65 viewport*: VkViewport | |
66 scissor*: VkRect2D | |
54 QueueFamily = object | 67 QueueFamily = object |
55 properties*: VkQueueFamilyProperties | 68 properties*: VkQueueFamilyProperties |
56 hasSurfaceSupport*: bool | 69 hasSurfaceSupport*: bool |
57 PhysicalDevice = object | 70 PhysicalDevice = object |
58 device*: VkPhysicalDevice | 71 device*: VkPhysicalDevice |
65 presentModes: seq[VkPresentModeKHR] | 78 presentModes: seq[VkPresentModeKHR] |
66 Vulkan* = object | 79 Vulkan* = object |
67 debugMessenger: VkDebugUtilsMessengerEXT | 80 debugMessenger: VkDebugUtilsMessengerEXT |
68 instance*: VkInstance | 81 instance*: VkInstance |
69 deviceList*: seq[PhysicalDevice] | 82 deviceList*: seq[PhysicalDevice] |
70 activePhysicalDevice*: PhysicalDevice | 83 device*: Device |
71 graphicsQueueFamily*: uint32 | |
72 graphicsQueue*: VkQueue | |
73 presentationQueueFamily*: uint32 | |
74 presentationQueue*: VkQueue | |
75 device*: VkDevice | |
76 surface*: VkSurfaceKHR | 84 surface*: VkSurfaceKHR |
77 selectedSurfaceFormat: VkSurfaceFormatKHR | 85 surfaceFormat: VkSurfaceFormatKHR |
78 selectedPresentationMode: VkPresentModeKHR | |
79 frameDimension: VkExtent2D | 86 frameDimension: VkExtent2D |
80 swapChain: VkSwapchainKHR | 87 swapchain: Swapchain |
81 swapImages: seq[VkImage] | 88 framebuffers: seq[VkFramebuffer] |
82 swapFramebuffers: seq[VkFramebuffer] | 89 renderPass*: VkRenderPass |
83 swapImageViews: seq[VkImageView] | 90 pipeline*: RenderPipeline |
84 pipeline*: GraphicsPipeline | |
85 commandPool*: VkCommandPool | 91 commandPool*: VkCommandPool |
86 commandBuffers*: array[MAX_FRAMES_IN_FLIGHT, VkCommandBuffer] | 92 commandBuffers*: array[MAX_FRAMES_IN_FLIGHT, VkCommandBuffer] |
87 viewport*: VkViewport | |
88 scissor*: VkRect2D | |
89 imageAvailableSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] | 93 imageAvailableSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] |
90 renderFinishedSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] | 94 renderFinishedSemaphores*: array[MAX_FRAMES_IN_FLIGHT, VkSemaphore] |
91 inFlightFences*: array[MAX_FRAMES_IN_FLIGHT, VkFence] | 95 inFlightFences*: array[MAX_FRAMES_IN_FLIGHT, VkFence] |
92 Engine* = object | 96 Window* = object |
93 display*: PDisplay | 97 display*: PDisplay |
94 window*: x.Window | 98 window*: x.Window |
99 Engine* = object | |
95 vulkan*: Vulkan | 100 vulkan*: Vulkan |
101 window: Window | |
96 | 102 |
97 | 103 |
98 proc getAllPhysicalDevices(instance: VkInstance, surface: VkSurfaceKHR): seq[PhysicalDevice] = | 104 proc getAllPhysicalDevices(instance: VkInstance, surface: VkSurfaceKHR): seq[PhysicalDevice] = |
99 for vulkanPhysicalDevice in getVulkanPhysicalDevices(instance): | 105 for vulkanPhysicalDevice in getVulkanPhysicalDevices(instance): |
100 var device = PhysicalDevice(device: vulkanPhysicalDevice, extensions: getDeviceExtensions(vulkanPhysicalDevice)) | 106 var device = PhysicalDevice(device: vulkanPhysicalDevice, extensions: getDeviceExtensions(vulkanPhysicalDevice)) |
129 | 135 |
130 for (device, graphicsQueueFamily, presentationQueueFamily) in result: | 136 for (device, graphicsQueueFamily, presentationQueueFamily) in result: |
131 debug(&"Viable device: {cleanString(device.properties.deviceName)} (graphics queue family {graphicsQueueFamily}, presentation queue family {presentationQueueFamily})") | 137 debug(&"Viable device: {cleanString(device.properties.deviceName)} (graphics queue family {graphicsQueueFamily}, presentation queue family {presentationQueueFamily})") |
132 | 138 |
133 | 139 |
134 proc getFrameDimension(display: PDisplay, window: Window, capabilities: VkSurfaceCapabilitiesKHR): VkExtent2D = | 140 proc getFrameDimension(window: Window, capabilities: VkSurfaceCapabilitiesKHR): VkExtent2D = |
135 if capabilities.currentExtent.width != high(uint32): | 141 if capabilities.currentExtent.width != high(uint32): |
136 return capabilities.currentExtent | 142 return capabilities.currentExtent |
137 else: | 143 else: |
138 let (width, height) = xlibFramebufferSize(display, window) | 144 let (width, height) = window.display.xlibFramebufferSize(window.window) |
139 return VkExtent2D( | 145 return VkExtent2D( |
140 width: min(max(uint32(width), capabilities.minImageExtent.width), capabilities.maxImageExtent.width), | 146 width: min(max(uint32(width), capabilities.minImageExtent.width), capabilities.maxImageExtent.width), |
141 height: min(max(uint32(height), capabilities.minImageExtent.height), capabilities.maxImageExtent.height), | 147 height: min(max(uint32(height), capabilities.minImageExtent.height), capabilities.maxImageExtent.height), |
142 ) | 148 ) |
143 | 149 |
144 proc createVulkanSurface(instance: VkInstance, display: PDisplay, window: Window): VkSurfaceKHR = | 150 proc setupDebugLog(instance: VkInstance): VkDebugUtilsMessengerEXT = |
151 var createInfo = VkDebugUtilsMessengerCreateInfoEXT( | |
152 sType: VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, | |
153 messageSeverity: VkDebugUtilsMessageSeverityFlagsEXT( | |
154 ord(VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) or | |
155 ord(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) or | |
156 ord(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) | |
157 ), | |
158 messageType: VkDebugUtilsMessageTypeFlagsEXT( | |
159 ord(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) or | |
160 ord(VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) or | |
161 ord(VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) | |
162 ), | |
163 pfnUserCallback: debugCallback, | |
164 pUserData: nil, | |
165 ) | |
166 checkVkResult instance.vkCreateDebugUtilsMessengerEXT(addr(createInfo), nil, addr(result)) | |
167 | |
168 proc createVulkanSurface(instance: VkInstance, window: Window): VkSurfaceKHR = | |
145 var surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR( | 169 var surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR( |
146 sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, | 170 sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, |
147 dpy: display, | 171 dpy: window.display, |
148 window: window, | 172 window: window.window, |
149 ) | 173 ) |
150 checkVkResult vkCreateXlibSurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) | 174 checkVkResult vkCreateXlibSurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) |
151 | 175 |
152 proc setupVulkanDeviceAndQueues(instance: VkInstance, surface: VkSurfaceKHR): (PhysicalDevice, uint32, uint32, VkDevice, VkQueue, VkQueue) = | 176 proc setupVulkanDeviceAndQueues(instance: VkInstance, surface: VkSurfaceKHR): Device = |
153 let usableDevices = instance.getAllPhysicalDevices(surface).filterForDevice() | 177 let usableDevices = instance.getAllPhysicalDevices(surface).filterForDevice() |
154 if len(usableDevices) == 0: | 178 if len(usableDevices) == 0: |
155 raise newException(Exception, "No suitable graphics device found") | 179 raise newException(Exception, "No suitable graphics device found") |
156 result[0] = usableDevices[0][0] | 180 result.physicalDevice = usableDevices[0][0] |
157 result[1] = usableDevices[0][1] | 181 result.graphicsQueueFamily = usableDevices[0][1] |
158 result[2] = usableDevices[0][2] | 182 result.presentationQueueFamily = usableDevices[0][2] |
159 | 183 |
160 debug(&"Chose device {cleanString(result[0].properties.deviceName)}") | 184 debug(&"Chose device {cleanString(result.physicalDevice.properties.deviceName)}") |
161 | 185 |
162 (result[3], result[4], result[5]) = getVulcanDevice( | 186 (result.device, result.graphicsQueue, result.presentationQueue) = getVulcanDevice( |
163 result[0].device, | 187 result.physicalDevice.device, |
164 result[0].features, | 188 result.physicalDevice.features, |
165 result[1], | 189 result.graphicsQueueFamily, |
166 result[2], | 190 result.presentationQueueFamily, |
167 ) | 191 ) |
168 | 192 |
169 proc igniteEngine*(): Engine = | 193 proc setupSwapChain(device: VkDevice, physicalDevice: PhysicalDevice, surface: VkSurfaceKHR, dimension: VkExtent2D, surfaceFormat: VkSurfaceFormatKHR): Swapchain = |
170 | 194 var selectedPresentationMode = getPresentMode(physicalDevice.presentModes) |
171 # init X11 window | |
172 (result.display, result.window) = xlibInit() | |
173 | |
174 # create vulkan instance | |
175 vkLoad1_0() | |
176 vkLoad1_1() | |
177 vkLoad1_2() | |
178 result.vulkan.instance = createVulkanInstance(VULKAN_VERSION) | |
179 when ENABLEVULKANVALIDATIONLAYERS: | |
180 var createInfo = VkDebugUtilsMessengerCreateInfoEXT( | |
181 sType: VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, | |
182 messageSeverity: VkDebugUtilsMessageSeverityFlagsEXT( | |
183 ord(VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) or | |
184 ord(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) or | |
185 ord(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) | |
186 ), | |
187 messageType: VkDebugUtilsMessageTypeFlagsEXT( | |
188 ord(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) or | |
189 ord(VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) or | |
190 ord(VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) | |
191 ), | |
192 pfnUserCallback: debugCallback, | |
193 pUserData: nil, | |
194 ) | |
195 checkVkResult vkCreateDebugUtilsMessengerEXT(result.vulkan.instance, addr(createInfo), nil, addr(result.vulkan.debugMessenger)) | |
196 | |
197 result.vulkan.surface = result.vulkan.instance.createVulkanSurface(result.display, result.window) | |
198 | |
199 ( | |
200 result.vulkan.activePhysicalDevice, | |
201 result.vulkan.graphicsQueueFamily, | |
202 result.vulkan.presentationQueueFamily, | |
203 result.vulkan.device, | |
204 result.vulkan.graphicsQueue, | |
205 result.vulkan.presentationQueue | |
206 ) = result.vulkan.instance.setupVulkanDeviceAndQueues(result.vulkan.surface) | |
207 | |
208 # determine surface format for swapchain | |
209 let usableSurfaceFormats = filterForSurfaceFormat(result.vulkan.activePhysicalDevice.surfaceFormats) | |
210 if len(usableSurfaceFormats) == 0: | |
211 raise newException(Exception, "No suitable surface formats found") | |
212 result.vulkan.selectedSurfaceFormat = usableSurfaceFormats[0] | |
213 result.vulkan.selectedPresentationMode = getPresentMode(result.vulkan.activePhysicalDevice.presentModes) | |
214 result.vulkan.frameDimension = result.display.getFrameDimension(result.window, result.vulkan.activePhysicalDevice.surfaceCapabilities) | |
215 | |
216 # setup swapchain | 195 # setup swapchain |
217 var swapchainCreateInfo = VkSwapchainCreateInfoKHR( | 196 var swapchainCreateInfo = VkSwapchainCreateInfoKHR( |
218 sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, | 197 sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, |
219 surface: result.vulkan.surface, | 198 surface: surface, |
220 minImageCount: max(result.vulkan.activePhysicalDevice.surfaceCapabilities.minImageCount + 1, result.vulkan.activePhysicalDevice.surfaceCapabilities.maxImageCount), | 199 minImageCount: max(physicalDevice.surfaceCapabilities.minImageCount + 1, physicalDevice.surfaceCapabilities.maxImageCount), |
221 imageFormat: result.vulkan.selectedSurfaceFormat.format, | 200 imageFormat: surfaceFormat.format, |
222 imageColorSpace: result.vulkan.selectedSurfaceFormat.colorSpace, | 201 imageColorSpace: surfaceFormat.colorSpace, |
223 imageExtent: result.vulkan.frameDimension, | 202 imageExtent: dimension, |
224 imageArrayLayers: 1, | 203 imageArrayLayers: 1, |
225 imageUsage: VkImageUsageFlags(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT), | 204 imageUsage: VkImageUsageFlags(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT), |
226 # VK_SHARING_MODE_CONCURRENT no supported (i.e cannot use different queue families for drawing to swap surface?) | 205 # VK_SHARING_MODE_CONCURRENT no supported (i.e cannot use different queue families for drawing to swap surface?) |
227 imageSharingMode: VK_SHARING_MODE_EXCLUSIVE, | 206 imageSharingMode: VK_SHARING_MODE_EXCLUSIVE, |
228 preTransform: result.vulkan.activePhysicalDevice.surfaceCapabilities.currentTransform, | 207 preTransform: physicalDevice.surfaceCapabilities.currentTransform, |
229 compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, | 208 compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, |
230 presentMode: result.vulkan.selectedPresentationMode, | 209 presentMode: selectedPresentationMode, |
231 clipped: VK_TRUE, | 210 clipped: VK_TRUE, |
232 oldSwapchain: VkSwapchainKHR(0), | 211 oldSwapchain: VkSwapchainKHR(0), |
233 ) | 212 ) |
234 checkVkResult result.vulkan.device.vkCreateSwapchainKHR(addr(swapchainCreateInfo), nil, addr(result.vulkan.swapChain)) | 213 checkVkResult device.vkCreateSwapchainKHR(addr(swapchainCreateInfo), nil, addr(result.swapchain)) |
235 result.vulkan.swapImages = result.vulkan.device.getSwapChainImages(result.vulkan.swapChain) | 214 result.images = device.getSwapChainImages(result.swapchain) |
236 | 215 |
237 # setup swapchian image views | 216 # setup swapchian image views |
238 result.vulkan.swapImageViews = newSeq[VkImageView](result.vulkan.swapImages.len) | 217 |
239 for i, image in enumerate(result.vulkan.swapImages): | 218 result.imageviews = newSeq[VkImageView](result.images.len) |
219 for i, image in enumerate(result.images): | |
240 var imageViewCreateInfo = VkImageViewCreateInfo( | 220 var imageViewCreateInfo = VkImageViewCreateInfo( |
241 sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 221 sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
242 image: image, | 222 image: image, |
243 viewType: VK_IMAGE_VIEW_TYPE_2D, | 223 viewType: VK_IMAGE_VIEW_TYPE_2D, |
244 format: result.vulkan.selectedSurfaceFormat.format, | 224 format: surfaceFormat.format, |
245 components: VkComponentMapping( | 225 components: VkComponentMapping( |
246 r: VK_COMPONENT_SWIZZLE_IDENTITY, | 226 r: VK_COMPONENT_SWIZZLE_IDENTITY, |
247 g: VK_COMPONENT_SWIZZLE_IDENTITY, | 227 g: VK_COMPONENT_SWIZZLE_IDENTITY, |
248 b: VK_COMPONENT_SWIZZLE_IDENTITY, | 228 b: VK_COMPONENT_SWIZZLE_IDENTITY, |
249 a: VK_COMPONENT_SWIZZLE_IDENTITY, | 229 a: VK_COMPONENT_SWIZZLE_IDENTITY, |
254 levelCount: 1, | 234 levelCount: 1, |
255 baseArrayLayer: 0, | 235 baseArrayLayer: 0, |
256 layerCount: 1, | 236 layerCount: 1, |
257 ), | 237 ), |
258 ) | 238 ) |
259 checkVkResult result.vulkan.device.vkCreateImageView(addr(imageViewCreateInfo), nil, addr(result.vulkan.swapImageViews[i])) | 239 checkVkResult device.vkCreateImageView(addr(imageViewCreateInfo), nil, addr(result.imageviews[i])) |
260 | 240 |
261 # init shader system | 241 proc setupRenderPass(device: VkDevice, format: VkFormat): VkRenderPass = |
262 checkGlslangResult glslang_initialize_process() | |
263 | |
264 # load shaders | |
265 result.vulkan.pipeline.shaderStages.add(result.vulkan.device.createShaderStage(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderCode)) | |
266 result.vulkan.pipeline.shaderStages.add(result.vulkan.device.createShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderCode)) | |
267 | |
268 # setup render passes | |
269 var | 242 var |
270 colorAttachment = VkAttachmentDescription( | 243 colorAttachment = VkAttachmentDescription( |
271 format: result.vulkan.selectedSurfaceFormat.format, | 244 format: format, |
272 samples: VK_SAMPLE_COUNT_1_BIT, | 245 samples: VK_SAMPLE_COUNT_1_BIT, |
273 loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, | 246 loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, |
274 storeOp: VK_ATTACHMENT_STORE_OP_STORE, | 247 storeOp: VK_ATTACHMENT_STORE_OP_STORE, |
275 stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE, | 248 stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
276 stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE, | 249 stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE, |
301 subpassCount: 1, | 274 subpassCount: 1, |
302 pSubpasses: addr(subpass), | 275 pSubpasses: addr(subpass), |
303 dependencyCount: 1, | 276 dependencyCount: 1, |
304 pDependencies: addr(dependency), | 277 pDependencies: addr(dependency), |
305 ) | 278 ) |
306 checkVkResult result.vulkan.device.vkCreateRenderPass(addr(renderPassCreateInfo), nil, addr(result.vulkan.pipeline.renderPass)) | 279 checkVkResult device.vkCreateRenderPass(addr(renderPassCreateInfo), nil, addr(result)) |
307 | 280 |
308 # create graphis pipeline | 281 proc setupRenderPipeline(device: VkDevice, frameDimension: VkExtent2D, renderPass: VkRenderPass): RenderPipeline = |
309 | 282 # (seq[VkPipelineShaderStageCreateInfo], VkViewport, VkRect2D, VkPipelineLayout, VkPipeline) = |
283 | |
284 # load shaders | |
285 result.shaderStages.add(device.createShaderStage(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderCode)) | |
286 result.shaderStages.add(device.createShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderCode)) | |
287 | |
310 var | 288 var |
311 # define which parts can be dynamic (pipeline is fixed after setup) | 289 # define which parts can be dynamic (pipeline is fixed after setup) |
312 dynamicStates = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] | 290 dynamicStates = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] |
313 dynamicState = VkPipelineDynamicStateCreateInfo( | 291 dynamicState = VkPipelineDynamicStateCreateInfo( |
314 sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, | 292 sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, |
315 dynamicStateCount: uint32(dynamicStates.len), | 293 dynamicStateCount: uint32(dynamicStates.len), |
316 pDynamicStates: addr(dynamicStates[0]), | 294 pDynamicStates: addr(dynamicStates[0]), |
317 ) | 295 ) |
318 | |
319 # define input data format | 296 # define input data format |
320 vertexInputInfo = VkPipelineVertexInputStateCreateInfo( | 297 vertexInputInfo = VkPipelineVertexInputStateCreateInfo( |
321 sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | 298 sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, |
322 vertexBindingDescriptionCount: 0, | 299 vertexBindingDescriptionCount: 0, |
323 pVertexBindingDescriptions: nil, | 300 pVertexBindingDescriptions: nil, |
329 topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, | 306 topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, |
330 primitiveRestartEnable: VK_FALSE, | 307 primitiveRestartEnable: VK_FALSE, |
331 ) | 308 ) |
332 | 309 |
333 # setup viewport | 310 # setup viewport |
334 result.vulkan.viewport = VkViewport( | 311 result.viewport = VkViewport( |
335 x: 0.0, | 312 x: 0.0, |
336 y: 0.0, | 313 y: 0.0, |
337 width: (float) result.vulkan.frameDimension.width, | 314 width: (float) frameDimension.width, |
338 height: (float) result.vulkan.frameDimension.height, | 315 height: (float) frameDimension.height, |
339 minDepth: 0.0, | 316 minDepth: 0.0, |
340 maxDepth: 1.0, | 317 maxDepth: 1.0, |
341 ) | 318 ) |
342 result.vulkan.scissor = VkRect2D( | 319 result.scissor = VkRect2D( |
343 offset: VkOffset2D(x: 0, y: 0), | 320 offset: VkOffset2D(x: 0, y: 0), |
344 extent: result.vulkan.frameDimension | 321 extent: frameDimension |
345 ) | 322 ) |
346 var viewportState = VkPipelineViewportStateCreateInfo( | 323 var viewportState = VkPipelineViewportStateCreateInfo( |
347 sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, | 324 sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, |
348 viewportCount: 1, | 325 viewportCount: 1, |
349 pViewports: addr(result.vulkan.viewport), | 326 pViewports: addr(result.viewport), |
350 scissorCount: 1, | 327 scissorCount: 1, |
351 pScissors: addr(result.vulkan.scissor), | 328 pScissors: addr(result.scissor), |
352 ) | 329 ) |
353 | 330 |
354 # rasterizerization config | 331 # rasterizerization config |
355 var | 332 var |
356 rasterizer = VkPipelineRasterizationStateCreateInfo( | 333 rasterizer = VkPipelineRasterizationStateCreateInfo( |
405 setLayoutCount: 0, | 382 setLayoutCount: 0, |
406 pSetLayouts: nil, | 383 pSetLayouts: nil, |
407 pushConstantRangeCount: 0, | 384 pushConstantRangeCount: 0, |
408 pPushConstantRanges: nil, | 385 pPushConstantRanges: nil, |
409 ) | 386 ) |
410 checkVkResult result.vulkan.device.vkCreatePipelineLayout(addr(pipelineLayoutInfo), nil, addr(result.vulkan.pipeline.layout)) | 387 checkVkResult device.vkCreatePipelineLayout(addr(pipelineLayoutInfo), nil, addr(result.layout)) |
411 | 388 |
412 var pipelineInfo = VkGraphicsPipelineCreateInfo( | 389 var pipelineInfo = VkGraphicsPipelineCreateInfo( |
413 sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | 390 sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, |
414 stageCount: 2, | 391 stageCount: 2, |
415 pStages: addr(result.vulkan.pipeline.shaderStages[0]), | 392 pStages: addr(result.shaderStages[0]), |
416 pVertexInputState: addr(vertexInputInfo), | 393 pVertexInputState: addr(vertexInputInfo), |
417 pInputAssemblyState: addr(inputAssembly), | 394 pInputAssemblyState: addr(inputAssembly), |
418 pViewportState: addr(viewportState), | 395 pViewportState: addr(viewportState), |
419 pRasterizationState: addr(rasterizer), | 396 pRasterizationState: addr(rasterizer), |
420 pMultisampleState: addr(multisampling), | 397 pMultisampleState: addr(multisampling), |
421 pDepthStencilState: nil, | 398 pDepthStencilState: nil, |
422 pColorBlendState: addr(colorBlending), | 399 pColorBlendState: addr(colorBlending), |
423 pDynamicState: addr(dynamicState), | 400 pDynamicState: addr(dynamicState), |
424 layout: result.vulkan.pipeline.layout, | 401 layout: result.layout, |
425 renderPass: result.vulkan.pipeline.renderPass, | 402 renderPass: renderPass, |
426 subpass: 0, | 403 subpass: 0, |
427 basePipelineHandle: VkPipeline(0), | 404 basePipelineHandle: VkPipeline(0), |
428 basePipelineIndex: -1, | 405 basePipelineIndex: -1, |
429 ) | 406 ) |
430 checkVkResult result.vulkan.device.vkCreateGraphicsPipelines( | 407 checkVkResult device.vkCreateGraphicsPipelines( |
431 VkPipelineCache(0), | 408 VkPipelineCache(0), |
432 1, | 409 1, |
433 addr(pipelineInfo), | 410 addr(pipelineInfo), |
434 nil, | 411 nil, |
435 addr(result.vulkan.pipeline.pipeline) | 412 addr(result.pipeline) |
436 ) | 413 ) |
437 | 414 |
438 # set up framebuffers | 415 proc setupFramebuffers(device: VkDevice, swapchain: var Swapchain, renderPass: VkRenderPass, dimension: VkExtent2D): seq[VkFramebuffer] = |
439 result.vulkan.swapFramebuffers = newSeq[VkFramebuffer](result.vulkan.swapImages.len) | 416 result = newSeq[VkFramebuffer](swapchain.images.len) |
440 | 417 for i, imageview in enumerate(swapchain.imageviews): |
441 for i, imageview in enumerate(result.vulkan.swapImageViews): | |
442 var framebufferInfo = VkFramebufferCreateInfo( | 418 var framebufferInfo = VkFramebufferCreateInfo( |
443 sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, | 419 sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, |
444 renderPass: result.vulkan.pipeline.renderPass, | 420 renderPass: renderPass, |
445 attachmentCount: 1, | 421 attachmentCount: 1, |
446 pAttachments: addr(result.vulkan.swapImageViews[i]), | 422 pAttachments: addr(swapchain.imageviews[i]), |
447 width: result.vulkan.frameDimension.width, | 423 width: dimension.width, |
448 height: result.vulkan.frameDimension.height, | 424 height: dimension.height, |
449 layers: 1, | 425 layers: 1, |
450 ) | 426 ) |
451 checkVkResult result.vulkan.device.vkCreateFramebuffer(addr(framebufferInfo), nil, addr(result.vulkan.swapFramebuffers[i])) | 427 checkVkResult device.vkCreateFramebuffer(addr(framebufferInfo), nil, addr(result[i])) |
452 | 428 |
429 proc recreateSwapchain(vulkan: Vulkan): (Swapchain, seq[VkFramebuffer]) = | |
430 checkVkResult vulkan.device.device.vkDeviceWaitIdle() | |
431 for framebuffer in vulkan.framebuffers: | |
432 vulkan.device.device.vkDestroyFramebuffer(framebuffer, nil) | |
433 for imageview in vulkan.swapchain.imageviews: | |
434 vulkan.device.device.vkDestroyImageView(imageview, nil) | |
435 vulkan.device.device.vkDestroySwapchainKHR(vulkan.swapchain.swapchain, nil) | |
436 | |
437 result[0] = vulkan.device.device.setupSwapChain( | |
438 vulkan.device.physicalDevice, | |
439 vulkan.surface, | |
440 vulkan.frameDimension, | |
441 vulkan.surfaceFormat | |
442 ) | |
443 result[1] = vulkan.device.device.setupFramebuffers( | |
444 result[0], | |
445 vulkan.renderPass, | |
446 vulkan.frameDimension | |
447 ) | |
448 | |
449 # createFramebuffers(); | |
450 | |
451 | |
452 proc setupCommandBuffers(device: VkDevice, graphicsQueueFamily: uint32): (VkCommandPool, array[MAX_FRAMES_IN_FLIGHT, VkCommandBuffer]) = | |
453 # set up command buffer | 453 # set up command buffer |
454 var poolInfo = VkCommandPoolCreateInfo( | 454 var poolInfo = VkCommandPoolCreateInfo( |
455 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, | 455 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, |
456 flags: VkCommandPoolCreateFlags(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT), | 456 flags: VkCommandPoolCreateFlags(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT), |
457 queueFamilyIndex: result.vulkan.graphicsQueueFamily, | 457 queueFamilyIndex: graphicsQueueFamily, |
458 ) | 458 ) |
459 checkVkResult result.vulkan.device.vkCreateCommandPool(addr(poolInfo), nil, addr(result.vulkan.commandPool)) | 459 checkVkResult device.vkCreateCommandPool(addr(poolInfo), nil, addr(result[0])) |
460 | 460 |
461 var allocInfo = VkCommandBufferAllocateInfo( | 461 var allocInfo = VkCommandBufferAllocateInfo( |
462 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | 462 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, |
463 commandPool: result.vulkan.commandPool, | 463 commandPool: result[0], |
464 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, | 464 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, |
465 commandBufferCount: result.vulkan.commandBuffers.len.uint32, | 465 commandBufferCount: result[1].len.uint32, |
466 ) | 466 ) |
467 checkVkResult result.vulkan.device.vkAllocateCommandBuffers(addr(allocInfo), addr(result.vulkan.commandBuffers[0])) | 467 checkVkResult device.vkAllocateCommandBuffers(addr(allocInfo), addr(result[1][0])) |
468 | 468 |
469 # create semaphores for syncing rendering | 469 proc setupSyncPrimitives(device: VkDevice): ( |
470 array[MAX_FRAMES_IN_FLIGHT, VkSemaphore], | |
471 array[MAX_FRAMES_IN_FLIGHT, VkSemaphore], | |
472 array[MAX_FRAMES_IN_FLIGHT, VkFence], | |
473 ) = | |
470 var semaphoreInfo = VkSemaphoreCreateInfo(sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO) | 474 var semaphoreInfo = VkSemaphoreCreateInfo(sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO) |
471 var fenceInfo = VkFenceCreateInfo( | 475 var fenceInfo = VkFenceCreateInfo( |
472 sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, | 476 sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
473 flags: VkFenceCreateFlags(VK_FENCE_CREATE_SIGNALED_BIT) | 477 flags: VkFenceCreateFlags(VK_FENCE_CREATE_SIGNALED_BIT) |
474 ) | 478 ) |
475 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: | 479 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: |
476 checkVkResult result.vulkan.device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result.vulkan.imageAvailableSemaphores[i])) | 480 checkVkResult device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result[0][i])) |
477 checkVkResult result.vulkan.device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result.vulkan.renderFinishedSemaphores[i])) | 481 checkVkResult device.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result[1][i])) |
478 checkVkResult result.vulkan.device.vkCreateFence(addr(fenceInfo), nil, addr(result.vulkan.inFlightFences[i])) | 482 checkVkResult device.vkCreateFence(addr(fenceInfo), nil, addr(result[2][i])) |
479 | 483 |
480 | 484 proc igniteEngine*(): Engine = |
481 proc recordCommandBuffer(vulkan: var Vulkan, commandBuffer: VkCommandBuffer, imageIndex: uint32) = | 485 |
486 # init X11 window | |
487 (result.window.display, result.window.window) = xlibInit() | |
488 | |
489 # setup vulkan functions | |
490 vkLoad1_0() | |
491 vkLoad1_1() | |
492 vkLoad1_2() | |
493 checkGlslangResult glslang_initialize_process() | |
494 | |
495 # create vulkan instance | |
496 result.vulkan.instance = createVulkanInstance(VULKAN_VERSION) | |
497 when ENABLEVULKANVALIDATIONLAYERS: | |
498 result.vulkan.debugMessenger = result.vulkan.instance.setupDebugLog() | |
499 result.vulkan.surface = result.vulkan.instance.createVulkanSurface(result.window) | |
500 result.vulkan.device = result.vulkan.instance.setupVulkanDeviceAndQueues(result.vulkan.surface) | |
501 | |
502 # get basic frame information | |
503 result.vulkan.surfaceFormat = result.vulkan.device.physicalDevice.surfaceFormats.getSuitableSurfaceFormat() | |
504 result.vulkan.frameDimension = result.window.getFrameDimension(result.vulkan.device.physicalDevice.surfaceCapabilities) | |
505 | |
506 # setup swapchain and render pipeline | |
507 result.vulkan.swapchain = result.vulkan.device.device.setupSwapChain( | |
508 result.vulkan.device.physicalDevice, | |
509 result.vulkan.surface, | |
510 result.vulkan.frameDimension, | |
511 result.vulkan.surfaceFormat | |
512 ) | |
513 result.vulkan.renderPass = result.vulkan.device.device.setupRenderPass(result.vulkan.surfaceFormat.format) | |
514 result.vulkan.pipeline = result.vulkan.device.device.setupRenderPipeline(result.vulkan.frameDimension, result.vulkan.renderPass) | |
515 result.vulkan.framebuffers = result.vulkan.device.device.setupFramebuffers( | |
516 result.vulkan.swapchain, | |
517 result.vulkan.renderPass, | |
518 result.vulkan.frameDimension | |
519 ) | |
520 | |
521 ( | |
522 result.vulkan.commandPool, | |
523 result.vulkan.commandBuffers, | |
524 ) = result.vulkan.device.device.setupCommandBuffers(result.vulkan.device.graphicsQueueFamily) | |
525 | |
526 ( | |
527 result.vulkan.imageAvailableSemaphores, | |
528 result.vulkan.renderFinishedSemaphores, | |
529 result.vulkan.inFlightFences, | |
530 ) = result.vulkan.device.device.setupSyncPrimitives() | |
531 | |
532 | |
533 proc recordCommandBuffer(renderPass: VkRenderPass, pipeline: var RenderPipeline, commandBuffer: VkCommandBuffer, framebuffer: VkFramebuffer) = | |
482 var beginInfo = VkCommandBufferBeginInfo( | 534 var beginInfo = VkCommandBufferBeginInfo( |
483 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | 535 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, |
484 pInheritanceInfo: nil, | 536 pInheritanceInfo: nil, |
485 ) | 537 ) |
486 checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo)) | 538 checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo)) |
487 | 539 |
488 var | 540 var |
489 clearColor = VkClearValue(color: VkClearColorValue(float32: [0.2'f, 0.2'f, 0.2'f, 1.0'f])) | 541 clearColor = VkClearValue(color: VkClearColorValue(float32: [0.2'f, 0.2'f, 0.2'f, 1.0'f])) |
490 renderPassInfo = VkRenderPassBeginInfo( | 542 renderPassInfo = VkRenderPassBeginInfo( |
491 sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | 543 sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, |
492 renderPass: vulkan.pipeline.renderPass, | 544 renderPass: renderPass, |
493 framebuffer: vulkan.swapFramebuffers[imageIndex], | 545 framebuffer: framebuffer, |
494 renderArea: VkRect2D( | 546 renderArea: VkRect2D( |
495 offset: VkOffset2D(x: 0, y: 0), | 547 offset: VkOffset2D(x: 0, y: 0), |
496 extent: vulkan.frameDimension, | 548 extent: VkExtent2D( |
549 width: uint32(pipeline.viewport.width), | |
550 height: uint32(pipeline.viewport.height) | |
551 ), | |
497 ), | 552 ), |
498 clearValueCount: 1, | 553 clearValueCount: 1, |
499 pClearValues: addr(clearColor), | 554 pClearValues: addr(clearColor), |
500 ) | 555 ) |
501 commandBuffer.vkCmdBeginRenderPass(addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) | 556 commandBuffer.vkCmdBeginRenderPass(addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) |
502 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan.pipeline.pipeline) | 557 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline) |
503 | 558 |
504 commandBuffer.vkCmdSetViewport(firstViewport=0, viewportCount=1, addr(vulkan.viewport)) | 559 commandBuffer.vkCmdSetViewport(firstViewport=0, viewportCount=1, addr(pipeline.viewport)) |
505 commandBuffer.vkCmdSetScissor(firstScissor=0, scissorCount=1, addr(vulkan.scissor)) | 560 commandBuffer.vkCmdSetScissor(firstScissor=0, scissorCount=1, addr(pipeline.scissor)) |
506 commandBuffer.vkCmdDraw(vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0) | 561 commandBuffer.vkCmdDraw(vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0) |
507 commandBuffer.vkCmdEndRenderPass() | 562 commandBuffer.vkCmdEndRenderPass() |
508 checkVkResult commandBuffer.vkEndCommandBuffer() | 563 checkVkResult commandBuffer.vkEndCommandBuffer() |
509 | 564 |
510 proc drawFrame(vulkan: var Vulkan, currentFrame: int) = | 565 proc drawFrame(window: Window, vulkan: var Vulkan, currentFrame: int) = |
511 checkVkResult vulkan.device.vkWaitForFences(1, addr(vulkan.inFlightFences[currentFrame]), VK_TRUE, high(uint64)) | 566 checkVkResult vulkan.device.device.vkWaitForFences(1, addr(vulkan.inFlightFences[currentFrame]), VK_TRUE, high(uint64)) |
512 checkVkResult vulkan.device.vkResetFences(1, addr(vulkan.inFlightFences[currentFrame])) | 567 checkVkResult vulkan.device.device.vkResetFences(1, addr(vulkan.inFlightFences[currentFrame])) |
513 var bufferImageIndex: uint32 | 568 var bufferImageIndex: uint32 |
514 checkVkResult vulkan.device.vkAcquireNextImageKHR( | 569 let nextImageResult = vulkan.device.device.vkAcquireNextImageKHR( |
515 vulkan.swapChain, | 570 vulkan.swapchain.swapchain, |
516 high(uint64), | 571 high(uint64), |
517 vulkan.imageAvailableSemaphores[currentFrame], | 572 vulkan.imageAvailableSemaphores[currentFrame], |
518 VkFence(0), | 573 VkFence(0), |
519 addr(bufferImageIndex) | 574 addr(bufferImageIndex) |
520 ) | 575 ) |
521 | 576 if nextImageResult == VK_ERROR_OUT_OF_DATE_KHR: |
522 checkVkResult vkResetCommandBuffer(vulkan.commandBuffers[currentFrame], VkCommandBufferResetFlags(0)) | 577 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.surfaceCapabilities) |
523 recordCommandBuffer(vulkan, vulkan.commandBuffers[currentFrame], bufferImageIndex) | 578 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain() |
579 return | |
580 | |
581 checkVkResult vulkan.commandBuffers[currentFrame].vkResetCommandBuffer(VkCommandBufferResetFlags(0)) | |
582 vulkan.renderPass.recordCommandBuffer(vulkan.pipeline, vulkan.commandBuffers[currentFrame], vulkan.framebuffers[bufferImageIndex]) | |
524 var | 583 var |
525 waitSemaphores = [vulkan.imageAvailableSemaphores[currentFrame]] | 584 waitSemaphores = [vulkan.imageAvailableSemaphores[currentFrame]] |
526 waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)] | 585 waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)] |
527 signalSemaphores = [vulkan.renderFinishedSemaphores[currentFrame]] | 586 signalSemaphores = [vulkan.renderFinishedSemaphores[currentFrame]] |
528 submitInfo = VkSubmitInfo( | 587 submitInfo = VkSubmitInfo( |
533 commandBufferCount: 1, | 592 commandBufferCount: 1, |
534 pCommandBuffers: addr(vulkan.commandBuffers[currentFrame]), | 593 pCommandBuffers: addr(vulkan.commandBuffers[currentFrame]), |
535 signalSemaphoreCount: 1, | 594 signalSemaphoreCount: 1, |
536 pSignalSemaphores: addr(signalSemaphores[0]), | 595 pSignalSemaphores: addr(signalSemaphores[0]), |
537 ) | 596 ) |
538 checkVkResult vkQueueSubmit(vulkan.graphicsQueue, 1, addr(submitInfo), vulkan.inFlightFences[currentFrame]) | 597 checkVkResult vkQueueSubmit(vulkan.device.graphicsQueue, 1, addr(submitInfo), vulkan.inFlightFences[currentFrame]) |
539 | 598 |
540 var presentInfo = VkPresentInfoKHR( | 599 var presentInfo = VkPresentInfoKHR( |
541 sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, | 600 sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, |
542 waitSemaphoreCount: 1, | 601 waitSemaphoreCount: 1, |
543 pWaitSemaphores: addr(signalSemaphores[0]), | 602 pWaitSemaphores: addr(signalSemaphores[0]), |
544 swapchainCount: 1, | 603 swapchainCount: 1, |
545 pSwapchains: addr(vulkan.swapChain), | 604 pSwapchains: addr(vulkan.swapchain.swapchain), |
546 pImageIndices: addr(bufferImageIndex), | 605 pImageIndices: addr(bufferImageIndex), |
547 pResults: nil, | 606 pResults: nil, |
548 ) | 607 ) |
549 checkVkResult vkQueuePresentKHR(vulkan.presentationQueue, addr(presentInfo)) | 608 let presentResult = vkQueuePresentKHR(vulkan.device.presentationQueue, addr(presentInfo)) |
609 | |
610 if presentResult == VK_ERROR_OUT_OF_DATE_KHR or presentResult == VK_SUBOPTIMAL_KHR: | |
611 vulkan.frameDimension = window.getFrameDimension(vulkan.device.physicalDevice.surfaceCapabilities) | |
612 (vulkan.swapchain, vulkan.framebuffers) = vulkan.recreateSwapchain() | |
613 return | |
550 | 614 |
551 | 615 |
552 proc fullThrottle*(engine: var Engine) = | 616 proc fullThrottle*(engine: var Engine) = |
553 var | 617 var |
554 event: XEvent | 618 event: XEvent |
555 killed = false | 619 killed = false |
556 currentFrame = 0 | 620 currentFrame = 0 |
557 | 621 |
558 while not killed: | 622 while not killed: |
559 while engine.display.XPending() > 0 and not killed: | 623 while engine.window.display.XPending() > 0 and not killed: |
560 discard engine.display.XNextEvent(addr(event)) | 624 discard engine.window.display.XNextEvent(addr(event)) |
561 case event.theType | 625 case event.theType |
562 of ClientMessage: | 626 of ClientMessage: |
563 if cast[Atom](event.xclient.data.l[0]) == deleteMessage: | 627 if cast[Atom](event.xclient.data.l[0]) == deleteMessage: |
564 killed = true | 628 killed = true |
565 of KeyPress: | 629 of KeyPress: |
566 let key = XLookupKeysym(cast[PXKeyEvent](addr(event)), 0) | 630 let key = XLookupKeysym(cast[PXKeyEvent](addr(event)), 0) |
567 if key == XK_Escape: | 631 if key == XK_Escape: |
568 killed = true | 632 killed = true |
633 of ConfigureNotify: | |
634 engine.vulkan.frameDimension = engine.window.getFrameDimension(engine.vulkan.device.physicalDevice.surfaceCapabilities) | |
635 (engine.vulkan.swapchain, engine.vulkan.framebuffers) = engine.vulkan.recreateSwapchain() | |
569 else: | 636 else: |
570 discard | 637 discard |
571 drawFrame(engine.vulkan, currentFrame) | 638 engine.window.drawFrame(engine.vulkan, currentFrame) |
572 currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT; | 639 currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT; |
573 checkVkResult engine.vulkan.device.vkDeviceWaitIdle() | 640 checkVkResult engine.vulkan.device.device.vkDeviceWaitIdle() |
574 | 641 |
575 | 642 |
576 proc trash*(engine: Engine) = | 643 proc trash*(engine: Engine) = |
644 checkVkResult engine.vulkan.device.device.vkDeviceWaitIdle() | |
577 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: | 645 for i in 0 ..< MAX_FRAMES_IN_FLIGHT: |
578 engine.vulkan.device.vkDestroySemaphore(engine.vulkan.imageAvailableSemaphores[i], nil) | 646 engine.vulkan.device.device.vkDestroySemaphore(engine.vulkan.imageAvailableSemaphores[i], nil) |
579 engine.vulkan.device.vkDestroySemaphore(engine.vulkan.renderFinishedSemaphores[i], nil) | 647 engine.vulkan.device.device.vkDestroySemaphore(engine.vulkan.renderFinishedSemaphores[i], nil) |
580 engine.vulkan.device.vkDestroyFence(engine.vulkan.inFlightFences[i], nil) | 648 engine.vulkan.device.device.vkDestroyFence(engine.vulkan.inFlightFences[i], nil) |
581 | 649 |
582 engine.vulkan.device.vkDestroyCommandPool(engine.vulkan.commandPool, nil) | 650 engine.vulkan.device.device.vkDestroyCommandPool(engine.vulkan.commandPool, nil) |
583 for framebuffer in engine.vulkan.swapFramebuffers: | 651 for framebuffer in engine.vulkan.framebuffers: |
584 engine.vulkan.device.vkDestroyFramebuffer(framebuffer, nil) | 652 engine.vulkan.device.device.vkDestroyFramebuffer(framebuffer, nil) |
585 | 653 |
586 engine.vulkan.device.vkDestroyPipeline(engine.vulkan.pipeline.pipeline, nil) | 654 engine.vulkan.device.device.vkDestroyPipeline(engine.vulkan.pipeline.pipeline, nil) |
587 engine.vulkan.device.vkDestroyPipelineLayout(engine.vulkan.pipeline.layout, nil) | 655 engine.vulkan.device.device.vkDestroyPipelineLayout(engine.vulkan.pipeline.layout, nil) |
588 engine.vulkan.device.vkDestroyRenderPass(engine.vulkan.pipeline.renderPass, nil) | 656 engine.vulkan.device.device.vkDestroyRenderPass(engine.vulkan.renderPass, nil) |
589 | 657 |
590 for shaderStage in engine.vulkan.pipeline.shaderStages: | 658 for shaderStage in engine.vulkan.pipeline.shaderStages: |
591 engine.vulkan.device.vkDestroyShaderModule(shaderStage.module, nil) | 659 engine.vulkan.device.device.vkDestroyShaderModule(shaderStage.module, nil) |
592 | 660 |
661 for imageview in engine.vulkan.swapchain.imageviews: | |
662 engine.vulkan.device.device.vkDestroyImageView(imageview, nil) | |
663 engine.vulkan.device.device.vkDestroySwapchainKHR(engine.vulkan.swapchain.swapchain, nil) | |
664 engine.vulkan.instance.vkDestroySurfaceKHR(engine.vulkan.surface, nil) | |
665 engine.vulkan.device.device.vkDestroyDevice(nil) | |
666 when ENABLEVULKANVALIDATIONLAYERS: | |
667 engine.vulkan.instance.vkDestroyDebugUtilsMessengerEXT(engine.vulkan.debugMessenger, nil) | |
593 glslang_finalize_process() | 668 glslang_finalize_process() |
594 engine.vulkan.device.vkDestroySwapchainKHR(engine.vulkan.swapChain, nil) | |
595 engine.vulkan.instance.vkDestroySurfaceKHR(engine.vulkan.surface, nil) | |
596 engine.vulkan.device.vkDestroyDevice(nil) | |
597 engine.vulkan.instance.vkDestroyInstance(nil) | 669 engine.vulkan.instance.vkDestroyInstance(nil) |
598 checkXlibResult engine.display.XDestroyWindow(engine.window) | 670 checkXlibResult engine.window.display.XDestroyWindow(engine.window.window) |
599 discard engine.display.XCloseDisplay() # always returns 0 | 671 discard engine.window.display.XCloseDisplay() # always returns 0 |