1488
|
1 import std/sequtils
|
|
2 import std/enumutils
|
1487
|
3 import std/tables
|
1485
|
4 import std/strutils
|
|
5 import std/logging
|
1486
|
6 import std/os
|
1485
|
7
|
|
8 include ./vkapi
|
|
9
|
1486
|
10 const VULKAN_VERSION = VK_MAKE_API_VERSION(0, 1, 3, 0)
|
|
11
|
1488
|
12 iterator items*[T: HoleyEnum](E: typedesc[T]): T =
|
|
13 for a in enumFullRange(E):
|
|
14 yield a
|
|
15
|
1485
|
16 template checkVkResult*(call: untyped) =
|
|
17 when defined(release):
|
|
18 discard call
|
|
19 else:
|
|
20 # yes, a bit cheap, but this is only for nice debug output
|
|
21 var callstr = astToStr(call).replace("\n", "")
|
|
22 while callstr.find(" ") >= 0:
|
|
23 callstr = callstr.replace(" ", " ")
|
|
24 debug "Calling vulkan: ", callstr
|
|
25 let value = call
|
|
26 if value != VK_SUCCESS:
|
|
27 error "Vulkan error: ", astToStr(call), " returned ", $value
|
|
28 raise newException(
|
|
29 Exception, "Vulkan error: " & astToStr(call) & " returned " & $value
|
|
30 )
|
|
31
|
|
32 type SVkInstance* = object
|
|
33 vkInstance: VkInstance
|
1486
|
34 debugMessenger: VkDebugUtilsMessengerEXT
|
1485
|
35
|
|
36 proc `=copy`(a: var SVkInstance, b: SVkInstance) {.error.}
|
|
37
|
|
38 proc `=destroy`(a: SVkInstance) =
|
|
39 if a.vkInstance.pointer != nil:
|
1486
|
40 if a.debugMessenger.pointer != nil:
|
|
41 vkDestroyDebugUtilsMessengerEXT(a.vkInstance, a.debugMessenger, nil)
|
1485
|
42 a.vkInstance.vkDestroyInstance(nil)
|
|
43
|
1486
|
44 proc debugCallback(
|
|
45 messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT,
|
|
46 messageTypes: VkDebugUtilsMessageTypeFlagsEXT,
|
|
47 pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT,
|
|
48 userData: pointer,
|
|
49 ): VkBool32 {.cdecl.} =
|
|
50 const LOG_LEVEL_MAPPING = {
|
|
51 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: lvlDebug,
|
|
52 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: lvlInfo,
|
|
53 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: lvlWarn,
|
|
54 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: lvlError,
|
|
55 }.toTable
|
|
56 log LOG_LEVEL_MAPPING[messageSeverity]
|
|
57 if messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
|
|
58 # stderr.write getStackTrace()
|
|
59 # stderr.writeLine LOG_LEVEL_MAPPING[messageSeverity], &"{toEnums messageTypes}: {pCallbackData.pMessage}"
|
|
60 let errorMsg = $pCallbackData.pMessage & ": " & getStackTrace()
|
|
61 raise newException(Exception, errorMsg)
|
|
62 return VK_FALSE
|
|
63
|
1485
|
64 proc svkCreateInstance*(
|
|
65 applicationName: string,
|
|
66 enabledLayers: openArray[string] = [],
|
1486
|
67 enabledExtensions: openArray[string] =
|
|
68 if defined(release):
|
|
69 @["VK_KHR_surface"]
|
|
70 else:
|
|
71 @["VK_KHR_surface", "VK_EXT_debug_utils"],
|
1485
|
72 engineName = "semicongine",
|
1486
|
73 withSwapchain = true,
|
1485
|
74 ): SVkInstance =
|
1486
|
75 putEnv("VK_LOADER_LAYERS_ENABLE", "*validation")
|
|
76 putEnv(
|
|
77 "VK_LAYER_ENABLES",
|
|
78 "VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD,VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXTVK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT",
|
|
79 )
|
|
80 initVulkanLoader()
|
|
81
|
1485
|
82 let
|
|
83 appinfo = VkApplicationInfo(
|
|
84 pApplicationName: applicationName,
|
|
85 pEngineName: engineName,
|
1486
|
86 apiVersion: VULKAN_VERSION,
|
1485
|
87 )
|
1486
|
88 enabledLayersC = allocCStringArray(enabledLayers)
|
|
89 enabledExtensionsC = allocCStringArray(enabledExtensions)
|
1485
|
90 createinfo = VkInstanceCreateInfo(
|
|
91 pApplicationInfo: addr appinfo,
|
|
92 enabledLayerCount: enabledLayers.len.uint32,
|
1486
|
93 ppEnabledLayerNames: enabledLayersC,
|
1485
|
94 enabledExtensionCount: enabledExtensions.len.uint32,
|
1486
|
95 ppEnabledExtensionNames: enabledExtensionsC,
|
1485
|
96 )
|
|
97 checkVkResult vkCreateInstance(addr createinfo, nil, addr result.vkInstance)
|
1486
|
98
|
|
99 enabledLayersC.deallocCStringArray()
|
|
100 enabledExtensionsC.deallocCStringArray()
|
|
101
|
|
102 load_VK_VERSION_1_0(result.vkInstance)
|
|
103 load_VK_VERSION_1_1(result.vkInstance)
|
|
104 load_VK_VERSION_1_2(result.vkInstance)
|
|
105 load_VK_VERSION_1_3(result.vkInstance)
|
|
106
|
|
107 for extension in enabledExtensions:
|
|
108 loadExtension(result.vkInstance, extension)
|
|
109 if withSwapchain:
|
|
110 load_VK_KHR_swapchain(result.vkInstance)
|
|
111
|
|
112 when not defined(release):
|
|
113 var debugMessengerCreateInfo = VkDebugUtilsMessengerCreateInfoEXT(
|
1488
|
114 messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT.items.toSeq,
|
|
115 messageType: VkDebugUtilsMessageTypeFlagBitsEXT.items.toSeq,
|
1486
|
116 pfnUserCallback: debugCallback,
|
|
117 )
|
|
118 checkVkResult vkCreateDebugUtilsMessengerEXT(
|
|
119 result.vkInstance, addr debugMessengerCreateInfo, nil, addr result.debugMessenger
|
|
120 )
|