Add some class from tutorial

This commit is contained in:
Florian RICHER 2024-10-13 20:36:13 +02:00
parent c4bd9d2558
commit a07c55cf0f
11 changed files with 687 additions and 5 deletions

View file

@ -15,7 +15,7 @@
devShells = {
default = pkgs.mkShell {
packages = with pkgs; [
jdk23 # When available
jdk22
maven
];
};

View file

@ -15,6 +15,7 @@
<maven.compiler.release>21</maven.compiler.release>
<lwjgl.version>3.3.4</lwjgl.version>
<joml.version>1.10.8</joml.version>
<tinylog.version>2.7.0</tinylog.version>
</properties>
<dependencies>
@ -38,6 +39,11 @@
<artifactId>joml</artifactId>
<version>${joml.version}</version>
</dependency>
<dependency>
<groupId>org.tinylog</groupId>
<artifactId>tinylog-impl</artifactId>
<version>${tinylog.version}</version>
</dependency>
<!-- Natives -->
<dependency>

View file

@ -1,16 +1,25 @@
package fr.mrdev023.vulkan_java;
import fr.mrdev023.vulkan_java.renderer.Vulkan;
import fr.mrdev023.vulkan_java.window.Display;
import fr.mrdev023.vulkan_java.window.Input;
public class App {
public static void main(String[] args) {
Display.create("My first application", 800, 600);
Display.printMonitorsInfo();
Input.init();
Vulkan.init();
while (!Display.isCloseRequested()) {
Display.updateEvent();
Input.update();
Display.updateFrame();
}
Vulkan.destroy();
Input.destroy();
Display.destroy();
}
}

View file

@ -0,0 +1,101 @@
package fr.mrdev023.vulkan_java.renderer;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.*;
import java.util.*;
import static fr.mrdev023.vulkan_java.renderer.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.KHRPortabilitySubset.VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME;
import static org.lwjgl.vulkan.VK11.*;
public class Device {
private final PhysicalDevice physicalDevice;
private final VkDevice vkDevice;
public Device(PhysicalDevice physicalDevice) {
Logger.debug("Creating device");
this.physicalDevice = physicalDevice;
try (MemoryStack stack = MemoryStack.stackPush()) {
// Define required extensions
Set<String> deviceExtensions = getDeviceExtensions();
boolean usePortability = deviceExtensions.contains(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) && VulkanUtils.getOS() == VulkanUtils.OSType.MACOS;
int numExtensions = usePortability ? 2 : 1;
PointerBuffer requiredExtensions = stack.mallocPointer(numExtensions);
requiredExtensions.put(stack.ASCII(KHRSwapchain.VK_KHR_SWAPCHAIN_EXTENSION_NAME));
if (usePortability) {
requiredExtensions.put(stack.ASCII(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME));
}
requiredExtensions.flip();
// Set up required features
VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.calloc(stack);
// Enable all the queue families
VkQueueFamilyProperties.Buffer queuePropsBuff = physicalDevice.getVkQueueFamilyProps();
int numQueuesFamilies = queuePropsBuff.capacity();
VkDeviceQueueCreateInfo.Buffer queueCreationInfoBuf = VkDeviceQueueCreateInfo.calloc(numQueuesFamilies, stack);
for (int i = 0; i < numQueuesFamilies; i++) {
FloatBuffer priorities = stack.callocFloat(queuePropsBuff.get(i).queueCount());
queueCreationInfoBuf.get(i)
.sType(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO)
.queueFamilyIndex(i)
.pQueuePriorities(priorities);
}
VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.calloc(stack)
.sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
.ppEnabledExtensionNames(requiredExtensions)
.pEnabledFeatures(features)
.pQueueCreateInfos(queueCreationInfoBuf);
PointerBuffer pp = stack.mallocPointer(1);
vkCheck(vkCreateDevice(physicalDevice.getVkPhysicalDevice(), deviceCreateInfo, null, pp),
"Failed to create device");
vkDevice = new VkDevice(pp.get(0), physicalDevice.getVkPhysicalDevice(), deviceCreateInfo);
}
}
public void destroy() {
Logger.debug("Destroying Vulkan device");
vkDestroyDevice(vkDevice, null);
}
private Set<String> getDeviceExtensions() {
Set<String> deviceExtensions = new HashSet<>();
try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer numExtensionsBuf = stack.callocInt(1);
vkEnumerateDeviceExtensionProperties(physicalDevice.getVkPhysicalDevice(), (String) null, numExtensionsBuf, null);
int numExtensions = numExtensionsBuf.get(0);
Logger.debug("Device supports [{}] extensions", numExtensions);
VkExtensionProperties.Buffer propsBuff = VkExtensionProperties.calloc(numExtensions, stack);
vkEnumerateDeviceExtensionProperties(physicalDevice.getVkPhysicalDevice(), (String) null, numExtensionsBuf, propsBuff);
for (int i = 0; i < numExtensions; i++) {
VkExtensionProperties props = propsBuff.get(i);
String extensionName = props.extensionNameString();
deviceExtensions.add(extensionName);
Logger.debug("Supported device extension [{}]", extensionName);
}
}
return deviceExtensions;
}
public PhysicalDevice getPhysicalDevice() {
return physicalDevice;
}
public VkDevice getVkDevice() {
return vkDevice;
}
public void waitIdle() {
vkDeviceWaitIdle(vkDevice);
}
}

