SwapChain Completed, command pool/buffer almost completed, working on semaphores and fences

This commit is contained in:
Harrison Corlett 2026-01-22 14:56:39 +00:00
parent d15d1a75af
commit edf13611b5
19 changed files with 326 additions and 22 deletions

View file

@ -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()){

View file

@ -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();

View file

@ -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");
}
}

View file

@ -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--;
}
}

View file

@ -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--;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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()

View file

@ -0,0 +1,5 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation;
public class Fence {
//To Be Completed Later
}

View file

@ -0,0 +1,5 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation;
public class Semaphore {
//To Be Completed Later
}

View file

@ -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(){

View file

@ -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;

View file

@ -0,0 +1,4 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen;
public class Image {
}

View file

@ -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;
}
}
}

View file

@ -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(){

View file

@ -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;
}
}

View file

@ -1,4 +0,0 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure;
public class ImageView {
}

View file

@ -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() {

View file

@ -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