Advertisement
Guest User

NimGL Vulkan Hello triangle

a guest
Aug 7th, 2020
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Nim 30.80 KB | None | 0 0
  1. import
  2.   nimgl/[vulkan, glfw, glfw/native],
  3.   winim,
  4.   options,
  5.   sequtils
  6.  
  7. type
  8.   QueueFamilyIndices = object
  9.     graphicsFamily: Option[uint32]
  10.     presentFamily: Option[uint32]
  11.   SwapChainSupportDetails = object
  12.     capabilities: VkSurfaceCapabilitiesKHR
  13.     formats: seq[VkSurfaceFormatKHR]
  14.     presentModes: seq[VkPresentModeKHR]
  15.  
  16. const
  17.   VK_NULL_HANDLE = VkNonDispatchableHandle(0)
  18.   WIDTH: uint32 = 800
  19.   HEIGHT: uint32 = 600
  20.   MAX_FRAMES_IN_FLIGHT = 2
  21.   enableValidationLayers = true
  22.  
  23. var
  24.   validationLayers = [
  25.     "VK_LAYER_KHRONOS_validation".cstring
  26.   ]
  27.   deviceExtensions = [
  28.     "VK_KHR_swapchain".cstring
  29.   ]
  30.  
  31. proc isComplete(self: var QueueFamilyIndices): bool =
  32.   return self.graphicsFamily.isSome() and self.presentFamily.isSome()
  33.  
  34. var
  35.   window: GLFWWindow
  36.   instance: VkInstance
  37.   debugMessenger: VkDebugUtilsMessengerEXT
  38.   surface: VkSurfaceKHR
  39.  
  40.   physicalDevice: VkPhysicalDevice = VkPhysicalDevice(VK_NULL_HANDLE)
  41.   device: VkDevice
  42.  
  43.   graphicsQueue: VkQueue
  44.   presentQueue: VkQueue
  45.  
  46.   swapChain: VkSwapchainKHR
  47.   swapChainImages: seq[VkImage]
  48.   swapChainImageFormat: VkFormat
  49.   swapChainExtent: VkExtent2D
  50.   swapChainImageViews: seq[VkImageView]
  51.   swapChainFramebuffers: seq[VkFramebuffer]
  52.  
  53.   renderPass: VkRenderPass
  54.   pipelineLayout: VkPipelineLayout
  55.   graphicsPipeline: VkPipeline
  56.  
  57.   commandPool: VkCommandPool
  58.   commandBuffers: seq[VkCommandBuffer]
  59.  
  60.   imageAvailableSemaphores: seq[VkSemaphore]
  61.   renderFinishedSemaphores: seq[VkSemaphore]
  62.   inFlightFences: seq[VkFence]
  63.   imagesInFlight: seq[VkFence]
  64.   currentFrame: uint64 = 0
  65.  
  66.  
  67. proc toString(chars: openArray[char]): string =
  68.   result = ""
  69.   for c in chars:
  70.     if c != '\0':
  71.       result.add(c)
  72.  
  73. proc checkValidationLayerSupport(): bool =
  74.   var layerCount: uint32
  75.   discard vkEnumerateInstanceLayerProperties(addr layerCount, nil)
  76.  
  77.   var availableLayers: seq[VkLayerProperties]
  78.   availableLayers.setLen(layerCount)
  79.   discard vkEnumerateInstanceLayerProperties(addr layerCount, addr availableLayers[0])
  80.  
  81.   for layerName in validationLayers:
  82.     result = false
  83.     for layerProperties in availableLayers:
  84.       if layerName == (cstring) layerProperties.layerName:
  85.         result = true
  86.         break
  87.  
  88.     if (not result):
  89.       return
  90.  
  91.   result = true
  92.  
  93. proc CreateDebugUtilsMessengerEXT(instance: VkInstance,pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pDebugMessenger: ptr VkDebugUtilsMessengerEXT): VkResult =
  94.   let vkFunc = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMessenger: ptr VkDebugUtilsMessengerEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"))
  95.   echo "vkCreateDebugUtilsMessengerEXT: ", toHex(cast[uint](vkFunc))
  96.   if vkFunc != nil:
  97.     result = vkFunc(instance, pCreateInfo, pAllocator, pDebugMessenger)
  98.   else:
  99.     result = VK_ERROR_EXTENSION_NOT_PRESENT
  100.  
  101. proc DestroyDebugUtilsMessengerEXT(instance: VkInstance, debugMessenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks) =
  102.   var vkFunc = cast[proc(instance: VkInstance, messenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}] (vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"))
  103.   echo "vkDestroyDebugUtilsMessengerEXT: ", toHex(cast[uint](vkFunc))
  104.   if vkFunc != nil:
  105.     vkFunc(instance, debugMessenger, pAllocator)
  106.  
  107. proc debugCallback(messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageType: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: VkDebugUtilsMessengerCallbackDataEXT, pUserData: pointer): VkBool32 {.cdecl.} =
  108.   echo "validation layer: ", pCallbackData.pMessage
  109.  
  110.   result = VkBool32(VK_FALSE)
  111.  
  112. proc populateDebugMessengerCreateInfo(createInfo: ptr VkDebugUtilsMessengerCreateInfoEXT) =
  113.   createInfo.sType = cast[VkStructureType](1000128004)
  114.   createInfo.messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT(0x00001101)
  115.   createInfo.messageType = VkDebugUtilsMessageTypeFlagsEXT(7)
  116.   createInfo.pfnUserCallback = debugCallback
  117.  
  118. proc setupDebugMessenger() =
  119.   if not enableValidationLayers: return
  120.  
  121.   var createInfo: VkDebugUtilsMessengerCreateInfoEXT
  122.   populateDebugMessengerCreateInfo(addr createInfo);
  123.  
  124.   if CreateDebugUtilsMessengerEXT(instance, addr createInfo, nil, addr debugMessenger) != VK_SUCCESS:
  125.     raise newException(Exception, "failed to set up debug messenger!");
  126.  
  127. proc checkValidationLayers(): bool =
  128.   var layerCount: uint32 = 0
  129.   discard vkEnumerateInstanceLayerProperties(layerCount.addr, nil)
  130.   var layers = newSeq[VkLayerProperties](layerCount)
  131.   discard vkEnumerateInstanceLayerProperties(layerCount.addr, layers[0].addr)
  132.  
  133.   for validate in validationLayers:
  134.     var found = false
  135.     for layer in layers:
  136.       if layer.layerName.toString() == validate:
  137.         found = true
  138.     if not found:
  139.       return false
  140.     else:
  141.       echo validate, " layer is not supported"
  142.  
  143. proc findQueueFamilies(pDevice: VkPhysicalDevice): QueueFamilyIndices =
  144.  
  145.   var queueFamilyCount: uint32 = 0
  146.   vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr queueFamilyCount, nil)
  147.   var queueFamilies: seq[VkQueueFamilyProperties]  
  148.   queueFamilies.setLen(queueFamilyCount)
  149.   vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr queueFamilyCount, addr queueFamilies[0])
  150.  
  151.   var indice: uint32 = 0
  152.   for queueFamily in queueFamilies:
  153.     if (queueFamily.queueFlags.uint32 and VkQueueGraphicsBit.uint32) > 0'u32:
  154.       result.graphicsFamily = some(indice)
  155.  
  156.     var presentSupport = VkBool32(VK_FALSE)
  157.     discard vkGetPhysicalDeviceSurfaceSupportKHR(pDevice, indice, surface, addr presentSupport)
  158.  
  159.     if int(presentSupport) == VK_TRUE:
  160.       result.presentFamily = some(indice)
  161.  
  162.     if result.isComplete():
  163.       break
  164.  
  165.     indice.inc
  166.  
  167. proc createLogicalDevice() =
  168.   var
  169.     indices = physicalDevice.findQueueFamilies()
  170.     queuePriority = 1.0
  171.     deviceFeatures = newSeq[VkPhysicalDeviceFeatures](1)
  172.  
  173.     deviceQueueCreateInfo = newVkDeviceQueueCreateInfo(
  174.       queueFamilyIndex = indices.graphicsFamily.get(),
  175.       queueCount = 1,
  176.       pQueuePriorities = queuePriority.addr
  177.     )
  178.     deviceCreateInfo = newVkDeviceCreateInfo(
  179.       pQueueCreateInfos = deviceQueueCreateInfo.addr,
  180.       queueCreateInfoCount = 1,
  181.       pEnabledFeatures = deviceFeatures[0].addr,
  182.       enabledExtensionCount = 0,
  183.       enabledLayerCount = 0,
  184.       ppEnabledLayerNames = nil,
  185.       ppEnabledExtensionNames = nil
  186.     )
  187.  
  188.   if vkCreateDevice(physicalDevice, addr deviceCreateInfo, nil, addr device) != VKSuccess:
  189.     echo "failed to create logical device"
  190.  
  191.   echo "Device: ", uint(device)
  192.  
  193.   vkGetDeviceQueue(device, get indices.graphicsFamily, 0, addr graphicsQueue)
  194.   vkGetDeviceQueue(device, get indices.presentFamily, 0, addr presentQueue)
  195.  
  196. proc getRequiredExtensions(): seq[cstring] =
  197.   var glfwExtensionCount: uint32 = 0
  198.   var glfwExtensions: cstringArray
  199.   glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount)
  200.  
  201.   result.setLen(glfwExtensionCount)
  202.  
  203.   for i in 0..<glfwExtensionCount:
  204.     result[i] = glfwExtensions[i]
  205.  
  206.   if enableValidationLayers:
  207.     result.add("VK_EXT_debug_utils")
  208.  
  209.  
  210. proc initWindow() =
  211.   if not glfwInit():
  212.     quit("failed to init glfw")
  213.  
  214.   glfwWindowHint(GLFWClientApi, GLFWNoApi)
  215.   glfwWindowHint(GLFWResizable, GLFWFalse)
  216.  
  217.   window = glfwCreateWindow(800, 600)
  218.  
  219.   if not vkInit():
  220.     quit("failed to load vulkan")
  221.  
  222. proc createInstance() =
  223.   if enableValidationLayers and not checkValidationLayerSupport():
  224.     raise newException(Exception, "validation layers requested, but not available!")
  225.  
  226.   var appInfo: VkApplicationInfo
  227.   appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO
  228.   appInfo.pApplicationName = "Hello Triangle"
  229.   appInfo.applicationVersion = vkMakeVersion(1, 0, 0)
  230.   appInfo.pEngineName = "No Engine"
  231.   appInfo.engineVersion = vkMakeVersion(1, 0, 0)
  232.   appInfo.apiVersion = vkApiVersion1_1
  233.  
  234.   var createInfo: VkInstanceCreateInfo
  235.   createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
  236.   createInfo.pApplicationInfo = addr appInfo
  237.  
  238.   var extensions = getRequiredExtensions()
  239.   createInfo.enabledExtensionCount = uint32(extensions.len())
  240.   createInfo.ppEnabledExtensionNames = cast[cstringArray](addr extensions[0])
  241.  
  242.   var debugCreateInfo: VkDebugUtilsMessengerCreateInfoEXT
  243.   if enableValidationLayers:
  244.     createInfo.enabledLayerCount = (uint32) validationLayers.len()
  245.     createInfo.ppEnabledLayerNames = cast[cstringArray](addr validationLayers[0])
  246.  
  247.     populateDebugMessengerCreateInfo(debugCreateInfo);
  248.     createInfo.pNext = addr debugCreateInfo
  249.   else:
  250.     createInfo.enabledLayerCount = 0;
  251.  
  252.     createInfo.pNext = nil
  253.  
  254.   if vkCreateInstance(addr createInfo, nil, addr instance) != VK_SUCCESS:
  255.     raise newException(Exception, "failed to create instance!")
  256.  
  257. proc createShaderModule(code: TaintedString): VkShaderModule =
  258.   var createInfo: VkShaderModuleCreateInfo = newVkShaderModuleCreateInfo(
  259.     codeSize = (uint) len(code),
  260.     pCode = cast[ptr uint32](code)
  261.   )
  262.  
  263.   if vkCreateShaderModule(device, addr createInfo, nil, addr result) != VK_SUCCESS:
  264.     raise newException(Exception, "Vulkan shader uninitialized")
  265.  
  266. proc createGraphicsPipeline() =
  267.   var vertShaderCode = readFile("vert.spv")
  268.   var fragShaderCode = readFile("frag.spv")
  269.  
  270.   var vertShaderModule = createShaderModule(vertShaderCode)
  271.   var fragShaderModule = createShaderModule(fragShaderCode)
  272.  
  273.   var vertShaderStageInfo = newVkPipelineShaderStageCreateInfo(
  274.     sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  275.     stage = VK_SHADER_STAGE_VERTEX_BIT,
  276.     module = fragShaderModule,
  277.     pName = "main",
  278.     pSpecializationInfo = nil
  279.   )
  280.  
  281.   var fragShaderStageInfo = newVkPipelineShaderStageCreateInfo(
  282.     sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  283.     stage = (VkShaderStageFlagBits) 0x00000080,
  284.     module = fragShaderModule,
  285.     pName = "main",
  286.     pSpecializationInfo = nil
  287.   )
  288.  
  289.   var shaderStages = [vertShaderStageInfo, fragShaderStageInfo]
  290.  
  291.   var vertexInputInfo = newVkPipelineVertexInputStateCreateInfo(
  292.     sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
  293.     vertexBindingDescriptionCount = 0,
  294.     pVertexBindingDescriptions = nil,
  295.     vertexAttributeDescriptionCount = 0,
  296.     pVertexAttributeDescriptions = nil
  297.   )
  298.  
  299.   var inputAssembly = newVkPipelineInputAssemblyStateCreateInfo(
  300.     sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
  301.     topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
  302.     primitiveRestartEnable = VkBool32(VK_FALSE)
  303.   )
  304.  
  305.   var viewport = newVkViewport(
  306.     x = 0.0f,
  307.     y = 0.0f,
  308.     width = (float) swapChainExtent.width,
  309.     height = (float) swapChainExtent.height,
  310.     minDepth = 0.0f,
  311.     maxDepth = 1.0f
  312.   )
  313.  
  314.   var scissor = newVkRect2D(
  315.     offset = newVkOffset2D(0, 0),
  316.     extent = swapChainExtent
  317.   )
  318.  
  319.   var viewportState = newVkPipelineViewportStateCreateInfo(
  320.     sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
  321.     viewportCount = 1,
  322.     pViewports = addr viewport,
  323.     scissorCount = 1,
  324.     pScissors = addr scissor
  325.   )
  326.  
  327.   var rasterizer: VkPipelineRasterizationStateCreateInfo
  328.  
  329.   rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
  330.   rasterizer.depthClampEnable = VkBool32(VK_FALSE)
  331.   rasterizer.rasterizerDiscardEnable = VkBool32(VK_FALSE)
  332.   rasterizer.polygonMode = VK_POLYGON_MODE_FILL
  333.   rasterizer.lineWidth = 1.0f
  334.   rasterizer.cullMode = VkCullModeFlags(2)
  335.   rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE
  336.   rasterizer.depthBiasEnable = VkBool32(VK_FALSE)
  337.  
  338.   var multisampling: VkPipelineMultisampleStateCreateInfo
  339.  
  340.   multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
  341.   multisampling.sampleShadingEnable = VkBool32(VK_FALSE)
  342.   multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
  343.  
  344.   var colorBlendAttachment: VkPipelineColorBlendAttachmentState
  345.  
  346.   colorBlendAttachment.colorWriteMask = VkColorComponentFlags(0x00000001 or 0x00000002 or 0x00000004 or 0x00000008)
  347.   colorBlendAttachment.blendEnable = VkBool32(VK_FALSE)
  348.  
  349.   var colorBlending: VkPipelineColorBlendStateCreateInfo
  350.  
  351.   colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
  352.   colorBlending.logicOpEnable = VkBool32(VK_FALSE)
  353.   colorBlending.logicOp = VK_LOGIC_OP_COPY
  354.   colorBlending.attachmentCount = 1
  355.   colorBlending.pAttachments = addr colorBlendAttachment
  356.   colorBlending.blendConstants = [0.0, 0.0, 0.0, 0.0]
  357.  
  358.   var pipelineLayoutInfo: VkPipelineLayoutCreateInfo
  359.  
  360.   pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
  361.   pipelineLayoutInfo.setLayoutCount = 0
  362.   pipelineLayoutInfo.pushConstantRangeCount = 0
  363.  
  364.   if vkCreatePipelineLayout(device, addr pipelineLayoutInfo, nil, addr pipelineLayout) != VK_SUCCESS:
  365.     raise newException(Exception, "failed to create pipeline layout!")
  366.  
  367.   var pipelineInfo: VkGraphicsPipelineCreateInfo
  368.   pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
  369.   pipelineInfo.stageCount = 2
  370.   pipelineInfo.pStages = addr shaderStages[0]
  371.   pipelineInfo.pVertexInputState = addr vertexInputInfo
  372.   pipelineInfo.pInputAssemblyState = addr inputAssembly
  373.   pipelineInfo.pViewportState = addr viewportState
  374.   pipelineInfo.pRasterizationState = addr rasterizer
  375.   pipelineInfo.pMultisampleState = addr multisampling
  376.   pipelineInfo.pColorBlendState = addr colorBlending
  377.   pipelineInfo.layout = pipelineLayout
  378.   pipelineInfo.renderPass = renderPass
  379.   pipelineInfo.subpass = 0
  380.   pipelineInfo.basePipelineHandle = VkPipeline(VK_NULL_HANDLE)
  381.  
  382.   if vkCreateGraphicsPipelines(device, VkPipelineCache(VK_NULL_HANDLE), 1, addr pipelineInfo, nil, addr graphicsPipeline) != VK_SUCCESS:
  383.     raise newException(Exception, "failed to create graphics pipeline!")
  384.  
  385.   vkDestroyShaderModule(device, fragShaderModule, nil)
  386.   vkDestroyShaderModule(device, vertShaderModule, nil)
  387.  
  388. proc createSurface() =
  389.   var createInfo = newVkWin32SurfaceCreateInfoKHR(
  390.     sType = cast[VkStructureType](1000009000),
  391.     hwnd = cast[vulkan.HWND](getWin32Window(window)),
  392.     hinstance = cast[vulkan.HINSTANCE](GetModuleHandle(nil))
  393.   )
  394.  
  395.   if vkCreateWin32SurfaceKHR(instance, addr createInfo, nil, addr surface) != VK_SUCCESS:
  396.     raise newException(Exception, "failed to create window surface!")
  397.  
  398. proc querySwapChainSupport(device: VkPhysicalDevice): SwapChainSupportDetails =
  399.  
  400.   discard vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &result.capabilities)
  401.  
  402.   var formatCount: uint32
  403.   discard vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr formatCount, nil)
  404.  
  405.   if formatCount != 0:
  406.       result.formats.setLen(formatCount)
  407.       discard vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, addr result.formats[0])
  408.  
  409.   var presentModeCount: uint32
  410.   discard vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nil)
  411.  
  412.   if presentModeCount != 0:
  413.       result.presentModes.setLen(presentModeCount)
  414.       discard vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, addr result.presentModes[0])
  415.  
  416. proc checkDeviceExtensionSupport(device: VkPhysicalDevice): bool =
  417.   var extensionCount: uint32
  418.   discard vkEnumerateDeviceExtensionProperties(device, nil, addr extensionCount, nil)
  419.  
  420.   var availableExtensions = newSeq[VkExtensionProperties](extensionCount)
  421.   discard vkEnumerateDeviceExtensionProperties(device, nil, addr extensionCount, addr availableExtensions[0])
  422.  
  423.   var requiredExtensions = toSeq(deviceExtensions)
  424.  
  425.   for extension in availableExtensions:
  426.     requiredExtensions.keepIf(proc(x: cstring): bool {.closure.} = x != (cstring) extension.extensionName)
  427.  
  428.   result = requiredExtensions.len() == 0
  429.  
  430.  
  431. proc isDeviceSuitable(pDevice: VkPhysicalDevice): bool =
  432.   var indices = findQueueFamilies(pDevice)
  433.   var extensionsSupported = checkDeviceExtensionSupport(pDevice)
  434.  
  435.   echo "Indices: ", indices
  436.   echo "extensionsSupported: ", extensionsSupported
  437.  
  438.   var swapChainAdequate = false
  439.   if extensionsSupported:
  440.     var swapChainSupport = querySwapChainSupport(pDevice)
  441.     swapChainAdequate = swapChainSupport.formats.len != 0 and swapChainSupport.presentModes.len != 0
  442.  
  443.   echo "[indices.isComplete(), extensionsSupported, swapChainAdequate]", [indices.isComplete(), extensionsSupported, swapChainAdequate]
  444.  
  445.   return indices.isComplete() and extensionsSupported and swapChainAdequate
  446.  
  447. proc pickPhysicalDevice() =
  448.   var deviceCount: uint32 = 0
  449.   discard vkEnumeratePhysicalDevices(instance, addr deviceCount, nil)
  450.   var devices = newSeq[VkPhysicalDevice](deviceCount)
  451.   discard vkEnumeratePhysicalDevices(instance, addr deviceCount, addr devices[0])
  452.  
  453.   echo deviceCount
  454.  
  455.   for pDevice in devices:
  456.     if pDevice.isDeviceSuitable():
  457.       physicalDevice = pDevice
  458.  
  459.   if VkNonDispatchableHandle(physicalDevice) == VK_NULL_HANDLE:
  460.     raise newException(Exception, "failed to find a suitable GPU!");
  461.  
  462. proc chooseSwapSurfaceFormat(availableFormats: seq[VkSurfaceFormatKHR]): VkSurfaceFormatKHR =
  463.   for availableFormat in availableFormats:
  464.     if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB and availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR):
  465.       result = availableFormat
  466.       return
  467.  
  468.   result = availableFormats[0]
  469.  
  470. proc chooseSwapPresentMode(availablePresentModes: seq[VkPresentModeKHR] ): VkPresentModeKHR =
  471.   for availablePresentMode in availablePresentModes:
  472.     if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR):
  473.       result = availablePresentMode
  474.       return
  475.  
  476.   result = VK_PRESENT_MODE_FIFO_KHR
  477.  
  478. proc chooseSwapExtent(capabilities: VkSurfaceCapabilitiesKHR): VkExtent2D =
  479.   if capabilities.currentExtent.width != uint32.high():  
  480.     result = capabilities.currentExtent
  481.   else:
  482.     var actualExtent = newVkExtent2D(WIDTH, HEIGHT)
  483.  
  484.     actualExtent.width = max(capabilities.minImageExtent.width, min(capabilities.maxImageExtent.width, actualExtent.width))
  485.     actualExtent.height = max(capabilities.minImageExtent.height, min(capabilities.maxImageExtent.height, actualExtent.height))
  486.  
  487.     result = actualExtent
  488.  
  489. proc createSwapChain() =
  490.   var swapChainSupport = querySwapChainSupport(physicalDevice)
  491.  
  492.   var surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats)
  493.   var presentMode = chooseSwapPresentMode(swapChainSupport.presentModes)
  494.   var extent = chooseSwapExtent(swapChainSupport.capabilities)
  495.  
  496.   var imageCount: uint32 = swapChainSupport.capabilities.minImageCount + 1
  497.   if (swapChainSupport.capabilities.maxImageCount > 0 and imageCount > swapChainSupport.capabilities.maxImageCount):
  498.       imageCount = swapChainSupport.capabilities.maxImageCount
  499.  
  500.   echo ((uint(surfaceFormat.format), uint(surfaceFormat.colorSpace), uint(presentMode)))
  501.  
  502.   var createInfo: VkSwapchainCreateInfoKHR
  503.  
  504.   createInfo.sType = cast[VkStructureType](1000001000)
  505.   createInfo.surface = surface
  506.   createInfo.pNext = nil
  507.  
  508.   createInfo.minImageCount = imageCount
  509.   createInfo.imageFormat = surfaceFormat.format
  510.   createInfo.imageColorSpace = surfaceFormat.colorSpace
  511.   createInfo.imageExtent = extent
  512.   createInfo.imageArrayLayers = 1
  513.   createInfo.imageUsage = cast[VkImageUsageFlags](0x00000010)
  514.  
  515.   var indices = findQueueFamilies(physicalDevice)
  516.   var queueFamilyIndices {.global.}: array[2, uint32]  
  517.   queueFamilyIndices = [get indices.graphicsFamily, get indices.presentFamily]
  518.  
  519.   if (isSome indices.graphicsFamily) != (isSome indices.presentFamily):
  520.     createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT
  521.     createInfo.queueFamilyIndexCount = 2
  522.     createInfo.pQueueFamilyIndices = addr queueFamilyIndices[0]
  523.   else:
  524.     createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE
  525.     createInfo.pQueueFamilyIndices = nil
  526.  
  527.   createInfo.preTransform = swapChainSupport.capabilities.currentTransform
  528.   createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
  529.   createInfo.presentMode = presentMode
  530.   createInfo.clipped = VkBool32(VK_TRUE)
  531.  
  532.   createInfo.oldSwapchain = VkSwapchainKHR(VK_NULL_HANDLE)
  533.  
  534.   if vkCreateSwapchainKHR(device, addr createInfo, nil, addr swapChain) != VK_SUCCESS:
  535.     raise newException(Exception, "failed to create swap chain!")
  536.  
  537.   echo "SwapchainHandle: ", toHex(uint(swapChain))
  538.  
  539.   discard vkGetSwapchainImagesKHR(device, swapChain, addr imageCount, nil)
  540.   swapChainImages.setLen(imageCount)
  541.   discard vkGetSwapchainImagesKHR(device, swapChain, addr imageCount, addr swapChainImages[0])
  542.  
  543.   swapChainImageFormat = surfaceFormat.format
  544.   swapChainExtent = extent
  545.  
  546. proc createImageViews() =
  547.   swapChainImageViews.setLen(len(swapChainImages))
  548.  
  549.   for i, swapChainImage in pairs(swapChainImages):
  550.     var createInfo: VkImageViewCreateInfo
  551.     createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
  552.     createInfo.pNext = nil
  553.     createInfo.image = swapChainImage
  554.     createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D
  555.     createInfo.format = swapChainImageFormat
  556.     createInfo.components = newVkComponentMapping(
  557.       VK_COMPONENT_SWIZZLE_IDENTITY,
  558.       VK_COMPONENT_SWIZZLE_IDENTITY,
  559.       VK_COMPONENT_SWIZZLE_IDENTITY,
  560.       VK_COMPONENT_SWIZZLE_IDENTITY
  561.       )
  562.     createInfo.subresourceRange = newVkImageSubresourceRange(
  563.       aspectMask = VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT),
  564.       baseMipLevel = 0,
  565.       levelCount = 1,
  566.       baseArrayLayer = 0,
  567.       layerCount = 1
  568.     )
  569.    
  570.     echo "Indice: ", i, " Device: ", toHex(uint(device)), " swapChainImage: ", toHex(cast[uint](swapChainImage))
  571.     if vkCreateImageView(device, addr createInfo, nil, addr swapChainImageViews[i]) != VK_SUCCESS:
  572.       raise newException(Exception, "failed to create image views!")
  573.  
  574. proc createRenderPass() =
  575.   var colorAttachment: VkAttachmentDescription
  576.   colorAttachment.format = swapChainImageFormat
  577.   colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT
  578.   colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR
  579.   colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE
  580.   colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE
  581.   colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE
  582.   colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
  583.   colorAttachment.finalLayout = cast[VkImageLayout](1000001002)
  584.  
  585.   var colorAttachmentRef: VkAttachmentReference
  586.   colorAttachmentRef.attachment = 0
  587.   colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
  588.  
  589.   var subpass: VkSubpassDescription
  590.   subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS
  591.   subpass.colorAttachmentCount = 1
  592.   subpass.pColorAttachments = addr colorAttachmentRef
  593.  
  594.   var renderPassInfo: VkRenderPassCreateInfo
  595.   renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
  596.   renderPassInfo.attachmentCount = 1
  597.   renderPassInfo.pAttachments = addr colorAttachment
  598.   renderPassInfo.subpassCount = 1
  599.   renderPassInfo.pSubpasses = addr subpass
  600.  
  601.   if vkCreateRenderPass(device, addr renderPassInfo, nil, addr renderPass) != VK_SUCCESS:
  602.     raise newException(Exception, "failed to create render pass!")
  603.  
  604. proc createFramebuffers() =
  605.   swapChainFramebuffers.setLen(swapChainImageViews.len())
  606.  
  607.   for i, swapChainImageView in pairs(swapChainImageViews):
  608.     var attachments = [ swapChainImageView ]
  609.  
  610.     var framebufferInfo: VkFramebufferCreateInfo
  611.     framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
  612.     framebufferInfo.renderPass = renderPass
  613.     framebufferInfo.attachmentCount = 1
  614.     framebufferInfo.pAttachments = addr attachments[0]
  615.     framebufferInfo.width = swapChainExtent.width
  616.     framebufferInfo.height = swapChainExtent.height
  617.     framebufferInfo.layers = 1
  618.  
  619.     if (vkCreateFramebuffer(device, addr framebufferInfo, nil, addr swapChainFramebuffers[i]) != VK_SUCCESS):
  620.       raise newException(Exception, "failed to create framebuffer!")
  621.  
  622. proc createCommandPool() =
  623.   var queueFamilyIndices = findQueueFamilies(physicalDevice)
  624.  
  625.   var poolInfo: VkCommandPoolCreateInfo
  626.   poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
  627.   poolInfo.queueFamilyIndex = get queueFamilyIndices.graphicsFamily
  628.  
  629.   if vkCreateCommandPool(device, addr poolInfo, nil, addr commandPool) != VK_SUCCESS:
  630.     raise newException(Exception, "failed to create command pool!")
  631.  
  632. proc createCommandBuffers() =
  633.   commandBuffers.setLen(swapChainFramebuffers.len())
  634.  
  635.   var allocInfo: VkCommandBufferAllocateInfo
  636.   allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
  637.   allocInfo.commandPool = commandPool
  638.   allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY
  639.   allocInfo.commandBufferCount = (uint32) commandBuffers.len()
  640.  
  641.   if vkAllocateCommandBuffers(device, addr allocInfo, addr commandBuffers[0]) != VK_SUCCESS:
  642.     raise newException(Exception, "failed to allocate command buffers!")
  643.  
  644.   for i, commandBuffer in pairs(commandBuffers):
  645.     var beginInfo: VkCommandBufferBeginInfo
  646.     beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
  647.  
  648.     if vkBeginCommandBuffer(commandBuffer, addr beginInfo) != VK_SUCCESS:
  649.       raise newException(Exception, "failed to begin recording command buffer!")
  650.  
  651.     var renderPassInfo: VkRenderPassBeginInfo
  652.     renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
  653.     renderPassInfo.renderPass = renderPass
  654.     renderPassInfo.framebuffer = swapChainFramebuffers[i]
  655.     renderPassInfo.renderArea.offset = newVkOffset2D(0, 0)
  656.     renderPassInfo.renderArea.extent = swapChainExtent
  657.  
  658.     var clearColor: VkClearValue
  659.     clearColor.color.float32 = [0.0, 0.0, 0.0, 1.0]
  660.     clearColor.depthStencil = newVkClearDepthStencilValue(0.0, 0)
  661.     renderPassInfo.clearValueCount = 1
  662.     renderPassInfo.pClearValues = addr clearColor
  663.  
  664.     vkCmdBeginRenderPass(commandBuffer, addr renderPassInfo, VK_SUBPASS_CONTENTS_INLINE)
  665.  
  666.     vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline)
  667.  
  668.     vkCmdDraw(commandBuffer, 3, 1, 0, 0)
  669.  
  670.     vkCmdEndRenderPass(commandBuffer)
  671.  
  672.     if vkEndCommandBuffer(commandBuffer) != VK_SUCCESS:
  673.       raise newException(Exception, "failed to record command buffer!")
  674.  
  675. proc createSyncObjects() =
  676.   imageAvailableSemaphores.setLen(MAX_FRAMES_IN_FLIGHT)
  677.   renderFinishedSemaphores.setLen(MAX_FRAMES_IN_FLIGHT)
  678.   inFlightFences.setLen(MAX_FRAMES_IN_FLIGHT)
  679.   imagesInFlight.setLen(swapChainImages.len())
  680.  
  681.   var semaphoreInfo: VkSemaphoreCreateInfo
  682.   semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
  683.  
  684.   var fenceInfo: VkFenceCreateInfo
  685.   fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
  686.   fenceInfo.flags = VkFenceCreateFlags(VK_FENCE_CREATE_SIGNALED_BIT)
  687.  
  688.   for i in {0, MAX_FRAMES_IN_FLIGHT}:
  689.     if (vkCreateSemaphore(device, addr semaphoreInfo, nil, addr imageAvailableSemaphores[i]) != VK_SUCCESS or
  690.         vkCreateSemaphore(device, addr semaphoreInfo, nil, addr renderFinishedSemaphores[i]) != VK_SUCCESS or
  691.         vkCreateFence(device, addr fenceInfo, nil, addr inFlightFences[i]) != VK_SUCCESS):
  692.       raise newException(Exception, "failed to create synchronization objects for a frame!")
  693.  
  694. proc drawFrame() =
  695.   discard vkWaitForFences(device, 1, addr inFlightFences[currentFrame], VkBool32(VK_TRUE), uint64.high())
  696.  
  697.   var imageIndex: uint32
  698.   discard vkAcquireNextImageKHR(device, swapChain, uint64.high(), imageAvailableSemaphores[currentFrame], VkFence(VK_NULL_HANDLE), addr imageIndex)
  699.  
  700.   if VkNonDispatchableHandle(imagesInFlight[imageIndex]) != VK_NULL_HANDLE:
  701.     discard vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VkBool32(VK_TRUE), uint64.high())
  702.   imagesInFlight[imageIndex] = inFlightFences[currentFrame]
  703.  
  704.   var submitInfo: VkSubmitInfo
  705.   submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO
  706.  
  707.   var waitSemaphores = [imageAvailableSemaphores[currentFrame]]
  708.   var waitStages = [ VkPipelineStageFlags(0x00000400) ]
  709.   submitInfo.waitSemaphoreCount = 1
  710.   submitInfo.pWaitSemaphores = addr waitSemaphores[0]
  711.   submitInfo.pWaitDstStageMask = addr waitStages[0]
  712.  
  713.   submitInfo.commandBufferCount = 1
  714.   submitInfo.pCommandBuffers = addr commandBuffers[imageIndex]
  715.  
  716.   var signalSemaphores = [ renderFinishedSemaphores[currentFrame] ]
  717.   submitInfo.signalSemaphoreCount = 1
  718.   submitInfo.pSignalSemaphores = addr signalSemaphores[0]
  719.  
  720.   discard vkResetFences(device, 1, addr inFlightFences[currentFrame])
  721.  
  722.   if vkQueueSubmit(graphicsQueue, 1, addr submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS:
  723.     raise newException(Exception, "failed to submit draw command buffer!")
  724.  
  725.   var presentInfo: VkPresentInfoKHR
  726.   presentInfo.sType = cast[VkStructureType](1000001001)
  727.  
  728.   presentInfo.waitSemaphoreCount = 1
  729.   presentInfo.pWaitSemaphores = addr signalSemaphores[0]
  730.  
  731.   var swapChains = [swapChain]
  732.   presentInfo.swapchainCount = 1
  733.   presentInfo.pSwapchains = addr swapChains[0]
  734.  
  735.   presentInfo.pImageIndices = addr imageIndex
  736.  
  737.   discard vkQueuePresentKHR(presentQueue, addr presentInfo)
  738.  
  739.   currentFrame = (currentFrame + 1) mod MAX_FRAMES_IN_FLIGHT
  740.  
  741. template mention(name: string, body: untyped): untyped =
  742.   echo "Attempting ", `name`
  743.   `body`
  744.  
  745. proc initVulkan() =
  746.   mention "createInstance":       createInstance()
  747.   #mention "setupDebugMessenger":  setupDebugMessenger()
  748.   mention "createSurface":        createSurface()
  749.   mention "pickPhysicalDevice":   pickPhysicalDevice()
  750.   mention "createLogicalDevice":  createLogicalDevice()
  751.   mention "createSwapChain":      createSwapChain()
  752.   mention "createImageViews":     createImageViews()
  753.   mention "createRenderPass":     createRenderPass()
  754.   mention "createGraphicsPipeline": createGraphicsPipeline()
  755.   mention "createFramebuffers":   createFramebuffers()
  756.   mention "createCommandPool":    createCommandPool()
  757.   mention "createCommandBuffers": createCommandBuffers()
  758.   mention "createSyncObjects":    createSyncObjects()
  759.  
  760. proc cleanUp() =
  761.   for i in { 0, MAX_FRAMES_IN_FLIGHT }:
  762.     vkDestroySemaphore(device, renderFinishedSemaphores[i], nil)
  763.     vkDestroySemaphore(device, imageAvailableSemaphores[i], nil)
  764.     vkDestroyFence(device, inFlightFences[i], nil)
  765.  
  766.   vkDestroyCommandPool(device, commandPool, nil)
  767.  
  768.   for framebuffer in swapChainFramebuffers:
  769.     vkDestroyFramebuffer(device, framebuffer, nil)
  770.  
  771.   vkDestroyPipeline(device, graphicsPipeline, nil)
  772.   vkDestroyPipelineLayout(device, pipelineLayout, nil)
  773.   vkDestroyRenderPass(device, renderPass, nil)
  774.  
  775.   for imageView in swapChainImageViews:
  776.     vkDestroyImageView(device, imageView, nil)
  777.  
  778.   vkDestroySwapchainKHR(device, swapChain, nil)
  779.   vkDestroyDevice(device, nil)
  780.  
  781.   #if enableValidationLayers:
  782.   #  DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nil)
  783.  
  784.   vkDestroySurfaceKHR(instance, surface, nil)
  785.   vkDestroyInstance(instance, nil)
  786.  
  787.   window.destroyWindow()
  788.   glfwTerminate()
  789.  
  790.  
  791. proc loop() =
  792.   while not window.windowShouldClose():
  793.     var count {.global.}: int32  = 29
  794.     count.inc
  795.     if (count == 30):
  796.       echo "Loop is definitely working"
  797.       count = 0
  798.     glfwPollEvents()
  799.     drawFrame()
  800.  
  801.   discard vkQueueWaitIdle(presentQueue)
  802.  
  803. proc main() =
  804.   loadVK_KHR_win32_surface()
  805.   loadVK_KHR_surface()
  806.   loadVK_KHR_swapchain()
  807.   loadVK_KHR_display_swapchain()
  808.  
  809.   mention "initWindow": initWindow()
  810.   initVulkan()
  811.   loop()
  812.   cleanUp()
  813.  
  814. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement