{"id":13721551,"url":"https://github.com/maierfelix/nvk","last_synced_at":"2025-05-16T10:06:52.086Z","repository":{"id":46493656,"uuid":"146889623","full_name":"maierfelix/nvk","owner":"maierfelix","description":"Vulkan API for JavaScript/TypeScript","archived":false,"fork":false,"pushed_at":"2021-01-03T02:41:19.000Z","size":363572,"stargazers_count":930,"open_issues_count":7,"forks_count":32,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-04-09T07:01:10.637Z","etag":null,"topics":["bindings","javascript","vulkan"],"latest_commit_sha":null,"homepage":"https://maierfelix.github.io/nvk/1.2.162/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maierfelix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://www.paypal.me/maierfelix"}},"created_at":"2018-08-31T12:34:00.000Z","updated_at":"2025-03-16T11:10:10.000Z","dependencies_parsed_at":"2022-08-12T12:51:02.465Z","dependency_job_id":null,"html_url":"https://github.com/maierfelix/nvk","commit_stats":null,"previous_names":["maierfelix/node-vulkan"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maierfelix%2Fnvk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maierfelix%2Fnvk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maierfelix%2Fnvk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maierfelix%2Fnvk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maierfelix","download_url":"https://codeload.github.com/maierfelix/nvk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254509476,"owners_count":22082891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bindings","javascript","vulkan"],"created_at":"2024-08-03T01:01:18.486Z","updated_at":"2025-05-16T10:06:47.077Z","avatar_url":"https://github.com/maierfelix.png","language":"C++","funding_links":["https://www.paypal.me/maierfelix"],"categories":["Bindings","C++"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"#\"\u003e\n    \u003cimg src=\"https://i.imgur.com/7rnMbVp.png\" height=\"204\"\u003e\n  \u003c/a\u003e\n  \u003cbr/\u003e\n  \u003cbr/\u003e\n  \u003ca href=\"https://www.npmjs.com/package/nvk\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/nvk.svg?style=flat-square\" alt=\"NPM Version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"#\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/vulkan-1.2.162-f07178.svg?style=flat-square\" alt=\"Vulkan Header Version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"//www.npmjs.com/package/nvk\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/dt/nvk.svg?style=flat-square\" alt=\"NPM Downloads\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n#\n\nThis is a low-abstraction, high-performance [Vulkan](https://en.wikipedia.org/wiki/Vulkan_(API)) API with interfaces for JavaScript and [TypeScript](#typescript).\n\n### Platforms:\n\n*nvk* comes with pre-built N-API binaries for the following platforms:\n\n|       OS      |     Status    |\n| ------------- | ------------- |\n| \u003cimg src=\"https://i.imgur.com/FF3Ssp6.png\" alt=\"\" height=\"16px\"\u003e  Windows       | ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ✔ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌|\n| \u003cimg src=\"https://i.imgur.com/bkBCY7V.png\" alt=\"\" height=\"16px\"\u003e  Linux         | ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ✔ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌|\n| \u003cimg src=\"https://i.imgur.com/iPt4GHz.png\" alt=\"\" height=\"16px\"\u003e  MacOS         | ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ✔ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌|\n\n### Examples:\n\n| Real-Time RTX Ray Tracer |\n:-------------------------:|\n\u003ca\u003e\u003cimg src=\"https://i.imgur.com/ga6CJca.png\" height=\"228\"\u003e\u003c/a\u003e\n\n### Why Vulkan in JavaScript?\n - Vulkan is a binding friendly API\n - Less overhead than WebGL/OpenGL\n - Essential features like Compute, Geometry and Tesselation shaders\n - Support for [Real-Time Ray Tracing](https://devblogs.nvidia.com/vulkan-raytracing/), [Mesh shaders](https://devblogs.nvidia.com/introduction-turing-mesh-shaders/), ...\n - Supports Multithreading\n - Low-level memory control using [ArrayBuffers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)\n\nThis project is a thin layer on top of native Vulkan, built with simplicity and performance in mind. Native memory for Vulkan gets constructed entirely within JavaScript to reduce trampolining overhead.\nBounding checks and type validations are enabled by default, but can be disabled using the `--disable-validation-checks` flag.\n\n#\n\n  * [Installation](#installation)\n  * [Example](#example)\n  * [TypeScript](#typescript)\n  * [Syntactic Sugar](#syntactic-sugar)\n      - [sType auto-filling](#stype-auto-filling)\n      - [Structure creation shortcut](#structure-creation-shortcut)\n      - [Nested Structures](#nested-structures)\n      - [Cached Structures](#cached-structures)\n  * [Project Structure](#project-structure)\n  * [Binding Code Generator](#binding-code-generator)\n  * [Linking](#linking)\n  * [Build Instructions](#build-instructions)\n    + [Requirements](#requirements)\n    + [Windows](#windows)\n    + [Linux](#linux)\n    + [MacOS](#macos)\n    + [Releasing](#releasing)\n    + [Publishing](#publishing)\n  * [CLI](#cli)\n      - [Syntax](#syntax)\n      - [Flags](#flags)\n    + [Usage](#usage)\n      - [General](#general)\n      - [Generating](#generating)\n      - [Building](#building)\n  * [RenderDoc](#renderdoc)\n  * [TODOs](#todos)\n\n## Installation:\n\n````\nnpm install nvk\n````\n\n## Example:\n\nIn most cases the bindings match the C99 style of Vulkan. This allows you to follow existing C/C++ tutorials, but write the implementation itself with *nvk*. Note that both interfaces end up with a similar amount of code. Optionally you can use some [syntactic sugar](#syntactic-sugar) to write things quicker.\n\nJavaScript/TypeScript:\n````js\nlet instance = new VkInstance();\nlet appInfo = new VkApplicationInfo();\nappInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;\nappInfo.pApplicationName = \"App\";\nappInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);\nappInfo.pEngineName = \"Engine\";\nappInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);\nappInfo.apiVersion = VK_API_VERSION_1_2;\n\nlet validationLayers = [\n  \"VK_LAYER_KHRONOS_validation\"\n];\nlet instanceInfo = new VkInstanceCreateInfo();\ninstanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;\ninstanceInfo.pApplicationInfo = appInfo;\ninstanceInfo.ppEnabledLayerNames = validationLayers;\ninstanceInfo.enabledLayerCount = validationLayers.length;\nvkCreateInstance(instanceInfo, null, instance);\n````\n\nC++:\n````cpp\nVkInstance instance;\nVkApplicationInfo appInfo = {};\nappInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;\nappInfo.pApplicationName = \"App\";\nappInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);\nappInfo.pEngineName = \"Engine\";\nappInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);\nappInfo.apiVersion = VK_API_VERSION_1_2;\n\nconst std::vector\u003cconst char*\u003e validationLayers = {\n  \"VK_LAYER_KHRONOS_validation\"\n};\nVkInstanceCreateInfo instanceInfo = {};\ninstanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;\ninstanceInfo.pApplicationInfo = \u0026appInfo;\ninstanceInfo.ppEnabledLayerNames = validationLayers.data();\ninstanceInfo.enabledLayerCount = static_cast\u003cuint32_t\u003e(validationLayers.size());\nvkCreateInstance(\u0026instanceInfo, nullptr, \u0026instance);\n````\n\n## TypeScript:\n\nTo use the TypeScript definition file, simply follow the installation steps above or use [this](https://github.com/maierfelix/nvk-examples/tree/master/typescript) example as a reference. Afterwards in your `.ts` file, import and use *nvk* as follows:\n\n````ts\nimport * as nvk from \"nvk\";\n\nObject.assign(global, nvk);\n\nlet win = new VulkanWindow({\n  width: 480,\n  height: 320,\n  title: \"typescript-example\"\n});\n\nlet appInfo = new VkApplicationInfo({\n  pApplicationName: \"Hello!\",\n  applicationVersion: VK_MAKE_VERSION(1, 0, 0),\n  pEngineName: \"No Engine\",\n  engineVersion: VK_MAKE_VERSION(1, 0, 0),\n  apiVersion: VK_API_VERSION_1_2\n});\n````\n\nAlso note, that it is recommended to enable the `--strict` mode in the TS compiler options and use the latest version of the TS compiler.\n\n## Syntactic Sugar:\n\nThe API gives you some sugar to write things quicker, but still gives you the option to write everything explicitly\n\n#### sType auto-filling\n`sType` members get auto-filled, but you can still set them yourself\n\n````js\nlet appInfo = new VkApplicationInfo();\nappInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;\n````\n\nBecomes:\n````js\nlet appInfo = new VkApplicationInfo(); // sType auto-filled\n````\n\n#### Structure creation shortcut\n\nInstead of:\n````js\nlet offset = new VkOffset2D();\noffset.x = 0;\noffset.y = 0;\nlet extent = new VkExtent2D();\nextent.width = 640;\nextent.height = 480;\nlet renderArea = new VkRect2D();\nrenderArea.offset = offset;\nrenderArea.extent = extent;\n````\n\nYou can write:\n````js\nlet renderArea = new VkRect2D({\n  offset: new VkOffset2D({ x: 0, y: 0 }),\n  extent: new VkExtent2D({ width: 640, height: 480 })\n});\n````\n\n#### Nested Structures\n\n*nvk* allows to use nested structures to improve memory usage and performance. A nested structure is pre-allocated automatically and shares the native memory of it's top-level structure.\nYou can use the `--enable-shared-memory-hints` flag, to get hints where you could've used a nested structure in your code.\n\nInstead of:\n````js\nlet scissor = new VkRect2D();\nscissor.offset = new VkOffset2D();\nscissor.extent = new VkExtent2D();\nscissor.offset.x = 0;\nscissor.offset.y = 0;\nscissor.extent.width = 480;\nscissor.extent.height = 320;\n````\n\nYou can write:\n````js\nlet scissor = new VkRect2D();\nscissor.offset.x = 0;\nscissor.offset.y = 0;\nscissor.extent.width = 480;\nscissor.extent.height = 320;\n````\n\n#### Cached Structures\n\nTo reduce GC pressure, *nvk* allows to use cached structures. Instead of having to allocate a structure every time on the heap, *nvk* allows to use a caching mechanism to mimic stack allocation.\n\nImagine the following situation:\n````js\nlet commandBuffers = [...Array(8)].map(() =\u003e new VkCommandBuffer());\nfor (let ii = 0; ii \u003c commandBuffers.length; ++ii) {\n  let commandBufferBeginInfo = new VkCommandBufferBeginInfo();\n  vkBeginCommandBuffer(commandBuffers[ii], cmdBufferBeginInfo);\n  ...\n};\n````\nThis results in *8* allocations of `VkCommandBufferBeginInfo` structures. When this code gets executed in frequently used code sections, the heap pressure will be high.\n\nNow *nvk* has a mechanism to simulate stack allocation:\n````js\nlet commandBuffers = [...Array(8)].map(() =\u003e new VkCommandBuffer());\nfor (let ii = 0; ii \u003c commandBuffers.length; ++ii) {\n  let commandBufferBeginInfo = VkCommandBufferBeginInfo(\"0x0\");\n  vkBeginCommandBuffer(commandBuffers[ii], cmdBufferBeginInfo);\n  ...\n};\n````\n\nOn the first iteration of the loop, a `VkCommandBufferBeginInfo` structure is allocated on the heap but also gets cached internally. Based on the String id `0x0` you have added, *nvk* uses this id to identify this structure and return a cached one whenever this code gets executed again.\n\nObviously, you don't want to add your own ids to each structure by hand. There is a [rollup](https://rollupjs.org/) plugin, which detects *nvk* structure calls (when invoked without `new`) and inserts a unique id automatically. You can find the rollup plugin [here](https://www.npmjs.com/package/nvk-struct-cache) and a project example [here](https://github.com/maierfelix/nvk-examples/tree/master/struct-caching).\n\n## Project Structure:\n - `docs`: generated vulkan documentation files\n - `generator`: code for binding generation\n - `generated`: the generated binding code\n - `examples`: ready-to-run examples\n - `lib`: required third party libs\n - `src`: classes for e.g. window creation\n\nThis tool uses a new JavaScript type called [`BigInt`](https://developers.google.com/web/updates/2018/05/bigint) to represent memory addresses returned by Vulkan. The `BigInt` type was recently added, so make sure you use a recent node.js version.\n\n## Binding Code Generator:\n\nThe Generator generates code based on a `vk.xml` specification file. It first converts the XML file into an [AST](https://raw.githubusercontent.com/maierfelix/nvk/master/generated/1.2.162/ast.json), which is then used by the code generator. Currently more than `~300.000` lines of code get generated, where `~60.000` lines are JavaScript, `~50.000` lines are TypeScript, `~40.000` lines are C++ code and the rest code for the documentation and AST.\n\nStarting from version `0.5.0`, *nvk* now uses a concept called *Hybrid bindings*, which reduces the overhead of JavaScript\u003c-\u003eC++ context switching. Structures tend to have many members, where each member has to be a getter/setter function. Before this change, these getters/setters were written in C++, so there were many tiny context switches. Now the native memory of Structures and Handles just get filled entirely within JavaScript (see the file [here](https://raw.githubusercontent.com/maierfelix/nvk/master/generated/1.2.162/win32/interfaces.js)), resulting in much less overhead and much simpler binding and generator code.\n\n## Linking:\n\nThis section is of interest, if you have an existing C++ project and want to link against this one.\n\nThis project mostly doesn't requires to be linked against. All structures and handles have properties to access the underlying memory directly. For example, see [VkApplicationInfo](https://maierfelix.github.io/nvk/1.2.162/structs/VkApplicationInfo.html) (#Default Properties).\n\nStructures and handles come with these 3 properties:\n\n - *.memoryBuffer*: Reference to the underlying native memory, wrapped inside an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)\n - *.memoryAddress*: Native address (BigInt) of *memoryBuffer*. To convert BigInt into a native type, see e.g. [this](https://github.com/nodejs/node-addon-api/blob/master/doc/bigint.md#int64value) document\n - *.byteLength*: Total native bytelength of the structure/handle\n\n## Build Instructions:\n\n**Warning**: You may want to **skip this section**, as *nvk* uses [N-API](https://nodejs.org/api/n-api.html#n_api_n_api) and ships pre-compiled binaries. This section is only of interest if you want to generate and build the bindings yourself, which is likely not your intention!\n\nThis project requires two-pass compilation which means, after initially compiling the bindings, a second compilation is required. This is necessary, because this project constructs Vulkan memory entirely from within JavaScript.\n - At the first compilation, memory layouts of vulkan structures get stored inside a JSON file\n - At the second pass, these memory layout then get used to inline memory offsets inside the JavaScript binding code\n\n### Requirements:\n - node.js \u003e= v10.9.0 recommended\n\n### Windows:\nIf you already have Visual Studio \u003e= 15 installed, then just make sure to have Python `2.7.x` installed.\n\nIf you don't have Visual Studio, then install the following package:\n````\nnpm install --global --production windows-build-tools\n````\n\nNow install the corresponding Vulkan SDK version from [here](https://vulkan.lunarg.com/sdk/home#windows).\n\nNext, clone this repository.\n\nTo generate and compile the bindings, run:\n````\nnpm run generate --vkversion=x\nnpm run build --vkversion=x\n````\n\n### Linux:\n\nDownload and setup the corresponding Vulkan SDK version from [here](https://vulkan.lunarg.com/sdk/home#linux).\n\nFollow the guide on how to correctly setup the SDK.\nMake sure that the environment variables are correctly set, e.g. `echo $VULKAN_SDK`.\n\nNext, clone this repository.\n\nTo generate and compile the bindings, run:\n````\nnpm run generate --vkversion=x\nnpm run build --vkversion=x\n````\n\n### MacOS:\n\nDownload and setup the corresponding Vulkan SDK version from [here](https://vulkan.lunarg.com/sdk/home#mac).\n\nFollow the guide on how to correctly setup the SDK.\nMake sure that the environment variables are correctly set, e.g. `echo $VULKAN_SDK`.\n\nNext, clone this repository.\n\nTo generate and compile the bindings, run:\n````\nnpm run generate --vkversion=x\nnpm run build --vkversion=x\n````\n\n### Releasing:\nWhen updating the bindings to a newer Vulkan version, or other drastic changes were made:\n\n - Update the [package.json](https://github.com/maierfelix/nvk/blob/master/package.json):\n   - Add the previously used Vulkan version to `config.OUTDATED`\n   - Add the new Vulkan version to `config.POST_DEFAULT_BINDING_VERSION`\n   - Edit the TS type reference lines at the beginning of [index.js](https://github.com/maierfelix/nvk/blob/master/index.js) to contain the new Vulkan version\n - Update the [.npmignore](https://github.com/maierfelix/nvk/blob/master/.npmignore)\n   - Make sure that the `config.OUTDATED` section in [package.json](https://github.com/maierfelix/nvk/blob/master/package.json) matches the content in there, so previous/outdated Vulkan bindings dont't get included in the npm package\n - Update the [README.md](https://github.com/maierfelix/nvk/blob/master/README.md) to contain links to the new Vulkan version\n - Update the Website link of the repository\n\n### Publishing:\nWhen a new version of this project should be published (e.g. to *npm*), consider the following steps:\n\n - Update the [package.json](https://github.com/maierfelix/nvk/blob/master/package.json):\n   - Update the npm package version (if necessary)\n - Make sure that the bindings for all platforms were generated with:\n   - The `--docs` flag enabled, to include a documentation\n   - The `--disable-minification` flag **not** enabled\n - Before running `npm init \u0026 npm publish`, you should preview the files which will land into the package. This can be done using the command `npm pack --dry-run`\n\n## CLI:\n\n#### Syntax:\n````\nnpm run [script] [flag] [value]\n````\n\n### Usage:\n\n#### General:\n````\n[--disable-validation-checks]: Disables type and bounding checks for better performance\n[--enable-shared-memory-hints]: Enables console hints, reporting to use nested structures when possible - useful for performance optimization\n````\n\n#### Generating:\nYou can generate bindings with:\n````\nnpm run generate --vkversion=1.2.162\n````\n\nThe generated bindings can then be found in `generated/{vkversion}/${platform}`\n\n - Make sure the specified version to generate bindings for can be found [here](https://github.com/KhronosGroup/Vulkan-Docs/releases)\n - The binding specification file gets auto-downloaded and is stored in `generate/specifications/{vkversion}.xml`\u003cbr/\u003e\n - `--incremental` flag should only be used if you're a developer of *nvk*\n\n##### Flags:\n````\n[--vkversion]: The Vulkan version to generate bindings for\n[--fake-platform]: Allows to specify a fake platform to generate bindings for. Only use this when the native bindings don't have to be recompiled! A useful but dangerous flag\n[--disable-minification]: Disables code minification of the JavaScript interfaces\n[--incremental]: Enables incremental builds when building the bindings\n[--docs]: Generates HTML-based documentation, also used for TypeScript type annotations\n````\n\n#### Building:\nYou can build the generated bindings with:\n````\nnpm run build --vkversion=1.2.162\n````\n\nThe compiled bindings can then be found in `generated/{vkversion}/build`\n\n##### Flags:\n````\n[--vkversion]: The Vulkan version to build bindings for\n[--msvsversion]: The Visual Studio version to build the bindings with\n````\n\n### RenderDoc:\n\nUsing [RenderDoc](https://renderdoc.org/) is simple. Open RenderDoc and in the *Launch Application* tab, enter e.g.:\n\n - Executable Path: `C:\\Program Files\\nodejs\\node.exe`\n - Command-line Arguments: `--experimental-modules C:\\GitHub\\nvk-examples\\triangle\\index.mjs`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaierfelix%2Fnvk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaierfelix%2Fnvk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaierfelix%2Fnvk/lists"}