View file

@ -0,0 +1,223 @@
package fr.mrdev023.vulkan_java.renderer;
import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFWVulkan;
import org.lwjgl.system.*;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.*;
import java.util.*;
import static fr.mrdev023.vulkan_java.renderer.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.EXTDebugUtils.*;
import static org.lwjgl.vulkan.KHRPortabilityEnumeration.VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
import static org.lwjgl.vulkan.VK11.*;
public class Instance {
public static final int MESSAGE_SEVERITY_BITMASK = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
public static final int MESSAGE_TYPE_BITMASK = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
private static final String PORTABILITY_EXTENSION = "VK_KHR_portability_enumeration";
private final VkInstance vkInstance;
private VkDebugUtilsMessengerCreateInfoEXT debugUtils;
private long vkDebugHandle;
public Instance(boolean validate) {
Logger.debug("Creating Vulkan instance");
try (MemoryStack stack = MemoryStack.stackPush()) {
// Create application information
ByteBuffer appShortName = stack.UTF8("VulkanBook");
VkApplicationInfo appInfo = VkApplicationInfo.calloc(stack)
.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO)
.pApplicationName(appShortName)
.applicationVersion(1)
.pEngineName(appShortName)
.engineVersion(0)
.apiVersion(VK_API_VERSION_1_1);
// Validation layers
List<String> validationLayers = getSupportedValidationLayers();
int numValidationLayers = validationLayers.size();
boolean supportsValidation = validate;
if (validate && numValidationLayers == 0) {
supportsValidation = false;
Logger.warn("Request validation but no supported validation layers found. Falling back to no validation");
}
Logger.debug("Validation: {}", supportsValidation);
// Set required layers
PointerBuffer requiredLayers = null;
if (supportsValidation) {
requiredLayers = stack.mallocPointer(numValidationLayers);
for (int i = 0; i < numValidationLayers; i++) {
Logger.debug("Using validation layer [{}]", validationLayers.get(i));
requiredLayers.put(i, stack.ASCII(validationLayers.get(i)));
}
}
Set<String> instanceExtensions = getInstanceExtensions();
// GLFW Extension
PointerBuffer glfwExtensions = GLFWVulkan.glfwGetRequiredInstanceExtensions();
if (glfwExtensions == null) {
throw new RuntimeException("Failed to find the GLFW platform surface extensions");
}
PointerBuffer requiredExtensions;
boolean usePortability = instanceExtensions.contains(PORTABILITY_EXTENSION) &&
VulkanUtils.getOS() == VulkanUtils.OSType.MACOS;
if (supportsValidation) {
ByteBuffer vkDebugUtilsExtension = stack.UTF8(EXTDebugUtils.VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
int numExtensions = usePortability ? glfwExtensions.remaining() + 2 : glfwExtensions.remaining() + 1;
requiredExtensions = stack.mallocPointer(numExtensions);
requiredExtensions.put(glfwExtensions).put(vkDebugUtilsExtension);
if (usePortability) {
requiredExtensions.put(stack.UTF8(PORTABILITY_EXTENSION));
}
} else {
int numExtensions = usePortability ? glfwExtensions.remaining() + 1 : glfwExtensions.remaining();
requiredExtensions = stack.mallocPointer(numExtensions);
requiredExtensions.put(glfwExtensions);
if (usePortability) {
requiredExtensions.put(stack.UTF8(KHRPortabilitySubset.VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME));
}
}
requiredExtensions.flip();
long extension = MemoryUtil.NULL;
if (supportsValidation) {
debugUtils = createDebugCallBack();
extension = debugUtils.address();
}
// Create instance info
VkInstanceCreateInfo instanceInfo = VkInstanceCreateInfo.calloc(stack)
.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
.pNext(extension)
.pApplicationInfo(appInfo)
.ppEnabledLayerNames(requiredLayers)
.ppEnabledExtensionNames(requiredExtensions);
if (usePortability) {
instanceInfo.flags(VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR);
}
PointerBuffer pInstance = stack.mallocPointer(1);
vkCheck(vkCreateInstance(instanceInfo, null, pInstance), "Error creating instance");
vkInstance = new VkInstance(pInstance.get(0), instanceInfo);
vkDebugHandle = VK_NULL_HANDLE;
if (supportsValidation) {
LongBuffer longBuff = stack.mallocLong(1);
vkCheck(vkCreateDebugUtilsMessengerEXT(vkInstance, debugUtils, null, longBuff), "Error creating debug utils");
vkDebugHandle = longBuff.get(0);
}
}
}
private static VkDebugUtilsMessengerCreateInfoEXT createDebugCallBack() {
return VkDebugUtilsMessengerCreateInfoEXT
.calloc()
.sType(VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT)
.messageSeverity(MESSAGE_SEVERITY_BITMASK)
.messageType(MESSAGE_TYPE_BITMASK)
.pfnUserCallback((messageSeverity, messageTypes, pCallbackData, pUserData) -> {
VkDebugUtilsMessengerCallbackDataEXT callbackData = VkDebugUtilsMessengerCallbackDataEXT.create(pCallbackData);
if ((messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
Logger.info("VkDebugUtilsCallback, {}", callbackData.pMessageString());
} else if ((messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
Logger.warn("VkDebugUtilsCallback, {}", callbackData.pMessageString());
} else if ((messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
Logger.error("VkDebugUtilsCallback, {}", callbackData.pMessageString());
} else {
Logger.debug("VkDebugUtilsCallback, {}", callbackData.pMessageString());
}
return VK_FALSE;
});
}
public void destroy() {
Logger.debug("Destroying Vulkan instance");
if (vkDebugHandle != VK_NULL_HANDLE) {
vkDestroyDebugUtilsMessengerEXT(vkInstance, vkDebugHandle, null);
}
vkDestroyInstance(vkInstance, null);
if (debugUtils != null) {
debugUtils.pfnUserCallback().free();
debugUtils.free();
}
}
private Set<String> getInstanceExtensions() {
Set<String> instanceExtensions = new HashSet<>();
try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer numExtensionsBuf = stack.callocInt(1);
vkEnumerateInstanceExtensionProperties((String) null, numExtensionsBuf, null);
int numExtensions = numExtensionsBuf.get(0);
Logger.debug("Instance supports [{}] extensions", numExtensions);
VkExtensionProperties.Buffer instanceExtensionsProps = VkExtensionProperties.calloc(numExtensions, stack);
vkEnumerateInstanceExtensionProperties((String) null, numExtensionsBuf, instanceExtensionsProps);
for (int i = 0; i < numExtensions; i++) {
VkExtensionProperties props = instanceExtensionsProps.get(i);
String extensionName = props.extensionNameString();
instanceExtensions.add(extensionName);
Logger.debug("Supported instance extension [{}]", extensionName);
}
}
return instanceExtensions;
}
private List<String> getSupportedValidationLayers() {
try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer numLayersArr = stack.callocInt(1);
vkEnumerateInstanceLayerProperties(numLayersArr, null);
int numLayers = numLayersArr.get(0);
Logger.debug("Instance supports [{}] layers", numLayers);
VkLayerProperties.Buffer propsBuf = VkLayerProperties.calloc(numLayers, stack);
vkEnumerateInstanceLayerProperties(numLayersArr, propsBuf);
List<String> supportedLayers = new ArrayList<>();
for (int i = 0; i < numLayers; i++) {
VkLayerProperties props = propsBuf.get(i);
String layerName = props.layerNameString();
supportedLayers.add(layerName);
Logger.debug("Supported layer [{}]", layerName);
}
List<String> layersToUse = new ArrayList<>();
// Main validation layer
if (supportedLayers.contains("VK_LAYER_KHRONOS_validation")) {
layersToUse.add("VK_LAYER_KHRONOS_validation");
return layersToUse;
}
// Fallback 1
if (supportedLayers.contains("VK_LAYER_LUNARG_standard_validation")) {
layersToUse.add("VK_LAYER_LUNARG_standard_validation");
return layersToUse;
}
// Fallback 2 (set)
List<String> requestedLayers = new ArrayList<>();
requestedLayers.add("VK_LAYER_GOOGLE_threading");
requestedLayers.add("VK_LAYER_LUNARG_parameter_validation");
requestedLayers.add("VK_LAYER_LUNARG_object_tracker");
requestedLayers.add("VK_LAYER_LUNARG_core_validation");
requestedLayers.add("VK_LAYER_GOOGLE_unique_objects");
return requestedLayers.stream().filter(supportedLayers::contains).toList();
}
}
public VkInstance getVkInstance() {
return vkInstance;
}
}

View file

@ -0,0 +1,178 @@
package fr.mrdev023.vulkan_java.renderer;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.IntBuffer;
import java.util.*;
import static fr.mrdev023.vulkan_java.renderer.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.VK11.*;
public class PhysicalDevice {
private final VkExtensionProperties.Buffer vkDeviceExtensions;
private final VkPhysicalDeviceMemoryProperties vkMemoryProperties;
private final VkPhysicalDevice vkPhysicalDevice;
private final VkPhysicalDeviceFeatures vkPhysicalDeviceFeatures;
private final VkPhysicalDeviceProperties vkPhysicalDeviceProperties;
private final VkQueueFamilyProperties.Buffer vkQueueFamilyProps;
private PhysicalDevice(VkPhysicalDevice vkPhysicalDevice) {
try (MemoryStack stack = MemoryStack.stackPush()) {
this.vkPhysicalDevice = vkPhysicalDevice;
IntBuffer intBuffer = stack.mallocInt(1);
// Get device properties
vkPhysicalDeviceProperties = VkPhysicalDeviceProperties.calloc();
vkGetPhysicalDeviceProperties(vkPhysicalDevice, vkPhysicalDeviceProperties);
// Get device extensions
vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice, (String) null, intBuffer, null),
"Failed to get number of device extension properties");
vkDeviceExtensions = VkExtensionProperties.calloc(intBuffer.get(0));
vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice, (String) null, intBuffer, vkDeviceExtensions),
"Failed to get extension properties");
// Get Queue family properties
vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, intBuffer, null);
vkQueueFamilyProps = VkQueueFamilyProperties.calloc(intBuffer.get(0));
vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, intBuffer, vkQueueFamilyProps);
vkPhysicalDeviceFeatures = VkPhysicalDeviceFeatures.calloc();
vkGetPhysicalDeviceFeatures(vkPhysicalDevice, vkPhysicalDeviceFeatures);
// Get Memory information and properties
vkMemoryProperties = VkPhysicalDeviceMemoryProperties.calloc();
vkGetPhysicalDeviceMemoryProperties(vkPhysicalDevice, vkMemoryProperties);
}
}
public static PhysicalDevice createPhysicalDevice(Instance instance, Optional<String> preferredDeviceName) {
Logger.debug("Selecting physical devices");
PhysicalDevice selectedPhysicalDevice = null;
try (MemoryStack stack = MemoryStack.stackPush()) {
// Get available devices
PointerBuffer pPhysicalDevices = getPhysicalDevices(instance, stack);
int numDevices = pPhysicalDevices.capacity();
if (numDevices <= 0) {
throw new RuntimeException("No physical devices found");
}
// Populate available devices
List<PhysicalDevice> devices = new ArrayList<>();
for (int i = 0; i < numDevices; i++) {
VkPhysicalDevice vkPhysicalDevice = new VkPhysicalDevice(pPhysicalDevices.get(i), instance.getVkInstance());
PhysicalDevice physicalDevice = new PhysicalDevice(vkPhysicalDevice);
String deviceName = physicalDevice.getDeviceName();
if (physicalDevice.hasGraphicsQueueFamily() && physicalDevice.hasKHRSwapChainExtension()) {
Logger.debug("Device [{}] supports required extensions", deviceName);
if (preferredDeviceName.isPresent() && preferredDeviceName.get().equals(deviceName)) {
selectedPhysicalDevice = physicalDevice;
break;
}
devices.add(physicalDevice);
} else {
Logger.debug("Device [{}] does not support required extensions", deviceName);
physicalDevice.destroy();
}
}
// No preferred device or it does not meet requirements, just pick the first one
selectedPhysicalDevice = selectedPhysicalDevice == null && !devices.isEmpty() ? devices.remove(0) : selectedPhysicalDevice;
// Clean up non-selected devices
for (PhysicalDevice physicalDevice : devices) {
physicalDevice.destroy();
}
if (selectedPhysicalDevice == null) {
throw new RuntimeException("No suitable physical devices found");
}
Logger.debug("Selected device: [{}]", selectedPhysicalDevice.getDeviceName());
}
return selectedPhysicalDevice;
}
protected static PointerBuffer getPhysicalDevices(Instance instance, MemoryStack stack) {
PointerBuffer pPhysicalDevices;
// Get number of physical devices
IntBuffer intBuffer = stack.mallocInt(1);
vkCheck(vkEnumeratePhysicalDevices(instance.getVkInstance(), intBuffer, null),
"Failed to get number of physical devices");
int numDevices = intBuffer.get(0);
Logger.debug("Detected {} physical device(s)", numDevices);
// Populate physical devices list pointer
pPhysicalDevices = stack.mallocPointer(numDevices);
vkCheck(vkEnumeratePhysicalDevices(instance.getVkInstance(), intBuffer, pPhysicalDevices),
"Failed to get physical devices");
return pPhysicalDevices;
}
public void destroy() {
if (Logger.isDebugEnabled()) {
Logger.debug("Destroying physical device [{}]", vkPhysicalDeviceProperties.deviceNameString());
}
vkMemoryProperties.free();
vkPhysicalDeviceFeatures.free();
vkQueueFamilyProps.free();
vkDeviceExtensions.free();
vkPhysicalDeviceProperties.free();
}
public String getDeviceName() {
return vkPhysicalDeviceProperties.deviceNameString();
}
public VkPhysicalDeviceMemoryProperties getVkMemoryProperties() {
return vkMemoryProperties;
}
public VkPhysicalDevice getVkPhysicalDevice() {
return vkPhysicalDevice;
}
public VkPhysicalDeviceFeatures getVkPhysicalDeviceFeatures() {
return vkPhysicalDeviceFeatures;
}
public VkPhysicalDeviceProperties getVkPhysicalDeviceProperties() {
return vkPhysicalDeviceProperties;
}
public VkQueueFamilyProperties.Buffer getVkQueueFamilyProps() {
return vkQueueFamilyProps;
}
private boolean hasGraphicsQueueFamily() {
boolean result = false;
int numQueueFamilies = vkQueueFamilyProps != null ? vkQueueFamilyProps.capacity() : 0;
for (int i = 0; i < numQueueFamilies; i++) {
VkQueueFamilyProperties familyProps = vkQueueFamilyProps.get(i);
if ((familyProps.queueFlags() & VK_QUEUE_GRAPHICS_BIT) != 0) {
result = true;
break;
}
}
return result;
}
private boolean hasKHRSwapChainExtension() {
boolean result = false;
int numExtensions = vkDeviceExtensions != null ? vkDeviceExtensions.capacity() : 0;
for (int i = 0; i < numExtensions; i++) {
String extensionName = vkDeviceExtensions.get(i).extensionNameString();
if (KHRSwapchain.VK_KHR_SWAPCHAIN_EXTENSION_NAME.equals(extensionName)) {
result = true;
break;
}
}
return result;
}
}

