Kgpu
A Cross Platform Graphics API For Kotlin JVM/JS
Warning: Because WebGPU is under active development, kgpu is very unstable! Once the specification is more finalized, this will not be an issue.
Requirements:
- JDK 11
Supported Platforms:
- Windows 10
- MacOS (See Issue #1)
- Linux
- Chrome Canary
- Firefox Nightly
Links
Modules
kgpu is split into multiple modules:
- kgpu: The core of this library (Kotlin bindings to WebGPU)
- kcgmath: A cross platform graphics library for Kotlin based on the Rust crate cgmath
- kshader: A library to help compile GLSL to SPIR-V
Images
Examples
To run the examples on Desktop:
gradlew runTriangleExample
gradlew runCubeExample
gradlew runTextureExample
gradlew runEarthExample
To run the examples on the Web:
gradlew buildWeb startWebServer
Then navigate to http://localhost:8080/index.html
How to add to Gradle (Kotlin DSL)
First you need to add the snapshots repository:
repositories {
maven(url = "https://oss.sonatype.org/content/repositories/snapshots/")
}
Then you can add the dependency:
dependencies {
//Add it to a kotlin multiplatform project
implementation("io.github.kgpu:kgpu:0.1.0-SNAPSHOT")
//Or you can add a specific platform
implementation("io.github.kgpu:kgpu-common:0.1.0-SNAPSHOT")
implementation("io.github.kgpu:kgpu-js:0.1.0-SNAPSHOT")
implementation("io.github.kgpu:kgpu-jvm:0.1.0-SNAPSHOT")
}
Introduction
Kgpu is cross platform library that exposes the WebGPU api for Kotlin Javascript, and for Kotlin on the JVM. This allows users to write code that can be run on both web browsers and natively on their computers.
What is WebGPU
According to the W3C website, WebGPU is,
an interface between the Web Platform and modern 3D graphics and computation capabilities present in native system platforms. The goal is to design a new Web API that exposes these modern technologies in a performant, powerful and safe manner. It should work with existing platform APIs such as Direct3D 12 from Microsoft, Metal from Apple, and Vulkan from the Khronos Group. This API will also expose the generic computational facilities available in today's GPUs to the Web, and investigate shader languages to produce a cross-platform solution.
What is Wgpu
Wgpu is Mozilla's Rust implementation of the WebGPU specification. It is similar to Dawn, Google's WebGPU implementation for Chromium
Modules
kgpu
The core of kgpu. It provides the following APIs:
-
WebGPU Bindings
- JVM/Desktop: Native Bindings to wgpu
- JS/Web: Javascript Bindings
-
Window API
- JVM/Desktop: GLFW Bindings via LWJGL
- JS/Web: Canvas API via Web Browser
-
Image Loading API:
- JVM/Desktop: AWT Image Loading
- JS/Web: Off-screen Canvas Image Loading
kcgmath
Kotlin Computer Graphics Math Library
A cross platform graphics library for Kotlin based on the Rust crate cgmath
Note: This library is meant to be used as a basic computer graphics library for WebGPU. If you are using OpenGL or want something more complex, you may want to consider one of the following:
kshader
A library to help compile GLSL to SPIR-V
On the JVM/Desktop it uses Shaderc via LWJGL.
For JS/Web it uses the glslang library.
Getting Started
To start a new project, you can use the kgpu-template repository. It allows you to get a basic project setup by only needing to change a few files.
Cloning the project
Using Github
- Navigate to the kgpu-template repository
- Click the
Use This Template
Button
For more info, see Creating a repository from a template
No Github Account
- Navigate to the kgpu-template repository
- Click the
Clone or Download
(orCode
) dropdown - Select the
Download Zip
option
Editing the project settings
Once you have the project copied, then you can open it in any text editor,
and then open the gradle.properties
file.
You can edit the file to change the name of the project, the project's group, and the version of KGPU to use.
Here is an example properties file:
kotlin.code.style=official
kgpuVersion=0.1.0-SNAPSHOT
projectName=ProjectName
projectGroup=your.group.here
projectVersion=0.1.0
desktopMainClass=DesktopKt
Editing Website
The last part of setup is setting up the index.html page to use.
Open the src/jsMain/resources/index.html
file
Then change the ProjectName in the script source, to the name you set in
the gradle.properties
file.
<script>
if (!navigator.gpu) {
document.body.className = 'error';
document.getElementById('content').hidden = true
document.getElementById('errorMessage').hidden = false
}
</script>
<script src="ProjectName.js"></script> <!-- Change this line! -->
Start Coding
You can now start working on your project! There are three kotlin files in the template: Application
, Desktop
,
and Browser
src/commonMain/kotlin/Application.kt:
This is the code that is shared between all of the platforms.
src/jsMain/kotlin/Browser.kt:
This is the code that will be compiled into javascript for the browser
src/jvmMain/kotlin/Desktop.kt:
This is the code that will be compiled into java classes and executed on the Desktop via the JVM.
Running the application
To run on the desktop:
gradlew runJvm
To build the examples for the Web:
gradlew jsBrowserDistribution
And you can start a static file server for the web:
gradlew startWebServer
And then navigate to http://localhost:8080/index.html
Coordinates
In kgpu, both textures and screen coordinates start in the top left:
Internal Structure
This page documents the non-library projects in the kgpu repo. These libraries should not be used directly and do not have stable APIs. If you want to see info about the different public modules kgpu provides, see this page
examples
This contains the example code for Kgpu. Like the core library, it is split into three parts: common, js, and jvm. The js and jvm modules are responible for setting up the basic application, and selecting which example to run.
The common folder contains all of the core code examples, and the resources used (images, shaders)
wgpuj
This module is written in Java and has the FFI code between the JVM and wgpu. It uses the jnr-ffi library, which creates JNI bindings at runtime. Most of the code in this module is generated by jnr-gen
wgpuj/jnrgen
jnr-gen is a tool that generates jnr enum and struct classes from the wgpu.h header. For more info see this page all about jnr-gen.
JNR Gen
JNR Gen is a program to generate Java enums, structs, and constants from a c header file. To run JNR Gen and update the java files, run the following command:
gradlew wgpuj:updateBindings
Example Enum
package io.github.kgpu.wgpuj.jni;
/** NOTE: THIS FILE WAS PRE-GENERATED BY JNR_GEN! */
public enum WgpuBindingType {
UNIFORM_BUFFER,
STORAGE_BUFFER,
READONLY_STORAGE_BUFFER,
SAMPLER,
COMPARISON_SAMPLER,
SAMPLED_TEXTURE,
READONLY_STORAGE_TEXTURE,
WRITEONLY_STORAGE_TEXTURE,
}
Example Struct
package io.github.kgpu.wgpuj.jni;
import io.github.kgpu.wgpuj.WgpuJava;
import io.github.kgpu.wgpuj.util.WgpuJavaStruct;
import io.github.kgpu.wgpuj.util.CStrPointer;
import io.github.kgpu.wgpuj.util.RustCString;
import jnr.ffi.Runtime;
import jnr.ffi.Struct;
/** NOTE: THIS FILE WAS PRE-GENERATED BY JNR_GEN! */
public class WgpuBindGroupDescriptor extends WgpuJavaStruct {
private final @CStrPointer Struct.Pointer label = new Struct.Pointer();
private final DynamicStructRef<WgpuBindGroupEntry> entries = new DynamicStructRef<>(WgpuBindGroupEntry.class);
protected WgpuBindGroupDescriptor(boolean direct){
if(direct){
useDirectMemory();
}
}
@Deprecated
public WgpuBindGroupDescriptor(Runtime runtime){
super(runtime);
}
public static WgpuBindGroupDescriptor createHeap(){
return new WgpuBindGroupDescriptor(false);
}
public static WgpuBindGroupDescriptor createDirect(){
return new WgpuBindGroupDescriptor(true);
}
public java.lang.String getLabel(){
return RustCString.fromPointer(label.get());
}
public void setLabel(java.lang.String x){
this.label.set(RustCString.toPointer(x));
}
public DynamicStructRef<WgpuBindGroupEntry> getEntries(){
return entries;
}
public void setEntries(WgpuBindGroupEntry... x){
if(x.length == 0 || x[0] == null){
this.entries.set(WgpuJava.createNullPointer());
} else {
this.entries.set(x);
}
}
}
Example Constants
package io.github.kgpu.wgpuj.jni;
/** NOTE: THIS FILE WAS PRE-GENERATED BY JNR_GEN! */
public final class Wgpu{
public static final int BIND_BUFFER_ALIGNMENT = 256;
public static final int COPY_BYTES_PER_ROW_ALIGNMENT = 256;
public static final int DEFAULT_BIND_GROUPS = 4;
public static final int DESIRED_NUM_FRAMES = 3;
public static final int MAX_ANISOTROPY = 16;
public static final int MAX_COLOR_TARGETS = 4;
public static final int MAX_MIP_LEVELS = 16;
public static final int MAX_VERTEX_BUFFERS = 16;
public static final class ShaderStage{
public static final int NONE = 0;
public static final int VERTEX = 1;
public static final int FRAGMENT = 2;
public static final int COMPUTE = 4;
}
}