From cb3ccbef0b58f8812a3268853eacde636e7f0489 Mon Sep 17 00:00:00 2001 From: austin Date: Thu, 22 May 2025 19:06:40 -0400 Subject: [PATCH] small performance gains --- buildNumber.properties | 4 +- docs/src/progress/renderertodo.md | 2 + .../ui/menu/debug/render/ImGuiRenderer.java | 3 ++ .../electrosphere/entity/DrawableUtils.java | 9 ++++ .../electrosphere/renderer/model/Model.java | 19 ++++++++ .../pipelines/MainContentPipeline.java | 46 ++++++++++++++++--- .../renderer/pipelines/ShadowMapPipeline.java | 14 +++--- .../renderer/target/DrawTargetEvaluator.java | 6 ++- 8 files changed, 88 insertions(+), 15 deletions(-) diff --git a/buildNumber.properties b/buildNumber.properties index 4e052b86..50dbbb7b 100644 --- a/buildNumber.properties +++ b/buildNumber.properties @@ -1,3 +1,3 @@ #maven.buildNumber.plugin properties file -#Tue May 20 18:51:57 EDT 2025 -buildNumber=629 +#Thu May 22 18:46:40 EDT 2025 +buildNumber=630 diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 4c3c4b63..d1adc82b 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1937,6 +1937,8 @@ Debug view of entity colliders Fix lookup bug in debug physics ui Floating point starting to play nice with engine Fix geom-body collision sending wrong vector to body +Per-mesh draw calls in batched static draw calls +Main content pipeline tracking diff --git a/src/main/java/electrosphere/client/ui/menu/debug/render/ImGuiRenderer.java b/src/main/java/electrosphere/client/ui/menu/debug/render/ImGuiRenderer.java index ce9d4b8b..7109dd76 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/render/ImGuiRenderer.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/render/ImGuiRenderer.java @@ -31,6 +31,9 @@ public class ImGuiRenderer { shadowMapPipeline.setFarPlane(farPlaneArr[0]); } } + if(ImGui.collapsingHeader("Main Content Pipeline")){ + ImGui.textWrapped(Globals.renderingEngine.getMainContentPipeline().getTrackingInfo()); + } if(ImGui.collapsingHeader("Post Processing Pipeline")){ PostProcessingPipeline postProcessingPipeline = Globals.renderingEngine.getPostProcessingPipeline(); if(ImGui.button("Toggle Blur")){ diff --git a/src/main/java/electrosphere/entity/DrawableUtils.java b/src/main/java/electrosphere/entity/DrawableUtils.java index e0e76db8..767f23af 100644 --- a/src/main/java/electrosphere/entity/DrawableUtils.java +++ b/src/main/java/electrosphere/entity/DrawableUtils.java @@ -27,4 +27,13 @@ public class DrawableUtils { } } + /** + * Checks if the entity has a unique model + * @param entity The entity + * @return true if it has a unique model, false otherwise + */ + public static boolean hasUniqueModel(Entity entity){ + return entity.containsKey(EntityDataStrings.HAS_UNIQUE_MODEL); + } + } diff --git a/src/main/java/electrosphere/renderer/model/Model.java b/src/main/java/electrosphere/renderer/model/Model.java index de3638d0..805a4eb8 100644 --- a/src/main/java/electrosphere/renderer/model/Model.java +++ b/src/main/java/electrosphere/renderer/model/Model.java @@ -304,6 +304,25 @@ public class Model { Globals.profiler.endCpuSample(); } + /** + * Draws a specific mesh + * @param i The index of the mesh + */ + public void drawMesh(RenderPipelineState renderPipelineState, OpenGLState openGLState, int i){ + if(i < 0 || i >= this.meshes.size()){ + throw new Error("Invalid mesh! " + i); + } + this.meshes.get(i).complexDraw(renderPipelineState, openGLState); + } + + /** + * Gets the number of meshes in the model + * @return The number of meshes + */ + public int getMeshCount(){ + return this.meshes.size(); + } + /** * Determines the correct shader to use for a given mesh * @param shaderMask The shader mask diff --git a/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java b/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java index 25ffad5d..031d8bb1 100644 --- a/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java +++ b/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java @@ -44,9 +44,15 @@ public class MainContentPipeline implements RenderPipeline { */ private List standardDrawCall = new LinkedList(); + /** + * Number of terrain chunks rendered + */ + private int terrainChunks = 0; + @Override public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) { Globals.profiler.beginCpuSample("MainContentPipeline.render"); + this.clearTrackingData(); Matrix4d modelTransformMatrix = new Matrix4d(); @@ -107,6 +113,11 @@ public class MainContentPipeline implements RenderPipeline { currentActor.applySpatialData(new Matrix4d(modelTransformMatrix),new Vector3d(position)); //draw currentActor.draw(renderPipelineState,openGLState); + + //tracking + if(currentEntity.containsKey(EntityDataStrings.TERRAIN_IS_TERRAIN)){ + this.terrainChunks++; + } } } for(ModelAccumulatorData accumulator : this.drawTargetAccumulator.getCalls()){ @@ -116,12 +127,14 @@ public class MainContentPipeline implements RenderPipeline { List transforms = accumulator.getTransforms(); List positions = accumulator.getPositions(); model.setMeshMask(null); - for(int i = 0; i < count; i++){ - Vector3d position = positions.get(i); - Matrix4d transform = transforms.get(i); - model.setWorldPos(position); - model.setModelMatrix(transform); - model.draw(renderPipelineState, openGLState); + for(int meshIndex = 0; meshIndex < model.getMeshCount(); meshIndex++){ + for(int i = 0; i < count; i++){ + Vector3d position = positions.get(i); + Matrix4d transform = transforms.get(i); + model.setWorldPos(position); + model.setModelMatrix(transform); + model.drawMesh(renderPipelineState, openGLState, meshIndex); + } } } } @@ -327,6 +340,13 @@ public class MainContentPipeline implements RenderPipeline { ; } + /** + * Clears the tracking data + */ + private void clearTrackingData(){ + this.terrainChunks = 0; + } + /** * Get the first person pipeline * @param firstPersonItemsPipeline the first person pipeline @@ -350,5 +370,19 @@ public class MainContentPipeline implements RenderPipeline { public List getStandardEntityQueue(){ return standardDrawCall; } + + /** + * Gets the tracking info + * @return The tracking info + */ + public String getTrackingInfo(){ + String message = "" + + "Terrain entities:" + this.terrainChunks + "\n" + + ""; + for(DrawTargetAccumulator.ModelAccumulatorData data : this.drawTargetAccumulator.getCalls()){ + message = message + data.getModelPath() + ": " + data.getCount() + "\n"; + } + return message; + } } diff --git a/src/main/java/electrosphere/renderer/pipelines/ShadowMapPipeline.java b/src/main/java/electrosphere/renderer/pipelines/ShadowMapPipeline.java index 1e1e11f2..8a8ba702 100644 --- a/src/main/java/electrosphere/renderer/pipelines/ShadowMapPipeline.java +++ b/src/main/java/electrosphere/renderer/pipelines/ShadowMapPipeline.java @@ -147,12 +147,14 @@ public class ShadowMapPipeline implements RenderPipeline { List transforms = accumulator.getTransforms(); List positions = accumulator.getPositions(); model.setMeshMask(null); - for(int i = 0; i < count; i++){ - Vector3d position = positions.get(i); - Matrix4d transform = transforms.get(i); - model.setWorldPos(position); - model.setModelMatrix(transform); - model.draw(renderPipelineState, openGLState); + for(int meshIndex = 0; meshIndex < model.getMeshCount(); meshIndex++){ + for(int i = 0; i < count; i++){ + Vector3d position = positions.get(i); + Matrix4d transform = transforms.get(i); + model.setWorldPos(position); + model.setModelMatrix(transform); + model.drawMesh(renderPipelineState, openGLState, meshIndex); + } } } } diff --git a/src/main/java/electrosphere/renderer/target/DrawTargetEvaluator.java b/src/main/java/electrosphere/renderer/target/DrawTargetEvaluator.java index 7a9f6756..592fe619 100644 --- a/src/main/java/electrosphere/renderer/target/DrawTargetEvaluator.java +++ b/src/main/java/electrosphere/renderer/target/DrawTargetEvaluator.java @@ -8,6 +8,7 @@ import org.joml.Vector3d; import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.engine.Globals; +import electrosphere.entity.DrawableUtils; import electrosphere.entity.Entity; import electrosphere.entity.EntityTags; import electrosphere.entity.EntityUtils; @@ -23,6 +24,7 @@ public class DrawTargetEvaluator { * Evaluates the draw targets */ public static void evaluate(){ + Globals.profiler.beginCpuSample("DrawTargetEvaluator.evaluate"); //main content pipeline structures DrawTargetAccumulator mainAccumulator = Globals.renderingEngine.getMainContentPipeline().getDrawTargetAccumulator(); List mainQueue = Globals.renderingEngine.getMainContentPipeline().getStandardEntityQueue(); @@ -52,7 +54,7 @@ public class DrawTargetEvaluator { Vector3d position = EntityUtils.getPosition(currentEntity); //fetch actor Actor currentActor = EntityUtils.getActor(currentEntity); - if(currentActor.isStaticDrawCall()){ + if(!DrawableUtils.hasUniqueModel(currentEntity) && currentActor.isStaticDrawCall()){ //calculate camera-modified vector3d Vector3d cameraModifiedPosition = positionVec.set(position).sub(cameraCenter); //calculate and apply model transform @@ -106,6 +108,8 @@ public class DrawTargetEvaluator { // } // } // } + + Globals.profiler.endCpuSample(); } }