View file

@ -0,0 +1,59 @@
package fr.mrdev023.vulkan_java.renderer;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import static org.lwjgl.vulkan.VK11.*;
public class Queue {
private final VkQueue vkQueue;
public Queue(Device device, int queueFamilyIndex, int queueIndex) {
Logger.debug("Creating queue");
try (MemoryStack stack = MemoryStack.stackPush()) {
PointerBuffer pQueue = stack.mallocPointer(1);
vkGetDeviceQueue(device.getVkDevice(), queueFamilyIndex, queueIndex, pQueue);
long queue = pQueue.get(0);
vkQueue = new VkQueue(queue, device.getVkDevice());
}
}
public VkQueue getVkQueue() {
return vkQueue;
}
public void waitIdle() {
vkQueueWaitIdle(vkQueue);
}
public static class GraphicsQueue extends Queue {
public GraphicsQueue(Device device, int queueIndex) {
super(device, getGraphicsQueueFamilyIndex(device), queueIndex);
}
private static int getGraphicsQueueFamilyIndex(Device device) {
int index = -1;
PhysicalDevice physicalDevice = device.getPhysicalDevice();
VkQueueFamilyProperties.Buffer queuePropsBuff = physicalDevice.getVkQueueFamilyProps();
int numQueuesFamilies = queuePropsBuff.capacity();
for (int i = 0; i < numQueuesFamilies; i++) {
VkQueueFamilyProperties props = queuePropsBuff.get(i);
boolean graphicsQueue = (props.queueFlags() & VK_QUEUE_GRAPHICS_BIT) != 0;
if (graphicsQueue) {
index = i;
break;
}
}
if (index < 0) {
throw new RuntimeException("Failed to get graphics Queue family index");
}
return index;
}
}
}

