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 |
