Mercurial > games > semicongine
comparison src/vulkan_helpers.nim @ 461:59d861a6a5c4
add: initial version
author | Sam <sam@basx.dev> |
---|---|
date | Wed, 14 Dec 2022 00:49:35 +0700 |
parents | |
children | bb2a7d3a7003 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 461:59d861a6a5c4 |
---|---|
1 import std/strutils | |
2 import std/enumerate | |
3 import vulkan | |
4 | |
5 when defined(release): | |
6 const ENABLEVULKANVALIDATIONLAYERS = false | |
7 else: | |
8 const ENABLEVULKANVALIDATIONLAYERS = true | |
9 | |
10 | |
11 template checkVkResult*(call: untyped) = | |
12 let value = call | |
13 if value != VK_SUCCESS: | |
14 raise newException(Exception, "Vulkan error: " & astToStr(call) & " returned " & $value) | |
15 | |
16 | |
17 proc VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} = | |
18 (variant shl 29) or (major shl 22) or (minor shl 12) or patch | |
19 | |
20 proc getInstanceExtensions*(): seq[string] = | |
21 var extensionCount: uint32 | |
22 checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), nil) | |
23 var extensions = newSeq[VkExtensionProperties](extensionCount) | |
24 checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), addr(extensions[0])) | |
25 | |
26 for extension in extensions: | |
27 result.add(join(extension.extensionName).strip(chars={char(0)})) | |
28 | |
29 | |
30 proc getDeviceExtensions*(device: VkPhysicalDevice): seq[string] = | |
31 var extensionCount: uint32 | |
32 checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), nil) | |
33 var extensions = newSeq[VkExtensionProperties](extensionCount) | |
34 checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), addr(extensions[0])) | |
35 | |
36 for extension in extensions: | |
37 result.add(join(extension.extensionName).strip(chars={char(0)})) | |
38 | |
39 | |
40 proc getValidationLayers*(): seq[string] = | |
41 var n_layers: uint32 | |
42 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), nil) | |
43 var layers = newSeq[VkLayerProperties](n_layers) | |
44 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), addr(layers[0])) | |
45 | |
46 for layer in layers: | |
47 result.add(join(layer.layerName).strip(chars={char(0)})) | |
48 | |
49 | |
50 proc getVulkanPhysicalDevices*(instance: VkInstance): seq[VkPhysicalDevice] = | |
51 var n_devices: uint32 | |
52 checkVkResult vkEnumeratePhysicalDevices(instance, addr(n_devices), nil) | |
53 result = newSeq[VkPhysicalDevice](n_devices) | |
54 checkVkResult vkEnumeratePhysicalDevices(instance, addr(n_devices), addr(result[0])) | |
55 | |
56 | |
57 proc getQueueFamilies*(device: VkPhysicalDevice): seq[VkQueueFamilyProperties] = | |
58 var n_queuefamilies: uint32 | |
59 vkGetPhysicalDeviceQueueFamilyProperties(device, addr(n_queuefamilies), nil) | |
60 result = newSeq[VkQueueFamilyProperties](n_queuefamilies) | |
61 vkGetPhysicalDeviceQueueFamilyProperties(device, addr(n_queuefamilies), addr(result[0])) | |
62 | |
63 | |
64 proc getDeviceSurfaceFormats*(device: VkPhysicalDevice, surface: VkSurfaceKHR): seq[VkSurfaceFormatKHR] = | |
65 var n_formats: uint32 | |
66 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr(n_formats), nil); | |
67 result = newSeq[VkSurfaceFormatKHR](n_formats) | |
68 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr(n_formats), addr(result[0])) | |
69 | |
70 | |
71 proc getDeviceSurfacePresentModes*(device: VkPhysicalDevice, surface: VkSurfaceKHR): seq[VkPresentModeKHR] = | |
72 var n_modes: uint32 | |
73 checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, addr(n_modes), nil); | |
74 result = newSeq[VkPresentModeKHR](n_modes) | |
75 checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, addr(n_modes), addr(result[0])) | |
76 | |
77 | |
78 proc getSwapChainImages*(device: VkDevice, swapChain: VkSwapchainKHR): seq[VkImage] = | |
79 var n_images: uint32 | |
80 checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), nil); | |
81 result = newSeq[VkImage](n_images) | |
82 checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), addr(result[0])); | |
83 | |
84 | |
85 proc getPresentMode*(modes: seq[VkPresentModeKHR]): VkPresentModeKHR = | |
86 let preferredModes = [ | |
87 VK_PRESENT_MODE_MAILBOX_KHR, | |
88 VK_PRESENT_MODE_FIFO_RELAXED_KHR, | |
89 VK_PRESENT_MODE_FIFO_KHR, | |
90 VK_PRESENT_MODE_IMMEDIATE_KHR, | |
91 ] | |
92 for preferredMode in preferredModes: | |
93 for mode in modes: | |
94 if preferredMode == mode: | |
95 return mode | |
96 # should never be reached, but seems to be garuanteed by vulkan specs to always be available | |
97 return VK_PRESENT_MODE_FIFO_KHR | |
98 | |
99 | |
100 proc createVulkanInstance*(vulkanVersion: uint32): VkInstance = | |
101 var requiredExtensions = [ | |
102 "VK_EXT_acquire_xlib_display".cstring, | |
103 "VK_EXT_direct_mode_display".cstring, | |
104 "VK_KHR_display".cstring, | |
105 "VK_KHR_surface".cstring, | |
106 "VK_KHR_xlib_surface".cstring, | |
107 ] | |
108 let availableExtensions = getInstanceExtensions() | |
109 for extension in requiredExtensions: | |
110 assert $extension in availableExtensions | |
111 | |
112 let desiredLayers = ["VK_LAYER_KHRONOS_validation".cstring, "VK_LAYER_MESA_overlay".cstring] | |
113 let availableLayers = getValidationLayers() | |
114 var usableLayers = newSeq[cstring]() | |
115 | |
116 when ENABLEVULKANVALIDATIONLAYERS: | |
117 for layer in desiredLayers: | |
118 if $layer in availableLayers: | |
119 usableLayers.add(layer) | |
120 | |
121 echo "Using validation layers: ", usableLayers | |
122 echo "Using extensions: ", requiredExtensions | |
123 | |
124 var appinfo = VkApplicationInfo( | |
125 sType: VK_STRUCTURE_TYPE_APPLICATION_INFO, | |
126 pApplicationName: "Hello Triangle", | |
127 pEngineName: "Custom engine", | |
128 apiVersion: vulkanVersion, | |
129 ) | |
130 var createinfo = VkInstanceCreateInfo( | |
131 sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, | |
132 pApplicationInfo: addr(appinfo), | |
133 enabledLayerCount: usableLayers.len.uint32, | |
134 ppEnabledLayerNames: cast[ptr UncheckedArray[cstring]](addr(usableLayers[0])), | |
135 enabledExtensionCount: requiredExtensions.len.uint32, | |
136 ppEnabledExtensionNames: cast[ptr UncheckedArray[cstring]](addr(requiredExtensions)) | |
137 ) | |
138 checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result)) | |
139 | |
140 loadVK_KHR_surface() | |
141 loadVK_KHR_xlib_surface() | |
142 loadVK_KHR_swapchain() | |
143 | |
144 | |
145 proc getVulcanDevice*( | |
146 physicalDevice: var VkPhysicalDevice, | |
147 features: var VkPhysicalDeviceFeatures, | |
148 selectedQueueFamily: uint32, | |
149 ): (VkDevice, VkQueue) = | |
150 # setup queue and device | |
151 var priority = 1.0'f32 | |
152 var queueCreateInfo = VkDeviceQueueCreateInfo( | |
153 sType: VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, | |
154 queueFamilyIndex: uint32(selectedQueueFamily), | |
155 queueCount: 1, | |
156 pQueuePriorities: addr(priority), | |
157 ) | |
158 | |
159 var requiredExtensions = ["VK_KHR_swapchain".cstring] | |
160 var deviceCreateInfo = VkDeviceCreateInfo( | |
161 sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, | |
162 pQueueCreateInfos: addr(queueCreateInfo), | |
163 queueCreateInfoCount: 1, | |
164 pEnabledFeatures: addr(features), | |
165 enabledExtensionCount: requiredExtensions.len.uint32, | |
166 ppEnabledExtensionNames: cast[ptr UncheckedArray[cstring]](addr(requiredExtensions)) | |
167 ) | |
168 checkVkResult vkCreateDevice(physicalDevice, addr(deviceCreateInfo), nil, addr(result[0])) | |
169 vkGetDeviceQueue(result[0], selectedQueueFamily, 0'u32, addr(result[1])); |