Mercurial > games > semicongine
comparison src/vulkan_helpers.nim @ 5:4ed9cb098315
add: structure code for crossplatform, add some input handling + bugfixes
| author | Sam <sam@basx.dev> |
|---|---|
| date | Thu, 22 Dec 2022 00:06:40 +0700 |
| parents | af9183acb173 |
| children | 0660ba9d1930 |
comparison
equal
deleted
inserted
replaced
| 4:af9183acb173 | 5:4ed9cb098315 |
|---|---|
| 3 import std/strformat | 3 import std/strformat |
| 4 import std/logging | 4 import std/logging |
| 5 | 5 |
| 6 import ./glslang/glslang | 6 import ./glslang/glslang |
| 7 import ./vulkan | 7 import ./vulkan |
| 8 import ./window | |
| 8 | 9 |
| 9 when defined(release): | 10 when defined(release): |
| 10 const ENABLEVULKANVALIDATIONLAYERS* = false | 11 const ENABLEVULKANVALIDATIONLAYERS* = false |
| 11 else: | 12 else: |
| 12 const ENABLEVULKANVALIDATIONLAYERS* = true | 13 const ENABLEVULKANVALIDATIONLAYERS* = true |
| 19 debug(&"CALLING vulkan: {astToStr(call)}") | 20 debug(&"CALLING vulkan: {astToStr(call)}") |
| 20 let value = call | 21 let value = call |
| 21 if value != VK_SUCCESS: | 22 if value != VK_SUCCESS: |
| 22 raise newException(Exception, "Vulkan error: " & astToStr(call) & " returned " & $value) | 23 raise newException(Exception, "Vulkan error: " & astToStr(call) & " returned " & $value) |
| 23 | 24 |
| 25 func addrOrNil[T](obj: var openArray[T]): ptr T = | |
| 26 if obj.len > 0: addr(obj[0]) else: nil | |
| 24 | 27 |
| 25 proc VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} = | 28 proc VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} = |
| 26 (variant shl 29) or (major shl 22) or (minor shl 12) or patch | 29 (variant shl 29) or (major shl 22) or (minor shl 12) or patch |
| 27 | 30 |
| 28 | 31 |
| 46 | 49 |
| 47 proc getInstanceExtensions*(): seq[string] = | 50 proc getInstanceExtensions*(): seq[string] = |
| 48 var extensionCount: uint32 | 51 var extensionCount: uint32 |
| 49 checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), nil) | 52 checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), nil) |
| 50 var extensions = newSeq[VkExtensionProperties](extensionCount) | 53 var extensions = newSeq[VkExtensionProperties](extensionCount) |
| 51 checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), addr(extensions[0])) | 54 checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), addrOrNil(extensions)) |
| 52 | 55 |
| 53 for extension in extensions: | 56 for extension in extensions: |
| 54 result.add(cleanString(extension.extensionName)) | 57 result.add(cleanString(extension.extensionName)) |
| 55 | 58 |
| 56 | 59 |
| 57 proc getDeviceExtensions*(device: VkPhysicalDevice): seq[string] = | 60 proc getDeviceExtensions*(device: VkPhysicalDevice): seq[string] = |
| 58 var extensionCount: uint32 | 61 var extensionCount: uint32 |
| 59 checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), nil) | 62 checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), nil) |
| 60 var extensions = newSeq[VkExtensionProperties](extensionCount) | 63 var extensions = newSeq[VkExtensionProperties](extensionCount) |
| 61 checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), addr(extensions[0])) | 64 checkVkResult vkEnumerateDeviceExtensionProperties(device, nil, addr(extensionCount), addrOrNil(extensions)) |
| 62 | 65 |
| 63 for extension in extensions: | 66 for extension in extensions: |
| 64 result.add(cleanString(extension.extensionName)) | 67 result.add(cleanString(extension.extensionName)) |
| 65 | 68 |
| 66 | 69 |
| 67 proc getValidationLayers*(): seq[string] = | 70 proc getValidationLayers*(): seq[string] = |
| 68 var n_layers: uint32 | 71 var n_layers: uint32 |
| 69 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), nil) | 72 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), nil) |
| 70 var layers = newSeq[VkLayerProperties](n_layers) | 73 var layers = newSeq[VkLayerProperties](n_layers) |
| 71 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), addr(layers[0])) | 74 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), addrOrNil(layers)) |
| 72 | 75 |
| 73 for layer in layers: | 76 for layer in layers: |
| 74 result.add(cleanString(layer.layerName)) | 77 result.add(cleanString(layer.layerName)) |
| 75 | 78 |
| 76 | 79 |
| 77 proc getVulkanPhysicalDevices*(instance: VkInstance): seq[VkPhysicalDevice] = | 80 proc getVulkanPhysicalDevices*(instance: VkInstance): seq[VkPhysicalDevice] = |
| 78 var n_devices: uint32 | 81 var n_devices: uint32 |
| 79 checkVkResult vkEnumeratePhysicalDevices(instance, addr(n_devices), nil) | 82 checkVkResult vkEnumeratePhysicalDevices(instance, addr(n_devices), nil) |
| 80 result = newSeq[VkPhysicalDevice](n_devices) | 83 result = newSeq[VkPhysicalDevice](n_devices) |
| 81 checkVkResult vkEnumeratePhysicalDevices(instance, addr(n_devices), addr(result[0])) | 84 checkVkResult vkEnumeratePhysicalDevices(instance, addr(n_devices), addrOrNil(result)) |
| 82 | 85 |
| 83 | 86 |
| 84 proc getQueueFamilies*(device: VkPhysicalDevice): seq[VkQueueFamilyProperties] = | 87 proc getQueueFamilies*(device: VkPhysicalDevice): seq[VkQueueFamilyProperties] = |
| 85 var n_queuefamilies: uint32 | 88 var n_queuefamilies: uint32 |
| 86 vkGetPhysicalDeviceQueueFamilyProperties(device, addr(n_queuefamilies), nil) | 89 vkGetPhysicalDeviceQueueFamilyProperties(device, addr(n_queuefamilies), nil) |
| 87 result = newSeq[VkQueueFamilyProperties](n_queuefamilies) | 90 result = newSeq[VkQueueFamilyProperties](n_queuefamilies) |
| 88 vkGetPhysicalDeviceQueueFamilyProperties(device, addr(n_queuefamilies), addr(result[0])) | 91 vkGetPhysicalDeviceQueueFamilyProperties(device, addr(n_queuefamilies), addrOrNil(result)) |
| 89 | 92 |
| 90 | 93 |
| 91 proc getDeviceSurfaceFormats*(device: VkPhysicalDevice, surface: VkSurfaceKHR): seq[VkSurfaceFormatKHR] = | 94 proc getDeviceSurfaceFormats*(device: VkPhysicalDevice, surface: VkSurfaceKHR): seq[VkSurfaceFormatKHR] = |
| 92 var n_formats: uint32 | 95 var n_formats: uint32 |
| 93 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr(n_formats), nil); | 96 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr(n_formats), nil); |
| 94 result = newSeq[VkSurfaceFormatKHR](n_formats) | 97 result = newSeq[VkSurfaceFormatKHR](n_formats) |
| 95 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr(n_formats), addr(result[0])) | 98 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, addr(n_formats), addrOrNil(result)) |
| 96 | 99 |
| 97 | 100 |
| 98 proc getDeviceSurfacePresentModes*(device: VkPhysicalDevice, surface: VkSurfaceKHR): seq[VkPresentModeKHR] = | 101 proc getDeviceSurfacePresentModes*(device: VkPhysicalDevice, surface: VkSurfaceKHR): seq[VkPresentModeKHR] = |
| 99 var n_modes: uint32 | 102 var n_modes: uint32 |
| 100 checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, addr(n_modes), nil); | 103 checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, addr(n_modes), nil); |
| 101 result = newSeq[VkPresentModeKHR](n_modes) | 104 result = newSeq[VkPresentModeKHR](n_modes) |
| 102 checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, addr(n_modes), addr(result[0])) | 105 checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, addr(n_modes), addrOrNil(result)) |
| 103 | 106 |
| 104 | 107 |
| 105 proc getSwapChainImages*(device: VkDevice, swapChain: VkSwapchainKHR): seq[VkImage] = | 108 proc getSwapChainImages*(device: VkDevice, swapChain: VkSwapchainKHR): seq[VkImage] = |
| 106 var n_images: uint32 | 109 var n_images: uint32 |
| 107 checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), nil); | 110 checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), nil); |
| 108 result = newSeq[VkImage](n_images) | 111 result = newSeq[VkImage](n_images) |
| 109 checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), addr(result[0])); | 112 checkVkResult vkGetSwapchainImagesKHR(device, swapChain, addr(n_images), addrOrNil(result)); |
| 110 | 113 |
| 111 | 114 |
| 112 proc getPresentMode*(modes: seq[VkPresentModeKHR]): VkPresentModeKHR = | 115 proc getPresentMode*(modes: seq[VkPresentModeKHR]): VkPresentModeKHR = |
| 113 let preferredModes = [ | 116 let preferredModes = [ |
| 114 VK_PRESENT_MODE_MAILBOX_KHR, # triple buffering | 117 VK_PRESENT_MODE_MAILBOX_KHR, # triple buffering |
| 159 ) | 162 ) |
| 160 var createinfo = VkInstanceCreateInfo( | 163 var createinfo = VkInstanceCreateInfo( |
| 161 sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, | 164 sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, |
| 162 pApplicationInfo: addr(appinfo), | 165 pApplicationInfo: addr(appinfo), |
| 163 enabledLayerCount: usableLayers.len.uint32, | 166 enabledLayerCount: usableLayers.len.uint32, |
| 164 ppEnabledLayerNames: cast[ptr UncheckedArray[cstring]](addr(usableLayers[0])), | 167 ppEnabledLayerNames: cast[ptr UncheckedArray[cstring]](addrOrNil(usableLayers)), |
| 165 enabledExtensionCount: requiredExtensions.len.uint32, | 168 enabledExtensionCount: requiredExtensions.len.uint32, |
| 166 ppEnabledExtensionNames: cast[ptr UncheckedArray[cstring]](addr(requiredExtensions)) | 169 ppEnabledExtensionNames: cast[ptr UncheckedArray[cstring]](addr(requiredExtensions)) |
| 167 ) | 170 ) |
| 168 checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result)) | 171 checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result)) |
| 169 | 172 |
| 194 | 197 |
| 195 var requiredExtensions = ["VK_KHR_swapchain".cstring] | 198 var requiredExtensions = ["VK_KHR_swapchain".cstring] |
| 196 var deviceCreateInfo = VkDeviceCreateInfo( | 199 var deviceCreateInfo = VkDeviceCreateInfo( |
| 197 sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, | 200 sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, |
| 198 queueCreateInfoCount: uint32(queueCreateInfo.len), | 201 queueCreateInfoCount: uint32(queueCreateInfo.len), |
| 199 pQueueCreateInfos: addr(queueCreateInfo[0]), | 202 pQueueCreateInfos: addrOrNil(queueCreateInfo), |
| 200 pEnabledFeatures: addr(features), | 203 pEnabledFeatures: addr(features), |
| 201 enabledExtensionCount: requiredExtensions.len.uint32, | 204 enabledExtensionCount: requiredExtensions.len.uint32, |
| 202 ppEnabledExtensionNames: cast[ptr UncheckedArray[cstring]](addr(requiredExtensions)) | 205 ppEnabledExtensionNames: cast[ptr UncheckedArray[cstring]](addr(requiredExtensions)) |
| 203 ) | 206 ) |
| 204 checkVkResult vkCreateDevice(physicalDevice, addr(deviceCreateInfo), nil, addr(result[0])) | 207 checkVkResult vkCreateDevice(physicalDevice, addr(deviceCreateInfo), nil, addr(result[0])) |
| 212 }.toTable() | 215 }.toTable() |
| 213 var code = compileGLSLToSPIRV(VK_GLSL_MAP[stage], shader, "<memory-shader>") | 216 var code = compileGLSLToSPIRV(VK_GLSL_MAP[stage], shader, "<memory-shader>") |
| 214 var createInfo = VkShaderModuleCreateInfo( | 217 var createInfo = VkShaderModuleCreateInfo( |
| 215 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | 218 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| 216 codeSize: uint(code.len * sizeof(uint32)), | 219 codeSize: uint(code.len * sizeof(uint32)), |
| 217 pCode: addr(code[0]), | 220 pCode: addrOrNil(code), |
| 218 ) | 221 ) |
| 219 var shaderModule: VkShaderModule | 222 var shaderModule: VkShaderModule |
| 220 checkVkResult vkCreateShaderModule(device, addr(createInfo), nil, addr(shaderModule)) | 223 checkVkResult vkCreateShaderModule(device, addr(createInfo), nil, addr(shaderModule)) |
| 221 | 224 |
| 222 return VkPipelineShaderStageCreateInfo( | 225 return VkPipelineShaderStageCreateInfo( |
| 232 pCallbackData: VkDebugUtilsMessengerCallbackDataEXT, | 235 pCallbackData: VkDebugUtilsMessengerCallbackDataEXT, |
| 233 userData: pointer | 236 userData: pointer |
| 234 ): VkBool32 {.cdecl.} = | 237 ): VkBool32 {.cdecl.} = |
| 235 echo &"{messageSeverity}: {VkDebugUtilsMessageTypeFlagBitsEXT(messageTypes)}: {pCallbackData.pMessage}" | 238 echo &"{messageSeverity}: {VkDebugUtilsMessageTypeFlagBitsEXT(messageTypes)}: {pCallbackData.pMessage}" |
| 236 return VK_FALSE | 239 return VK_FALSE |
| 240 | |
| 241 proc getSurfaceCapabilities*(device: VkPhysicalDevice, surface: VkSurfaceKHR): VkSurfaceCapabilitiesKHR = | |
| 242 checkVkResult device.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(surface, addr(result)) | |
| 243 | |
| 244 when defined(linux): | |
| 245 proc createVulkanSurface*(instance: VkInstance, window: NativeWindow): VkSurfaceKHR = | |
| 246 var surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR( | |
| 247 sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, | |
| 248 dpy: window.display, | |
| 249 window: window.window, | |
| 250 ) | |
| 251 checkVkResult vkCreateXlibSurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) | |
| 252 when defined(windows): | |
| 253 proc createVulkanSurface*(instance: VkInstance, window: NativeWindow): VkSurfaceKHR = | |
| 254 var surfaceCreateInfo = VkWin32SurfaceCreateInfoKHR( | |
| 255 sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, | |
| 256 hinstance: window.hinstance, | |
| 257 hwnd: window.hwnd, | |
| 258 ) | |
| 259 checkVkResult vkCreateWin32SurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) |
