diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/Device.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/Device.java index 0c57951..3e3fc2c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/Device.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/Device.java @@ -1,25 +1,33 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkDevice; import org.lwjgl.vulkan.VkDeviceCreateInfo; import org.lwjgl.vulkan.VkDeviceQueueCreateInfo; +import org.lwjgl.vulkan.VkExtensionProperties; import org.tinylog.Logger; +import java.awt.*; +import java.nio.ByteBuffer; import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; -import static org.lwjgl.vulkan.VK10.vkCreateDevice; +import static org.lwjgl.vulkan.KHRPortabilitySubset.VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME; +import static org.lwjgl.vulkan.VK10.*; public class Device { - VkDevice VulkanDevice; + private final VkDevice VulkanDevice; public Device(PhysicalDevice PhysDevice){ - PointerBuffer RequiredExtensions = null; // to be finished later - Logger.debug("Creating Device Interface Layer"); try (var MemStack = MemoryStack.stackPush()) { + PointerBuffer RequiredExtensions = CreateRequiredExtensions(PhysDevice, MemStack); var QueuePropertyBuffer = PhysDevice.GetQueueFamilyProperties(); int QueueFamilyCount = QueuePropertyBuffer.capacity(); var QueueCreationInfoBuffer = VkDeviceQueueCreateInfo.calloc(QueueFamilyCount, MemStack); @@ -39,6 +47,62 @@ public class Device { VulkanDevice = new VkDevice(pp.get(0), PhysDevice.GetPhysicalDevice(), DeviceCreateInfo); } } + + private static PointerBuffer CreateRequiredExtensions(PhysicalDevice PhysDevice, MemoryStack MemStack){ + Set DeviceExtensions = GetDeviceExtensions(PhysDevice); + //cross platform support for that fuckass Metal API mac uses + boolean UsePortability = DeviceExtensions.contains(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) && VulkanUtils.getOS() == VulkanUtils.OSType.MACOS; + + var ExtentionList = new ArrayList(); + for(String Extension : PhysicalDevice.REQUIRED_EXTENSIONS){ + ExtentionList.add(MemStack.ASCII(Extension)); + } + if (UsePortability){ + ExtentionList.add(MemStack.ASCII(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)); + } + + PointerBuffer RequiredExtensions = MemStack.mallocPointer(ExtentionList.size()); + ExtentionList.forEach(RequiredExtensions::put); + RequiredExtensions.flip(); + + return RequiredExtensions; + } + + private static Set GetDeviceExtensions(PhysicalDevice PhysDevice){ + Set DeviceExtensions = new HashSet<>(); + try(var MemStack = MemoryStack.stackPush()){ + IntBuffer ExtensionsBufferCount = MemStack.callocInt(1); + vkEnumerateDeviceExtensionProperties(PhysDevice.GetPhysicalDevice(),(String) null, ExtensionsBufferCount, null); + int ExtensionCount = ExtensionsBufferCount.get(0); + Logger.trace("Device supports [{}] number of extensions", ExtensionCount); + + try(var PropertiesBuffer = VkExtensionProperties.calloc(ExtensionCount)){ + vkEnumerateDeviceExtensionProperties(PhysDevice.GetPhysicalDevice(), (String) null, ExtensionsBufferCount,PropertiesBuffer); + for(int i = 0; i < ExtensionCount; i++){ + VkExtensionProperties Properties = PropertiesBuffer.get(i); + String ExtensionName = Properties.extensionNameString(); + DeviceExtensions.add(ExtensionName); + Logger.trace("[{}] is a supported extension", ExtensionCount); + } + } + } + return DeviceExtensions; + } + + public void cleanup(){ + Logger.debug("Removing Vulkan Device"); + vkDestroyDevice(VulkanDevice,null); + } + + public VkDevice FetchVulkanDevice() + { + return VulkanDevice; + } + + public void waitIdle(){ + vkDeviceWaitIdle(VulkanDevice); + } + } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Surface.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Surface.java index 7a806a8..5db4379 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Surface.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Surface.java @@ -1,4 +1,85 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure; +import net.halbear.Terrain4J.EngineCore.Display.Window; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice; +import org.lwjgl.glfw.GLFWVulkan; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.KHRSurface; +import org.lwjgl.vulkan.VkSurfaceCapabilitiesKHR; +import org.lwjgl.vulkan.VkSurfaceFormatKHR; +import org.tinylog.Logger; + +import java.awt.*; +import java.nio.IntBuffer; +import java.nio.LongBuffer; + +import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; +import static org.lwjgl.vulkan.VK10.VK_FORMAT_B8G8R8A8_SRGB; + public class Surface { + private final VkSurfaceCapabilitiesKHR SurfaceCapabilities; + private final SurfaceFormat SurfaceFormatVar; + private final long VulkanSurface; + + public record SurfaceFormat(int ImageFormat, int ColourSpace){ + + } + + public Surface(VulkanInstance VkInstance, PhysicalDevice PhysDevice, Window window){ + Logger.debug("Creating Vulkan Surface"); + try(var MemStack = MemoryStack.stackPush()){ + LongBuffer SurfacePtr = MemStack.mallocLong(1); + GLFWVulkan.glfwCreateWindowSurface(VkInstance.getVkInstance(), window.getHandle(), null, SurfacePtr); + VulkanSurface = SurfacePtr.get(0); + + SurfaceCapabilities = VkSurfaceCapabilitiesKHR.calloc(); + vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PhysDevice.GetPhysicalDevice(), VulkanSurface,SurfaceCapabilities),"Failed to get surface capabilities"); + + SurfaceFormatVar = CalculateSurfaceFormat(PhysDevice, VulkanSurface); + } + } + + public static SurfaceFormat CalculateSurfaceFormat(PhysicalDevice PhysDevice, long VulkanSurface){ + int ImageFormat; + int ColourSpace ; + try(var MemStack = MemoryStack.stackPush()){ + IntBuffer IntPointer = MemStack.mallocInt(1); + vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDevice.GetPhysicalDevice(), VulkanSurface, IntPointer, null),"Failed to get number of surface formats"); + int SurfaceFormatCount = IntPointer.get(0); + if (SurfaceFormatCount <= 0){ + throw new RuntimeException("Vulkan Error: Unable to locate and surface formats"); + } + + var SurfaceFormats = VkSurfaceFormatKHR.calloc(SurfaceFormatCount, MemStack); + vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDevice.GetPhysicalDevice(),VulkanSurface, IntPointer, SurfaceFormats), "Failed to get surface formats"); + + ImageFormat = VK_FORMAT_B8G8R8A8_SRGB; + ColourSpace = SurfaceFormats.get(0).colorSpace(); + for(int i = 0; i < SurfaceFormatCount; i++){ + VkSurfaceFormatKHR SurfaceFormatKHR = SurfaceFormats.get(i); + if (SurfaceFormatKHR.format() == VK_FORMAT_B8G8R8A8_SRGB && SurfaceFormatKHR.colorSpace() == KHRSurface.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ + ImageFormat = SurfaceFormatKHR.format(); + ColourSpace = SurfaceFormatKHR.colorSpace(); + break; + } + } + } + return new SurfaceFormat(ImageFormat, ColourSpace); + } + public void cleanup(VulkanInstance instance){ + Logger.debug("Cleaning Up Surfaces"); + SurfaceCapabilities.free(); + KHRSurface.vkDestroySurfaceKHR(instance.getVkInstance(), VulkanSurface, null); + } + + public VkSurfaceCapabilitiesKHR GetSurfaceCapabilities(){ + return SurfaceCapabilities; + } + public SurfaceFormat GetSurfaceFormat(){ + return SurfaceFormatVar; + } + public long GetVkSurface(){ + return VulkanSurface; + } + }