diff --git a/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl b/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl index 03d4636..0dd511b 100644 --- a/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl +++ b/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl @@ -20,14 +20,12 @@ vec4 gamma(vec4 color){ return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a); } - vec4 msaa(int sampleCount, sampler2DMS textureIn,vec2 TextCoord){ ivec2 pixelCoords = ivec2(TextCoord * textureSize(textureIn)); vec4 colorSum = vec4(0.0); for(int i = 0; i < sampleCount; ++i) { vec4 sampleColor = texelFetch(textureIn, pixelCoords, i); - sampleColor.rgb = sampleColor.rgb / (sampleColor.rgb + vec3(1.0)); colorSum += sampleColor; } return colorSum / float(sampleCount); diff --git a/resources/EngineResources/shaders/post_process_frag.glsl b/resources/EngineResources/shaders/post_process_frag.glsl index df90574..e4c4353 100644 --- a/resources/EngineResources/shaders/post_process_frag.glsl +++ b/resources/EngineResources/shaders/post_process_frag.glsl @@ -21,7 +21,6 @@ vec4 gamma(vec4 color){ } // Sourced from: https://mini.gmshaders.com/p/gm-shaders-mini-fxaa - vec4 fxaa(sampler2D tex, vec2 uv) { vec2 u_texel = 1.0 / screenSize.size; diff --git a/resources/models/Sponza/Sponza.idx b/resources/models/Sponza/Sponza.idx new file mode 100644 index 0000000..0c21746 Binary files /dev/null and b/resources/models/Sponza/Sponza.idx differ diff --git a/resources/models/Sponza/Sponza.json b/resources/models/Sponza/Sponza.json new file mode 100644 index 0000000..b8ece7f --- /dev/null +++ b/resources/models/Sponza/Sponza.json @@ -0,0 +1,207 @@ +{ + "ID": "Sponza", + "Meshes": [ + { + "ID": "meshes[0]-53_0", + "MaterialID": "Sponza-mat-0", + "OffsetVertex": 0, + "VertexSize": 482200, + "OffsetIndex": 0, + "IndexSize": 377232 + }, + { + "ID": "meshes[0]-93_1", + "MaterialID": "Sponza-mat-1", + "OffsetVertex": 482200, + "VertexSize": 78640, + "OffsetIndex": 377232, + "IndexSize": 41664 + }, + { + "ID": "meshes[0]-94_2", + "MaterialID": "Sponza-mat-2", + "OffsetVertex": 560840, + "VertexSize": 196800, + "OffsetIndex": 418896, + "IndexSize": 212256 + }, + { + "ID": "meshes[0]-99_3", + "MaterialID": "Sponza-mat-3", + "OffsetVertex": 757640, + "VertexSize": 44820, + "OffsetIndex": 631152, + "IndexSize": 49032 + }, + { + "ID": "meshes[0]-102_4", + "MaterialID": "Sponza-mat-4", + "OffsetVertex": 802460, + "VertexSize": 21060, + "OffsetIndex": 680184, + "IndexSize": 9552 + }, + { + "ID": "meshes[0]-48_5", + "MaterialID": "Sponza-mat-5", + "OffsetVertex": 823520, + "VertexSize": 193580, + "OffsetIndex": 689736, + "IndexSize": 122016 + }, + { + "ID": "meshes[0]-33_6", + "MaterialID": "Sponza-mat-6", + "OffsetVertex": 1017100, + "VertexSize": 99960, + "OffsetIndex": 811752, + "IndexSize": 70512 + }, + { + "ID": "meshes[0]-47_7", + "MaterialID": "Sponza-mat-7", + "OffsetVertex": 1117060, + "VertexSize": 62480, + "OffsetIndex": 882264, + "IndexSize": 33792 + }, + { + "ID": "meshes[0]-46_8", + "MaterialID": "Sponza-mat-8", + "OffsetVertex": 1179540, + "VertexSize": 460, + "OffsetIndex": 916056, + "IndexSize": 252 + }, + { + "ID": "meshes[0]-44_9", + "MaterialID": "Sponza-mat-9", + "OffsetVertex": 1180000, + "VertexSize": 236400, + "OffsetIndex": 916308, + "IndexSize": 85056 + }, + { + "ID": "meshes[0]-42_10", + "MaterialID": "Sponza-mat-10", + "OffsetVertex": 1416400, + "VertexSize": 21960, + "OffsetIndex": 1001364, + "IndexSize": 10560 + }, + { + "ID": "meshes[0]-49_11", + "MaterialID": "Sponza-mat-11", + "OffsetVertex": 1438360, + "VertexSize": 456400, + "OffsetIndex": 1011924, + "IndexSize": 278496 + }, + { + "ID": "meshes[0]-50_12", + "MaterialID": "Sponza-mat-12", + "OffsetVertex": 1894760, + "VertexSize": 720, + "OffsetIndex": 1290420, + "IndexSize": 216 + }, + { + "ID": "meshes[0]-62_13", + "MaterialID": "Sponza-mat-13", + "OffsetVertex": 1895480, + "VertexSize": 243240, + "OffsetIndex": 1290636, + "IndexSize": 197952 + }, + { + "ID": "meshes[0]-59_14", + "MaterialID": "Sponza-mat-14", + "OffsetVertex": 2138720, + "VertexSize": 182520, + "OffsetIndex": 1488588, + "IndexSize": 198144 + }, + { + "ID": "meshes[0]-61_15", + "MaterialID": "Sponza-mat-15", + "OffsetVertex": 2321240, + "VertexSize": 182520, + "OffsetIndex": 1686732, + "IndexSize": 198144 + }, + { + "ID": "meshes[0]-60_16", + "MaterialID": "Sponza-mat-16", + "OffsetVertex": 2503760, + "VertexSize": 121680, + "OffsetIndex": 1884876, + "IndexSize": 132096 + }, + { + "ID": "meshes[0]-72_17", + "MaterialID": "Sponza-mat-17", + "OffsetVertex": 2625440, + "VertexSize": 147960, + "OffsetIndex": 2016972, + "IndexSize": 172032 + }, + { + "ID": "meshes[0]-71_18", + "MaterialID": "Sponza-mat-18", + "OffsetVertex": 2773400, + "VertexSize": 198080, + "OffsetIndex": 2189004, + "IndexSize": 227328 + }, + { + "ID": "meshes[0]-70_19", + "MaterialID": "Sponza-mat-19", + "OffsetVertex": 2971480, + "VertexSize": 147960, + "OffsetIndex": 2416332, + "IndexSize": 172032 + }, + { + "ID": "meshes[0]-79_20", + "MaterialID": "Sponza-mat-20", + "OffsetVertex": 3119440, + "VertexSize": 1280, + "OffsetIndex": 2588364, + "IndexSize": 384 + }, + { + "ID": "meshes[0]-80_21", + "MaterialID": "Sponza-mat-21", + "OffsetVertex": 3120720, + "VertexSize": 208240, + "OffsetIndex": 2588748, + "IndexSize": 237936 + }, + { + "ID": "meshes[0]-95_22", + "MaterialID": "Sponza-mat-22", + "OffsetVertex": 3328960, + "VertexSize": 106160, + "OffsetIndex": 2826684, + "IndexSize": 110208 + }, + { + "ID": "meshes[0]-98_23", + "MaterialID": "Sponza-mat-23", + "OffsetVertex": 3435120, + "VertexSize": 34560, + "OffsetIndex": 2936892, + "IndexSize": 36504 + }, + { + "ID": "meshes[0]-101_24", + "MaterialID": "Sponza-mat-24", + "OffsetVertex": 3469680, + "VertexSize": 218360, + "OffsetIndex": 2973396, + "IndexSize": 173808 + } + ], + "VertexPath": "resources/models/Sponza/Sponza.vtx", + "IndexPath": "resources/models/Sponza/Sponza.idx" +} \ No newline at end of file diff --git a/resources/models/Sponza/Sponza.vtx b/resources/models/Sponza/Sponza.vtx new file mode 100644 index 0000000..f58ad49 Binary files /dev/null and b/resources/models/Sponza/Sponza.vtx differ diff --git a/resources/models/Sponza/Sponza_mat.json b/resources/models/Sponza/Sponza_mat.json new file mode 100644 index 0000000..66c1448 --- /dev/null +++ b/resources/models/Sponza/Sponza_mat.json @@ -0,0 +1,262 @@ +[ + { + "ID": "Sponza-mat-0", + "TexturePath": "resources\\models\\Sponza\\5061699253647017043.png", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-1", + "TexturePath": "resources\\models\\Sponza\\8006627369776289000.png", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-2", + "TexturePath": "resources\\models\\Sponza\\7268504077753552595.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-3", + "TexturePath": "resources\\models\\Sponza\\8750083169368950601.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-4", + "TexturePath": "resources\\models\\Sponza\\5792855332885324923.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-5", + "TexturePath": "resources\\models\\Sponza\\14650633544276105767.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-6", + "TexturePath": "resources\\models\\Sponza\\15295713303328085182.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-7", + "TexturePath": "resources\\models\\Sponza\\6047387724914829168.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-8", + "TexturePath": "resources\\models\\Sponza\\5823059166183034438.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-9", + "TexturePath": "resources\\models\\Sponza\\7441062115984513793.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-10", + "TexturePath": "resources\\models\\Sponza\\11490520546946913238.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-11", + "TexturePath": "resources\\models\\Sponza\\6151467286084645207.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-12", + "TexturePath": "resources\\models\\Sponza\\white.png", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-13", + "TexturePath": "resources\\models\\Sponza\\4975155472559461469.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-14", + "TexturePath": "resources\\models\\Sponza\\4675343432951571524.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-15", + "TexturePath": "resources\\models\\Sponza\\2775690330959970771.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-16", + "TexturePath": "resources\\models\\Sponza\\2185409758123873465.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-17", + "TexturePath": "resources\\models\\Sponza\\17876391417123941155.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-18", + "TexturePath": "resources\\models\\Sponza\\11474523244911310074.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-19", + "TexturePath": "resources\\models\\Sponza\\9288698199695299068.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-20", + "TexturePath": "resources\\models\\Sponza\\16275776544635328252.png", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-21", + "TexturePath": "resources\\models\\Sponza\\755318871556304029.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-22", + "TexturePath": "resources\\models\\Sponza\\8481240838833932244.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-23", + "TexturePath": "resources\\models\\Sponza\\6772804448157695701.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-24", + "TexturePath": "resources\\models\\Sponza\\2969916736137545357.jpg", + "DiffuseColour": { + "X": 0.588, + "Y": 0.588, + "Z": 0.588, + "W": 1.0 + } + }, + { + "ID": "Sponza-mat-25", + "TexturePath": "", + "DiffuseColour": { + "X": 1.0, + "Y": 1.0, + "Z": 1.0, + "W": 1.0 + } + } +] \ No newline at end of file diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java index bae024f..bd86643 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java @@ -55,6 +55,7 @@ public class Render { public TextureCache GetTextureCache(){return textureCache;} public MaterialsCache GetMaterialsCache(){return materialsCache;} + public VulkanContext GetVulkanContext(){return RendererContext;} public Render(EngineInstance engineInstance) { RendererContext = new VulkanContext(engineInstance.window()); 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 e0c1103..84db53f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java @@ -6,6 +6,8 @@ import org.tinylog.Logger; import java.io.*; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import static org.lwjgl.vulkan.VK10.*; @@ -30,10 +32,15 @@ public class EngineConfig { private int Width; private int Height; public static int FrameRate_PRIMARYTHREAD =0; + public static int TPS_PRIMARYTHREAD =0; public static int TPS =0; + public static long LAST_AVERAGE_GPU_TIME = 0; public static int FrameRate_MAINENGINETHREAD =0; + public static int TPS_MAINENGINETHREAD =0; public static int FrameRate_FASTENGINETHREAD =0; + public static int TPS_FASTENGINETHREAD =0; public static int FrameRate_RENDERTHREAD =0; + public static int TPS_RENDERTHREAD =0; public static int FrameRate_WINDOW =0; public static int RENDERFRAMES =0; public static boolean VSYNC = false; @@ -55,7 +62,23 @@ public class EngineConfig { private int MaxDescriptors = 1000; private int AAValue = 1; private AntiAliasType AAMode = AntiAliasType.FXAA; + private List MemoryProfiling = new ArrayList<>(); + private List SystemProfiling = new ArrayList<>(); + public String GPU_NAME = "Vulkan compatible device"; + public String CPU_NAME = "Vulkan compatible device"; + public int CPU_CORE_COUNT = 0; + public String CPU_DETAILS = ""; + public String GetGPU(){return GPU_NAME;} + public void SetGPU(String Gpu){GPU_NAME = Gpu;} + public void SetCPU(String Name, int CoreCount){ + CPU_NAME = Name; + CPU_CORE_COUNT = CoreCount; + CPU_DETAILS = CPU_NAME + " with " + CPU_CORE_COUNT + " Threads"; + } + public int GetCoreCount(){return CPU_CORE_COUNT;} + public String GetCPUName(){return CPU_NAME;} + public String GetCPUDetails(){return CPU_DETAILS;} public void GPU_Does_Not_Support_Logging(){ GPU_SUPPORTS_LOGGING = false; } @@ -63,6 +86,11 @@ public class EngineConfig { public String GetDefaultTexturePath(){return DefaultTexturePath;} public int GetMaxDescriptors(){return MaxDescriptors;} public int RenderAA(){return AAValue;} + public AntiAliasType RenderAAType(){return AAMode;} + public List GetMemoryProfiling(){return MemoryProfiling;} + public List GetSystemProfiling(){return SystemProfiling;} + public void SetMemoryProfiling(List memory){MemoryProfiling = memory;} + public void SetSystemProfiling(List Profiling){SystemProfiling = Profiling;} public enum AntiAliasType{ NONE, diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/GameLogic.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/GameLogic.java index 8a96ab3..616b733 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/GameLogic.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/GameLogic.java @@ -10,4 +10,5 @@ public interface GameLogic { void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds); void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds); void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds); + void SecondUpdate(EngineInstance engineInstance); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java index fcb5deb..6dd1599 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -4,6 +4,7 @@ import imgui.ImGui; import imgui.ImGuiIO; import imgui.ImVec2; import imgui.flag.ImGuiCond; +import imgui.flag.ImGuiWindowFlags; import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput; import net.halbear.Terrain4J.EngineCore.Input.MouseListener; @@ -12,6 +13,8 @@ import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor; import net.halbear.Terrain4J.EngineCore.Main.Scene.Camera; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; +import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor; +import net.halbear.Terrain4J.EngineCore.Profiling.GPUProfiler; import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiTexture; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; @@ -20,13 +23,14 @@ import org.joml.Vector3f; import java.util.ArrayList; import java.util.List; +import java.util.function.UnaryOperator; import static org.lwjgl.glfw.GLFW.*; public class GameCore implements GameLogic { private static final float MOUSE_SENSITIVITY = 0.1f; - private static final float MOVEMENT_SPEED = 0.01f; + private static final float MOVEMENT_SPEED = 1f; private final Vector3f rotatingAngle = new Vector3f(0, 1, 0); private float angle = 180; private List angles = new ArrayList<>(); @@ -38,6 +42,9 @@ public class GameCore implements GameLogic { private int Ticks = 0; private int GUI_MODE = 0; private GuiTexture guiTexture; + private List PerformanceMetrics = new ArrayList<>(); + private List SettingPerformanceMetrics = new ArrayList<>(); + private boolean FetchingMetrics = false; @Override public void cleanup() { @@ -49,38 +56,38 @@ public class GameCore implements GameLogic { Scene scene = engineInstance.scene(); List models = new ArrayList<>(); - //ModelData SponzaData = ModelLoader.LoadModel("resources/models/Unit02/evangelion_unit-02.json"); - //List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Unit02/evangelion_unit-02_mat.json"); - //ModelData SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json"); - //List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json"); - // ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json"); - // List SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json"); - //scene.AddActor(new Actor("Sponza1", SponzaData.ID(), new Vector3f(0,0,-5f))); - //scene.AddActor(new Actor("Sponza2", SponzaData1.ID(), new Vector3f(0,0,-5f))); + //ModelData SponzaData = ModelLoader.LoadModel("resources/models/Sponza/Sponza.json"); + //List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Sponza/Sponza_mat.json"); + ModelData SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json"); + List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json"); + ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json"); + List SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json"); + scene.AddActor(new Actor("Sponza1", SponzaData.ID(), new Vector3f(0,0,-5f))); + scene.AddActor(new Actor("Sponza2", SponzaData1.ID(), new Vector3f(0,0,-5f))); - models.add(ModelLoader.LoadModel("resources/models/Metro/OBJ/MetroLeadCar.json")); - models.add(ModelLoader.LoadModel("resources/models/melona/melona.json")); - models.add(ModelLoader.LoadModel("resources/models/Alice/Welsh040Alice.json")); - models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json")); - models.add(ModelLoader.LoadModel("resources/models/Corvette/corvetteclass.json")); - for(int i = 0; i < 5000; i++) { - CubeActors.add(new Actor("AdvancedModel" + i, models.get((int)Math.round(Math.min(Math.max(Math.random() *(Math.random() * models.size() - 1),0),models.size() - 1))).ID(), new Vector3f((float)(-200 + Math.random() * 400), (float)(-50 + Math.random() * 100), (float)(250 + Math.random() * -500)))); - angles.add((float)(Math.random() * 360)); - rotatingAngles.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2))); - Velocities.add(new Vector3f((float)(-2 + Math.random()*4), -2 + (float)(Math.random()*4), -2 + (float)(Math.random()*4))); - } + //models.add(ModelLoader.LoadModel("resources/models/Metro/OBJ/MetroLeadCar.json")); + //models.add(ModelLoader.LoadModel("resources/models/melona/melona.json")); + //models.add(ModelLoader.LoadModel("resources/models/Alice/Welsh040Alice.json")); + //models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json")); + //models.add(ModelLoader.LoadModel("resources/models/Corvette/corvetteclass.json")); + //for(int i = 0; i < 0; i++) { + // CubeActors.add(new Actor("AdvancedModel" + i, models.get((int)Math.round(Math.min(Math.max(Math.random() *(Math.random() * models.size() - 1),0),models.size() - 1))).ID(), new Vector3f((float)(-200 + Math.random() * 400), (float)(-50 + Math.random() * 100), (float)(250 + Math.random() * -500)))); + // angles.add((float)(Math.random() * 360)); + // rotatingAngles.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2))); + // Velocities.add(new Vector3f((float)(-2 + Math.random()*4), -2 + (float)(Math.random()*4), -2 + (float)(Math.random()*4))); + // } CubeActors.forEach(scene::AddActor); List materials = new ArrayList<>(); - materials.addAll(ModelLoader.LoadMaterials("resources/models/Metro/OBJ/MetroLeadCar_mat.json")); - materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/corvetteclass_mat.json")); - materials.addAll(ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json")); - materials.addAll(ModelLoader.LoadMaterials("resources/models/Alice/Welsh040Alice_mat.json")); - materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json")); - // materials.addAll(SponzaMaterial); - //materials.addAll(SponzaMaterial1); - //models.add(SponzaData); - //models.add(SponzaData1); + //materials.addAll(ModelLoader.LoadMaterials("resources/models/Metro/OBJ/MetroLeadCar_mat.json")); + //materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/corvetteclass_mat.json")); + //materials.addAll(ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json")); + //materials.addAll(ModelLoader.LoadMaterials("resources/models/Alice/Welsh040Alice_mat.json")); + //materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json")); + materials.addAll(SponzaMaterial); + materials.addAll(SponzaMaterial1); + models.add(SponzaData); + models.add(SponzaData1); Camera camera = scene.GetCamera(); camera.SetPosition(40.0f, 155.0f, -42.0f); camera.SetPosition(0,0,0); @@ -120,7 +127,7 @@ public class GameCore implements GameLogic { @Override public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { - HandleGui(engineInstance); + HandleGui(engineInstance, FrameDiffNanoSeconds); } @Override @@ -163,7 +170,8 @@ public class GameCore implements GameLogic { } else camera.Sprint(false); } - private boolean HandleGui(EngineInstance engineInstance){ + private boolean HandleGui(EngineInstance engineInstance, long frameTimeNS){ + FetchingMetrics = true; ImGuiIO imGuiIO = ImGui.getIO(); MouseListener mouseListener = engineInstance.window().getMouseInput(); Vector2f mousePosition = mouseListener.getCurrentPos(); @@ -172,8 +180,38 @@ public class GameCore implements GameLogic { imGuiIO.addMouseButtonEvent(1,mouseListener.isRightButtonPressed()); if(GUI_MODE == 0){ + double FrameTimeMS = (frameTimeNS/1000000.0); + double AverageGPUTimeMS = EngineConfig.LAST_AVERAGE_GPU_TIME/1000000.0; + int windowFlags = ImGuiWindowFlags.NoDecoration + | ImGuiWindowFlags.AlwaysAutoResize + | ImGuiWindowFlags.NoSavedSettings + | ImGuiWindowFlags.NoFocusOnAppearing + | ImGuiWindowFlags.NoNav + | ImGuiWindowFlags.NoMove; ImGui.newFrame(); - ImGui.showDemoWindow(); + ImGui.setNextWindowPos(0,0, ImGuiCond.Always); + //ImGui.setNextWindowSize(300,100); + ImGui.begin("FPS overlay",windowFlags); + ImGui.text("PERFORMANCE METRICS:"); + ImGui.separator(); + ImGui.text(String.format("Vulkan FPS: " + EngineConfig.FrameRate_RENDERTHREAD + "fps | FrameTime: %.2f" + "ms | Avg. GPU Time: %.3f" + "ms | TPS: " + EngineConfig.TPS_RENDERTHREAD,FrameTimeMS,AverageGPUTimeMS)); + ImGui.text(String.format("Primary Thread FPS: " + EngineConfig.FrameRate_PRIMARYTHREAD + "fps | GLFW Window FrameRate:" + EngineConfig.FrameRate_WINDOW + "fps | TPS: " + EngineConfig.TPS_PRIMARYTHREAD)); + ImGui.text(String.format("Main Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + "fps | TPS: " + EngineConfig.TPS_MAINENGINETHREAD)); + ImGui.text(String.format("Fast Thread FPS: " + EngineConfig.FrameRate_FASTENGINETHREAD + "fps | TPS: " + EngineConfig.TPS_FASTENGINETHREAD)); + if(PerformanceMetrics.size() > 0) { + ImGui.text(" "); + ImGui.separator(); + for (int i = 0; i < PerformanceMetrics.size(); i++) { + + String[] memoryUsageMetrics = PerformanceMetrics.get(i); + for(int j = 0; j < memoryUsageMetrics.length; j++){ + ImGui.text(memoryUsageMetrics[j]); + } + ImGui.separator(); + ImGui.text(" "); + } + } + ImGui.end(); ImGui.endFrame(); ImGui.render(); } else if (GUI_MODE == 1){ @@ -190,6 +228,7 @@ public class GameCore implements GameLogic { ImGui.endFrame(); ImGui.render(); } + FetchingMetrics = false; return imGuiIO.getWantCaptureKeyboard(); } @@ -218,4 +257,30 @@ public class GameCore implements GameLogic { CubeActors.get(i).UpdateModelMatrix(); } } + + @Override + public void SecondUpdate(EngineInstance engineInstance) { + SettingPerformanceMetrics.clear(); + List Metrics = new ArrayList<>(); + String[] SceneDetails = new String[5]; + Vector3f Position = engineInstance.scene().GetCamera().GetPosition(); + Vector3f Rotation = engineInstance.scene().GetCamera().GetRotation(); + SceneDetails[0] = String.format("INSTANCE INFORMATION: "); + SceneDetails[1] = String.format(" Camera Position: X: %.2f Y: %.2f Z: %.2f",Position.x ,Position.y ,Position.z); + SceneDetails[2] = String.format(" Camera Rotation: X: %.2f° Y: %.2f° Z: %.2f°",Rotation.x *EngineConfig.RadToDeg,Rotation.y *EngineConfig.RadToDeg ,Rotation.z *EngineConfig.RadToDeg); + SceneDetails[3] = String.format(" Anti Aliasing: " + EngineConfig.getInstance().RenderAAType().name()); + SceneDetails[4] = String.format(" FOV: %.2f°",(EngineConfig.getInstance().GetFOV()*EngineConfig.RadToDeg)); + String[] DeviceInfo = new String[5]; + DeviceInfo[0] = String.format("SYSTEM INFORMATION: "); + DeviceInfo[1] = String.format(" CPU: " + EngineConfig.getInstance().GetCPUDetails()); + DeviceInfo[2] = String.format(" RAM: " + CPUMonitor.RamSize); + DeviceInfo[3] = String.format(" GPU: " + EngineConfig.getInstance().GetGPU()); + DeviceInfo[4] = String.format(" VRAM: " + GPUProfiler.GetVramCapacity()); + Metrics.add(SceneDetails); + Metrics.add(DeviceInfo); + SettingPerformanceMetrics.addAll(Metrics); + SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetMemoryProfiling()); + SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetSystemProfiling()); + PerformanceMetrics = List.copyOf(SettingPerformanceMetrics); + } } 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 7511a9b..ce5da37 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java @@ -34,6 +34,8 @@ public class PrimaryRuntime { public final CPUMonitor cpuProfiler; private static GameLogic gameLogic; + public static GameLogic GetGameCore(){return gameLogic;} + public PrimaryRuntime(String windowTitle, GameLogic appLogic) { String[] knownDLSSfiles = {"nvngx_dlss.dll", "nvngx_dlssg.dll", "_nvngx.dll"}; for (String dllName : knownDLSSfiles) { @@ -57,6 +59,7 @@ public class PrimaryRuntime { FastThread = new FastTickThread(engineInstance, appLogic); DrawingThread = new RenderThread(window, engineInstance, initData, appLogic); cpuProfiler = new CPUMonitor(); + EngineConfig.getInstance().SetCPU(CPUMonitor.getCpuName(), CPUMonitor.getCoreCount()); Thread.currentThread().setName("Terrain4J Primary Runtime Thread"); } public static MainThread GetMainThread(){return PrimaryThread;} @@ -121,8 +124,7 @@ public class PrimaryRuntime { SecondCounter = 0; EngineConfig.FrameRate_WINDOW = EngineConfig.RENDERFRAMES; EngineConfig.FrameRate_PRIMARYTHREAD = Frames; - EngineConfig.TPS = TickFrames; - Logger.info("Primary Thread FPS: " + Frames + " TPS: " + TickFrames + " Window Draw FPS: " + EngineConfig.RENDERFRAMES); + EngineConfig.TPS_PRIMARYTHREAD = TickFrames; Frames = 0; TickFrames = 0; EngineConfig.RENDERFRAMES = 0; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java index ac08796..9400ba9 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/CPUMonitor.java @@ -1,19 +1,102 @@ package net.halbear.Terrain4J.EngineCore.Profiling; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import org.tinylog.Logger; +import java.io.BufferedReader; +import java.io.InputStreamReader; import java.lang.management.ManagementFactory; -import java.lang.management.OperatingSystemMXBean; +import com.sun.management.OperatingSystemMXBean; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; public class CPUMonitor { private final OperatingSystemMXBean OSBean; + public static String RamSize = "0.0GB"; public CPUMonitor(){ - OSBean = ManagementFactory.getOperatingSystemMXBean(); + OSBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); } - public String LogCPUUsage(){ - return ""; + public static String GetRamSize(){return RamSize;} + + public static String[] LogCPUUsage(){ + OperatingSystemMXBean OSBean= (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + double processCPU = OSBean.getProcessCpuLoad(); + double SystemCPU = OSBean.getCpuLoad(); + long totalPhysicalMemory = OSBean.getTotalPhysicalMemorySize(); + long freePhysicalMemory = OSBean.getFreePhysicalMemorySize(); + long usedPhysicalMemory = totalPhysicalMemory - freePhysicalMemory; + + RamSize = String.format("%.2f" + "gb",ConvertToGB(totalPhysicalMemory)); + + Runtime runtime = Runtime.getRuntime(); + long maxHeap = runtime.maxMemory(); + long totalHeap = runtime.totalMemory(); + long freeHeap = runtime.freeMemory(); + long usedHeap = totalHeap - freeHeap; + int TotalCores = Runtime.getRuntime().availableProcessors(); + double ActiveSystemCores = TotalCores * SystemCPU; + double ActiveProcessCores = TotalCores * processCPU; + String[] CPUMetrics = new String[6]; + CPUMetrics[0] = String.format("CPU & SYSTEM MEMORY USAGE:\n"); + CPUMetrics[1] = String.format(" Terrain4J CPU Core Usage: %d / %d", (int)Math.ceil(ActiveProcessCores),TotalCores); + CPUMetrics[2] = String.format(" Terrain4J CPU Usage: %.2f%%%n", processCPU * 100); + CPUMetrics[3] = String.format(" Terrain4J Memory Usage: %d MB / %d MB%n", ConvertToMB(usedHeap), ConvertToMB(maxHeap)); + CPUMetrics[4] = String.format(" Total CPU Load: %.2f%%%n", SystemCPU * 100); + CPUMetrics[5] = String.format(" System Memory Used: %d MB / %d MB%n", ConvertToMB(usedPhysicalMemory), ConvertToMB(totalPhysicalMemory)); + return CPUMetrics; + } + + public static List GetThreadsInUse(){ + List Threads = new ArrayList<>(); + Thread.getAllStackTraces().keySet().forEach(thread -> + { + Threads.add(thread.getName()); + }); + return Threads; + } + + private static double ConvertToGB(long bytes) { + return (double)(bytes / (1024 * 1024* 1024)); + } + private static long ConvertToMB(long bytes) { + return bytes / (1024 * 1024); + } + public static int getCoreCount(){ + return Runtime.getRuntime().availableProcessors(); + } + public static String getCpuName() { + String os = System.getProperty("os.name").toLowerCase(); + String command = ""; + + if (os.contains("win")) { + command = "wmic cpu get name"; + } else if (os.contains("mac")) { + command = "sysctl -n machdep.cpu.brand_string"; + } else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) { + command = "sh -c lscpu | grep 'Model name:'"; + } else { + return "Unknown OS - Cannot fetch CPU name"; + } + + try { + Process process = Runtime.getRuntime().exec(command); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + StringBuilder output = new StringBuilder(); + + while ((line = reader.readLine()) != null) { + if (!line.trim().isEmpty() && !line.toLowerCase().contains("name")) { + output.append(line.trim()); + break; + } + } + return output.toString().isEmpty() ? "Unknown CPU" : output.toString(); + } + } catch (Exception e) { + return "Error reading CPU name: " + e.getMessage(); + } } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/GPUProfiler.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/GPUProfiler.java index f49b75e..1f50cea 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/GPUProfiler.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Profiling/GPUProfiler.java @@ -1,17 +1,56 @@ package net.halbear.Terrain4J.EngineCore.Profiling; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.VkCommandBuffer; -import org.lwjgl.vulkan.VkDevice; -import org.lwjgl.vulkan.VkQueryPoolCreateInfo; +import org.lwjgl.vulkan.*; import java.nio.LongBuffer; +import java.util.ArrayList; +import java.util.List; +import static org.lwjgl.vulkan.EXTMemoryBudget.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; import static org.lwjgl.vulkan.VK13.*; public class GPUProfiler { + + private static String VramCapacity = ""; + public static String GetVramCapacity(){return VramCapacity;} + + public static List GetVramUsage(VkPhysicalDevice physicalDevice){ + List result = new ArrayList<>(); + try(var MemStack = MemoryStack.stackPush()){ + VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget = + VkPhysicalDeviceMemoryBudgetPropertiesEXT.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT); + VkPhysicalDeviceMemoryProperties2 MemoryProperties2 = VkPhysicalDeviceMemoryProperties2.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2) + .pNext(memoryBudget.address()); + vkGetPhysicalDeviceMemoryProperties2(physicalDevice,MemoryProperties2); + + VkPhysicalDeviceMemoryProperties MemoryProperties = MemoryProperties2.memoryProperties(); + int HeapCount = MemoryProperties.memoryHeapCount(); + for(int i = 0; i < HeapCount; i++){ + VkMemoryHeap heap = MemoryProperties.memoryHeaps(i); + if ((heap.flags() & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0) { + long AllocatedByProcess = memoryBudget.heapUsage(i); + long OverallSystemBudget = memoryBudget.heapBudget(i); + long TotalHeapSize = heap.size(); + String[] properties = new String[5]; + VramCapacity = String.format(" %.2f GB\n",TotalHeapSize / (1024.0 * 1024.0*1024.0)); + properties[0] = String.format("VIDEO MEMORY USAGE METRICS:\n"); + properties[1] = String.format("VRAM Heap %d :", i); + properties[2] = String.format(" Total Capacity: %.2f MB\n", TotalHeapSize / (1024.0 * 1024.0)); + properties[3] = String.format(" Terrain4J Usage: %.2f MB\n", AllocatedByProcess / (1024.0 * 1024.0)); + properties[4] = String.format(" System Budget: %.2f MB\n", OverallSystemBudget / (1024.0 * 1024.0)); + result.add(properties); + } + } + } + return result; + } + private long RemoteryInstance; public GPUProfiler(){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java index 3d7979e..0011117 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java @@ -83,6 +83,7 @@ public class EngineThread implements Runnable{ FrameTimes[1] += FrameTimes[0]; FrameTimes[2] += FrameTimes[0]; FrameTimes[3] += FrameTimes[0]; + CycleEvent(); if (FrameTimes[1] >= EngineAccuracy){ FrameEvent(now, InitialTime); Frames++; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java index 5080445..c0168cc 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java @@ -29,7 +29,7 @@ public class FastTickThread extends EngineThread { @Override public void SecondEvent(){ EngineConfig.FrameRate_FASTENGINETHREAD = Frames; - Logger.info(ThreadName + " Thread FPS: " + EngineConfig.FrameRate_FASTENGINETHREAD + " TPS: " + TickFrames); + EngineConfig.TPS_FASTENGINETHREAD = TickFrames; } public void UpdateTickRateThreshold(){ 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 b9c38e6..87a5eda 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java @@ -4,8 +4,13 @@ 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.Main.PrimaryRuntime; +import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor; import org.tinylog.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public class MainThread extends EngineThread { @Override @@ -14,6 +19,7 @@ public class MainThread extends EngineThread { } @Override public void FrameEvent(long now, long InitialTime){ + gameLogic.Update(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); } @Override public void CycleEvent(){ @@ -22,7 +28,24 @@ public class MainThread extends EngineThread { @Override public void SecondEvent(){ EngineConfig.FrameRate_MAINENGINETHREAD = Frames; - Logger.info(ThreadName + " Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + " TPS: " + TickFrames); + EngineConfig.TPS_MAINENGINETHREAD = TickFrames; + List profiling = new ArrayList<>(); + profiling.addAll(Collections.singleton(CPUMonitor.LogCPUUsage())); + List Threads = CPUMonitor.GetThreadsInUse(); + String[] ThreadInformation = new String[Math.min(Threads.size() + 3,14)]; + ThreadInformation[0] = "\nTERRAIN4J PROCESS INFORMATION:\n"; + ThreadInformation[1] = String.format("Thread Count: %d \n",Threads.size()); + ThreadInformation[2] = "v Threads In Use v\n"; + for(int i = 0; i < Math.min(Threads.size(),10); i++){ + ThreadInformation[3 + i] = String.format("Thread %d -> %s",i,Threads.get(i)); + } + if(Threads.size() > 10){ + ThreadInformation[13] = "..."; + } + profiling.addAll(Collections.singleton(ThreadInformation)); + EngineConfig.getInstance().SetSystemProfiling(profiling); + gameLogic.SecondUpdate(PrimaryRuntime.GetEngineInstance()); + } public void UpdateTickRateThreshold(){ CappedToTickRate = EngineConfig.getInstance().GetMainTickCap(); 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 3355778..0ad957f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java @@ -5,8 +5,15 @@ import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Logic.*; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; +import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor; +import net.halbear.Terrain4J.EngineCore.Profiling.GPUProfiler; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRender; import org.tinylog.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public class RenderThread extends EngineThread { private final Render render; private Window window; @@ -26,16 +33,21 @@ public class RenderThread extends EngineThread { @Override public void FrameEvent(long now, long InitialTime){ gameLogic.RenderThreadInput(PrimaryRuntime.GetEngineInstance(), (now-InitialTime)); - gameLogic.Update(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); render.render(PrimaryRuntime.GetEngineInstance()); } @Override public void CycleEvent(){ } + + @Override public void SecondEvent(){ - Logger.info("Render FPS: " + Frames); + EngineConfig.LAST_AVERAGE_GPU_TIME = SceneRender.GetGPUTimeNS(); + List Profiling =GPUProfiler.GetVramUsage(render.GetVulkanContext().GetPhysicalDevice().GetPhysicalDevice()); + EngineConfig.getInstance().SetMemoryProfiling(Profiling); + EngineConfig.FrameRate_RENDERTHREAD = Frames; + EngineConfig.TPS_RENDERTHREAD = TickFrames; } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java index 19a4581..3d233e6 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java @@ -20,47 +20,37 @@ import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; public class TextureCache { public static final int MAX_TEXTURES = 500; private final IndexedLinkedHashMap TextureMap; - private final IndexedLinkedHashMap UnpaddedTextureMap; + private final List ActualTextures; public TextureCache(){ TextureMap = new IndexedLinkedHashMap<>(); - UnpaddedTextureMap = new IndexedLinkedHashMap<>(); + ActualTextures = new ArrayList<>(); } - public Texture AddToMainMap(VulkanContext VkCtx, String ID, String TexturePath, int Format) { - ImageSrc imageSrc = null; - Texture result = null; - try{ - imageSrc = GraphUtils.LoadImage(TexturePath); - result = AddTexture(VkCtx, ID, imageSrc, Format); - } catch (IOException exception){ - Logger.error("Could not load texture from patch [{}], exception: {}",TexturePath, exception); - } finally{ - if(imageSrc != null){ - GraphUtils.CleanImageData(imageSrc); - } - } - return result; + public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format) { + return AddTexture(VkCtx,ID,imageSrc,Format,false); } - public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format){ + public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format, boolean PaddingTexture){ if(TextureMap.size() > MAX_TEXTURES){ throw new IllegalArgumentException("Texture Cache Is Full"); } - Texture newTexture = UnpaddedTextureMap.get(ID); + Texture newTexture = TextureMap.get(ID); if(newTexture == null){ newTexture = new Texture(VkCtx, ID, imageSrc, Format); - UnpaddedTextureMap.put(ID, newTexture); + if(!PaddingTexture)ActualTextures.add(ID); TextureMap.put(ID, newTexture); } return newTexture; } public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) { + return AddTexture(VkCtx,ID,TexturePath,Format,false); + } + public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format, boolean PaddingTexture) { ImageSrc imageSrc = null; Texture result = null; try{ - imageSrc = GraphUtils.LoadImage(TexturePath); - result = AddTexture(VkCtx, ID, imageSrc, Format); + result = AddTexture(VkCtx, ID, imageSrc, Format,PaddingTexture); } catch (IOException exception){ Logger.error("Could not load texture from patch [{}], exception: {}",TexturePath, exception); } finally{ @@ -73,14 +63,21 @@ public class TextureCache { public void TransitionTexts(VulkanContext VkCtx, CommandPool CmdPool, Queue queue){ Logger.debug("Recording Texture Transition"); + IndexedLinkedHashMap NewTextureMap = new IndexedLinkedHashMap<>(); + TextureMap.forEach((name,texture)->{ + if(ActualTextures.contains(name)){ + NewTextureMap.put(name,texture); + } + }); TextureMap.clear(); - TextureMap.putAll(UnpaddedTextureMap); + TextureMap.putAll(NewTextureMap); + NewTextureMap.clear(); int TextureCount = TextureMap.size(); if(TextureCount < MAX_TEXTURES){ int PaddingTextCount = MAX_TEXTURES - TextureCount; String DefaultTexturePath = EngineConfig.getInstance().GetDefaultTexturePath(); for(int i = 0; i < PaddingTextCount; i++){ - AddToMainMap(VkCtx, UUID.randomUUID().toString(), DefaultTexturePath, VK_FORMAT_R8G8B8A8_SRGB); + AddTexture(VkCtx, UUID.randomUUID().toString(), DefaultTexturePath, VK_FORMAT_R8G8B8A8_SRGB,true); } } var CommandBuffer = new CommandBuffer(VkCtx, CmdPool, true, true); 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 5c3838e..a793be2 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.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; import org.lwjgl.PointerBuffer; @@ -13,6 +14,7 @@ import java.util.HashSet; import java.util.Set; import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; +import static org.lwjgl.vulkan.EXTMemoryBudget.VK_EXT_MEMORY_BUDGET_EXTENSION_NAME; import static org.lwjgl.vulkan.VK13.*; public class PhysicalDevice { @@ -28,6 +30,7 @@ public class PhysicalDevice { static{ REQUIRED_EXTENSIONS = new HashSet<>(); REQUIRED_EXTENSIONS.add(KHRSwapchain.VK_KHR_SWAPCHAIN_EXTENSION_NAME); + REQUIRED_EXTENSIONS.add(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); } private PhysicalDevice(VkPhysicalDevice VulkanPhysicalDevice){ @@ -92,6 +95,7 @@ public class PhysicalDevice { if (result == null){ throw new RuntimeException("No Graphics Driver Found!"); } + EngineConfig.getInstance().SetGPU(result.FetchDeviceName()); Logger.debug("Selected Graphics Driver: [{}]", result.FetchDeviceName()); } return result; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java index e1218d8..46f06a5 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java @@ -51,7 +51,7 @@ public class SceneRender implements SceneRenderer {//dynamic rendering private final TextureSampler textureSampler; private static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; - private static final int DEPTH_FORMAT = VK_FORMAT_D16_UNORM; + private static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT; private final VkClearValue ClearValueDepth; private final ByteBuffer PushConstBuffer; private Attachment AttachmentDepth; @@ -68,6 +68,8 @@ public class SceneRender implements SceneRenderer {//dynamic rendering private boolean Bb = false; public int Frames = 0; private static String LastGPULog = ""; + public static long GPUTIME = 0; + public static long CYCLES = 0; private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment.glsl"; private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; @@ -77,9 +79,19 @@ public class SceneRender implements SceneRenderer {//dynamic rendering private final Pipeline VkPipeline; private Matrix4f ProjectionMatrix; + public static long GetGPUTimeNS(){ + long time = 0; + if(CYCLES > 0){ + time = GPUTIME/CYCLES; + } + GPUTIME = 0; + CYCLES = 0; + return time; + } + public SceneRender(VulkanContext vulkanContext){ ClearValueColour = VkClearValue.calloc().color( - c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 0.0f)); + c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f)); ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f)); AttachmentColour = CreateColourAttachment(vulkanContext); AttachmentDepth = CreateDepthAttachment(vulkanContext); @@ -222,6 +234,7 @@ public class SceneRender implements SceneRenderer {//dynamic rendering VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_DEPTH_BIT); + long InitialTime = System.nanoTime(); vkCmdBeginRendering(CommandHandle, RenderInfo); vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipeline()); @@ -255,6 +268,8 @@ public class SceneRender implements SceneRenderer {//dynamic rendering RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true); vkCmdEndRendering(CommandHandle); + GPUTIME += System.nanoTime() - InitialTime; + CYCLES++; } } diff --git a/src/main/resources/DefaultEngineConfig.properties b/src/main/resources/DefaultEngineConfig.properties index dfff69c..cb2db50 100644 --- a/src/main/resources/DefaultEngineConfig.properties +++ b/src/main/resources/DefaultEngineConfig.properties @@ -11,16 +11,23 @@ display_width=640 #the precision of frames, set this to 16000000, and it will limit the whole engine to 64FPS frame_accuracy=0 throttle_on_unfocus=true -throttle_accuracy=500000000 +throttle_accuracy=100000000 #event tick rate for game process -master_tick_rate=120 +master_tick_rate=240 main_thread_tickrate=120 fast_thread_tickrate=240 -cap_master_to_tickrate=false +cap_master_to_tickrate=true cap_main_to_tickrate=true cap_fast_to_tickrate=true #Renderer Properties +#AA settings +#0=No AA +#1=FXAA +#2=MSAAx2 +#3=MSAAx4 +#4=MSAAx8 +anti_alias_mode=0 Debug_Shaders = false ShaderRecompiling = true #Vulkan Debugging toggle @@ -34,5 +41,7 @@ PhysicalDeviceName= #3D Projection Properties field_of_view=60.0f -z_near_plane=1.0f -z_far_plane=100.0f +z_far_plane=0.1f +z_near_plane=10000.0f + + diff --git a/terrain4j.properties b/terrain4j.properties index 6162312..adb63c6 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -11,7 +11,7 @@ display_width=640 #the precision of frames, set this to 16000000, and it will limit the whole engine to 64FPS frame_accuracy=0 throttle_on_unfocus=true -throttle_accuracy=500000000 +throttle_accuracy=100000000 #event tick rate for game process master_tick_rate=240 main_thread_tickrate=120 @@ -27,7 +27,7 @@ cap_fast_to_tickrate=true #2=MSAAx2 #3=MSAAx4 #4=MSAAx8 -anti_alias_mode=0 +anti_alias_mode=4 Debug_Shaders = false ShaderRecompiling = true #Vulkan Debugging toggle @@ -41,7 +41,7 @@ PhysicalDeviceName= #3D Projection Properties field_of_view=60.0f -z_far_plane=1f +z_far_plane=0.1f z_near_plane=10000.0f