Skip to content

Vulkan backend bindings #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
79eeaf2
Initial Implementation of unsafe native bindings for dear imgui vulka…
tlf30 Mar 6, 2022
01274c9
Added LWJGL (safe) wrapper for vulkan impl. Got native builds to work…
tlf30 Mar 6, 2022
e7e06ec
Code cleanup
tlf30 Mar 7, 2022
4b4cc8b
Fix javadoc errors
tlf30 Mar 7, 2022
3cb3756
Java 8 javadocs are annoying. Long live jdk 17.
tlf30 Mar 7, 2022
98096e0
Still fighting javadocs
tlf30 Mar 7, 2022
760a4f4
Expand linker search path for vulkan for ci
tlf30 Mar 7, 2022
0bdb556
Debugging vulkan linking
tlf30 Mar 7, 2022
6b784c3
Testing loading vulkan in linker
tlf30 Mar 7, 2022
235ab05
Trying again to link vk
tlf30 Mar 7, 2022
8d17c3c
Fix finding vulkan lib for macos ci
tlf30 Mar 7, 2022
259c249
Working on win vulkan ci
tlf30 Mar 7, 2022
b1bd050
Debugging windows ci
tlf30 Mar 7, 2022
03bda19
Debugging windows ci
tlf30 Mar 7, 2022
c28fa43
Debugging windows ci
tlf30 Mar 7, 2022
0b6735e
Debugging windows ci
tlf30 Mar 7, 2022
7ee1875
Debugging windows ci
tlf30 Mar 7, 2022
27d5a12
Debugging windows ci
tlf30 Mar 7, 2022
423babe
Remove some debugging
tlf30 Mar 7, 2022
4592193
Initial implementation of opengl/vulkan abstraction for app
tlf30 Mar 7, 2022
b3d2fee
Simplify ci, test #1
tlf30 Mar 7, 2022
2805b75
Test implementation for custom backend for imgui-app
tlf30 Mar 7, 2022
b1759f2
Fix vulkan app backend integration for glfw. Add vulkan support to re…
tlf30 Mar 7, 2022
823ab7f
Initial vulkan rendering framework.
tlf30 Mar 25, 2022
f2f3e9c
Calling it a night. ImGui Vulkan backend added to vk renderer. Access…
tlf30 Mar 25, 2022
0b32822
Added VkResult callback. Large code cleanup
tlf30 Mar 25, 2022
ef79492
Fixing linux compilation error for vulkan natives.
tlf30 Mar 25, 2022
50c3414
Syncing up for the night.
tlf30 Mar 26, 2022
7d680f3
Syncing up to change workstations
tlf30 Mar 29, 2022
14df2c1
Dynamic linker error on run... Calling it a night.
tlf30 Mar 30, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ jobs:

- if: matrix.os == 'ubuntu-latest'
name: Install MinGW-w64/GCC/G++
run: sudo apt install mingw-w64
run: |
sudo apt install mingw-w64