View file

@ -0,0 +1,34 @@
package fr.mrdev023.vulkan_java.renderer;
import org.lwjgl.glfw.GLFWVulkan;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.KHRSurface;
import org.tinylog.Logger;
import java.nio.LongBuffer;
public class Surface {
private final PhysicalDevice physicalDevice;
private final long vkSurface;
public Surface(PhysicalDevice physicalDevice, long windowHandle) {
Logger.debug("Creating Vulkan surface");
this.physicalDevice = physicalDevice;
try (MemoryStack stack = MemoryStack.stackPush()) {
LongBuffer pSurface = stack.mallocLong(1);
GLFWVulkan.glfwCreateWindowSurface(this.physicalDevice.getVkPhysicalDevice().getInstance(), windowHandle,
null, pSurface);
vkSurface = pSurface.get(0);
}
}
public void destroy() {
Logger.debug("Destroying Vulkan surface");
KHRSurface.vkDestroySurfaceKHR(physicalDevice.getVkPhysicalDevice().getInstance(), vkSurface, null);
}
public long getVkSurface() {
return vkSurface;
}
}

View file

@ -0,0 +1,36 @@
package fr.mrdev023.vulkan_java.renderer;
import fr.mrdev023.vulkan_java.window.Display;
import java.util.Optional;
import static org.lwjgl.glfw.GLFWVulkan.glfwVulkanSupported;
public class Vulkan {
private static Instance instance;
private static PhysicalDevice physicalDevice;
private static Device device;
private static Surface surface;
private static Queue.GraphicsQueue graphicsQueue;
public static void init() {
if (!glfwVulkanSupported()) {
throw new IllegalStateException("Cannot find a compatible Vulkan installable client driver (ICD)");
}
instance = new Instance(true);
physicalDevice = PhysicalDevice.createPhysicalDevice(instance, Optional.empty());
device = new Device(physicalDevice);
surface = new Surface(physicalDevice, Display.getWindow());
graphicsQueue = new Queue.GraphicsQueue(device, 0);
}
public static void destroy() {
surface.destroy();
device.destroy();
physicalDevice.destroy();
instance.destroy();
}
}

