diff --git a/graphics/vulkan/build.gradle b/graphics/vulkan/build.gradle
new file mode 100644
index 0000000..399589e
--- /dev/null
+++ b/graphics/vulkan/build.gradle
@@ -0,0 +1,93 @@
+import org.gradle.internal.os.OperatingSystem
+
+plugins {
+ id 'java'
+ id 'io.freefair.lombok' version "${pluginLombok}"
+}
+
+// Determine LWJGL native stuff
+switch (OperatingSystem.current()) {
+ case OperatingSystem.LINUX:
+ project.dependencyLwjglNatives = "natives-linux"
+ def osArch = System.getProperty("os.arch")
+ if (osArch.startsWith("arm") || osArch.startsWith("aarch64")) {
+ project.dependencyLwjglNatives += osArch.contains("64") || osArch.startsWith("armv8") ? "-arm64" : "-arm32"
+ } else if (osArch.startsWith("ppc")) {
+ project.dependencyLwjglNatives += "-ppc64le"
+ } else if (osArch.startsWith("riscv")) {
+ project.dependencyLwjglNatives += "-riscv64"
+ }
+ break
+ case OperatingSystem.MAC_OS:
+ project.dependencyLwjglNatives = System.getProperty("os.arch").startsWith("aarch64") ? "natives-macos-arm64" : "natives-macos"
+ break
+ case OperatingSystem.WINDOWS:
+ def osArch = System.getProperty("os.arch")
+ project.dependencyLwjglNatives = osArch.contains("64")
+ ? "natives-windows${osArch.startsWith("aarch64") ? "-arm64" : ""}"
+ : "natives-windows-x86"
+ break
+}
+
+dependencies {
+ // -> Runtime <-
+ // Lombok
+ compileOnly 'org.projectlombok:lombok:' + project.dependencyLombok
+ annotationProcessor 'org.projectlombok:lombok:' + project.dependencyLombok
+
+ // JetBrains Annotations
+ compileOnly 'org.jetbrains:annotations:' + project.dependencyJetbrainsAnnotations
+
+ // LWJGL
+ implementation platform("org.lwjgl:lwjgl-bom:${dependencyLwjgl}")
+ implementation "org.lwjgl:lwjgl"
+ implementation "org.lwjgl:lwjgl-bgfx"
+ implementation "org.lwjgl:lwjgl-egl"
+ implementation "org.lwjgl:lwjgl-glfw"
+ implementation "org.lwjgl:lwjgl-ktx"
+ implementation "org.lwjgl:lwjgl-shaderc"
+ implementation "org.lwjgl:lwjgl-sse"
+ implementation "org.lwjgl:lwjgl-vma"
+ implementation "org.lwjgl:lwjgl-vulkan"
+ runtimeOnly "org.lwjgl:lwjgl::${dependencyLwjglNatives}"
+ runtimeOnly "org.lwjgl:lwjgl-bgfx::${dependencyLwjglNatives}"
+ runtimeOnly "org.lwjgl:lwjgl-glfw::${dependencyLwjglNatives}"
+ runtimeOnly "org.lwjgl:lwjgl-ktx::${dependencyLwjglNatives}"
+ runtimeOnly "org.lwjgl:lwjgl-shaderc::${dependencyLwjglNatives}"
+ runtimeOnly "org.lwjgl:lwjgl-sse::${dependencyLwjglNatives}"
+ runtimeOnly "org.lwjgl:lwjgl-vma::${dependencyLwjglNatives}"
+ if (project.dependencyLwjglNatives == "natives-macos" || project.dependencyLwjglNatives == "natives-macos-arm64") runtimeOnly "org.lwjgl:lwjgl-vulkan::${dependencyLwjglNatives}"
+
+ // -> Testing <-
+ // Jetbrains Annotations
+ testCompileOnly 'org.jetbrains:annotations:' + project.dependencyJetbrainsAnnotations
+
+ // JUnit
+ testImplementation platform('org.junit:junit-bom:5.' + project.dependencyJunit)
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+ testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
+
+ // jOOR
+ testImplementation 'org.jooq:joor:' + project.dependencyJoor
+
+ // -> Project <-
+ implementation project(":base")
+ implementation project(":graphics")
+}
+
+javadoc.options {
+ setMemberLevel(JavadocMemberLevel.PUBLIC)
+ setOverview("src/main/javadoc/overview.html")
+ setLocale("en_US")
+ setJFlags([
+ // Force Javadoc to use English translations
+ "-Duser.language=en_US"
+ ])
+}
+
+test {
+ useJUnitPlatform()
+ testLogging {
+ events "passed", "skipped", "failed"
+ }
+}
diff --git a/graphics/vulkan/gradle b/graphics/vulkan/gradle
new file mode 120000
index 0000000..1ce6c4c
--- /dev/null
+++ b/graphics/vulkan/gradle
@@ -0,0 +1 @@
+../../gradle
\ No newline at end of file
diff --git a/graphics/vulkan/gradlew b/graphics/vulkan/gradlew
new file mode 120000
index 0000000..343e0d2
--- /dev/null
+++ b/graphics/vulkan/gradlew
@@ -0,0 +1 @@
+../../gradlew
\ No newline at end of file
diff --git a/graphics/vulkan/gradlew.bat b/graphics/vulkan/gradlew.bat
new file mode 120000
index 0000000..cb5a946
--- /dev/null
+++ b/graphics/vulkan/gradlew.bat
@@ -0,0 +1 @@
+../../gradlew.bat
\ No newline at end of file
diff --git a/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/VulkanManagement.java b/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/VulkanManagement.java
new file mode 100644
index 0000000..ddd4241
--- /dev/null
+++ b/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/VulkanManagement.java
@@ -0,0 +1,34 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Contributors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.sosengine.graphics.vulkan;
+
+import de.staropensource.sosengine.base.classes.Vec2i;
+import de.staropensource.sosengine.graphics.classes.ApiManagementClass;
+import de.staropensource.sosengine.graphics.classes.Window;
+import org.jetbrains.annotations.NotNull;
+
+public class VulkanManagement implements ApiManagementClass {
+ /** {@inheritDoc} */
+ @NotNull
+ @Override
+ public Window createWindow(String title, Vec2i size) {
+ return null;
+ }
+}
diff --git a/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/VulkanSubsystem.java b/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/VulkanSubsystem.java
new file mode 100644
index 0000000..5e74be5
--- /dev/null
+++ b/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/VulkanSubsystem.java
@@ -0,0 +1,162 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Contributors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.sosengine.graphics.vulkan;
+
+import de.staropensource.sosengine.base.annotations.EventListener;
+import de.staropensource.sosengine.base.classes.EventPriority;
+import de.staropensource.sosengine.base.logging.LoggerInstance;
+import de.staropensource.sosengine.base.types.LogIssuer;
+import de.staropensource.sosengine.base.utility.Miscellaneous;
+import de.staropensource.sosengine.graphics.GraphicsSubsystem;
+import de.staropensource.sosengine.graphics.classes.ApiMainClass;
+import de.staropensource.sosengine.graphics.classes.ApiManagementClass;
+import de.staropensource.sosengine.graphics.vulkan.events.GraphicsErrorEvent;
+import lombok.Getter;
+import org.lwjgl.glfw.GLFWErrorCallback;
+
+import static org.lwjgl.glfw.GLFW.*;
+
+/**
+ * The main object for the Vulkan Graphics API.
+ *
+ * @since 1-alpha0
+ */
+@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" })
+public final class VulkanSubsystem implements ApiMainClass {
+ /**
+ * Instance.
+ *
+ * @since 1-alpha0
+ *
+ * -- GETTER --
+ * Returns the {@link VulkanSubsystem} instance.
+ *
+ * @return {@link VulkanSubsystem} instance unless uninitialized
+ * @since 1-alpha0
+ */
+ @Getter
+ private static VulkanSubsystem instance = null;
+
+ /**
+ * Logger instance.
+ *
+ * @see LoggerInstance
+ * @since 1-alpha0
+ */
+ private final LoggerInstance logger = new LoggerInstance(new LogIssuer(getClass()));
+
+ /**
+ * The Graphics API management class.
+ *
+ * @see ApiManagementClass
+ * @since 1-alpha0
+ *
+ * -- GETTER --
+ * {@inheritDoc}
+ */
+ @Getter
+ private ApiManagementClass management;
+
+ /**
+ * Constructor.
+ *
+ * @since 1-alpha0
+ */
+ public VulkanSubsystem() {
+ // Check if subsystem has already initialized
+ if (instance == null)
+ instance = this;
+ else {
+ instance.logger.crash("The subsystem tried to initialize twice");
+ return;
+ }
+
+ // Warn about instability
+ logger.warn("The Vulkan Graphics API is unfinished. Trying to initialize it will lead to an engine crash.");
+
+ // Register Graphics API
+ GraphicsSubsystem.getInstance().registerGraphicsApi(this);
+
+ logger.info("Initialized subsystem");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void initializeApi() {
+ logger.verb("Initializing Graphics API");
+
+ long initTime = Miscellaneous.measureExecutionTime(() -> {
+ logger.crash("The Vulkan Graphics API subsystem is unfinished.");
+
+ // Set error callback
+ try (GLFWErrorCallback errorCallback = GLFWErrorCallback.create(new GraphicsErrorEvent())) {
+ errorCallback.set();
+ }
+
+ // Initialize GLFW
+ if (!glfwInit())
+ logger.crash("Unable to initialize GLFW");
+ });
+
+ logger.info("Initialized Graphics API in " + initTime + "ms");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getApiName() {
+ return "Vulkan";
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isCompatible() {
+ return false;
+ }
+
+ /**
+ * Called when a graphics error occurs. This method just logs the error and returns.
+ *
+ * @param error graphics error
+ * @since 1-alpha0
+ */
+ @EventListener(event = GraphicsErrorEvent.class, priority = EventPriority.EXTREMELY_IMPORTANT)
+ public static void onGraphicsError(String error) {
+ instance.logger.error("An error occurred: " + error);
+ }
+
+ /**
+ * Shuts the graphics subsystem down.
+ *
+ * @since 1-alpha0
+ */
+ public static void shutdownApi() {
+ LoggerInstance logger = instance.logger;
+ logger.verb("Shutting down");
+
+ @SuppressWarnings("resource")
+ long shutdownTime = Miscellaneous.measureExecutionTime(() -> {
+ glfwTerminate();
+ //noinspection DataFlowIssue
+ glfwSetErrorCallback(null).free();
+ });
+
+ logger.info("Shut down in " + shutdownTime + "ms");
+ }
+}
diff --git a/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/events/GraphicsErrorEvent.java b/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/events/GraphicsErrorEvent.java
new file mode 100644
index 0000000..dd0fef0
--- /dev/null
+++ b/graphics/vulkan/src/main/java/de/staropensource/sosengine/graphics/vulkan/events/GraphicsErrorEvent.java
@@ -0,0 +1,42 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Contributors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.sosengine.graphics.vulkan.events;
+
+import org.lwjgl.glfw.GLFWErrorCallbackI;
+
+/**
+ * Called when a graphics error occurs.
+ *
+ * @since 1-alpha0
+ */
+@SuppressWarnings({ "unused" })
+public class GraphicsErrorEvent extends de.staropensource.sosengine.graphics.events.GraphicsErrorEvent implements GLFWErrorCallbackI {
+ /**
+ * Constructor.
+ */
+ public GraphicsErrorEvent() {}
+
+
+ /** {@inheritDoc} */
+ @Override
+ public void invoke(int error, long description) {
+ callEvent(description + " (" + error + ")");
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index a43ff67..fe8f07b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -3,4 +3,5 @@ rootProject.name = 'sosengine'
include 'base'
include 'slf4j-compat'
include 'graphics'
+include 'graphics:vulkan'
include 'testapp'
diff --git a/testapp/build.gradle b/testapp/build.gradle
index 16ae7c3..685f99e 100644
--- a/testapp/build.gradle
+++ b/testapp/build.gradle
@@ -18,6 +18,7 @@ dependencies {
implementation project(":base")
implementation project(":slf4j-compat")
implementation project(":graphics")
+ implementation project(":graphics:vulkan")
}
javadoc.options {
diff --git a/testapp/src/main/java/de/staropensource/sosengine/testapp/Main.java b/testapp/src/main/java/de/staropensource/sosengine/testapp/Main.java
index 43e51d0..3476c5a 100644
--- a/testapp/src/main/java/de/staropensource/sosengine/testapp/Main.java
+++ b/testapp/src/main/java/de/staropensource/sosengine/testapp/Main.java
@@ -26,6 +26,7 @@ import de.staropensource.sosengine.base.types.LogIssuer;
import de.staropensource.sosengine.graphics.GraphicsSubsystem;
import de.staropensource.sosengine.graphics.classes.ApiMainClass;
import de.staropensource.sosengine.graphics.classes.ApiManagementClass;
+import de.staropensource.sosengine.graphics.vulkan.VulkanSubsystem;
import de.staropensource.sosengine.slf4j_compat.Slf4jCompatibilitySubsystem;
import lombok.Getter;
import lombok.SneakyThrows;
@@ -101,6 +102,7 @@ public class Main {
// Initialize subsystems
new Slf4jCompatibilitySubsystem();
new GraphicsSubsystem();
+ new VulkanSubsystem();
// Choose Graphics API to use
if (!GraphicsSubsystem.getInstance().setGraphicsApi()) {