- if: matrix.os == 'ubuntu-latest' && matrix.type == 'linux' && matrix.freetype == true
name: FreeType - Install
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@
[submodule "include/imgui_club"]
path = include/imgui_club
url = https://github.com/ocornut/imgui_club
[submodule "include/Vulkan-Headers"]
path = include/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers
[submodule "include/glfw"]
path = include/glfw
url = https://github.com/glfw/glfw
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ JNI based binding for [Dear ImGui](https://github.com/ocornut/imgui) with no dep
Read official [documentation](https://github.com/ocornut/imgui#usage) and [wiki](https://github.com/ocornut/imgui/wiki) to see how to work with Dear ImGui.
Almost everything from C++ could be done in Java in the same way.

Binding has an OpenGL renderer and a GLFW backend implementation, using a [LWJGL3](https://www.lwjgl.org/) library. Could be found in [imgui-lwjgl3](https://github.com/SpaiR/imgui-java/blob/v1.86.3/imgui-lwjgl3) module.<br>
Binding has an OpenGL/Vulkan renderer and a GLFW backendType implementation, using a [LWJGL3](https://www.lwjgl.org/) library. Could be found in [imgui-lwjgl3](https://github.com/SpaiR/imgui-java/blob/v1.86.3/imgui-lwjgl3) module.<br>
They are recommended, yet optional to use. The advantage of Dear ImGui is a portability, so feel free to copy-paste classes or write your own implementations.<br>

Additionally, there is an [imgui-app](https://github.com/SpaiR/imgui-java/blob/v1.86.3/imgui-app) module, which provides **a high abstraction layer**.<br>
Expand Down Expand Up @@ -53,9 +53,10 @@ You can use this video as a basic step-by-step tutorial. It shows how to integra
Take a note, that integration itself is a very flexible process. It could be done in one way or another. If you just need a framework for your GUI - use **Application** module. Otherwise, if you need more control, the best way is not just to repeat steps, but to understand what each step does.

## Application
If you don't care about OpenGL or other low-level stuff, then you can use application layer from [imgui-app](https://github.com/SpaiR/imgui-java/blob/v1.86.3/imgui-app) module.
It is a **one jar solution** which includes: GLFW, OpenGL and Dear ImGui itself. So you only need **one dependency** line or **one jar in classpath** to make everything to work. <ins>You don't need to add separate dependencies to LWJGL or native libraries, since they are already included.</ins><br>
Application module is the best choice if everything you care is the GUI for your app.
If you don't care about OpenGL, Vulkan or other low-level stuff, then you can use application layer from [imgui-app](https://github.com/SpaiR/imgui-java/blob/v1.86.3/imgui-app) module.
It is a **one jar solution** which includes: GLFW, OpenGL, Vulkan and Dear ImGui itself. So you only need **one dependency** line or **one jar in classpath** to make everything to work. <ins>You don't need to add separate dependencies to LWJGL or native libraries, since they are already included.</ins><br>
Application module is the best choice if everything you care is the GUI for your app.
Note on Vulkan: No vulkan natives are provided since these are provided by your GPU driver.

At the same time, Application gives an option to override any life-cycle method it has. That means that if you're seeking for a bit more low-level control - you can gain it too.

Expand All @@ -69,6 +70,9 @@ public class Main extends Application {
@Override
protected void configure(Configuration config) {
config.setTitle("Dear ImGui is Awesome!");

//Optional, by default it will use opengl
config.setBackendType(Backend.OPENGL); //Set to Backend.VULKAN for vulkan
}

@Override
Expand Down Expand Up @@ -355,20 +359,28 @@ Ensure you've downloaded git submodules. That could be achieved:
* Mingw-w64 (recommended way: use [MSYS2](https://www.msys2.org/) and install [mingw-w64-x86_64-toolchain](https://packages.msys2.org/group/mingw-w64-x86_64-toolchain) group)
- Build with: `./gradlew :imgui-binding:generateLibs -Denvs=win -Dlocal`
- Run with: `./gradlew :example:run -PlibPath="../imgui-binding/build/libsNative/windows64"`
- Or run with Vulkan: `./gradlew :example:run -PlibPath="../imgui-binding/build/libsNative/windows64" -PuseVulkan=true`

### Linux
- Install dependencies: `openjdk8`, `mingw-w64-gcc`, `ant`. (Package names could vary from system to system.)
- Build with: `./gradlew :imgui-binding:generateLibs -Denvs=linux -Dlocal`
- Run with: `./gradlew :example:run -PlibPath=../imgui-binding/build/libsNative/linux64`
- Or run with Vulkan: `./gradlew :example:run -PlibPath="../imgui-binding/build/libsNative/linux64" -PuseVulkan=true`

### MacOS
- Check dependencies from "Linux" section and make sure you have them installed.
- Build with: `./gradlew :imgui-binding:generateLibs -Denvs=mac -Dlocal`
- Run with: `./gradlew :example:run -PlibPath=../imgui-binding/build/libsNative/macosx64`
- Or run with Vulkan: `./gradlew :example:run -PlibPath="../imgui-binding/build/libsNative/macosx64" -PuseVulkan=true`

In `envs` parameter next values could be used `win`, `linux` or `mac`.<br>
`-Dlocal` is optional and means that natives will be built under the `./imgui-binding/build/` folder. Otherwise `/tmp/imgui` folder will be used.
On Windows always use local build.

### Vulkan bindings
Vulkan Loader binaries are stored in `/bin/vulkan/...` for each platform. These binaries are used to link against during
the build process when building the native libraries. To link against a different version of the vulkan loader, simply
replace the binary for your platform in `/bin/vulkan`. These binaries are not included in the distibution.

# License
See the LICENSE file for license rights and limitations (Apache-2.0).
Binary file added bin/glfw/LINUX/libglfw.so
Binary file not shown.
Binary file added bin/glfw/MACOS/libglfw.dylib
Binary file not shown.
Binary file added bin/glfw/MACOS/libglfw_async.dylib
Binary file not shown.
Binary file added bin/glfw/WINDOWS/glfw.dll
Binary file not shown.
Binary file added bin/vulkan/LINUX/libvulkan.so.1
Binary file not shown.
Binary file added bin/vulkan/MACOS/libvulkan.1.3.204.dylib
Binary file not shown.
Binary file added bin/vulkan/MACOS/libvulkan.1.dylib
Binary file not shown.
Binary file added bin/vulkan/MACOS/libvulkan.dylib
Binary file not shown.
Binary file added bin/vulkan/WINDOWS/vulkan-1.dll
Binary file not shown.
2 changes: 1 addition & 1 deletion buildSrc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ repositories {
}

ext {
jnigenVersion = '2.0.1'
jnigenVersion = '2.3.1'
}

dependencies {
Expand Down
70 changes: 69 additions & 1 deletion buildSrc/src/main/groovy/tool/generator/GenerateLibs.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import org.gradle.api.file.CopySpec
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import org.gradle.internal.os.OperatingSystem
import org.gradle.process.ExecSpec

@CompileStatic
class GenerateLibs extends DefaultTask {
Expand All @@ -27,6 +29,8 @@ class GenerateLibs extends DefaultTask {
private final String classpath = project.file('build/classes/java/main')
private final String jniDir = (isLocal ? project.buildDir.path : '/tmp/imgui') + '/jni'
private final String tmpFolder = (isLocal ? project.buildDir.path : '/tmp/imgui') + '/tmp'
private final String vulkanDir = project.rootProject.file('bin/vulkan')
private final String glfwDir = project.rootProject.file('bin/glfw')
private final String libsFolder = 'libsNative'

@TaskAction
Expand All @@ -35,15 +39,18 @@ class GenerateLibs extends DefaultTask {
println "Build targets: $buildEnvs"
println "Local: $isLocal"
println "FreeType: $withFreeType"
println "Vulkan Libs: $vulkanDir"
println "GLFW Libs: $glfwDir"
println '====================================='

if (!buildEnvs) {
println 'No build targets. Task is cancelled.'
return
}

println "Generating C/C++ jni bindings"
// Generate h/cpp files for JNI
new NativeCodeGenerator().generate(sourceDir, classpath, jniDir)
new NativeCodeGenerator().generate(sourceDir, classpath, jniDir, null, new String[]{"**/package-info.java"})

// Copy ImGui h/cpp files
project.copy { CopySpec spec ->
Expand Down Expand Up @@ -71,6 +78,34 @@ class GenerateLibs extends DefaultTask {
spec.into(jniDir + '/dirent')
}

//Copy glfw
project.copy { CopySpec spec ->
['include/glfw/include/GLFW'].each {
spec.from(project.rootProject.file(it)) { CopySpec s -> s.include('*.h') }
}
spec.into(jniDir + "/GLFW")
}

//Copy vulkan
project.copy { CopySpec spec ->
['include/Vulkan-Headers/include/vulkan'].each {
spec.from(project.rootProject.file(it)) { CopySpec s -> s.include('*.h', "*.hpp", '*.cpp', '*.inl') }
}
spec.into(jniDir + "/vulkan")
}

//Copy backends
def backendsToCopy = ['imgui_impl_vulkan*', 'imgui_impl_glfw*']
project.copy { CopySpec spec ->
['include/imgui/backends'].each {
spec.from(project.rootProject.file(it)) {
CopySpec s -> s.include(backendsToCopy)
}
}

spec.into(jniDir + "/backends")
}

if (withFreeType) {
project.copy { CopySpec spec ->
spec.from(project.rootProject.file('include/imgui/misc/freetype')) { CopySpec it -> it.include('*.h', '*.cpp') }
Expand All @@ -80,19 +115,42 @@ class GenerateLibs extends DefaultTask {
enableDefine('IMGUI_ENABLE_FREETYPE')
}

println "Building natives"
// Generate platform dependant ant configs and header files
def buildConfig = new BuildConfig('imgui-java', tmpFolder, libsFolder, jniDir)
def buildTargets = [] as BuildTarget[]

if (forWindows) {
def win64 = BuildTarget.newDefaultTarget(BuildTarget.TargetOs.Windows, true)
addFreeTypeIfEnabled(win64)

//Add vulkan for linker
win64.linkerFlags += " -L $vulkanDir/WINDOWS"
win64.libraries += ' -l:vulkan-1.dll'

//Add glfw for linker
win64.linkerFlags += " -L $glfwDir/WINDOWS"
win64.libraries += ' -l:glfw.dll'

//Win Api
win64.libraries += ' -limm32'
win64.libraries += ' -ldwmapi'

buildTargets += win64
}

if (forLinux) {
def linux64 = BuildTarget.newDefaultTarget(BuildTarget.TargetOs.Linux, true)
addFreeTypeIfEnabled(linux64)

//Vulkan
linux64.linkerFlags += " -L $vulkanDir/LINUX"
linux64.libraries += ' -l:libvulkan.so.1'

//Add glfw for linker
linux64.linkerFlags += " -L $glfwDir/LINUX"
linux64.libraries += ' -l:libglfw.so'

buildTargets += linux64
}

Expand All @@ -102,7 +160,17 @@ class GenerateLibs extends DefaultTask {
mac64.cppFlags += ' -std=c++14'
mac64.cppFlags = mac64.cppFlags.replace('10.7', minMacOsVersion)
mac64.linkerFlags = mac64.linkerFlags.replace('10.7', minMacOsVersion)

addFreeTypeIfEnabled(mac64)

//Vulkan
mac64.linkerFlags += " -L $vulkanDir/MACOS"
mac64.libraries += ' -l:vulkan'

//Add glfw for linker
mac64.linkerFlags += " -L $glfwDir/MACOS"
mac64.libraries += ' -l:glfw'

buildTargets += mac64
}

Expand Down
8 changes: 8 additions & 0 deletions example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,12 @@ run {
if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
jvmArgs += ['-XstartOnFirstThread', '-Djava.awt.headless=true']
}
try {
if (useVulkan) {
args += 'vulkan'
}
} catch (ignored) {
// ignore
}

}
2 changes: 1 addition & 1 deletion example/src/main/java/FontAwesomeIcons.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Font Awesome icons codepoints, can be used to render icons with imgui in any place where text can be rendered.
*
* To preview and search for icons use: https://fontawesome.com/icons?d=gallery&p=2&m=free
* To preview and search for icons use: <a href="https://fontawesome.com/icons?d=gallery&p=2&m=free">icons</a>
*/
@SuppressWarnings("unused")
public class FontAwesomeIcons {
Expand Down
18 changes: 17 additions & 1 deletion example/src/main/java/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import imgui.ImGui;
import imgui.ImGuiIO;
import imgui.app.Application;
import imgui.app.BackendType;
import imgui.app.Configuration;
import imgui.flag.ImGuiConfigFlags;
import imgui.flag.ImGuiInputTextFlags;
Expand All @@ -18,9 +19,20 @@ public class Main extends Application {
private final float[] flt = new float[1];
private int count = 0;

private final boolean useVulkan;

public Main() {
useVulkan = false;
}

public Main(boolean useVulkan) {
this.useVulkan = useVulkan;
}

@Override
protected void configure(final Configuration config) {
config.setTitle("Example Application");
config.setBackendType(useVulkan ? BackendType.VULKAN : BackendType.OPENGL);
}

@Override
Expand Down Expand Up @@ -93,7 +105,11 @@ private static byte[] loadFromResources(String name) {
}

public static void main(final String[] args) {
launch(new Main());
if (args.length == 1 && args[0].equals("vulkan")) {
launch(new Main(true));
} else {
launch(new Main());
}
System.exit(0);
}
}
1 change: 1 addition & 0 deletions imgui-app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies {
api 'org.lwjgl:lwjgl'
api 'org.lwjgl:lwjgl-glfw'
api 'org.lwjgl:lwjgl-opengl'
api 'org.lwjgl:lwjgl-vulkan'

['natives-linux', 'natives-windows', 'natives-macos'].each {
api "org.lwjgl:lwjgl::$it"
Expand Down
19 changes: 19 additions & 0 deletions imgui-app/src/main/java/imgui/app/Backend.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package imgui.app;

public interface Backend {
default void preCreateWindow() {
}

default void postCreateWindow(long windowHandle) {
}

void init(Color clearColor);

void begin();

void end();

void destroy();

void resize(long windowHandle, int width, int height);
}
7 changes: 7 additions & 0 deletions imgui-app/src/main/java/imgui/app/BackendType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package imgui.app;

public enum BackendType {
OPENGL,
VULKAN,
CUSTOM
}
12 changes: 12 additions & 0 deletions imgui-app/src/main/java/imgui/app/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public class Configuration {
* When true, application will be maximized by default.
*/
private boolean fullScreen = false;
/**
* Backend rendering API to use for ImGUI
*/
private BackendType backendType = BackendType.OPENGL;

public String getTitle() {
return title;
Expand Down Expand Up @@ -52,4 +56,12 @@ public boolean isFullScreen() {
public void setFullScreen(final boolean fullScreen) {
this.fullScreen = fullScreen;
}

public BackendType getBackendType() {
return backendType;
}

public void setBackendType(final BackendType backendType) {
this.backendType = backendType;
}
}
Loading