View file

@ -0,0 +1,36 @@
package fr.mrdev023.vulkan_java.renderer;
import java.util.Locale;
import static org.lwjgl.vulkan.VK11.VK_SUCCESS;
public class VulkanUtils {
private VulkanUtils() {
// Utility class
}
public static OSType getOS() {
OSType result;
String os = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
if (os.contains("mac") || os.contains("darwin")) {
result = OSType.MACOS;
} else if (os.contains("win")) {
result = OSType.WINDOWS;
} else if (os.contains("nux")) {
result = OSType.LINUX;
} else {
result = OSType.OTHER;
}
return result;
}
public static void vkCheck(int err, String errMsg) {
if (err != VK_SUCCESS) {
throw new RuntimeException(errMsg + ": " + err);
}
}
public enum OSType {WINDOWS, MACOS, LINUX, OTHER}
}

View file

@ -1,5 +1,6 @@
package fr.mrdev023.vulkan_java.window;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.*;
@ -22,6 +23,7 @@ public class Display {
TITLE = title;
displayMode = new DisplayMode(width, height);
window = glfwCreateWindow(displayMode.getWidth(), displayMode.getHeight(), TITLE, NULL, NULL);
glfwMakeContextCurrent(window);
}
public static void setMouseGrabbed(boolean a) {
@ -80,6 +82,8 @@ public class Display {
}
for (int i = 0; i < monitors.capacity(); i++) {
m = glfwGetVideoMode(monitors.get(i));
if (m == null) continue;
System.out.println(glfwGetMonitorName(monitors.get(i)) + "(" + i + ") : " + m.width() + "x" + m.height() + ":" + m.refreshRate() + "Hz");
}
@ -89,10 +93,6 @@ public class Display {
return glfwWindowShouldClose(window);
}
public static void createContext() {
glfwMakeContextCurrent(window);
}
public static void updateEvent() {
glfwPollEvents();
}