comparison fuhtark_test/generate_vulkan_api.sh @ 1501:f40d9d814c08 default tip

did: correct vulkan-api generator
author sam <sam@basx.dev>
date Wed, 26 Nov 2025 23:34:29 +0700
parents 91c8c3b7cbf0
children
comparison
equal deleted inserted replaced
1500:91c8c3b7cbf0 1501:f40d9d814c08
1 #!/bin/sh -e 1 #!/bin/sh -e
2 2
3 # Variables 3 # Variables
4 BASE_INCLUDE=$( realpath $( dirname $0 ) )"/include" 4 VULKAN_VERSION=1.4.334
5 WIN_INCLUDE=$( realpath $( dirname $0 ) )"/include/winapi" 5 HOME_DIR=$( realpath $( dirname $0 ) )
6 BASE_INCLUDE="$HOME_DIR/include"
7 WIN_INCLUDE="$HOME_DIR/include/winapi"
8 VULKAN_INCLUDE="$HOME_DIR/Vulkan-Headers-$VULKAN_VERSION/include/vulkan"
6 OUT_BIN=vulkan 9 OUT_BIN=vulkan
7 OUTFILE=$OUT_BIN.nim 10 OUTFILE=$OUT_BIN.nim
8 OUTFILE_FUTHARK=$OUT_BIN".gen.nim" 11 OUTFILE_FUTHARK=$OUT_BIN".gen.nim"
12
13 # setup
14 # sudo apt install clang libclang-dev
15 # nimble install futhark
16 # rm -rf Vulkan-Headers-$VULKAN_VERSION
17 # curl -L https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v$VULKAN_VERSION.tar.gz | tar -xzf -
9 18
10 # Convert C-headers to Nim using Futhark, if not existing yet 19 # Convert C-headers to Nim using Futhark, if not existing yet
11 NIM_GEN_CODE='import futhark, os 20 NIM_GEN_CODE='import futhark, os
12 importc: 21 importc:
13 outputPath "'"$OUTFILE_FUTHARK"'" 22 outputPath "'"$OUTFILE_FUTHARK"'"
14 define VK_USE_PLATFORM_WIN32_KHR 23 define VK_USE_PLATFORM_WIN32_KHR
15 define VK_USE_PLATFORM_XLIB_KHR 24 define VK_USE_PLATFORM_XLIB_KHR
25 define VK_ENABLE_BETA_EXTENSIONS
16 sysPath "'"$BASE_INCLUDE"'" 26 sysPath "'"$BASE_INCLUDE"'"
17 sysPath "'"$WIN_INCLUDE"'" 27 sysPath "'"$WIN_INCLUDE"'"
18 path "/usr/include/vulkan" 28 path "'"$VULKAN_INCLUDE"'"
19 "vulkan.h"' 29 "vulkan.h"'
20 30
21 if [ ! -f $OUTFILE_FUTHARK ] ; then 31 if [ ! -f $OUTFILE_FUTHARK ] ; then
22 nim c --maxLoopIterationsVM:1000000000 --eval:"$NIM_GEN_CODE" 32 nim c --maxLoopIterationsVM:1000000000 --eval:"$NIM_GEN_CODE"
23 fi 33 fi
34 sed -i '/struct_Vk.*pure,$/{N;s/\n/ /}' $OUTFILE 44 sed -i '/struct_Vk.*pure,$/{N;s/\n/ /}' $OUTFILE
35 sed -i '/struct_Vk.* {\.$/{N;s/\n/ /}' $OUTFILE 45 sed -i '/struct_Vk.* {\.$/{N;s/\n/ /}' $OUTFILE
36 46
37 # set default struct values for member "sType" 47 # set default struct values for member "sType"
38 # not very clean, as we "abuse" the fact that Nim does not differentiate between camel-case and snake-case for identifiers 48 # not very clean, as we "abuse" the fact that Nim does not differentiate between camel-case and snake-case for identifiers
49
50 # VkStructureType_1124073999 = (when declared(VkStructureType):
51 TYPESTRUCTNAME=$( cat $OUTFILE | awk '/enum_VkStructureType\* =/ { print $3; }' )
39 awk -i inplace '{ 52 awk -i inplace '{
40 if ( $0 ~ /^ struct_Vk.* = object/ && ! $0 ~ /VkBaseInStructure/ ) { 53 if ( $0 ~ /^ struct_Vk.* = object/ && $0 !~ /VkBaseInStructure/ && $0 !~ /VkBaseOutStructure/ ) {
41 split($0, arr, "_"); 54 split($0, arr, "_");
42 print $0; 55 print $0;
43 getline; 56 getline;
44 if ( $0 ~ / sType\*:/ ) { 57 if ( $0 ~ / sType\*:/ ) {
45 split($0, arr2, "##"); 58 split($0, arr2, "##");
46 print arr2[1] "= VK_STRUCTURE_TYPE_" substr(arr[2], 3) " ##" arr2[2]; 59 print " sType*: '$TYPESTRUCTNAME' = '$TYPESTRUCTNAME'.VK_STRUCTURE_TYPE_" substr(arr[2], 3) " ##" arr2[2];
47 } else { 60 } else {
48 print; 61 print;
49 } 62 }
50 } else { 63 } else {
51 print; 64 print;
59 cat <<EOF >> $OUTFILE 72 cat <<EOF >> $OUTFILE
60 73
61 import std/dynlib 74 import std/dynlib
62 import std/strutils 75 import std/strutils
63 import std/logging 76 import std/logging
77 import std/envvars
64 78
65 var vkInstance*: VkInstance = VkInstance(nil) 79 var vkInstance*: VkInstance = VkInstance(nil)
66 var vkPhysicalDevices: seq[VkPhysicalDevice] 80 var vkPhysicalDevices: seq[VkPhysicalDevice]
67 81
68 template checkVkResult*(call: untyped) = 82 template checkVkResult*(call: untyped) =
82 ) 96 )
83 97
84 proc loadFunc[T](instance: VkInstance, f: var T, name: string) = 98 proc loadFunc[T](instance: VkInstance, f: var T, name: string) =
85 f = cast[T](vkGetInstanceProcAddr(instance, name)) 99 f = cast[T](vkGetInstanceProcAddr(instance, name))
86 100
101 proc hasValidationLayer*(): bool =
102 const val_layer = "VK_LAYER_KHRONOS_validation"
103 var n_layers: uint32
104 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), nil)
105 if n_layers > 0:
106 var layers = newSeq[VkLayerProperties](n_layers)
107 checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), addr layers[0])
108 for layer in layers:
109 let layerName = \$(cast[cstring](addr layer.layerName[0]))
110 if layerName.startsWith(val_layer):
111 return true
112 return false
113
87 proc initVulkan*() = 114 proc initVulkan*() =
88 if vkGetInstanceProcAddr != nil: 115 if vkGetInstanceProcAddr != nil:
89 return 116 return
90 117
91 when defined(linux): 118 when defined(linux):
98 # load function-pointer resolver function 125 # load function-pointer resolver function
99 vkGetInstanceProcAddr = cast[typeof(vkGetInstanceProcAddr)](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr")) 126 vkGetInstanceProcAddr = cast[typeof(vkGetInstanceProcAddr)](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr"))
100 127
101 # need to create an instance before loading other function points 128 # need to create an instance before loading other function points
102 loadFunc(vkInstance, vkCreateInstance, "vkCreateInstance") 129 loadFunc(vkInstance, vkCreateInstance, "vkCreateInstance")
130 # and this one, to check which layers are available for instance creation
131 loadFunc(vkInstance, vkEnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties")
132
133 # extensions
134 var extensions = @["VK_KHR_surface"]
135 when not defined(release):
136 extensions.add "VK_EXT_debug_utils"
137 when defined(windows):
138 extensions.add "VK_KHR_win32_surface"
139 when defined(linux):
140 extensions.add "VK_KHR_xlib_surface"
141 let extensionsC = allocCStringArray(extensions)
142 defer: deallocCStringArray(extensionsC)
143
144 # layers
145 var layers: seq[string]
146 when not defined(release):
147 if hasValidationLayer():
148 layers.add "VK_LAYER_KHRONOS_validation"
149 var layersC = allocCStringArray(layers)
150 defer: deallocCStringArray(layersC)
151
152 putEnv(
153 "VK_LAYER_ENABLES",
154 "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",
155 )
156
157 echo "Use instance extensions: ", extensions
158 echo "Use layers: ", layers
103 let createInfo = VkInstanceCreateInfo( 159 let createInfo = VkInstanceCreateInfo(
104 pNext: nil, 160 pNext: nil,
105 flags: 0, 161 flags: 0,
106 pApplicationInfo: nil, 162 pApplicationInfo: nil,
107 enabledLayerCount: 0, 163 enabledLayerCount: layers.len.uint32,
108 ppEnabledLayerNames: nil, 164 ppEnabledLayerNames: cast[ptr cstring](layersC),
109 enabledExtensionCount: 0, 165 enabledExtensionCount: extensions.len.uint32,
110 ppEnabledExtensionNames: nil, 166 ppEnabledExtensionNames: cast[ptr cstring](extensionsC),
111 ) 167 )
112 checkVkResult vkCreateInstance(addr createInfo, nil, addr vkInstance) 168 checkVkResult vkCreateInstance(addr createInfo, nil, addr vkInstance)
113 169
114 # load all functions (some might be null, not checking here) 170 # load all functions (some might be null, not checking here)
115 EOF 171 EOF