diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java index 73a3122..b2afd57 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java @@ -32,6 +32,14 @@ public class EngineConfig { public static boolean VSYNC = false; private boolean vkValidated; private String PhysicalDeviceName; + private int RequestedImages; + + public int GetRequestedImages(){ + return RequestedImages; + } + public boolean GetVSYNC(){ + return VSYNC; + } private EngineConfig() { var EngineConfigVar = new Properties(); @@ -80,8 +88,9 @@ public class EngineConfig { TickRate = Integer.parseInt(EngineConfigVar.getOrDefault("master_tick_rate", DEFAULT_TICKRATE).toString()); Width = Integer.parseInt(EngineConfigVar.getOrDefault("display_width", "1280").toString()); Height = Integer.parseInt(EngineConfigVar.getOrDefault("display_height", "720").toString()); - VSYNC = Boolean.parseBoolean(EngineConfigVar.getOrDefault("vsync", false).toString()); + VSYNC = Boolean.parseBoolean(EngineConfigVar.getOrDefault("vsync", true).toString()); vkValidated = Boolean.parseBoolean(EngineConfigVar.getOrDefault("vkValidated", false).toString()); + RequestedImages = Integer.parseInt(EngineConfigVar.getOrDefault("RequestedImages", 3).toString()); Logger.debug("\n\nsuccessfully loaded configuration: \n{}\n\n",EngineConfigVar.toString()); } else if(!ConfigFile.exists()){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java index 1fc75d5..ce7124f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java @@ -3,14 +3,17 @@ package net.halbear.Terrain4J.EngineCore.Logic; import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice; -import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.Surface; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; public class VulkanContext { + public static int VulkanLayersOpen = 0; private final VulkanInstance Instance; private final Device device; private Surface surface; private final PhysicalDevice PhysDevice; + private SwapChain swapChain; public VulkanContext(Window window){ var EngineGlobals = EngineConfig.getInstance(); @@ -18,9 +21,12 @@ public class VulkanContext { PhysDevice = PhysicalDevice.createPhysicalDevice(Instance,EngineGlobals.GetPhysicalDeviceName()); device = new Device(PhysDevice); surface = new Surface(Instance, PhysDevice, window); + swapChain = new SwapChain(window, device, surface, EngineGlobals.GetRequestedImages(), EngineGlobals.GetVSYNC()); + VulkanLayersOpen+=5; } public void cleanup(){ + swapChain.cleanup(device); surface.cleanup(Instance); device.cleanup(); PhysDevice.cleanup(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java index 5498c9e..6d09ffe 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java @@ -4,6 +4,7 @@ import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.GameLogic; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import net.halbear.Terrain4J.EngineCore.Threads.MainThread; import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; import org.tinylog.Logger; @@ -17,6 +18,7 @@ public class PrimaryRuntime { private static boolean running = true; private static Window window; private static EngineInstance engineInstance; + public static int ThreadsOpen = 0; public PrimaryRuntime(String windowTitle, GameLogic appLogic) { window = new Window(windowTitle); @@ -55,7 +57,7 @@ public class PrimaryRuntime { updateTime = now; TickDiff = 0; } - if (SecondCounter >= 1000000000){ + if (SecondCounter >= 1000000000L){ SecondCounter = 0; EngineConfig.FrameRate_WINDOW = EngineConfig.RENDERFRAMES; EngineConfig.FrameRate_PRIMARYTHREAD = Frames; @@ -72,6 +74,11 @@ public class PrimaryRuntime { PrimaryThread.KillThread(); DrawingThread.KillThread(); cleanup(); + Logger.debug("Waiting to close Primary Thread, making sure vulkan has shut down properly first and Engine Threads are closed"); + while(ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > 0){ + + } + Logger.debug("Closing Primary Thread"); } @@ -84,6 +91,5 @@ public class PrimaryRuntime { private void cleanup() { engineInstance.cleanup(); window.cleanup(); - Logger.debug("Closing Primary Thread"); } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java index f84c525..1c32894 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java @@ -49,6 +49,7 @@ public class MainThread implements Runnable { } @Override public void run() { + PrimaryRuntime.ThreadsOpen++; long InitialTime = System.nanoTime(); long updateTime = InitialTime; double FrameDiff =0; @@ -73,7 +74,7 @@ public class MainThread implements Runnable { updateTime = now; TickDiff = 0; } - if (SecondCounter >= 1000000000){ + if (SecondCounter >= 1000000000L){ SecondCounter = 0; EngineConfig.FrameRate_MAINENGINETHREAD = Frames; Logger.info("Main Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + " TPS: " + TickFrames); @@ -85,5 +86,6 @@ public class MainThread implements Runnable { InitialTime = now; } cleanup(); + PrimaryRuntime.ThreadsOpen--; } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java index b6185b4..0ff7a28 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java @@ -35,6 +35,7 @@ public class RenderThread implements Runnable { } @Override public void run() { + PrimaryRuntime.ThreadsOpen++; long InitialTime = System.nanoTime(); double FrameDiff =0; double SecondCounter =0; @@ -48,7 +49,7 @@ public class RenderThread implements Runnable { SecondCounter += cycleDiff; if (FrameDiff >= FrameAccuracy){ Frames++; - if (SecondCounter >= 1000000000){ + if (SecondCounter >= 1000000000L){ SecondCounter = 0; EngineConfig.FrameRate_RENDERTHREAD = Frames; Logger.info("Render FPS: " + Frames); @@ -61,5 +62,6 @@ public class RenderThread implements Runnable { } //PrimaryRuntime.CloseRuntime(); cleanup(); + PrimaryRuntime.ThreadsOpen--; } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/CommandBuffer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/CommandBuffer.java new file mode 100644 index 0000000..8fb9b1a --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/CommandBuffer.java @@ -0,0 +1,82 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers; + +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; +import org.lwjgl.PointerBuffer; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.*; +import org.tinylog.Logger; + +import java.nio.IntBuffer; + +import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; +import static org.lwjgl.vulkan.VK13.*; +public class CommandBuffer { + private final boolean OneTimeSubmit; + private final boolean Primary; + private final VkCommandBuffer VulkanCommandBuffer; + + public CommandBuffer(VulkanContext vulkanContext, CommandPool commandPool, boolean primary, boolean oneTimeSubmit){ + Logger.debug("Creating Command Buffer"); + OneTimeSubmit = oneTimeSubmit; + Primary = primary; + VkDevice VulkanDevice = vulkanContext.GetDevice().FetchVulkanDevice(); + + try(var MemStack = MemoryStack.stackPush()){ + var CommandBufferAllocateInfo = VkCommandBufferAllocateInfo.calloc(MemStack) + .sType$Default() + .commandPool(commandPool.GetVulkanCommandPool()) + .level(primary ? VK_COMMAND_BUFFER_LEVEL_PRIMARY : VK_COMMAND_BUFFER_LEVEL_SECONDARY) + .commandBufferCount(1); + PointerBuffer pointerBuffer = MemStack.mallocPointer(1); + vkCheck(vkAllocateCommandBuffers(VulkanDevice, CommandBufferAllocateInfo, pointerBuffer),"Failed to allocated Vulkan Renderer Command Buffer"); + VulkanCommandBuffer = new VkCommandBuffer(pointerBuffer.get(0),VulkanDevice); + } + } + + public void BeginRecording(){ + BeginRecording(null); + } + public void BeginRecording(InheritanceInfo inheritanceInfo){ + try(var MemStack = MemoryStack.stackPush()){ + var CommandBufferInfo = VkCommandBufferBeginInfo.calloc(MemStack).sType$Default(); + if (OneTimeSubmit){ + CommandBufferInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + } + if(!Primary){ + if (inheritanceInfo == null){ + throw new RuntimeException("Secondary Command Buffer lacks correct inheritance information"); + } + int ColourFormatCount = inheritanceInfo.ColourFormats.length; + IntBuffer ColourFormatPointer = MemStack.callocInt(inheritanceInfo.ColourFormats.length); + for(int i = 0; i < ColourFormatCount; i++){ + ColourFormatPointer.put(0,inheritanceInfo.ColourFormats[i]); + } + var RenderInfo = VkCommandBufferInheritanceRenderingInfo.calloc(MemStack) + .sType$Default() + .depthAttachmentFormat(inheritanceInfo.DepthFormat) + .pColorAttachmentFormats(ColourFormatPointer) + .rasterizationSamples(inheritanceInfo.RasterizationSamples); + var VulkanInheritanceInfo = VkCommandBufferInheritanceInfo.calloc(MemStack) + .sType$Default() + .pNext(RenderInfo); + CommandBufferInfo.pInheritanceInfo(VulkanInheritanceInfo); + } + vkCheck(vkBeginCommandBuffer(VulkanCommandBuffer, CommandBufferInfo),"Failed to begin Command Buffer"); + } + } + public record InheritanceInfo(int DepthFormat, int[] ColourFormats, int RasterizationSamples){} + + public void cleanup(VulkanContext vulkanContext,CommandPool commandPool){ + Logger.trace("Destroyed Command Buffer"); + vkFreeCommandBuffers(vulkanContext.GetDevice().FetchVulkanDevice(), commandPool.GetVulkanCommandPool(), VulkanCommandBuffer); + } + public void EndRecording(){ + vkCheck(vkEndCommandBuffer(VulkanCommandBuffer), "Failed to end command buffer recording"); + } + public VkCommandBuffer GetVulkanCommandBuffer(){ + return VulkanCommandBuffer; + } + public void ResetCommandBuffer(){ + vkResetCommandBuffer(VulkanCommandBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/CommandPool.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/CommandPool.java new file mode 100644 index 0000000..b4c63d3 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/CommandPool.java @@ -0,0 +1,37 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VkCommandPoolCreateInfo; +import org.tinylog.Logger; + +import java.nio.LongBuffer; + +import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; +import static org.lwjgl.vulkan.VK13.*; +public class CommandPool { + private final long VulkanCommandPool; + public CommandPool(VulkanContext vulkanContext, int QueueFamilyIndex, boolean SupportReset){ + Logger.debug("Creating Vulkan Command Pool"); + try(var MemStack = MemoryStack.stackPush()){ + var CommandPoolInfo = VkCommandPoolCreateInfo.calloc(MemStack) + .sType$Default() + .queueFamilyIndex(QueueFamilyIndex); + if (SupportReset){ + CommandPoolInfo.flags(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); + } + LongBuffer LongPointer = MemStack.mallocLong(1); + vkCheck(vkCreateCommandPool(vulkanContext.GetDevice().FetchVulkanDevice(), CommandPoolInfo, null, LongPointer),"Failed to create Command Pool"); + VulkanCommandPool = LongPointer.get(0); + } + } + public void cleanup(VulkanContext vulkanContext){ + Logger.debug("Destroying Vulkan Command Pool"); + vkDestroyCommandPool(vulkanContext.GetDevice().FetchVulkanDevice(), VulkanCommandPool,null); + } + public long GetVulkanCommandPool(){ + return VulkanCommandPool; + } + public void Reset(VulkanContext vulkanContext){ + vkResetCommandPool(vulkanContext.GetDevice().FetchVulkanDevice(), VulkanCommandPool, 0); + } +} 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 6d3ae8f..95df705 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,5 +1,6 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; @@ -91,7 +92,8 @@ public class Device { public void cleanup(){ Logger.debug("Removing Vulkan Device"); - vkDestroyDevice(VulkanDevice,null); + vkDestroyDevice(VulkanDevice, null); + VulkanContext.VulkanLayersOpen--; } public VkDevice FetchVulkanDevice() diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Fence.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Fence.java new file mode 100644 index 0000000..7a814da --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Fence.java @@ -0,0 +1,5 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation; + +public class Fence { + //To Be Completed Later +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Semaphore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Semaphore.java new file mode 100644 index 0000000..b0f5cd4 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Semaphore.java @@ -0,0 +1,5 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation; + +public class Semaphore { + //To Be Completed Later +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/PhysicalDevice.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/PhysicalDevice.java index 80490e6..5de5c92 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/PhysicalDevice.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/PhysicalDevice.java @@ -1,5 +1,6 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; @@ -144,6 +145,7 @@ public class PhysicalDevice { vkQueueFamilyProperties.free(); vkDeviceExtensions.free(); vkPhysicalDeviceProperties.free(); + VulkanContext.VulkanLayersOpen--; } public String FetchDeviceName(){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Queue.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/Queues/Queue.java similarity index 96% rename from src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Queue.java rename to src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/Queues/Queue.java index 6d843f9..53f4b40 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Queue.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/Queues/Queue.java @@ -1,4 +1,4 @@ -package net.halbear.Terrain4J.EngineCore.Vulkan.Structure; +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues; import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import org.lwjgl.PointerBuffer; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Image.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Image.java new file mode 100644 index 0000000..d3408fa --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Image.java @@ -0,0 +1,4 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; + +public class Image { +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/ImageView.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/ImageView.java new file mode 100644 index 0000000..611d0b9 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/ImageView.java @@ -0,0 +1,94 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; + +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VkImageViewCreateInfo; + +import java.nio.LongBuffer; + +import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; +import static org.lwjgl.vulkan.VK10.*; + +public class ImageView { + + private final int AspectMask; + private final int MipLevels; + private final long VulkanImage; + private final long VulkanImageView; + + public ImageView(Device device, long vulkanImage, ImageViewData imageViewData){ + this.AspectMask = imageViewData.AspectMask; + this.MipLevels = imageViewData.MipLevels; + this.VulkanImage = vulkanImage; + try(var MemStack = MemoryStack.stackPush()){ + LongBuffer LongPointer = MemStack.mallocLong(1); + var ViewCreateInfo = VkImageViewCreateInfo.calloc(MemStack) + .sType$Default() + .image(VulkanImage) + .viewType(imageViewData.ViewType) + .format(imageViewData.Format) + .subresourceRange(it -> it + .aspectMask(AspectMask) + .baseMipLevel(0) + .levelCount(MipLevels) + .baseArrayLayer(imageViewData.BaseArrayLayer) + .layerCount(imageViewData.LayerCount)); + vkCheck(vkCreateImageView(device.FetchVulkanDevice(), ViewCreateInfo, null, LongPointer),"Failed to create ImageView"); + VulkanImageView = LongPointer.get(0); + } + } + + public void cleanup(Device device){ + vkDestroyImageView(device.FetchVulkanDevice(), VulkanImageView, null); + } + + public int GetAspectMask(){ + return AspectMask; + } + public int GetMipLevels(){ + return MipLevels; + } + public long GetVulkanImageView(){ + return VulkanImageView; + } + + public static class ImageViewData{ + private int AspectMask; + private int BaseArrayLayer; + private int Format; + private int LayerCount; + private int MipLevels; + private int ViewType; + + public ImageViewData(){ + this.BaseArrayLayer = 0; + this.LayerCount = 1; + this.MipLevels = 1; + this.ViewType = VK_IMAGE_VIEW_TYPE_2D; + } + public ImageView.ImageViewData AspectMask(int aspectMask){ + this.AspectMask = aspectMask; + return this; + } + public ImageView.ImageViewData BaseArrayLayer(int baseArrayLayer){ + this.BaseArrayLayer = baseArrayLayer; + return this; + } + public ImageView.ImageViewData Format(int format){ + this.Format = format; + return this; + } + public ImageView.ImageViewData LayerCount(int layerCount){ + this.LayerCount = layerCount; + return this; + } + public ImageView.ImageViewData MipLevels(int mipLevels){ + this.MipLevels = mipLevels; + return this; + } + public ImageView.ImageViewData ViewType(int viewType){ + this.ViewType = viewType; + return this; + } + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Surface.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Surface.java similarity index 93% rename from src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Surface.java rename to src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Surface.java index 175f90e..df643fe 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/Surface.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Surface.java @@ -1,7 +1,9 @@ -package net.halbear.Terrain4J.EngineCore.Vulkan.Structure; +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; import net.halbear.Terrain4J.EngineCore.Display.Window; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; import org.lwjgl.glfw.GLFWVulkan; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.KHRSurface; @@ -9,7 +11,6 @@ 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; @@ -68,6 +69,7 @@ public class Surface { Logger.debug("Cleaning Up Surfaces"); SurfaceCapabilities.free(); KHRSurface.vkDestroySurfaceKHR(instance.getVkInstance(), VulkanSurface, null); + VulkanContext.VulkanLayersOpen--; } public VkSurfaceCapabilitiesKHR GetSurfaceCapabilities(){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SwapChain.java similarity index 56% rename from src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain.java rename to src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SwapChain.java index a96fb70..589651b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SwapChain.java @@ -1,14 +1,18 @@ -package net.halbear.Terrain4J.EngineCore.Vulkan.Structure; +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; import net.halbear.Terrain4J.EngineCore.Display.Window; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.*; import org.tinylog.Logger; +import java.nio.IntBuffer; import java.nio.LongBuffer; +import java.util.Arrays; import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; +import static org.lwjgl.vulkan.VK10.VK_IMAGE_ASPECT_COLOR_BIT; import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; public class SwapChain { @@ -55,18 +59,61 @@ public class SwapChain { public static int CalculateImageCount(VkSurfaceCapabilitiesKHR SurfaceCapabilities, int RequestedImages){ int MaxImages = SurfaceCapabilities.maxImageCount(); int MinImages = SurfaceCapabilities.minImageCount(); - int result = MinImages; + int ReturnValue = MinImages; if(MaxImages != 0){ return Math.min(RequestedImages, MaxImages); } - result = Math.max(result, MinImages); - Logger.debug("Requested Image Count: [{}]\nReceived [{}] Images\nSurfaceCapabilities-> MaxImgs:[{}] MinImgs:[{}] ",RequestedImages,result,MaxImages,MinImages); - return result; + ReturnValue = Math.max(ReturnValue, MinImages); + Logger.debug("Requested Image Count: [{}]\nReceived [{}] Images\nSurfaceCapabilities-> MaxImgs:[{}] MinImgs:[{}] ",RequestedImages,ReturnValue,MaxImages,MinImages); + return ReturnValue; } public static VkExtent2D CalculateSwapChainExtent(Window window, VkSurfaceCapabilitiesKHR SurfaceCapabilities){ - return null; //finish later + var ReturnValue = VkExtent2D.calloc(); + if(SurfaceCapabilities.currentExtent().width() == 0xFFFFFFFF){ + int Width = Math.min(window.getWidth(), SurfaceCapabilities.maxImageExtent().width()); + Width= Math.max(Width, SurfaceCapabilities.minImageExtent().width()); + + int Height = Math.min(window.getHeight(), SurfaceCapabilities.maxImageExtent().height()); + Height = Math.max(Height, SurfaceCapabilities.minImageExtent().height()); + + ReturnValue.width(Width); + ReturnValue.height(Height); + } else{ + ReturnValue.set(SurfaceCapabilities.currentExtent()); + } + return ReturnValue; } public static ImageView[] CreateImageViews(MemoryStack MemStack, Device device, long SwapChain, int Format){ - return null; //finish later + IntBuffer IntPointer = MemStack.mallocInt(1); + vkCheck(KHRSwapchain.vkGetSwapchainImagesKHR(device.FetchVulkanDevice(), SwapChain, IntPointer, null),"Failed to get number of surface Images"); + int ImageCount = IntPointer.get(0); + LongBuffer SwapChainImages = MemStack.mallocLong(ImageCount); + vkCheck(KHRSwapchain.vkGetSwapchainImagesKHR(device.FetchVulkanDevice(), SwapChain, IntPointer, SwapChainImages),"Failed to get surface Images"); + + var ReturnResult = new ImageView[ImageCount]; + var ImageViewData = new ImageView.ImageViewData().Format(Format).AspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + for(int i = 0; i < ImageCount; i++){ + ReturnResult[i] = new ImageView(device, SwapChainImages.get(i),ImageViewData); + } + return ReturnResult; + } + + public void cleanup(Device device){ + Logger.debug("Destroying Vulkan Swapchain"); + SwapChainExtent.free(); + Arrays.asList(ImageViewArray).forEach(i->i.cleanup(device)); + KHRSwapchain.vkDestroySwapchainKHR(device.FetchVulkanDevice(), VulkanSwapChain, null); + VulkanContext.VulkanLayersOpen--; + } + + public ImageView GetVulkanImageView(int index){ + return ImageViewArray[index]; + } + + public int GetImageCount(){ + return ImageCount; + } + public VkExtent2D GetSwapChainExtent(){ + return SwapChainExtent; } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/ImageView.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/ImageView.java deleted file mode 100644 index c49b815..0000000 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/ImageView.java +++ /dev/null @@ -1,4 +0,0 @@ -package net.halbear.Terrain4J.EngineCore.Vulkan.Structure; - -public class ImageView { -} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/VulkanInstance.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/VulkanInstance.java index 6e233c7..9506102 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/VulkanInstance.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/VulkanInstance.java @@ -1,5 +1,6 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.lwjgl.PointerBuffer; import org.lwjgl.glfw.GLFWVulkan; @@ -159,6 +160,7 @@ public class VulkanInstance { DebugUtils.pfnUserCallback().free(); DebugUtils.free(); } + VulkanContext.VulkanLayersOpen--; } public VkInstance getVkInstance() { diff --git a/terrain4j.properties b/terrain4j.properties index 2f62165..f95993b 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -7,11 +7,12 @@ frame_accuracy=0 master_tick_rate=120 main_thread_tickrate=120 fast_thread_tickrate=240 -cap_main_to_tickrate=true +cap_main_to_tickrate=false #Vulkan Debugging toggle vkValidated=true vsync=true +RequestedImages=3 #This is the name of the GPU you want the engine to use PhysicalDeviceName= #Title that shows up on app window