Code Monkey home page Code Monkey logo

nvk's Introduction



NPM Version Vulkan Header Version NPM Downloads

This is a low-abstraction, high-performance Vulkan API with interfaces for JavaScript and TypeScript.

Platforms:

nvk comes with pre-built N-API binaries for the following platforms:

OS Status
Windows ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ✔ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
Linux ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ✔ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
MacOS ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ✔ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌

Why Vulkan in JavaScript?

This 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. Bounding checks and type validations are enabled by default, but can be disabled using the --disable-validation-checks flag.

Installation:

npm install nvk

Example:

In 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 to write things quicker.

JavaScript/TypeScript:

let instance = new VkInstance();
let appInfo = new VkApplicationInfo();
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "App";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;

let validationLayers = [
  "VK_LAYER_LUNARG_standard_validation"
];
let instanceInfo = new VkInstanceCreateInfo();
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pApplicationInfo = appInfo;
instanceInfo.ppEnabledLayerNames = validationLayers;
instanceInfo.enabledLayerCount = validationLayers.length;
vkCreateInstance(instanceInfo, null, instance);

C++:

VkInstance instance;
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "App";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;

const std::vector<const char*> validationLayers = {
  "VK_LAYER_LUNARG_standard_validation"
};
VkInstanceCreateInfo instanceInfo = {};
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pApplicationInfo = &appInfo;
instanceInfo.ppEnabledLayerNames = validationLayers.data();
instanceInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
vkCreateInstance(&instanceInfo, nullptr, &instance);

TypeScript:

To use the TypeScript definition file, simply follow the installation steps above or use this example as a reference. Afterwards in your .ts file, import and use nvk as follows:

import * as nvk from "nvk";

Object.assign(global, nvk);

let win = new VulkanWindow({
  width: 480,
  height: 320,
  title: "typescript-example"
});

let appInfo = new VkApplicationInfo({
  pApplicationName: "Hello!",
  applicationVersion: VK_MAKE_VERSION(1, 0, 0),
  pEngineName: "No Engine",
  engineVersion: VK_MAKE_VERSION(1, 0, 0),
  apiVersion: VK_API_VERSION_1_0
});

Also note, that it is recommended to enable the --strict mode in the TS compiler options and use the latest version of the TS compiler.

Syntactic Sugar:

The API gives you some sugar to write things quicker, but still gives you the option to write everything explicitly

sType auto-filling

sType members get auto-filled, but you can still set them yourself

let appInfo = new VkApplicationInfo();
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;

Becomes:

let appInfo = new VkApplicationInfo(); // sType auto-filled

Structure creation shortcut

Instead of:

let offset = new VkOffset2D();
offset.x = 0;
offset.y = 0;
let extent = new VkExtent2D();
extent.width = 640;
extent.height = 480;
let renderArea = new VkRect2D();
renderArea.offset = offset;
renderArea.extent = extent;

You can write:

let renderArea = new VkRect2D({
  offset: new VkOffset2D({ x: 0, y: 0 }),
  extent: new VkExtent2D({ width: 640, height: 480 })
});

Nested structures

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. You can use the --enable-shared-memory-hints flag, to get hints where you could've used a nested structure in your code.

Instead of:

let scissor = new VkRect2D();
scissor.offset = new VkOffset2D();
scissor.extent = new VkExtent2D();
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = 480;
scissor.extent.height = 320;

You can write:

let scissor = new VkRect2D();
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = 480;
scissor.extent.height = 320;

Project Structure:

  • docs: generated vulkan documentation files
  • generator: code for binding generation
  • generated: the generated binding code
  • examples: ready-to-run examples
  • lib: required third party libs
  • src: classes for e.g. window creation

This tool uses a new JavaScript type called BigInt to represent memory addresses returned by Vulkan. The BigInt type was recently added, so make sure you use a recent node.js version.

Binding Code Generator:

The Generator generates code based on a vk.xml specification file. It first converts the XML file into an AST, 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.

Starting from version 0.5.0, nvk now uses a concept called Hybrid bindings, which reduces the overhead of JavaScript<->C++ 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), resulting in much less overhead and much simpler binding and generator code.

Linking:

This section is of interest, if you have an existing C++ project and want to link against this one.

This 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 (#Default Properties).

Structures and handles come with these 3 properties:

  • .memoryBuffer: Reference to the underlying native memory, wrapped inside an ArrayBuffer
  • .memoryAddress: Native address (BigInt) of memoryBuffer. To convert BigInt into a native type, see e.g. this document
  • .byteLength: Total native bytelength of the structure/handle

Build Instructions:

Warning: You may want to skip this section, as nvk uses 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!

This 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.

  • At the first compilation, memory layouts of vulkan structures get stored inside a JSON file
  • At the second pass, these memory layout then get used to inline memory offsets inside the JavaScript binding code

Requirements:

  • node.js >= v10.9.0 recommended

Windows:

If you already have Visual Studio >= 15 installed, then just make sure to have Python 2.7.x installed.

If you don't have Visual Studio, then install the following package:

npm install --global --production windows-build-tools

Now install the corresponding Vulkan SDK version from here.

Next, clone this repository.

To generate and compile the bindings, run:

npm run generate --vkversion=x
npm run build --vkversion=x

Linux:

Download and setup the corresponding Vulkan SDK version from here.

Follow the guide on how to correctly setup the SDK. Make sure that the environment variables are correctly set, e.g. echo $VULKAN_SDK.

Next, clone this repository.

To generate and compile the bindings, run:

npm run generate --vkversion=x
npm run build --vkversion=x

MacOS:

Download and setup the corresponding Vulkan SDK version from here.

Follow the guide on how to correctly setup the SDK. Make sure that the environment variables are correctly set, e.g. echo $VULKAN_SDK.

Next, clone this repository.

To generate and compile the bindings, run:

npm run generate --vkversion=x
npm run build --vkversion=x

CLI:

Syntax:

npm run [script] [flag] [value]

Usage:

General:

[--disable-validation-checks]: Disables type and bounding checks for better performance
[--enable-shared-memory-hints]: Enables console hints, reporting to use nested structures when possible - useful for performance optimization

Generator:

You can generate bindings with:

npm run generate --vkversion=1.1.114

The generated bindings can then be found in generated/{vkversion}/${platform}

  • Make sure the specified version to generate bindings for can be found here
  • The binding specification file gets auto-downloaded and is stored in generate/specifications/{vkversion}.xml
  • --incremental flag should only be used if you're a developer of nvk
Flags:
[--vkversion]: The Vulkan version to generate bindings for
[--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
[--disable-minification]: Disables code minification of the JavaScript interfaces
[--incremental]: Enables incremental builds when building the bindings
[--docs]: Generates HTML-based documentation, also used for TypeScript type annotations

Building:

You can build the generated bindings with:

npm run build --vkversion=1.1.114

The compiled bindings can then be found in generated/{vkversion}/build

Flags:
[--vkversion]: The Vulkan version to build bindings for
[--msvsversion]: The Visual Studio version to build the bindings with

TODOs:

  • Function generation (~95%)
  • Documentation generator (95%)

nvk's People

Contributors

maierfelix avatar zeeshan595 avatar grille avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.