Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import
- nimgl/[vulkan, glfw, glfw/native],
- winim,
- options,
- sequtils
- type
- QueueFamilyIndices = object
- graphicsFamily: Option[uint32]
- presentFamily: Option[uint32]
- SwapChainSupportDetails = object
- capabilities: VkSurfaceCapabilitiesKHR
- formats: seq[VkSurfaceFormatKHR]
- presentModes: seq[VkPresentModeKHR]
- const
- VK_NULL_HANDLE = VkNonDispatchableHandle(0)
- WIDTH: uint32 = 800
- HEIGHT: uint32 = 600
- MAX_FRAMES_IN_FLIGHT = 2
- enableValidationLayers = true
- var
- validationLayers = [
- "VK_LAYER_KHRONOS_validation".cstring
- ]
- deviceExtensions = [
- "VK_KHR_swapchain".cstring
- ]
- proc isComplete(self: var QueueFamilyIndices): bool =
- return self.graphicsFamily.isSome() and self.presentFamily.isSome()
- var
- window: GLFWWindow
- instance: VkInstance
- debugMessenger: VkDebugUtilsMessengerEXT
- surface: VkSurfaceKHR
- physicalDevice: VkPhysicalDevice = VkPhysicalDevice(VK_NULL_HANDLE)
- device: VkDevice
- graphicsQueue: VkQueue
- presentQueue: VkQueue
- swapChain: VkSwapchainKHR
- swapChainImages: seq[VkImage]
- swapChainImageFormat: VkFormat
- swapChainExtent: VkExtent2D
- swapChainImageViews: seq[VkImageView]
- swapChainFramebuffers: seq[VkFramebuffer]
- renderPass: VkRenderPass
- pipelineLayout: VkPipelineLayout
- graphicsPipeline: VkPipeline
- commandPool: VkCommandPool
- commandBuffers: seq[VkCommandBuffer]
- imageAvailableSemaphores: seq[VkSemaphore]
- renderFinishedSemaphores: seq[VkSemaphore]
- inFlightFences: seq[VkFence]
- imagesInFlight: seq[VkFence]
- currentFrame: uint64 = 0
- proc toString(chars: openArray[char]): string =
- result = ""
- for c in chars:
- if c != '\0':
- result.add(c)
- proc checkValidationLayerSupport(): bool =
- var layerCount: uint32
- discard vkEnumerateInstanceLayerProperties(addr layerCount, nil)
- var availableLayers: seq[VkLayerProperties]
- availableLayers.setLen(layerCount)
- discard vkEnumerateInstanceLayerProperties(addr layerCount, addr availableLayers[0])
- for layerName in validationLayers:
- result = false
- for layerProperties in availableLayers:
- if layerName == (cstring) layerProperties.layerName:
- result = true
- break
- if (not result):
- return
- result = true
- proc CreateDebugUtilsMessengerEXT(instance: VkInstance,pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pDebugMessenger: ptr VkDebugUtilsMessengerEXT): VkResult =
- let vkFunc = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMessenger: ptr VkDebugUtilsMessengerEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"))
- echo "vkCreateDebugUtilsMessengerEXT: ", toHex(cast[uint](vkFunc))
- if vkFunc != nil:
- result = vkFunc(instance, pCreateInfo, pAllocator, pDebugMessenger)
- else:
- result = VK_ERROR_EXTENSION_NOT_PRESENT
- proc DestroyDebugUtilsMessengerEXT(instance: VkInstance, debugMessenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks) =
- var vkFunc = cast[proc(instance: VkInstance, messenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}] (vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"))
- echo "vkDestroyDebugUtilsMessengerEXT: ", toHex(cast[uint](vkFunc))
- if vkFunc != nil:
- vkFunc(instance, debugMessenger, pAllocator)
- proc debugCallback(messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageType: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: VkDebugUtilsMessengerCallbackDataEXT, pUserData: pointer): VkBool32 {.cdecl.} =
- echo "validation layer: ", pCallbackData.pMessage
- result = VkBool32(VK_FALSE)
- proc populateDebugMessengerCreateInfo(createInfo: ptr VkDebugUtilsMessengerCreateInfoEXT) =
- createInfo.sType = cast[VkStructureType](1000128004)
- createInfo.messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT(0x00001101)
- createInfo.messageType = VkDebugUtilsMessageTypeFlagsEXT(7)
- createInfo.pfnUserCallback = debugCallback
- proc setupDebugMessenger() =
- if not enableValidationLayers: return
- var createInfo: VkDebugUtilsMessengerCreateInfoEXT
- populateDebugMessengerCreateInfo(addr createInfo);
- if CreateDebugUtilsMessengerEXT(instance, addr createInfo, nil, addr debugMessenger) != VK_SUCCESS:
- raise newException(Exception, "failed to set up debug messenger!");
- proc checkValidationLayers(): bool =
- var layerCount: uint32 = 0
- discard vkEnumerateInstanceLayerProperties(layerCount.addr, nil)
- var layers = newSeq[VkLayerProperties](layerCount)
- discard vkEnumerateInstanceLayerProperties(layerCount.addr, layers[0].addr)
- for validate in validationLayers:
- var found = false
- for layer in layers:
- if layer.layerName.toString() == validate:
- found = true
- if not found:
- return false
- else:
- echo validate, " layer is not supported"
- proc findQueueFamilies(pDevice: VkPhysicalDevice): QueueFamilyIndices =
- var queueFamilyCount: uint32 = 0
- vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr queueFamilyCount, nil)
- var queueFamilies: seq[VkQueueFamilyProperties]
- queueFamilies.setLen(queueFamilyCount)
- vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr queueFamilyCount, addr queueFamilies[0])
- var indice: uint32 = 0
- for queueFamily in queueFamilies:
- if (queueFamily.queueFlags.uint32 and VkQueueGraphicsBit.uint32) > 0'u32:
- result.graphicsFamily = some(indice)
- var presentSupport = VkBool32(VK_FALSE)
- discard vkGetPhysicalDeviceSurfaceSupportKHR(pDevice, indice, surface, addr presentSupport)
- if int(presentSupport) == VK_TRUE:
- result.presentFamily = some(indice)
- if result.isComplete():
- break
- indice.inc
- proc createLogicalDevice() =
- var
- indices = physicalDevice.findQueueFamilies()
- queuePriority = 1.0
- deviceFeatures = newSeq[VkPhysicalDeviceFeatures](1)
- deviceQueueCreateInfo = newVkDeviceQueueCreateInfo(
- queueFamilyIndex = indices.graphicsFamily.get(),
- queueCount = 1,
- pQueuePriorities = queuePriority.addr
- )
- deviceCreateInfo = newVkDeviceCreateInfo(
- pQueueCreateInfos = deviceQueueCreateInfo.addr,
- queueCreateInfoCount = 1,
- pEnabledFeatures = deviceFeatures[0].addr,
- enabledExtensionCount = 0,
- enabledLayerCount = 0,
- ppEnabledLayerNames = nil,
- ppEnabledExtensionNames = nil
- )
- if vkCreateDevice(physicalDevice, addr deviceCreateInfo, nil, addr device) != VKSuccess:
- echo "failed to create logical device"
- echo "Device: ", uint(device)
- vkGetDeviceQueue(device, get indices.graphicsFamily, 0, addr graphicsQueue)
- vkGetDeviceQueue(device, get indices.presentFamily, 0, addr presentQueue)
- proc getRequiredExtensions(): seq[cstring] =
- var glfwExtensionCount: uint32 = 0
- var glfwExtensions: cstringArray
- glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount)
- result.setLen(glfwExtensionCount)
- for i in 0..<glfwExtensionCount:
- result[i] = glfwExtensions[i]
- if enableValidationLayers:
- result.add("VK_EXT_debug_utils")
- proc initWindow() =
- if not glfwInit():
- quit("failed to init glfw")
- glfwWindowHint(GLFWClientApi, GLFWNoApi)
- glfwWindowHint(GLFWResizable, GLFWFalse)
- window = glfwCreateWindow(800, 600)
- if not vkInit():
- quit("failed to load vulkan")
- proc createInstance() =
- if enableValidationLayers and not checkValidationLayerSupport():
- raise newException(Exception, "validation layers requested, but not available!")
- var appInfo: VkApplicationInfo
- appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO
- appInfo.pApplicationName = "Hello Triangle"
- appInfo.applicationVersion = vkMakeVersion(1, 0, 0)
- appInfo.pEngineName = "No Engine"
- appInfo.engineVersion = vkMakeVersion(1, 0, 0)
- appInfo.apiVersion = vkApiVersion1_1
- var createInfo: VkInstanceCreateInfo
- createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
- createInfo.pApplicationInfo = addr appInfo
- var extensions = getRequiredExtensions()
- createInfo.enabledExtensionCount = uint32(extensions.len())
- createInfo.ppEnabledExtensionNames = cast[cstringArray](addr extensions[0])
- var debugCreateInfo: VkDebugUtilsMessengerCreateInfoEXT
- if enableValidationLayers:
- createInfo.enabledLayerCount = (uint32) validationLayers.len()
- createInfo.ppEnabledLayerNames = cast[cstringArray](addr validationLayers[0])
- populateDebugMessengerCreateInfo(debugCreateInfo);
- createInfo.pNext = addr debugCreateInfo
- else:
- createInfo.enabledLayerCount = 0;
- createInfo.pNext = nil
- if vkCreateInstance(addr createInfo, nil, addr instance) != VK_SUCCESS:
- raise newException(Exception, "failed to create instance!")
- proc createShaderModule(code: TaintedString): VkShaderModule =
- var createInfo: VkShaderModuleCreateInfo = newVkShaderModuleCreateInfo(
- codeSize = (uint) len(code),
- pCode = cast[ptr uint32](code)
- )
- if vkCreateShaderModule(device, addr createInfo, nil, addr result) != VK_SUCCESS:
- raise newException(Exception, "Vulkan shader uninitialized")
- proc createGraphicsPipeline() =
- var vertShaderCode = readFile("vert.spv")
- var fragShaderCode = readFile("frag.spv")
- var vertShaderModule = createShaderModule(vertShaderCode)
- var fragShaderModule = createShaderModule(fragShaderCode)
- var vertShaderStageInfo = newVkPipelineShaderStageCreateInfo(
- sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- stage = VK_SHADER_STAGE_VERTEX_BIT,
- module = fragShaderModule,
- pName = "main",
- pSpecializationInfo = nil
- )
- var fragShaderStageInfo = newVkPipelineShaderStageCreateInfo(
- sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- stage = (VkShaderStageFlagBits) 0x00000080,
- module = fragShaderModule,
- pName = "main",
- pSpecializationInfo = nil
- )
- var shaderStages = [vertShaderStageInfo, fragShaderStageInfo]
- var vertexInputInfo = newVkPipelineVertexInputStateCreateInfo(
- sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- vertexBindingDescriptionCount = 0,
- pVertexBindingDescriptions = nil,
- vertexAttributeDescriptionCount = 0,
- pVertexAttributeDescriptions = nil
- )
- var inputAssembly = newVkPipelineInputAssemblyStateCreateInfo(
- sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
- topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
- primitiveRestartEnable = VkBool32(VK_FALSE)
- )
- var viewport = newVkViewport(
- x = 0.0f,
- y = 0.0f,
- width = (float) swapChainExtent.width,
- height = (float) swapChainExtent.height,
- minDepth = 0.0f,
- maxDepth = 1.0f
- )
- var scissor = newVkRect2D(
- offset = newVkOffset2D(0, 0),
- extent = swapChainExtent
- )
- var viewportState = newVkPipelineViewportStateCreateInfo(
- sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
- viewportCount = 1,
- pViewports = addr viewport,
- scissorCount = 1,
- pScissors = addr scissor
- )
- var rasterizer: VkPipelineRasterizationStateCreateInfo
- rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
- rasterizer.depthClampEnable = VkBool32(VK_FALSE)
- rasterizer.rasterizerDiscardEnable = VkBool32(VK_FALSE)
- rasterizer.polygonMode = VK_POLYGON_MODE_FILL
- rasterizer.lineWidth = 1.0f
- rasterizer.cullMode = VkCullModeFlags(2)
- rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE
- rasterizer.depthBiasEnable = VkBool32(VK_FALSE)
- var multisampling: VkPipelineMultisampleStateCreateInfo
- multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
- multisampling.sampleShadingEnable = VkBool32(VK_FALSE)
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
- var colorBlendAttachment: VkPipelineColorBlendAttachmentState
- colorBlendAttachment.colorWriteMask = VkColorComponentFlags(0x00000001 or 0x00000002 or 0x00000004 or 0x00000008)
- colorBlendAttachment.blendEnable = VkBool32(VK_FALSE)
- var colorBlending: VkPipelineColorBlendStateCreateInfo
- colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
- colorBlending.logicOpEnable = VkBool32(VK_FALSE)
- colorBlending.logicOp = VK_LOGIC_OP_COPY
- colorBlending.attachmentCount = 1
- colorBlending.pAttachments = addr colorBlendAttachment
- colorBlending.blendConstants = [0.0, 0.0, 0.0, 0.0]
- var pipelineLayoutInfo: VkPipelineLayoutCreateInfo
- pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
- pipelineLayoutInfo.setLayoutCount = 0
- pipelineLayoutInfo.pushConstantRangeCount = 0
- if vkCreatePipelineLayout(device, addr pipelineLayoutInfo, nil, addr pipelineLayout) != VK_SUCCESS:
- raise newException(Exception, "failed to create pipeline layout!")
- var pipelineInfo: VkGraphicsPipelineCreateInfo
- pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
- pipelineInfo.stageCount = 2
- pipelineInfo.pStages = addr shaderStages[0]
- pipelineInfo.pVertexInputState = addr vertexInputInfo
- pipelineInfo.pInputAssemblyState = addr inputAssembly
- pipelineInfo.pViewportState = addr viewportState
- pipelineInfo.pRasterizationState = addr rasterizer
- pipelineInfo.pMultisampleState = addr multisampling
- pipelineInfo.pColorBlendState = addr colorBlending
- pipelineInfo.layout = pipelineLayout
- pipelineInfo.renderPass = renderPass
- pipelineInfo.subpass = 0
- pipelineInfo.basePipelineHandle = VkPipeline(VK_NULL_HANDLE)
- if vkCreateGraphicsPipelines(device, VkPipelineCache(VK_NULL_HANDLE), 1, addr pipelineInfo, nil, addr graphicsPipeline) != VK_SUCCESS:
- raise newException(Exception, "failed to create graphics pipeline!")
- vkDestroyShaderModule(device, fragShaderModule, nil)
- vkDestroyShaderModule(device, vertShaderModule, nil)
- proc createSurface() =
- var createInfo = newVkWin32SurfaceCreateInfoKHR(
- sType = cast[VkStructureType](1000009000),
- hwnd = cast[vulkan.HWND](getWin32Window(window)),
- hinstance = cast[vulkan.HINSTANCE](GetModuleHandle(nil))
- )
- if vkCreateWin32SurfaceKHR(instance, addr createInfo, nil, addr surface) != VK_SUCCESS:
- raise newException(Exception, "failed to create window surface!")
- proc querySwapChainSupport(device: VkPhysicalDevice): SwapChainSupportDetails =
- discard vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &result.capabilities)
- var formatCount: uint32
- discard vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr formatCount, nil)
- if formatCount != 0:
- result.formats.setLen(formatCount)
- discard vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, addr result.formats[0])
- var presentModeCount: uint32
- discard vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nil)
- if presentModeCount != 0:
- result.presentModes.setLen(presentModeCount)
- discard vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, addr result.presentModes[0])
- proc checkDeviceExtensionSupport(device: VkPhysicalDevice): bool =
- var extensionCount: uint32
- discard vkEnumerateDeviceExtensionProperties(device, nil, addr extensionCount, nil)
- var availableExtensions = newSeq[VkExtensionProperties](extensionCount)
- discard vkEnumerateDeviceExtensionProperties(device, nil, addr extensionCount, addr availableExtensions[0])
- var requiredExtensions = toSeq(deviceExtensions)
- for extension in availableExtensions:
- requiredExtensions.keepIf(proc(x: cstring): bool {.closure.} = x != (cstring) extension.extensionName)
- result = requiredExtensions.len() == 0
- proc isDeviceSuitable(pDevice: VkPhysicalDevice): bool =
- var indices = findQueueFamilies(pDevice)
- var extensionsSupported = checkDeviceExtensionSupport(pDevice)
- echo "Indices: ", indices
- echo "extensionsSupported: ", extensionsSupported
- var swapChainAdequate = false
- if extensionsSupported:
- var swapChainSupport = querySwapChainSupport(pDevice)
- swapChainAdequate = swapChainSupport.formats.len != 0 and swapChainSupport.presentModes.len != 0
- echo "[indices.isComplete(), extensionsSupported, swapChainAdequate]", [indices.isComplete(), extensionsSupported, swapChainAdequate]
- return indices.isComplete() and extensionsSupported and swapChainAdequate
- proc pickPhysicalDevice() =
- var deviceCount: uint32 = 0
- discard vkEnumeratePhysicalDevices(instance, addr deviceCount, nil)
- var devices = newSeq[VkPhysicalDevice](deviceCount)
- discard vkEnumeratePhysicalDevices(instance, addr deviceCount, addr devices[0])
- echo deviceCount
- for pDevice in devices:
- if pDevice.isDeviceSuitable():
- physicalDevice = pDevice
- if VkNonDispatchableHandle(physicalDevice) == VK_NULL_HANDLE:
- raise newException(Exception, "failed to find a suitable GPU!");
- proc chooseSwapSurfaceFormat(availableFormats: seq[VkSurfaceFormatKHR]): VkSurfaceFormatKHR =
- for availableFormat in availableFormats:
- if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB and availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR):
- result = availableFormat
- return
- result = availableFormats[0]
- proc chooseSwapPresentMode(availablePresentModes: seq[VkPresentModeKHR] ): VkPresentModeKHR =
- for availablePresentMode in availablePresentModes:
- if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR):
- result = availablePresentMode
- return
- result = VK_PRESENT_MODE_FIFO_KHR
- proc chooseSwapExtent(capabilities: VkSurfaceCapabilitiesKHR): VkExtent2D =
- if capabilities.currentExtent.width != uint32.high():
- result = capabilities.currentExtent
- else:
- var actualExtent = newVkExtent2D(WIDTH, HEIGHT)
- actualExtent.width = max(capabilities.minImageExtent.width, min(capabilities.maxImageExtent.width, actualExtent.width))
- actualExtent.height = max(capabilities.minImageExtent.height, min(capabilities.maxImageExtent.height, actualExtent.height))
- result = actualExtent
- proc createSwapChain() =
- var swapChainSupport = querySwapChainSupport(physicalDevice)
- var surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats)
- var presentMode = chooseSwapPresentMode(swapChainSupport.presentModes)
- var extent = chooseSwapExtent(swapChainSupport.capabilities)
- var imageCount: uint32 = swapChainSupport.capabilities.minImageCount + 1
- if (swapChainSupport.capabilities.maxImageCount > 0 and imageCount > swapChainSupport.capabilities.maxImageCount):
- imageCount = swapChainSupport.capabilities.maxImageCount
- echo ((uint(surfaceFormat.format), uint(surfaceFormat.colorSpace), uint(presentMode)))
- var createInfo: VkSwapchainCreateInfoKHR
- createInfo.sType = cast[VkStructureType](1000001000)
- createInfo.surface = surface
- createInfo.pNext = nil
- createInfo.minImageCount = imageCount
- createInfo.imageFormat = surfaceFormat.format
- createInfo.imageColorSpace = surfaceFormat.colorSpace
- createInfo.imageExtent = extent
- createInfo.imageArrayLayers = 1
- createInfo.imageUsage = cast[VkImageUsageFlags](0x00000010)
- var indices = findQueueFamilies(physicalDevice)
- var queueFamilyIndices {.global.}: array[2, uint32]
- queueFamilyIndices = [get indices.graphicsFamily, get indices.presentFamily]
- if (isSome indices.graphicsFamily) != (isSome indices.presentFamily):
- createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT
- createInfo.queueFamilyIndexCount = 2
- createInfo.pQueueFamilyIndices = addr queueFamilyIndices[0]
- else:
- createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE
- createInfo.pQueueFamilyIndices = nil
- createInfo.preTransform = swapChainSupport.capabilities.currentTransform
- createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
- createInfo.presentMode = presentMode
- createInfo.clipped = VkBool32(VK_TRUE)
- createInfo.oldSwapchain = VkSwapchainKHR(VK_NULL_HANDLE)
- if vkCreateSwapchainKHR(device, addr createInfo, nil, addr swapChain) != VK_SUCCESS:
- raise newException(Exception, "failed to create swap chain!")
- echo "SwapchainHandle: ", toHex(uint(swapChain))
- discard vkGetSwapchainImagesKHR(device, swapChain, addr imageCount, nil)
- swapChainImages.setLen(imageCount)
- discard vkGetSwapchainImagesKHR(device, swapChain, addr imageCount, addr swapChainImages[0])
- swapChainImageFormat = surfaceFormat.format
- swapChainExtent = extent
- proc createImageViews() =
- swapChainImageViews.setLen(len(swapChainImages))
- for i, swapChainImage in pairs(swapChainImages):
- var createInfo: VkImageViewCreateInfo
- createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
- createInfo.pNext = nil
- createInfo.image = swapChainImage
- createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D
- createInfo.format = swapChainImageFormat
- createInfo.components = newVkComponentMapping(
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY
- )
- createInfo.subresourceRange = newVkImageSubresourceRange(
- aspectMask = VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT),
- baseMipLevel = 0,
- levelCount = 1,
- baseArrayLayer = 0,
- layerCount = 1
- )
- echo "Indice: ", i, " Device: ", toHex(uint(device)), " swapChainImage: ", toHex(cast[uint](swapChainImage))
- if vkCreateImageView(device, addr createInfo, nil, addr swapChainImageViews[i]) != VK_SUCCESS:
- raise newException(Exception, "failed to create image views!")
- proc createRenderPass() =
- var colorAttachment: VkAttachmentDescription
- colorAttachment.format = swapChainImageFormat
- colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT
- colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR
- colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE
- colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE
- colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE
- colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
- colorAttachment.finalLayout = cast[VkImageLayout](1000001002)
- var colorAttachmentRef: VkAttachmentReference
- colorAttachmentRef.attachment = 0
- colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
- var subpass: VkSubpassDescription
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS
- subpass.colorAttachmentCount = 1
- subpass.pColorAttachments = addr colorAttachmentRef
- var renderPassInfo: VkRenderPassCreateInfo
- renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
- renderPassInfo.attachmentCount = 1
- renderPassInfo.pAttachments = addr colorAttachment
- renderPassInfo.subpassCount = 1
- renderPassInfo.pSubpasses = addr subpass
- if vkCreateRenderPass(device, addr renderPassInfo, nil, addr renderPass) != VK_SUCCESS:
- raise newException(Exception, "failed to create render pass!")
- proc createFramebuffers() =
- swapChainFramebuffers.setLen(swapChainImageViews.len())
- for i, swapChainImageView in pairs(swapChainImageViews):
- var attachments = [ swapChainImageView ]
- var framebufferInfo: VkFramebufferCreateInfo
- framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
- framebufferInfo.renderPass = renderPass
- framebufferInfo.attachmentCount = 1
- framebufferInfo.pAttachments = addr attachments[0]
- framebufferInfo.width = swapChainExtent.width
- framebufferInfo.height = swapChainExtent.height
- framebufferInfo.layers = 1
- if (vkCreateFramebuffer(device, addr framebufferInfo, nil, addr swapChainFramebuffers[i]) != VK_SUCCESS):
- raise newException(Exception, "failed to create framebuffer!")
- proc createCommandPool() =
- var queueFamilyIndices = findQueueFamilies(physicalDevice)
- var poolInfo: VkCommandPoolCreateInfo
- poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
- poolInfo.queueFamilyIndex = get queueFamilyIndices.graphicsFamily
- if vkCreateCommandPool(device, addr poolInfo, nil, addr commandPool) != VK_SUCCESS:
- raise newException(Exception, "failed to create command pool!")
- proc createCommandBuffers() =
- commandBuffers.setLen(swapChainFramebuffers.len())
- var allocInfo: VkCommandBufferAllocateInfo
- allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
- allocInfo.commandPool = commandPool
- allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY
- allocInfo.commandBufferCount = (uint32) commandBuffers.len()
- if vkAllocateCommandBuffers(device, addr allocInfo, addr commandBuffers[0]) != VK_SUCCESS:
- raise newException(Exception, "failed to allocate command buffers!")
- for i, commandBuffer in pairs(commandBuffers):
- var beginInfo: VkCommandBufferBeginInfo
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
- if vkBeginCommandBuffer(commandBuffer, addr beginInfo) != VK_SUCCESS:
- raise newException(Exception, "failed to begin recording command buffer!")
- var renderPassInfo: VkRenderPassBeginInfo
- renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
- renderPassInfo.renderPass = renderPass
- renderPassInfo.framebuffer = swapChainFramebuffers[i]
- renderPassInfo.renderArea.offset = newVkOffset2D(0, 0)
- renderPassInfo.renderArea.extent = swapChainExtent
- var clearColor: VkClearValue
- clearColor.color.float32 = [0.0, 0.0, 0.0, 1.0]
- clearColor.depthStencil = newVkClearDepthStencilValue(0.0, 0)
- renderPassInfo.clearValueCount = 1
- renderPassInfo.pClearValues = addr clearColor
- vkCmdBeginRenderPass(commandBuffer, addr renderPassInfo, VK_SUBPASS_CONTENTS_INLINE)
- vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline)
- vkCmdDraw(commandBuffer, 3, 1, 0, 0)
- vkCmdEndRenderPass(commandBuffer)
- if vkEndCommandBuffer(commandBuffer) != VK_SUCCESS:
- raise newException(Exception, "failed to record command buffer!")
- proc createSyncObjects() =
- imageAvailableSemaphores.setLen(MAX_FRAMES_IN_FLIGHT)
- renderFinishedSemaphores.setLen(MAX_FRAMES_IN_FLIGHT)
- inFlightFences.setLen(MAX_FRAMES_IN_FLIGHT)
- imagesInFlight.setLen(swapChainImages.len())
- var semaphoreInfo: VkSemaphoreCreateInfo
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
- var fenceInfo: VkFenceCreateInfo
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
- fenceInfo.flags = VkFenceCreateFlags(VK_FENCE_CREATE_SIGNALED_BIT)
- for i in {0, MAX_FRAMES_IN_FLIGHT}:
- if (vkCreateSemaphore(device, addr semaphoreInfo, nil, addr imageAvailableSemaphores[i]) != VK_SUCCESS or
- vkCreateSemaphore(device, addr semaphoreInfo, nil, addr renderFinishedSemaphores[i]) != VK_SUCCESS or
- vkCreateFence(device, addr fenceInfo, nil, addr inFlightFences[i]) != VK_SUCCESS):
- raise newException(Exception, "failed to create synchronization objects for a frame!")
- proc drawFrame() =
- discard vkWaitForFences(device, 1, addr inFlightFences[currentFrame], VkBool32(VK_TRUE), uint64.high())
- var imageIndex: uint32
- discard vkAcquireNextImageKHR(device, swapChain, uint64.high(), imageAvailableSemaphores[currentFrame], VkFence(VK_NULL_HANDLE), addr imageIndex)
- if VkNonDispatchableHandle(imagesInFlight[imageIndex]) != VK_NULL_HANDLE:
- discard vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VkBool32(VK_TRUE), uint64.high())
- imagesInFlight[imageIndex] = inFlightFences[currentFrame]
- var submitInfo: VkSubmitInfo
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO
- var waitSemaphores = [imageAvailableSemaphores[currentFrame]]
- var waitStages = [ VkPipelineStageFlags(0x00000400) ]
- submitInfo.waitSemaphoreCount = 1
- submitInfo.pWaitSemaphores = addr waitSemaphores[0]
- submitInfo.pWaitDstStageMask = addr waitStages[0]
- submitInfo.commandBufferCount = 1
- submitInfo.pCommandBuffers = addr commandBuffers[imageIndex]
- var signalSemaphores = [ renderFinishedSemaphores[currentFrame] ]
- submitInfo.signalSemaphoreCount = 1
- submitInfo.pSignalSemaphores = addr signalSemaphores[0]
- discard vkResetFences(device, 1, addr inFlightFences[currentFrame])
- if vkQueueSubmit(graphicsQueue, 1, addr submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS:
- raise newException(Exception, "failed to submit draw command buffer!")
- var presentInfo: VkPresentInfoKHR
- presentInfo.sType = cast[VkStructureType](1000001001)
- presentInfo.waitSemaphoreCount = 1
- presentInfo.pWaitSemaphores = addr signalSemaphores[0]
- var swapChains = [swapChain]
- presentInfo.swapchainCount = 1
- presentInfo.pSwapchains = addr swapChains[0]
- presentInfo.pImageIndices = addr imageIndex
- discard vkQueuePresentKHR(presentQueue, addr presentInfo)
- currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT
- template mention(name: string, body: untyped): untyped =
- echo "Attempting ", `name`
- `body`
- proc initVulkan() =
- mention "createInstance": createInstance()
- #mention "setupDebugMessenger": setupDebugMessenger()
- mention "createSurface": createSurface()
- mention "pickPhysicalDevice": pickPhysicalDevice()
- mention "createLogicalDevice": createLogicalDevice()
- mention "createSwapChain": createSwapChain()
- mention "createImageViews": createImageViews()
- mention "createRenderPass": createRenderPass()
- mention "createGraphicsPipeline": createGraphicsPipeline()
- mention "createFramebuffers": createFramebuffers()
- mention "createCommandPool": createCommandPool()
- mention "createCommandBuffers": createCommandBuffers()
- mention "createSyncObjects": createSyncObjects()
- proc cleanUp() =
- for i in { 0, MAX_FRAMES_IN_FLIGHT }:
- vkDestroySemaphore(device, renderFinishedSemaphores[i], nil)
- vkDestroySemaphore(device, imageAvailableSemaphores[i], nil)
- vkDestroyFence(device, inFlightFences[i], nil)
- vkDestroyCommandPool(device, commandPool, nil)
- for framebuffer in swapChainFramebuffers:
- vkDestroyFramebuffer(device, framebuffer, nil)
- vkDestroyPipeline(device, graphicsPipeline, nil)
- vkDestroyPipelineLayout(device, pipelineLayout, nil)
- vkDestroyRenderPass(device, renderPass, nil)
- for imageView in swapChainImageViews:
- vkDestroyImageView(device, imageView, nil)
- vkDestroySwapchainKHR(device, swapChain, nil)
- vkDestroyDevice(device, nil)
- #if enableValidationLayers:
- # DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nil)
- vkDestroySurfaceKHR(instance, surface, nil)
- vkDestroyInstance(instance, nil)
- window.destroyWindow()
- glfwTerminate()
- proc loop() =
- while not window.windowShouldClose():
- var count {.global.}: int32 = 29
- count.inc
- if (count == 30):
- echo "Loop is definitely working"
- count = 0
- glfwPollEvents()
- drawFrame()
- discard vkQueueWaitIdle(presentQueue)
- proc main() =
- loadVK_KHR_win32_surface()
- loadVK_KHR_surface()
- loadVK_KHR_swapchain()
- loadVK_KHR_display_swapchain()
- mention "initWindow": initWindow()
- initVulkan()
- loop()
- cleanUp()
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement