├── .gitignore ├── LICENSE ├── README.md ├── VERSION ├── examples ├── modules │ └── vulkan └── vk_glfw_volk.v ├── include ├── GL │ └── glcorearb.h └── KHR │ └── khrplatform.h ├── src └── vulkan.v └── v.mod /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/pycharm 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=pycharm 3 | 4 | ### PyCharm ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/**/usage.statistics.xml 12 | .idea/**/dictionaries 13 | .idea/**/shelf 14 | 15 | # AWS User-specific 16 | .idea/**/aws.xml 17 | 18 | # Generated files 19 | .idea/**/contentModel.xml 20 | 21 | # Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | .idea/**/dbnavigator.xml 29 | 30 | # Gradle 31 | .idea/**/gradle.xml 32 | .idea/**/libraries 33 | 34 | # Gradle and Maven with auto-import 35 | # When using Gradle or Maven with auto-import, you should exclude module files, 36 | # since they will be recreated, and may cause churn. Uncomment if using 37 | # auto-import. 38 | # .idea/artifacts 39 | # .idea/compiler.xml 40 | # .idea/jarRepositories.xml 41 | # .idea/modules.xml 42 | # .idea/*.iml 43 | # .idea/modules 44 | # *.iml 45 | # *.ipr 46 | 47 | # CMake 48 | cmake-build-*/ 49 | 50 | # Mongo Explorer plugin 51 | .idea/**/mongoSettings.xml 52 | 53 | # File-based project format 54 | *.iws 55 | 56 | # IntelliJ 57 | out/ 58 | 59 | # mpeltonen/sbt-idea plugin 60 | .idea_modules/ 61 | 62 | # JIRA plugin 63 | atlassian-ide-plugin.xml 64 | 65 | # Cursive Clojure plugin 66 | .idea/replstate.xml 67 | 68 | # SonarLint plugin 69 | .idea/sonarlint/ 70 | 71 | # Crashlytics plugin (for Android Studio and IntelliJ) 72 | com_crashlytics_export_strings.xml 73 | crashlytics.properties 74 | crashlytics-build.properties 75 | fabric.properties 76 | 77 | # Editor-based Rest Client 78 | .idea/httpRequests 79 | 80 | # Android studio 3.1+ serialized cache file 81 | .idea/caches/build_file_checksums.ser 82 | 83 | ### PyCharm Patch ### 84 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 85 | 86 | # *.iml 87 | # modules.xml 88 | # .idea/misc.xml 89 | # *.ipr 90 | 91 | # Sonarlint plugin 92 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 93 | .idea/**/sonarlint/ 94 | 95 | # SonarQube Plugin 96 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 97 | .idea/**/sonarIssues.xml 98 | 99 | # Markdown Navigator plugin 100 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 101 | .idea/**/markdown-navigator.xml 102 | .idea/**/markdown-navigator-enh.xml 103 | .idea/**/markdown-navigator/ 104 | 105 | # Cache file creation bug 106 | # See https://youtrack.jetbrains.com/issue/JBR-2257 107 | .idea/$CACHE_FILE$ 108 | 109 | # CodeStream plugin 110 | # https://plugins.jetbrains.com/plugin/12206-codestream 111 | .idea/codestream.xml 112 | 113 | # Azure Toolkit for IntelliJ plugin 114 | # https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij 115 | .idea/**/azureSettings.xml 116 | 117 | # End of https://www.toptal.com/developers/gitignore/api/pycharm 118 | 119 | # Created by https://www.toptal.com/developers/gitignore/api/python 120 | # Edit at https://www.toptal.com/developers/gitignore?templates=python 121 | 122 | ### Python ### 123 | # Byte-compiled / optimized / DLL files 124 | __pycache__/ 125 | *.py[cod] 126 | *$py.class 127 | 128 | # C extensions 129 | *.so 130 | 131 | # Distribution / packaging 132 | .Python 133 | build/ 134 | develop-eggs/ 135 | dist/ 136 | downloads/ 137 | eggs/ 138 | .eggs/ 139 | lib/ 140 | lib64/ 141 | parts/ 142 | sdist/ 143 | var/ 144 | wheels/ 145 | share/python-wheels/ 146 | *.egg-info/ 147 | .installed.cfg 148 | *.egg 149 | MANIFEST 150 | 151 | # PyInstaller 152 | # Usually these files are written by a python script from a template 153 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 154 | *.manifest 155 | *.spec 156 | 157 | # Installer logs 158 | pip-log.txt 159 | pip-delete-this-directory.txt 160 | 161 | # Unit test / coverage reports 162 | htmlcov/ 163 | .tox/ 164 | .nox/ 165 | .coverage 166 | .coverage.* 167 | .cache 168 | nosetests.xml 169 | coverage.xml 170 | *.cover 171 | *.py,cover 172 | .hypothesis/ 173 | .pytest_cache/ 174 | cover/ 175 | 176 | # Translations 177 | *.mo 178 | *.pot 179 | 180 | # Django stuff: 181 | *.log 182 | local_settings.py 183 | db.sqlite3 184 | db.sqlite3-journal 185 | 186 | # Flask stuff: 187 | instance/ 188 | .webassets-cache 189 | 190 | # Scrapy stuff: 191 | .scrapy 192 | 193 | # Sphinx documentation 194 | docs/_build/ 195 | 196 | # PyBuilder 197 | .pybuilder/ 198 | target/ 199 | 200 | # Jupyter Notebook 201 | .ipynb_checkpoints 202 | 203 | # IPython 204 | profile_default/ 205 | ipython_config.py 206 | 207 | # pyenv 208 | # For a library or package, you might want to ignore these files since the code is 209 | # intended to run in multiple environments; otherwise, check them in: 210 | # .python-version 211 | 212 | # pipenv 213 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 214 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 215 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 216 | # install all needed dependencies. 217 | #Pipfile.lock 218 | 219 | # poetry 220 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 221 | # This is especially recommended for binary packages to ensure reproducibility, and is more 222 | # commonly ignored for libraries. 223 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 224 | #poetry.lock 225 | 226 | # pdm 227 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 228 | #pdm.lock 229 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 230 | # in version control. 231 | # https://pdm.fming.dev/#use-with-ide 232 | .pdm.toml 233 | 234 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 235 | __pypackages__/ 236 | 237 | # Celery stuff 238 | celerybeat-schedule 239 | celerybeat.pid 240 | 241 | # SageMath parsed files 242 | *.sage.py 243 | 244 | # Environments 245 | .env 246 | .venv 247 | env/ 248 | venv/ 249 | ENV/ 250 | env.bak/ 251 | venv.bak/ 252 | 253 | # Spyder project settings 254 | .spyderproject 255 | .spyproject 256 | 257 | # Rope project settings 258 | .ropeproject 259 | 260 | # mkdocs documentation 261 | /site 262 | 263 | # mypy 264 | .mypy_cache/ 265 | .dmypy.json 266 | dmypy.json 267 | 268 | # Pyre type checker 269 | .pyre/ 270 | 271 | # pytype static type analyzer 272 | .pytype/ 273 | 274 | # Cython debug symbols 275 | cython_debug/ 276 | 277 | # PyCharm 278 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 279 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 280 | # and can be added to the global gitignore or merged into this file. For a more nuclear 281 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 282 | #.idea/ 283 | 284 | ### Python Patch ### 285 | # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration 286 | poetry.toml 287 | 288 | # ruff 289 | .ruff_cache/ 290 | 291 | # LSP config files 292 | pyrightconfig.json 293 | 294 | # End of https://www.toptal.com/developers/gitignore/api/python 295 | 296 | spec_tools/ 297 | cache/ 298 | .idea/ 299 | 300 | *.gfxr 301 | *.so 302 | 303 | 304 | examples/vk_glfw_volk 305 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Public Domain 2 | 3 | This is free and unencumbered software released into the public domain. 4 | 5 | Anyone is free to copy, modify, publish, use, compile, sell, or 6 | distribute this software, either in source code form or as a compiled 7 | binary, for any purpose, commercial or non-commercial, and by any 8 | means. 9 | 10 | In jurisdictions that recognize copyright laws, the author or authors 11 | of this software dedicate any and all copyright interest in the 12 | software to the public domain. We make this dedication for the benefit 13 | of the public at large and to the detriment of our heirs and 14 | successors. We intend this dedication to be an overt act of 15 | relinquishment in perpetuity of all present and future rights to this 16 | software under copyright law. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Vulkan Bindings for [Vlang](https://vlang.io/) 4 | The bindings in `src/vulkan.v` were generated from the current [KhronosGroup](https://github.com/KhronosGroup/) [API description](https://github.com/KhronosGroup/Vulkan-Docs/blob/main/xml/vk.xml). 5 | 6 | ## Dependencies 7 | Please make sure to clone the commit tag matching your installed [Vulkan SDK](https://vulkan.lunarg.com/doc/sdk/latest/). 8 | 9 | ### Linux 10 | Please install the [Vulkan SDK](https://vulkan.lunarg.com/sdk/home). 11 | Further reading at [https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html). 12 | 13 | GLFW is required for the example app. It provides OS independent window creation. 14 | You can get it at [glfw.org download](https://www.glfw.org/download.html). 15 | Or just use the package manager. 16 | ``` 17 | 18 | $ apt search glfw 19 | 20 | libglfw3-dev/jammy,now 3.3.6-1 amd64 21 | 22 | portable library for OpenGL, window and input (development files) 23 | 24 | $ sudo apt install libglfw3-dev 25 | 26 | ``` 27 | `VULKAN_SDK` is an environment variable and should have the path to your [Vulkan SDK](https://vulkan.lunarg.com/doc/sdk/latest/), like `$HOME/vulkansdk-linux-x86_64-1.3.290.0/x86_64`. Besides that `LD_LIBRARY_PATH` and `VK_LAYER_PATH` have to be set. On linux you can append this to your shell start script 28 | ``` 29 | export VULKAN_SDK=$HOME/vulkansdk-linux-x86_64-/x86_64 30 | export LD_LIBRARY_PATH=$VULKAN_SDK/lib:$LD_LIBRARY_PATH 31 | export VK_LAYER_PATH=$VULKAN_SDK/share/vulkan/explicit_layer.d 32 | ``` 33 | 34 | ### Windows 35 | Please install the [Vulkan SDK](https://vulkan.lunarg.com/sdk/home). 36 | All environment variables are set automatically by the installer. 37 | 38 | GLFW is required for the example app. It provides OS independent window creation. 39 | You can get it at [glfw.org download](https://www.glfw.org/download.html). 40 | 41 | Set GLFW paths in `examples\vk_glfw_volk.v`. 42 | ``` 43 | #flag windows -I 44 | #flag windows -L 45 | ``` 46 | GLFW releases different binaries for different compilers, which are in different directories. 47 | You will also have to pass the `-cc ` parameter to V when compiling the app. 48 | 49 | ## Run Examples 50 | There is an app `vk_glfw_volk.v`, which opens a window and listens for keyboard events. 51 | Please make sure to pick the tag matching your SDK installation, like `--branch v1.3.290`. 52 | ### Linux 53 | ``` 54 | 55 | git clone --depth 1 --branch https://github.com/antono2/vulkan.git 56 | 57 | cd vulkan 58 | 59 | v run examples/vk_glfw_volk.v 60 | 61 | ``` 62 | ### Windows 63 | As of this writing, V expects a directory structure like `modules/vulkan/vulkan.v` for the example app to find the bindings. On Linux we can cheat with a symbolic link, on Windows we can duplicate `vulkan.v` and move the example app. Please make sure to pick the tag matching your SDK installation, like `--branch v1.3.290`. 64 | This is one way to run, using the [MinGW tool chain](https://github.com/niXman/mingw-builds-binaries). In case of another C compiler, please change the GLFW library search directory and v `-cc` parameter accordingly. 65 | 66 | ``` 67 | 68 | git clone --depth 1 --branch https://github.com/antono2/vulkan.git 69 | 70 | cd vulkan 71 | 72 | mkdir modules\vulkan 73 | 74 | copy examples\vk_glfw_volk.v . 75 | 76 | copy src\vulkan.v modules\vulkan 77 | 78 | v -cc x86_64-w64-mingw32-gcc run vk_glfw_volk.v 79 | 80 | ``` 81 | 82 | 83 | ## Further Reading 84 | ### Doesn't work. What now? 85 | For missing information, like `Could not create vulkan instance. VkResult: error_layer_not_present`, please double check for missing environment variables and correct paths. 86 | 87 | For vulkan related issues you can try [`VK_LOADER_DEBUG=all`](https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md#active-environment-variables). 88 | 89 | ### Compiler #Flags 90 | There are some `#include` in the vulkan bindings, for which the correct compiler flags have to be set by you. 91 | The example already contains all required flags for Windows and Linux x64. 92 | 93 | ### Why [Volk](https://github.com/zeux/volk)? 94 | Any vulkan function has some name (symbol) and address in your local library. These addresses have to be found either at compile time or dynamically. 95 | In V we can use `C.` function type definitions and a simple `#flag -lvulkan`, which does this at compile time. 96 | Unfortunately this requires conditional compilation for extension code blocks in the V vulkan bindings and additional work by the user to load required extension functions, when they need them. 97 | 98 | Alternatively we can load the function address whenever we first call it. Well, V has a [built in dynamic loader](https://modules.vlang.io/dl.loader.html), but there is a ready to use solution. We can just use [Volk](https://github.com/zeux/volk), which is provided by the [Vulkan SDK](https://vulkan.lunarg.com/doc/sdk/latest/) and does the same thing. 99 | 100 | ### [GLFW](https://www.glfw.org/download.html) Bindings? 101 | There are some C. functions for GLFW at the bottom of the example. V bindings for GLFW are available, but I prefer to control the global namespace for C. functions, as they might overlap and cause issues later. This will change in future. 102 | 103 | ## Pull Request 104 | There is always stuff to do and help is welcome. The goal is to cover some more vulkan functionality by example. Roughly like [this](https://github.com/SaschaWillems/Vulkan). 105 | 106 | Please rebase your local branch with origin/master and squash the commit log before creating the pull request. 107 | It helps with readability and generally improves life quality. 108 | Note that `vulkan.v` is generated in a different repository (not open source yet) and can not be edited directly. 109 | In that case, please feel free to open an issue or start a discussion. 110 | 111 | ## LICENSE 112 | 113 | `Public Domain` for anything in this repository. 114 | 115 | 116 | # Thanks 117 | Big thanks to [@spytheman](https://github.com/spytheman) for fixing my bugs in times of need.
118 | To [@JalonSolov](https://github.com/JalonSolov) for quick and solid answers to obscure questions. 119 | 120 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v1.4.316 2 | -------------------------------------------------------------------------------- /examples/modules/vulkan: -------------------------------------------------------------------------------- 1 | ../../src/ -------------------------------------------------------------------------------- /examples/vk_glfw_volk.v: -------------------------------------------------------------------------------- 1 | /* 2 | This program creates a window and prints a message on pressing Enter. Press ESC to exit. 3 | It provides examples for calling vulkan and glfw functions, using the bindings located at 4 | modules/vulkan/vulkan.v 5 | */ 6 | 7 | module main 8 | 9 | import vulkan as vk 10 | 11 | #flag linux -I$env('VULKAN_SDK')/include 12 | #flag linux -I$env('VULKAN_SDK')/include/vulkan 13 | #flag windows -I$env('VULKAN_SDK')/Include 14 | #flag windows -I$env('VULKAN_SDK')/Include/vulkan 15 | #flag linux -L$env('VULKAN_SDK')/lib 16 | #flag windows -L$env('VULKAN_SDK')/Lib 17 | 18 | // GLFW 19 | // https://www.glfw.org/docs/latest/vulkan_guide.html 20 | #flag windows -I 21 | #flag windows -Iinclude 22 | #flag linux -L/usr/lib/x86_64-linux-gnu 23 | #flag windows -L 24 | #flag linux -lglfw 25 | #flag windows -lglfw3 26 | #flag windows -lgdi32 27 | // Please see https://www.glfw.org/docs/latest/build_guide.html#build_macros for more information 28 | #flag windows -DGLFW_INCLUDE_GLCOREARB=1 // makes the GLFW header include the modern GL/glcorearb.h header (OpenGL/gl3.h on macOS) instead of the regular OpenGL header. 29 | 30 | // Volk 31 | // https://github.com/zeux/volk#basic-usage 32 | #flag windows -I$env('VULKAN_SDK')/Include/Volk 33 | // https://github.com/zeux/volk#building 34 | #flag -DVOLK_IMPLEMENTATION 35 | #include "volk.h" 36 | 37 | fn C.volkInitialize() 38 | fn C.volkLoadInstance(C.Instance) 39 | 40 | // This has to come after other includes 41 | #include "GLFW/glfw3.h" 42 | 43 | pub const glfw_true = 1 44 | pub const glfw_press = 1 45 | pub const glfw_key_enter = 257 46 | pub const glfw_key_escape = 256 47 | pub const glfw_client_api = 0x00022001 48 | pub const glfw_no_api = 0 49 | 50 | pub type C.GLFWwindow = voidptr 51 | 52 | @[heap] 53 | struct App { 54 | pub mut: 55 | main_window C.GLFWwindow 56 | vk_instance C.Instance 57 | share_data []string // some data to share between main() and glfw callback functions 58 | } 59 | 60 | fn init_app(window &C.GLFWwindow) App { 61 | new_app := App{ 62 | main_window: unsafe { window } 63 | vk_instance: unsafe { nil } 64 | share_data: [] 65 | } 66 | return new_app 67 | } 68 | 69 | fn main() { 70 | C.volkInitialize() 71 | // initialize GLFW ("init" is a reserved keyword in V) 72 | glfw_initialize() 73 | mut window := unsafe { nil } 74 | glfw_window_hint(glfw_client_api, glfw_no_api) 75 | window = glfw_create_window(960, 480, 'Greetings!', unsafe { nil }, 76 | unsafe { nil }) 77 | 78 | mut app := init_app(window) 79 | defer { 80 | glfw_terminate() 81 | unsafe { 82 | // TODO: vkDestroySurfaceKHR before vkDestroyInstance 83 | // use vk.destroy_instance instead of free 84 | free(app.vk_instance) 85 | } 86 | } 87 | 88 | // Set user pointer to &App 89 | // User pointer is a reference to your glfw user data, 90 | // which you might need inside glfw callback functions 91 | glfw_set_user_pointer(window, &app) 92 | // set callback function for keyboard input 93 | glfw_set_key_callback(window, key_callback_function) 94 | 95 | if !glfw_is_vulkan_supported() { 96 | panic('Vulkan loader could not be found by GLFW') 97 | } 98 | 99 | mut glfw_required_instance_extensions_cnt := u32(0) 100 | mut glfw_required_instance_extensions := glfw_get_required_instance_extensions(&glfw_required_instance_extensions_cnt) 101 | 102 | enabled_layer_names := [c'VK_LAYER_KHRONOS_validation'] 103 | enabled_layer_names_count := u32(1) 104 | 105 | create_info := vk.InstanceCreateInfo{ 106 | p_next: unsafe { nil } 107 | flags: 0 108 | p_application_info: &vk.ApplicationInfo{ 109 | s_type: vk.StructureType.structure_type_application_info 110 | p_next: unsafe { nil } 111 | p_application_name: c'Vulkan in Vlang' 112 | application_version: 1 113 | p_engine_name: c'Not an Engine' 114 | engine_version: 1 115 | api_version: vk.header_version_complete 116 | } 117 | pp_enabled_layer_names: &(enabled_layer_names[0]) 118 | enabled_layer_count: enabled_layer_names_count 119 | pp_enabled_extension_names: glfw_required_instance_extensions 120 | enabled_extension_count: glfw_required_instance_extensions_cnt 121 | } 122 | create_instance_result := vk.create_instance(&create_info, unsafe { nil }, &app.vk_instance) 123 | // Note: You can use string_VkResult in /usr/include/vulkan/generated/vk_enum_string_helper.h 124 | // otherwise the string value of ${result} will just be the enum name, eg. 'success' 125 | if create_instance_result != vk.Result.success { 126 | println('Could not create vulkan instance. VkResult: ${create_instance_result}') 127 | } 128 | // https://github.com/zeux/volk#basic-usage 129 | C.volkLoadInstance(app.vk_instance) 130 | 131 | // TODO: Use vkEnumerateInstanceLayerProperties and vkEnumerateInstanceExtensionProperties to 132 | // find supported properties of the current vk instance 133 | 134 | // TODO: Add debug extension in case of "v -d debug_vk" and vkCreateDebugUtilsMessengerEXT with debug callback. 135 | // https://github.com/vlang/v/blob/master/doc/docs.md#conditional-compilation 136 | 137 | mut surface := 0 138 | create_surface_result := glfw_create_window_surface(app.vk_instance, window, unsafe { nil }, 139 | surface) 140 | if create_surface_result != vk.Result.success { 141 | panic('Could not create glfw window surface') 142 | } 143 | mut physical_device_cnt := u32(0) 144 | vk.enumerate_physical_devices(app.vk_instance, &physical_device_cnt, unsafe { nil }) 145 | if physical_device_cnt == 0 { 146 | panic('Could not find GPUs with vulkan support') 147 | } 148 | mut physical_devices_c := unsafe { malloc(physical_device_cnt * sizeof(C.PhysicalDevice)) } 149 | unsafe { 150 | defer { free(physical_devices_c) } 151 | } 152 | if vk.enumerate_physical_devices(app.vk_instance, &physical_device_cnt, physical_devices_c) != vk.Result.success { 153 | panic('Could not enumerate physical devices') 154 | } 155 | mut physical_device := C.PhysicalDevice(unsafe { nil }) 156 | physical_devices := to_v_array[C.PhysicalDevice](physical_devices_c, physical_device_cnt) 157 | 158 | for i in 0 .. physical_device_cnt { 159 | if is_device_suitable(physical_devices[i]) { 160 | println('Found suitable physical device address: ${C.PhysicalDevice(physical_devices[i])}') 161 | physical_device = physical_devices[i] 162 | } 163 | } 164 | 165 | if !glfw_get_physical_device_presentation_support(app.vk_instance, physical_device, 166 | 0) { 167 | panic('Graphics card does not have presentation support for GLFW') 168 | } 169 | 170 | mut device_extension_properties_count := u32(0) 171 | mut enumerate_device_extension_properties_result := vk.enumerate_device_extension_properties(physical_device, 172 | unsafe { nil }, &device_extension_properties_count, unsafe { nil }) 173 | if enumerate_device_extension_properties_result != vk.Result.success { 174 | panic('Could not enumerate_device_extension_properties to get the number of properties') 175 | } 176 | mut device_extension_properties_c := unsafe { malloc(sizeof(vk.ExtensionProperties) * device_extension_properties_count) } 177 | enumerate_device_extension_properties_result = vk.enumerate_device_extension_properties(physical_device, 178 | unsafe { nil }, device_extension_properties_count, device_extension_properties_c) 179 | if enumerate_device_extension_properties_result != vk.Result.success { 180 | panic('Could not enumerate_device_extension_properties to get the properties array') 181 | } 182 | device_extensions_required := [c'VK_KHR_swapchain'] 183 | device_extension_properties := to_v_array[vk.ExtensionProperties](device_extension_properties_c, 184 | device_extension_properties_count) 185 | for i in 0 .. device_extensions_required.len { 186 | mut extension_is_supported_by_device := false 187 | for j in 0 .. device_extension_properties.len { 188 | tmp_compare_result := unsafe { device_extensions_required[i].vstring().compare(device_extension_properties[j].extension_name[0].vstring()) } 189 | if tmp_compare_result == 0 { 190 | extension_is_supported_by_device = true 191 | } 192 | } 193 | if !extension_is_supported_by_device { 194 | panic('Required extension ${unsafe { device_extensions_required[i].vstring() }} not supported by graphics card') 195 | } 196 | } 197 | 198 | println('All required vulkan device extensions are supported by your graphics card') 199 | 200 | for !(glfw_window_should_close(window)) { 201 | /* 202 | <-- Here you can do the rendering stuff and so on.. --> 203 | */ 204 | // now print the data (which could come from callback) from the app struct and remove it afterwards 205 | for _, s in app.share_data { 206 | println(s) 207 | } 208 | app.share_data = [] 209 | glfw_poll_events() 210 | } 211 | } 212 | 213 | // Called on a keyboard event 214 | // GLFW_PRESS, GLFW_RELEASE or GLFW_REPEAT 215 | // https://www.glfw.org/docs/latest/group__keys.html 216 | fn key_callback_function(window &C.GLFWwindow, key int, scancode int, action int, mods int) { 217 | if action == glfw_press { 218 | // get user data pointer from glfw.window 219 | mut app := unsafe { &App(glfw_get_user_pointer(window)) } 220 | if key == glfw_key_enter { 221 | txt := 'Enter key pressed' 222 | app.share_data << txt 223 | } 224 | if key == glfw_key_escape { 225 | unsafe { glfw_set_should_close(window, 1) } 226 | } 227 | } 228 | } 229 | 230 | fn is_device_suitable(device C.PhysicalDevice) bool { 231 | device_properties := vk.PhysicalDeviceProperties{} 232 | vk.get_physical_device_properties(device, &device_properties) 233 | return device_properties.device_type == vk.PhysicalDeviceType.physical_device_type_discrete_gpu 234 | } 235 | 236 | // NOTE: array d is consumed/freed 237 | fn to_v_array[T](d &T, len u32) []T { 238 | mut ret := unsafe { []T{len: int(len)} } 239 | for i in 0 .. len { 240 | unsafe { 241 | ret[i] = d[i] 242 | } 243 | } 244 | unsafe { 245 | free(d) 246 | } 247 | return ret 248 | } 249 | 250 | // Using heap, since window contains a pointer to user data, 251 | // which should not be cleaned up automatically 252 | @[heap; typedef] 253 | struct C.GLFWwindow { 254 | } 255 | 256 | @[typedef] 257 | struct C.GLFWmonitor { 258 | } 259 | 260 | fn C.glfwInit() int 261 | pub fn glfw_initialize() bool { 262 | return C.glfwInit() == glfw_true 263 | } 264 | 265 | fn C.glfwTerminate() 266 | pub fn glfw_terminate() { 267 | C.glfwTerminate() 268 | } 269 | 270 | fn C.glfwCreateWindow(width int, height int, title &char, monitor &C.GLFWmonitor, share &C.GLFWwindow) &C.GLFWwindow 271 | pub fn glfw_create_window(width int, height int, title string, monitor &C.GLFWmonitor, share &C.GLFWwindow) &C.GLFWwindow { 272 | return C.glfwCreateWindow(width, height, title.str, monitor, share) 273 | } 274 | 275 | fn C.glfwSetWindowUserPointer(window &C.GLFWwindow, pointer voidptr) 276 | pub fn glfw_set_user_pointer(window &C.GLFWwindow, pointer voidptr) { 277 | C.glfwSetWindowUserPointer(window, pointer) 278 | } 279 | 280 | fn C.glfwGetWindowUserPointer(window &C.GLFWwindow) voidptr 281 | pub fn glfw_get_user_pointer(window &C.GLFWwindow) voidptr { 282 | return C.glfwGetWindowUserPointer(window) 283 | } 284 | 285 | pub type GLFWFnKey = fn (window &C.GLFWwindow, key_id int, scan_code int, action int, bit_filed int) 286 | 287 | fn C.glfwSetKeyCallback(window &C.GLFWwindow, callback GLFWFnKey) 288 | pub fn glfw_set_key_callback(window &C.GLFWwindow, callback GLFWFnKey) { 289 | C.glfwSetKeyCallback(window, callback) 290 | } 291 | 292 | fn C.glfwMakeContextCurrent(window &C.GLFWwindow) 293 | pub fn glfw_make_context_current(window &C.GLFWwindow) { 294 | C.glfwMakeContextCurrent(window) 295 | } 296 | 297 | fn C.glfwVulkanSupported() int 298 | pub fn glfw_is_vulkan_supported() bool { 299 | return C.glfwVulkanSupported() == glfw_true 300 | } 301 | 302 | fn C.glfwSetWindowShouldClose(window &C.GLFWwindow, value int) 303 | pub fn glfw_set_should_close(window &C.GLFWwindow, flag int) { 304 | C.glfwSetWindowShouldClose(window, flag) 305 | } 306 | 307 | fn C.glfwWindowShouldClose(window &C.GLFWwindow) int 308 | pub fn glfw_window_should_close(window &C.GLFWwindow) bool { 309 | return C.glfwWindowShouldClose(window) == glfw_true 310 | } 311 | 312 | fn C.glfwPollEvents() 313 | pub fn glfw_poll_events() { 314 | C.glfwPollEvents() 315 | } 316 | 317 | fn C.glfwGetRequiredInstanceExtensions(count &u32) &&char 318 | pub fn glfw_get_required_instance_extensions(count &u32) &&char { 319 | return C.glfwGetRequiredInstanceExtensions(count) 320 | } 321 | 322 | fn C.glfwCreateWindowSurface(C.Instance, &C.GLFWwindow, &vk.AllocationCallbacks, &C.SurfaceKHR) vk.Result 323 | pub fn glfw_create_window_surface(instance C.Instance, window &C.GLFWwindow, allocator &vk.AllocationCallbacks, surface &C.SurfaceKHR) vk.Result { 324 | return C.glfwCreateWindowSurface(instance, window, allocator, surface) 325 | } 326 | 327 | fn C.glfwWindowHint(int, int) 328 | pub fn glfw_window_hint(hint int, value int) { 329 | C.glfwWindowHint(hint, value) 330 | } 331 | 332 | fn C.glfwGetPhysicalDevicePresentationSupport(C.Instance, C.PhysicalDevice, u32) int 333 | pub fn glfw_get_physical_device_presentation_support(instance C.Instance, device C.PhysicalDevice, queuefamily u32) bool { 334 | return C.glfwGetPhysicalDevicePresentationSupport(instance, device, queuefamily) == glfw_true 335 | } 336 | -------------------------------------------------------------------------------- /include/KHR/khrplatform.h: -------------------------------------------------------------------------------- 1 | #ifndef __khrplatform_h_ 2 | #define __khrplatform_h_ 3 | 4 | /* 5 | ** Copyright (c) 2008-2018 The Khronos Group Inc. 6 | ** 7 | ** Permission is hereby granted, free of charge, to any person obtaining a 8 | ** copy of this software and/or associated documentation files (the 9 | ** "Materials"), to deal in the Materials without restriction, including 10 | ** without limitation the rights to use, copy, modify, merge, publish, 11 | ** distribute, sublicense, and/or sell copies of the Materials, and to 12 | ** permit persons to whom the Materials are furnished to do so, subject to 13 | ** the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included 16 | ** in all copies or substantial portions of the Materials. 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 25 | */ 26 | 27 | /* Khronos platform-specific types and definitions. 28 | * 29 | * The master copy of khrplatform.h is maintained in the Khronos EGL 30 | * Registry repository at https://github.com/KhronosGroup/EGL-Registry 31 | * The last semantic modification to khrplatform.h was at commit ID: 32 | * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 33 | * 34 | * Adopters may modify this file to suit their platform. Adopters are 35 | * encouraged to submit platform specific modifications to the Khronos 36 | * group so that they can be included in future versions of this file. 37 | * Please submit changes by filing pull requests or issues on 38 | * the EGL Registry repository linked above. 39 | * 40 | * 41 | * See the Implementer's Guidelines for information about where this file 42 | * should be located on your system and for more details of its use: 43 | * http://www.khronos.org/registry/implementers_guide.pdf 44 | * 45 | * This file should be included as 46 | * #include 47 | * by Khronos client API header files that use its types and defines. 48 | * 49 | * The types in khrplatform.h should only be used to define API-specific types. 50 | * 51 | * Types defined in khrplatform.h: 52 | * khronos_int8_t signed 8 bit 53 | * khronos_uint8_t unsigned 8 bit 54 | * khronos_int16_t signed 16 bit 55 | * khronos_uint16_t unsigned 16 bit 56 | * khronos_int32_t signed 32 bit 57 | * khronos_uint32_t unsigned 32 bit 58 | * khronos_int64_t signed 64 bit 59 | * khronos_uint64_t unsigned 64 bit 60 | * khronos_intptr_t signed same number of bits as a pointer 61 | * khronos_uintptr_t unsigned same number of bits as a pointer 62 | * khronos_ssize_t signed size 63 | * khronos_usize_t unsigned size 64 | * khronos_float_t signed 32 bit floating point 65 | * khronos_time_ns_t unsigned 64 bit time in nanoseconds 66 | * khronos_utime_nanoseconds_t unsigned time interval or absolute time in 67 | * nanoseconds 68 | * khronos_stime_nanoseconds_t signed time interval in nanoseconds 69 | * khronos_boolean_enum_t enumerated boolean type. This should 70 | * only be used as a base type when a client API's boolean type is 71 | * an enum. Client APIs which use an integer or other type for 72 | * booleans cannot use this as the base type for their boolean. 73 | * 74 | * Tokens defined in khrplatform.h: 75 | * 76 | * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. 77 | * 78 | * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. 79 | * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. 80 | * 81 | * Calling convention macros defined in this file: 82 | * KHRONOS_APICALL 83 | * KHRONOS_APIENTRY 84 | * KHRONOS_APIATTRIBUTES 85 | * 86 | * These may be used in function prototypes as: 87 | * 88 | * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( 89 | * int arg1, 90 | * int arg2) KHRONOS_APIATTRIBUTES; 91 | */ 92 | 93 | #if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) 94 | # define KHRONOS_STATIC 1 95 | #endif 96 | 97 | /*------------------------------------------------------------------------- 98 | * Definition of KHRONOS_APICALL 99 | *------------------------------------------------------------------------- 100 | * This precedes the return type of the function in the function prototype. 101 | */ 102 | #if defined(KHRONOS_STATIC) 103 | /* If the preprocessor constant KHRONOS_STATIC is defined, make the 104 | * header compatible with static linking. */ 105 | # define KHRONOS_APICALL 106 | #elif defined(_WIN32) 107 | # define KHRONOS_APICALL __declspec(dllimport) 108 | #elif defined (__SYMBIAN32__) 109 | # define KHRONOS_APICALL IMPORT_C 110 | #elif defined(__ANDROID__) 111 | # define KHRONOS_APICALL __attribute__((visibility("default"))) 112 | #else 113 | # define KHRONOS_APICALL 114 | #endif 115 | 116 | /*------------------------------------------------------------------------- 117 | * Definition of KHRONOS_APIENTRY 118 | *------------------------------------------------------------------------- 119 | * This follows the return type of the function and precedes the function 120 | * name in the function prototype. 121 | */ 122 | #if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) 123 | /* Win32 but not WinCE */ 124 | # define KHRONOS_APIENTRY __stdcall 125 | #else 126 | # define KHRONOS_APIENTRY 127 | #endif 128 | 129 | /*------------------------------------------------------------------------- 130 | * Definition of KHRONOS_APIATTRIBUTES 131 | *------------------------------------------------------------------------- 132 | * This follows the closing parenthesis of the function prototype arguments. 133 | */ 134 | #if defined (__ARMCC_2__) 135 | #define KHRONOS_APIATTRIBUTES __softfp 136 | #else 137 | #define KHRONOS_APIATTRIBUTES 138 | #endif 139 | 140 | /*------------------------------------------------------------------------- 141 | * basic type definitions 142 | *-----------------------------------------------------------------------*/ 143 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) 144 | 145 | 146 | /* 147 | * Using 148 | */ 149 | #include 150 | typedef int32_t khronos_int32_t; 151 | typedef uint32_t khronos_uint32_t; 152 | typedef int64_t khronos_int64_t; 153 | typedef uint64_t khronos_uint64_t; 154 | #define KHRONOS_SUPPORT_INT64 1 155 | #define KHRONOS_SUPPORT_FLOAT 1 156 | /* 157 | * To support platform where unsigned long cannot be used interchangeably with 158 | * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. 159 | * Ideally, we could just use (u)intptr_t everywhere, but this could result in 160 | * ABI breakage if khronos_uintptr_t is changed from unsigned long to 161 | * unsigned long long or similar (this results in different C++ name mangling). 162 | * To avoid changes for existing platforms, we restrict usage of intptr_t to 163 | * platforms where the size of a pointer is larger than the size of long. 164 | */ 165 | #if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) 166 | #if __SIZEOF_POINTER__ > __SIZEOF_LONG__ 167 | #define KHRONOS_USE_INTPTR_T 168 | #endif 169 | #endif 170 | 171 | #elif defined(__VMS ) || defined(__sgi) 172 | 173 | /* 174 | * Using 175 | */ 176 | #include 177 | typedef int32_t khronos_int32_t; 178 | typedef uint32_t khronos_uint32_t; 179 | typedef int64_t khronos_int64_t; 180 | typedef uint64_t khronos_uint64_t; 181 | #define KHRONOS_SUPPORT_INT64 1 182 | #define KHRONOS_SUPPORT_FLOAT 1 183 | 184 | #elif defined(_WIN32) && !defined(__SCITECH_SNAP__) 185 | 186 | /* 187 | * Win32 188 | */ 189 | typedef __int32 khronos_int32_t; 190 | typedef unsigned __int32 khronos_uint32_t; 191 | typedef __int64 khronos_int64_t; 192 | typedef unsigned __int64 khronos_uint64_t; 193 | #define KHRONOS_SUPPORT_INT64 1 194 | #define KHRONOS_SUPPORT_FLOAT 1 195 | 196 | #elif defined(__sun__) || defined(__digital__) 197 | 198 | /* 199 | * Sun or Digital 200 | */ 201 | typedef int khronos_int32_t; 202 | typedef unsigned int khronos_uint32_t; 203 | #if defined(__arch64__) || defined(_LP64) 204 | typedef long int khronos_int64_t; 205 | typedef unsigned long int khronos_uint64_t; 206 | #else 207 | typedef long long int khronos_int64_t; 208 | typedef unsigned long long int khronos_uint64_t; 209 | #endif /* __arch64__ */ 210 | #define KHRONOS_SUPPORT_INT64 1 211 | #define KHRONOS_SUPPORT_FLOAT 1 212 | 213 | #elif 0 214 | 215 | /* 216 | * Hypothetical platform with no float or int64 support 217 | */ 218 | typedef int khronos_int32_t; 219 | typedef unsigned int khronos_uint32_t; 220 | #define KHRONOS_SUPPORT_INT64 0 221 | #define KHRONOS_SUPPORT_FLOAT 0 222 | 223 | #else 224 | 225 | /* 226 | * Generic fallback 227 | */ 228 | #include 229 | typedef int32_t khronos_int32_t; 230 | typedef uint32_t khronos_uint32_t; 231 | typedef int64_t khronos_int64_t; 232 | typedef uint64_t khronos_uint64_t; 233 | #define KHRONOS_SUPPORT_INT64 1 234 | #define KHRONOS_SUPPORT_FLOAT 1 235 | 236 | #endif 237 | 238 | 239 | /* 240 | * Types that are (so far) the same on all platforms 241 | */ 242 | typedef signed char khronos_int8_t; 243 | typedef unsigned char khronos_uint8_t; 244 | typedef signed short int khronos_int16_t; 245 | typedef unsigned short int khronos_uint16_t; 246 | 247 | /* 248 | * Types that differ between LLP64 and LP64 architectures - in LLP64, 249 | * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears 250 | * to be the only LLP64 architecture in current use. 251 | */ 252 | #ifdef KHRONOS_USE_INTPTR_T 253 | typedef intptr_t khronos_intptr_t; 254 | typedef uintptr_t khronos_uintptr_t; 255 | #elif defined(_WIN64) 256 | typedef signed long long int khronos_intptr_t; 257 | typedef unsigned long long int khronos_uintptr_t; 258 | #else 259 | typedef signed long int khronos_intptr_t; 260 | typedef unsigned long int khronos_uintptr_t; 261 | #endif 262 | 263 | #if defined(_WIN64) 264 | typedef signed long long int khronos_ssize_t; 265 | typedef unsigned long long int khronos_usize_t; 266 | #else 267 | typedef signed long int khronos_ssize_t; 268 | typedef unsigned long int khronos_usize_t; 269 | #endif 270 | 271 | #if KHRONOS_SUPPORT_FLOAT 272 | /* 273 | * Float type 274 | */ 275 | typedef float khronos_float_t; 276 | #endif 277 | 278 | #if KHRONOS_SUPPORT_INT64 279 | /* Time types 280 | * 281 | * These types can be used to represent a time interval in nanoseconds or 282 | * an absolute Unadjusted System Time. Unadjusted System Time is the number 283 | * of nanoseconds since some arbitrary system event (e.g. since the last 284 | * time the system booted). The Unadjusted System Time is an unsigned 285 | * 64 bit value that wraps back to 0 every 584 years. Time intervals 286 | * may be either signed or unsigned. 287 | */ 288 | typedef khronos_uint64_t khronos_utime_nanoseconds_t; 289 | typedef khronos_int64_t khronos_stime_nanoseconds_t; 290 | #endif 291 | 292 | /* 293 | * Dummy value used to pad enum types to 32 bits. 294 | */ 295 | #ifndef KHRONOS_MAX_ENUM 296 | #define KHRONOS_MAX_ENUM 0x7FFFFFFF 297 | #endif 298 | 299 | /* 300 | * Enumerated boolean type 301 | * 302 | * Values other than zero should be considered to be true. Therefore 303 | * comparisons should not be made against KHRONOS_TRUE. 304 | */ 305 | typedef enum { 306 | KHRONOS_FALSE = 0, 307 | KHRONOS_TRUE = 1, 308 | KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM 309 | } khronos_boolean_enum_t; 310 | 311 | #endif /* __khrplatform_h_ */ 312 | -------------------------------------------------------------------------------- /v.mod: -------------------------------------------------------------------------------- 1 | Module { 2 | name: 'vulkan' 3 | author: 'antono2@github.com' 4 | description: 'V Vulkan Bindings' 5 | version: '0.0.1' 6 | repo_url: 'https://github.com/antono2/vulkan' 7 | vcs: 'git' 8 | tags: ['vulkan','graphics'] 9 | license: 'Public Domain' 10 | dependencies: [] 11 | } 12 | --------------------------------------------------------------------------------